Main Content

Use symbolic dimensions to simulate various sets of dimension choices without regenerating code for every set. Set up your model with dimensions that you specify as symbols in blocks and data objects. These symbols propagate throughout the model during simulation, and then go into the generated code. Modeling constraints for symbols during simulation (for example, `C=A+B`

) are output as preprocessor conditionals in either the `model.h`

or the `model`

` _`

`types.h`

file.

You can directly specify dimension information as a symbol or a numeric constant for these blocks and data objects:

Inport

Outport

Signal Specification

Data Store Memory

Interpreted MATLAB Function

`Simulink.Signal`

`Simulink.Parameter`

`Simulink.BusElement`

`AUTOSAR.Parameter`

The Data Store Memory and Interpreted MATLAB Function blocks also support variable dimension signals. For these blocks, the symbolic dimensions control the maximum allowed size.

You must provide the initialization code for `Simulink.Parameter`

objects that contain symbolic dimensions. To prevent the generated code from initializing these parameters, you must either:

Configure the parameters to use a storage class with the

**Data scope**property set to`Imported`

, such as the`ImportedExtern`

or`ImportedExternPointer`

built-in storage classes.Configure the parameters to use a storage class with the

**Data initialization**property set to`None`

.

You use `Simulink.Parameter`

objects to specify dimension information as symbols. For more information on signal dimensions, see Determine Signal Dimensions.

You must fix symbolic dimension values at compile-time. You can not resolve a symbolic dimension to another variable and then vary it during run-time because you define the behavior during simulation.

**Note:** The dimension variants feature is on by default. You can turn off this feature by clearing the Allow symbolic dimension specification parameter in the Configuration Parameters dialog box.

**Define Symbolic Dimensions**

This example uses the model `rtwdemo_dimension_variants`

to show how to implement symbolic dimensions. This model has four modeling patterns involving vectors and matrices.

To show block names, on the

**Debug**tab, on the**Information Overlays**menu, clear the**Hide Automatic Block Names**parameter.Open the

**Embedded Coder**app. In the**C Code**tab, select**Code Interface > Individual Element Code Mappings**.In the Code Mappings editor, on the

**Parameters**tab, click the refresh button. Seven`Simulink.Parameter`

objects appear. Four of these objects are for specifying symbolic dimensions. These`Simulink.Parameter`

objects have the names`A`

,`B`

,`C`

, and`D`

. Notice that these parameters have a storage class of`CompilerFlag`

.

To use a `Simulink.Parameter`

object for dimension specification, it must be defined in the base workspace and have one of these storage classes:

`Define`

or`ImportedDefine`

with header file specified`CompilerFlag`

User-defined custom storage class that defines data as a macro in a specified header file

For `Simulink.Parameter`

objects with an `ImportedDefine`

custom storage class, provide a header file on the MATLAB path. Insert the name of the header file in the **HeaderFile** field in the Simulink.Parameter dialog box.

You can use MATLAB expressions to specify symbolic dimensions. For a list of supported MATLAB expressions, see the section Operators and Operands in Variant Condition Expressions in Introduction to Variant Controls.

**Specify Symbolic Dimensions for Blocks and Data Objects**

Click Inport Block

`In2`

. On the Property Inspector, on the**Parameters**tab, the**Port Dimensions**field contains the`Simulink.Parameter`

object`A`

. For Inport blocks, you specify symbolic dimensions in the**Port Dimensions**field.Click Inport block

`In3`

. The**Port Dimensions**field contains the`Simulink.Parameter`

object`B`

.Click the Constant block. The

**Constant value**parameter has a value of`Data`

. In the Code Mappings editor, on the**Parameters**tab, click the`Simulink.Parameter`

object`Data`

. On the Property Inspector, the**Dimension**field has the character vector`'[1,C]'`

, which is equivalent to`'[1,5]'`

because`C`

has a value of`5`

. The**Value**field contains an array with`5`

values, which is consistent with its dimensions. The dimensions of the data object must be consistent with the value of the`Simulink.Parameter`

object that is in the**Dimensions**field. Notice that`Data`

has a**Storage class**of`ImportedExtern`

.Open the

`1-D Lookup Table1`

block parameters dialog box. The**Table data**field contains the`Simulink.Parameter`

,`PT`

. The**Breakpoints 1**field contains the`Simulink.Parameter`

