Main Content

Preserve Dimensions of Multidimensional Arrays in Generated Code

By default, the generated code contains one-dimensional arrays for multidimensional model data. In the Configuration Parameters dialog box, if you set the Array layout parameter to Row-major, you can preserve dimensions of multidimensional arrays in the generated code. Preserving array dimensions in the generated code enhances integration with external code.

MATLAB® and C organize multidimensional data in different ways (see Dimension Preservation of Multidimensional Arrays). In the generated code, you can preserve dimensions of root-level inports and outports, parameters, signals, states, lookup tables, and data stores.

Configure Default Model Data Elements to Preserve Dimensions

In the Code Mappings > Data Defaults tab, you can configure these model data elements categories. You specify a storage class to preserve dimensions.

  • Inports

  • Outports

  • Signals, states, and internal data

  • Shared local data stores

  • Global data stores

  • Model parameters

  • External parameters

Then, when you set the Storage class to Auto or Model default on individual model data elements, by default, the code generator applies the configuration that you set up for the respective model data elements in the Data Defaults tab.

This example shows how to preserve array dimensions for the preceding model data element categories.

Open the example model PreserveArrayDims.

model = 'PreserveArrayDims';
open_system(model);

In the Configuration Parameters dialog box, verify that parameter Array layout is set to Row-major.

set_param('PreserveArrayDims', 'ArrayLayout', 'Row-major');

Open the Embedded Coder app. In the C Code tab, open the Code Mappings editor. Select Code Interface > Default Code Mappings. This option pins the Code Mappings editor open.

On the Data Defaults tab, select the Inports category. The Storage Class specified is ExportToFile. Click the edit icon and select the PreserveDimensions property.

To configure the PreserveDimensions property programmatically, use the coder.mapping.defaults.set function in the MATLAB command window

cm = coder.mapping.api.get('PreserveArrayDims');
setDataDefault(cm, 'Inports', 'PreserveDimensions', '1')

You can create a new storage class in Embedded Coder®, and then specify that class to preserve dimensions. For more details, see Preserve Dimensions for New Storage Classes.

For a list of supported storage classes, see Storage Classes Supported to Preserve Dimensions.

Generate and review code.

evalc('slbuild(''PreserveArrayDims'')');

The generated code preserves the dimensions of the root-level Inports.

file = fullfile('PreserveArrayDims_ert_rtw',...
    'PreserveArrayDims.c');
coder.example.extractLines(file,'real_T rtActuator', ...
    'real_T rtTemperature',0,1);
real_T rtPressure[2][3];               /* '<Root>/Pressure' */
real_T rtTargetVolume[2][3];           /* '<Root>/TargetVolume' */
real_T rtTemperature[2][3];            /* '<Root>/Temperature' */

Configure Individual Model Data Elements to Preserve Dimensions

You can override the default configurations specified in the Data Defaults tab by configuring individual model data element sources in other tabs such as Inports, Outports, Parameters, Data Stores, and Signals/States. Here is an example workflow that is applicable to the model data element categories.

Add Signal to Code Mappings Editor

  1. From the C Code tab, open Code Interface > Individual Element Code Mappings.

  2. In the Code Mappings editor, select the Signals/States tab. The Signals section is currently empty. There can be multiple signals in a given model. Some of these signals might not be important when configuring code generation. You can mark signals as signals of interest that are relevant to your code generation configuration. When you add a signal explicitly, it gets added to the Code Mappings editor.

  3. In the Code Mappings editor, open the Signals/States tab. Select the signal in the Simulink® Editor that you want to add to the Code Mappings editor. For this example, select the signal going from the subsystem Volume Controller to the outport Actuator Command. Pause on the ellipsis (...) that appears above or below the signal line to open the action bar. Click the Add selected signals to code mappings button. The signal is populated in the Signals table in the Code Mappings editor.

action_bar_add_signals.png

cm = coder.mapping.api.get('PreserveArrayDims');
vol_ports = get_param('PreserveArrayDims/Volume Controller','PortHandles');
vol_outPort = vol_ports.Outport(1);
addSignal(cm,vol_outPort);

Configure Signal Interface and Generate Code

As per the configurations in the Data Defaults tab, the default storage class for signals is Localizable. The default configuration for signals also specifies to preserve dimensions of multidimensional arrays. By default the Storage Class of the individually added signal is configured as Auto. You can override the default configuration for the individual signal by changing the specification of the added signal under Signals/States tab. If you want to apply the default settings, in the Signals/States tab, set the Storage Class to Model default: Localizable. If you want to maintain the same storage class, Localizable, but not preserve dimensions for the selected signal, specify Storage Class as Localizable and clear the PreserveDimensions property.

If you specify the Storage Class as Model default, you cannot override the default configurations specified in Data Defaults tab. To override the default specifications for the default storage class, select that storage class and change the configurations for the individual modeling element.

For this example, set the Storage Class to Localizable. Click the edit icon and specify a signal name in the Identifier property, such as VolumeController. Confirm that the PreserveDimensions property is cleared.

setSignal(cm,vol_outPort, 'StorageClass', 'Localizable', 'Identifier', 'VolumeController', 'PreserveDimensions', 0);

Generate and review the code.

evalc('slbuild(''PreserveArrayDims'')');

The generated code does not preserve dimensions of the individual signal but does for other signals.

file = fullfile('PreserveArrayDims_ert_rtw',...
    'PreserveArrayDims.c');
coder.example.extractLines(file,'/* Definition for custom storage class: Localizable */', ...
    'static real_T rtVolumedifference',0,1);
static real_T LogSignal[11][9];        /* '<S2>/Log volume difference' */
real_T VolumeController[6];            /* '<S3>/Gain' */
static real_T rtIterationCount[2][3];  /* '<S2>/PreviousVolumeErrorAverage' */
static real_T rtIterationCount_g[2][3];/* '<S2>/IterationCount' */
static real_T rtVolumedifference[2][3];/* '<S1>/Volume difference' */

Storage Classes Supported to Preserve Dimensions

You can preserve dimensions in the generated code for these storage classes:

  • Const

  • Volatile

  • ConstVolatile

  • ExportToFile

  • ImportFromFile

  • FileScope

  • Localizable

Preserve Dimensions for New Storage Classes

To preserve dimensions when you design your own storage class, in the Embedded Coder Dictionary, in the Property Inspector, set Storage Type to Unstructured and select the Preserve array dimensions property. Selecting this property preserves dimensions for instances of your storage class. To use the storage class, in the Code Mappings editor, configure the model element categories by specifying Storage Class to the new storage class that you created.

To preserve dimensions when you design your own storage class in the Custom Storage Class Designer, specify Type as Unstructured and select the Preserve array dimensions property. Preserve array dimensions has these options:

  • No (default) — Flattens the multidimensional array to one dimension in the generated code.

  • Yes — Preserves array dimensions for parameters of the specified storage class.

  • Instance Specific — If you want to preserve array dimensions for each instance of the storage class, enable the Preserve array dimensions property on the parameter object. For the Simulink package, this property setting is Instance Specific by default.

Limitations

  • The code generator does not preserve dimensions for parameters without data objects.

  • The code generator always produces one-dimensional arrays for N-dimensional vectors, even when you specify N-dimensional indexing.