,`PB`

.In the Code Mappings editor, click

`PB`

and`PT`

and view their properties. These parameters contain the character vector`'[1,D]'`

in their**Dimensions**field and are arrays consisting of 15 values. The value of`D`

is consistent with the dimension of the`PB`

and`PT`

parameters because`D`

has a value of`15`

.Simulate the model. Simulink propagates the dimensions symbolically in the diagram. During propagation, Simulink establishes modeling constraints among symbols. Simulink then checks for consistency with these constraints based on current numerical assignments. One modeling constraint for

`rtwdemo_dimension_variants`

is that`C=A+B`

. The**Diagnostic Viewer**produces a warning for any violations of constraints.Change the dimension specification to a different configuration and simulate the model again.

Though not shown in this example, you can specify an n-D dimension expression with one or more of the dimensions being a symbol (for example, `'[A,B,C]'`

or `'[1,A,3]'`

).

**Generate Code for a Model with Dimension Variants**

Once you have verified dimension specifications through model simulation, generate code for `rtwdemo_dimension_variants`

.

Create a temporary folder for the build and inspection process.

currentDir = pwd; [~,cgDir] = rtwdemodir();

Build the model.

```
model='rtwdemo_dimension_variants';
rtwbuild(model)
```

### Starting build procedure for: rtwdemo_dimension_variants ### Successful completion of build procedure for: rtwdemo_dimension_variants Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================================================== rtwdemo_dimension_variants Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 26.208s

View the generated code. In the `rtwdemo_dimension_variants.h`

file, symbolic dimensions are in data declarations.

hfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',... 'rtwdemo_dimension_variants.h'); rtwdemodbtype(hfile,'/* External inputs', '/* Real-time', 1, 0);

/* External inputs (root inport signals with default storage) */ typedef struct { real_T In2[A]; /* '<Root>/In2' */ real_T In3[B]; /* '<Root>/In3' */ } ExtU; /* External outputs (root outports fed by signals with default storage) */ typedef struct { real_T Out1[(A + B)]; /* '<Root>/Out1' */ real_T Out2[(A + B)]; /* '<Root>/Out2' */ } ExtY;

The `rtwdemo_dimension_variants.h`

file contains data definitions and preprocessor conditionals that define constraints established among the symbols during simulation. One of these constraints is that the value of a symbolic dimension must be greater than `1`

. This file also includes the user-provided header file for any `Simulink.Parameter`

objects with an `ImportedDefine`

custom storage class.

hfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',... 'rtwdemo_dimension_variants.h'); rtwdemodbtype(hfile,'#ifndef A', '/* Macros for accessing', 1, 0);

#ifndef A #error The variable for the parameter "A" is not defined #endif #ifndef B #error The variable for the parameter "B" is not defined #endif #ifndef C #error The variable for the parameter "C" is not defined #endif #ifndef D #error The variable for the parameter "D" is not defined #endif /* * Constraints for division operations in dimension variants */ #if (1 == 0) || (((A+B) % 1) != 0) # error "The preprocessor definition '1' must not be equal to zero and the division of '(A+B)' by '1' must not have a remainder." #endif /* * Registered constraints for dimension variants */ /* Constraint 'C == (A+B)' registered by: * '<Root>/1-D Lookup Table1' */ #if C != (A+B) # error "The preprocessor definition 'C' must be equal to '(A+B)'" #endif #if A <= 1 # error "The preprocessor definition 'A' must be greater than '1'" #endif #if B <= 1 # error "The preprocessor definition 'B' must be greater than '1'" #endif /* Constraint 'D > 1' registered by: * '<Root>/1-D Lookup Table1' */ #if D <= 1 # error "The preprocessor definition 'D' must be greater than '1'" #endif /* Constraint 'C > 1' registered by: * '<S2>/Assignment' */ #if C <= 1 # error "The preprocessor definition 'C' must be greater than '1'" #endif #if A >= 11 # error "The preprocessor definition 'A' must be less than '11'" #endif #if B >= 11 # error "The preprocessor definition 'B' must be less than '11'" #endif /* Constraint 'D < 21' registered by: * '<Root>/1-D Lookup Table1' */ #if D >= 21 # error "The preprocessor definition 'D' must be less than '21'" #endif /* Constraint 'C < 11' registered by: * '<S2>/Assignment' */ #if C >= 11 # error "The preprocessor definition 'C' must be less than '11'" #endif

In the `rtwdemo_dimension_variants.c`

file, symbolic dimensions participate in loop bound calculations, array size and index offset calculations, and a parameterized utility function (for example, Lookup Table block) calculation.

cfile = fullfile(cgDir,'rtwdemo_dimension_variants_ert_rtw',... 'rtwdemo_dimension_variants.c'); rtwdemodbtype(cfile,'/* Model step', '/* Model initialize', 1, 0);

/* Model step function */ void rtwdemo_dimension_variants_step(void) { real_T rtb_VectorConcatenate[A + B]; real_T rtb_VectorConcatenate_m; int32_T ForEach_itr; int32_T i; int32_T s2_iter; /* Gain: '<Root>/Gain' incorporates: * Inport: '<Root>/In2' */ for (ForEach_itr = 0; ForEach_itr <= (int32_T)(A - 1); ForEach_itr++) { rtb_VectorConcatenate[ForEach_itr] = 2.0 * rtU.In2[ForEach_itr]; } /* End of Gain: '<Root>/Gain' */ /* Gain: '<Root>/Gain1' incorporates: * Inport: '<Root>/In3' */ for (ForEach_itr = 0; ForEach_itr <= (int32_T)(B - 1); ForEach_itr++) { rtb_VectorConcatenate[(int32_T)(A + ForEach_itr)] = 3.0 * rtU.In3[ForEach_itr]; } /* End of Gain: '<Root>/Gain1' */ /* Outputs for Iterator SubSystem: '<Root>/For Each Subsystem' incorporates: * ForEach: '<S1>/For Each' */ for (ForEach_itr = 0; ForEach_itr <= (int32_T)((int32_T)(A + B) - 1); ForEach_itr++) { /* Sum: '<Root>/Add' incorporates: * Constant: '<Root>/Constant' * Lookup_n-D: '<Root>/1-D Lookup Table1' */ rtb_VectorConcatenate_m = rtb_VectorConcatenate[ForEach_itr] + look1_binlx (Data[ForEach_itr], PB, PT, (uint32_T)((uint32_T)D - 1U)); /* ForEachSliceAssignment generated from: '<S1>/Out1' incorporates: * MATLAB Function: '<S1>/MATLAB Function' */ /* MATLAB Function 'For Each Subsystem/MATLAB Function': '<S3>:1' */ /* '<S3>:1:4' y = 2*u; */ rtY.Out1[ForEach_itr] = 2.0 * rtb_VectorConcatenate_m; /* Sum: '<Root>/Add' */ rtb_VectorConcatenate[ForEach_itr] = rtb_VectorConcatenate_m; } /* End of Outputs for SubSystem: '<Root>/For Each Subsystem' */ /* Outputs for Iterator SubSystem: '<Root>/For Iterator Subsystem' incorporates: * ForIterator: '<S2>/For Iterator' */ /* Constant: '<Root>/Constant1' */ ForEach_itr = ((int32_T)A); if (((int32_T)A) < 0) { ForEach_itr = 0; } /* End of Constant: '<Root>/Constant1' */ for (s2_iter = 0; s2_iter < ForEach_itr; s2_iter++) { /* Assignment: '<S2>/Assignment' incorporates: * Constant: '<S2>/Constant' * Outport: '<Root>/Out2' * Product: '<S2>/Product' * Selector: '<S2>/Selector' */ if (s2_iter == 0) { for (i = 0; i <= (int32_T)((int32_T)(A + B) - 1); i++) { rtY.Out2[i] = rtb_VectorConcatenate[i]; } } rtY.Out2[s2_iter] = rtb_VectorConcatenate[s2_iter] * 2.0; /* End of Assignment: '<S2>/Assignment' */ } /* End of Outputs for SubSystem: '<Root>/For Iterator Subsystem' */ }

Close the model and code generation report.

bdclose(model) rtwdemoclean; cd(currentDir)

When you specify the dimensions of a parameter in a model by using a symbol, you must make sure that the parameter value is consistent with the dimension value. To simulate different choices for the dimension value, you must manually correct the parameter value.

For example, in the `rtwdemo_dimension_variants`

model , the
`Simulink.Parameter`

object `Data`

stores a vector value,
`[1 2 3 4 5]`

, and uses a symbolic dimension `C`

with
initial value `5`

. If you change the value of `C`

, to
simulate the model, you must make sure the number of elements in the vector value matches
the new value of `C`

.

To reduce the effort of maintenance when you change the value of `C`

,
you can set the value of `Data`

to an expression involving
`C`

.

Open the model.

rtwdemo_dimension_variants

At the command prompt, inspect the initial values of

`Data`

and`C`

. The value of`Data`

is a vector of integers from`1`

to`C`

.Data.Value

ans = 1 2 3 4 5

C.Value

ans = 5

In MATLAB

^{®}code syntax, the value of`Data`

is`1:C`

. To preserve this relationship between the parameter objects, set the value of`Data`

by using the`slexpr`

function.`Data.Value = slexpr('1:C');`

To prevent data type propagation errors, set the data type of

`Data`

explicitly to`double`

, which is the data type that the parameter acquired before you set the parameter value to an expression.`Data.DataType = 'double';`

Set the value of

`C`

to a different number, such as`6`

. Due to dimension constraints in the model, you must set the value of another dimension symbol,`A`

, to`3`

.C.Value = 6; A.Value = 3;

Simulate the model. The block diagram shows that the value of

`Data`

now has six elements.

For more complicated applications, you can write your own MATLAB function that returns parameter values based on dimension symbols. Set the value of the parameter data to an expression that calls your function.

For general information about using an expression to set the value of a
`Simulink.Parameter`

object, see Set Variable Value by Using a Mathematical Expression.

When you create a model with symbolic dimensions, be aware of the following optimization considerations:

The code generator reuses buffers only if dimension propagation establishes equivalence among buffers.

Two loops with symbolic loop bound calculations are fused together only if they share equivalent symbolic expression.

Optimizations do not eliminate a symbolic expression or condition check based on the current value of a symbolic dimension.

If an existing model uses `Simulink.Parameter`

objects to specify dimensions,
it can be incompatible with dimension variants. Here are two common scenarios:

Only a subset of blocks accepts symbolic dimension specifications. If a block is not compatible with symbolic dimensions, it causes an update diagram error.

`Simulink.Parameter`

objects that you use to define symbolic dimensions or have symbolic dimensions must have one of the storage classes described in this example. If these specifications are not met, the build procedure for the model fails during code generation.

You can address these backward compatibility issues by doing the following:

Turn off dimension variants feature by clearing the

**Allow symbolic dimension specification**parameter in the Configuration Parameters dialog box.Update

`Simulink.Parameter`

objects that define symbolic dimensions or have symbolic dimension specifications.Update the model so that only supported blocks have symbolic dimensions or propagate symbolic dimensions.

For a list of supported blocks, see the Block Support Table.
To access the information in this table, enter `showblockdatatypetable`

at
the MATLAB command prompt. Unsupported blocks (for example, MATLAB
Function) can still work in a model containing symbolic dimensions
as long as these blocks do not directly interact with symbolic dimensions.

In the following cases, supported blocks do not propagate symbolic dimensions.

For Assignment and Selector blocks, you set the

**Block Parameters**>**Index Option**parameter to`Index vector (dialog)`

. For Selector and Assignment blocks, if you specify a symbolic dimension for the Index parameter, the code generator does not honor the symbolic dimension in the generated code.For the Product block, you specify a value of

`1`

for the**Block Parameters**>**Number of inputs**parameter, and you set the**Multiply over**parameter to`Specified dimensions`

.For the ForEach block, you specify a symbolic dimension for the

**Partition Width**parameter.

Note that the following modeling patterns are among those modeling patterns that can cause Simulink to error out:

For Switch blocks, an input signal or the

**Threshold**parameter has symbolic dimensions, and you select**Allow different data input sizes (Results in variable-size output signal)**.A Data Store Read block selects elements of a

`Simulink.Bus`

signal that has symbolic dimensions.For Lookup Table blocks, on the

**Block Parameters**>**Algorithm**tab, you select the parameter**Use one input port for all input data**.

The following products and software capabilities support dimension variants in that they act on the numeric value of a symbolic dimension. These features do not support the propagation of symbolic dimensions during model simulation and the preservation of symbolic dimensions in the generated code.

Code Replacement for Lookup Tables

Software-in-the-Loop (SIL) and Processor-in-the-Loop (PIL) simulations

Accelerator and rapid accelerator simulation modes

Scope and simulation observation (for example, logging, SDI, and so on)

Model coverage

Simulink Design Verifier

Fixed-Point Designer

Data Dictionary

Simulink PLC Coder

HDL Coder

The following do not support dimension variants:

System Object

Stateflow charts that use MATLAB as the action language

Physical modeling

Discrete-event simulation

Frame data

MATLAB functions

The following limitations also apply to models that utilize symbolic dimensions.

For simulation, the size of a symbolic dimension can equal 1. For code generation, the size of a symbolic dimension must be greater than

`1`

.If a symbolic dimension is a MATLAB expression that contains an arithmetic expression and either a relational or logical expression, you must add

`+0`

after the relational or logical part of the MATLAB expression. If you do not add`+0`

, the model errors out during simulation because you cannot mix a`boolean`

data type with integer or`double`

data types. Adding`+0`

converts the data type of the relational or logical part of the expression from a`boolean`

to a`double`

.For example, suppose in the Inport block parameters dialog box, the

**Port dimensions**parameter has the expression`[(C==8)*D+E,3]`

. The**Data type**parameter is set to`double`

. Since`C==8`

is a relational expression, you must change the expression to`[((C==8)+0)*D+E,3]`

to prevent the model from producing an error during simulation.Simulink propagates symbolic dimensions for an entire structure or matrix, but not for a part of a structure or matrix. For example, the

`Simulink.Parameter`

`P`

is a`2x3`

matrix with symbolic dimensions`[Dim,Dim1]`

.p=Simulink.Parameter(struct('A',[1 2 3;4 5 6])) p.DataType='Bus:bo' bo=Simulink.Bus bo.Elements(1).Name='A' bo.Elements(1).Dimensions='[Dim,Dim1]' Dim=Simulink.Parameter(2) Dim1=Simulink.Parameter(3) p.CoderInfo.StorageClass='Custom' p.CoderInfo.CustomStorageClass='Define' Dim.CoderInfo.StorageClass='Custom' Dim.CoderInfo.CustomStorageClass='Define' Dim1.CoderInfo.StorageClass='Custom' Dim1.CoderInfo.CustomStorageClass='Define'

If you specify

`p.A`

for a dimensions parameter, Simulink propagates the symbolic dimensions`[Dim,Dim1]`

. If you specify`p.A(1,:)`

, Simulink propagates the numeric dimension`3`

but not the symbolic dimension,`Dim1`

.The MATLAB expression

`A(:)`

does not maintain symbolic dimension information. Use`A`

instead.The MATLAB expression

`P(2:A)`

does not maintain symbolic dimension information. Use the Selector block instead.The MATLAB expression

`P(2,:)`

is not a tunable expression, so it does not maintain symbolic dimension information.Suppose that you set the value of a mask parameter,

`myMaskParam`

, by using a field of a structure or by using a subset of the structures in an array of structures. You store the structure or array of structures in a`Simulink.Parameter`

object so that you can use a`Simulink.Bus`

object to apply symbolic dimensions to the structure fields. Under the mask, you configure a block parameter to use one of the fields that have symbolic dimensions. The table shows some example cases.Description Value of mask parameter ( `myMaskParam`

)Value of block parameter `myStruct`

is a structure with field`gains`

, which uses symbolic dimensions.`myStruct.gains`

`myMaskParam`

`myStruct`

is a structure with field hierarchy`myStruct.subStruct.gains`

. The field`gains`

uses symbolic dimensions.`myStruct.subStruct`

`myMaskParam.gains`

`myStructs`

is an array of structures. Each structure has a field`gains`

, which uses symbolic dimensions.`myStructs(2)`

`myMaskParam.gains`

In these cases, you cannot generate code from the model. As a workaround, choose one of these techniques:

Use the entire structure (

`myStruct`

) or array of structures (`myStructs`

) as the value of the mask parameter. Under the mask, configure the block parameter to dereference the target field from the mask parameter by using an expression such as`myMaskParam.subStruct.gains`

.Use literal dimensions instead of symbolic dimensions for the target field (

`gains`

).

This limitation also applies when you use a field of a structure or a subset of the structures in an array of structures as the value of a model argument in a Model block.