При повторении алгоритмов на диаграмме путем копирования и вставки блоков и подсистем ведение модели может стать затруднительным. Отдельные сигнальные линии и подсистемы могут перекрывать схему, снижая читаемость и затрудняя простые изменения. Переменные также могут объединять рабочие пространства, снижая переносимость модели. Модель может развивать эти проблемы эффективности по мере того, как вы добавляете к конструкции с течением времени.
Чтобы повторить алгоритм, можно выполнить итерацию алгоритма по сигналам, подсистемам и параметрам, сгруппированным в массивы и структуры. В этом примере показано, как преобразовать неэффективно сложный алгоритм повторения в компактную форму, которой проще управлять.
Открыть пример модели ex_repeat_algorithm. Модель создает около 30 переменных в базовой рабочей области.
Осмотрите Burner_1_Analysis подсистемы. Эта подсистема выполняет алгоритм с использованием базовых переменных рабочей области в качестве параметров в таких блоках, как Constant и Discrete-Time Integrator.
Осмотрите подсистемы Burner_2_Analysis и Burner_3_Analysis. Все три подсистемы выполняют один и тот же алгоритм, но используют различные переменные рабочей области для параметризации блоков.
Осмотрите три подсистемы Analysis_Delay. Эти подсистемы повторяют алгоритм, отличный от алгоритма в подсистемах анализа.
Вернитесь к верхнему уровню модели. Блоки памяти задерживают входные сигналы перед их входом в подсистемы Analysis_Delay.
Просмотрите панель Импорт/экспорт данных (Data Import/Export) диалогового окна Параметры конфигурации (Configuration Parameters). Модель использует переменные SensorsInput и t в качестве входных данных моделирования.
Во время моделирования каждый из девяти столбцов переменной матрицы SensorsInput предоставляет входные данные для блока Inport на верхнем уровне модели.
Шины можно использовать для группирования связанных сигналов в единый структурированный сигнал, уменьшая плотность линий и улучшая удобочитаемость модели.
Для каждой подсистемы в примерной модели требуется три сигнальных входа. Можно объединить каждую группу из трех сигналов в одну шину.
Для использования шин можно изменить все подсистемы в модели примера. Однако, поскольку некоторые подсистемы идентичны, их можно удалить, а затем заменить блоками «Для каждой подсистемы».
Откройте редактор шины.
buseditor
Создание типа шины SensorData с тремя элементами сигнала: sensor1, sensor2, и sensor3.

Удалите блоки, как показано на рисунке, оставив только блоки Burner_1_Sensor1 и Burner_1_Delay1 в качестве входных данных для двух оставшихся подсистем.

На вкладке Signal Attributes Burner_1_Sensor1 Inport
блокируют диалоговое окно, устанавливают Тип данных в Bus: SensorData.
Выходной сигнал блока представляет собой шину, которая содержит три сигнальных элемента. sensor1, sensor2, и sensor3.
Откройте Burner_1_Analysis подсистемы. Удалите выходные сигнальные линии трех блоков Inport. Удалите блоки In2 и In3 Inport.
Добавьте блок выбора шины справа от блока In1 Inport. Подключите выходной блок Inport к блоку Bus Selector.
В диалоговом окне «Bus Selector block» выберите сигналы. sensor1, sensor2, и sensor3.

Блок выбора шины извлекает три сигнальных элемента из входной шины. Другие блоки в модели могут использовать извлеченные сигнальные элементы.
В подсистеме подключите блоки, как показано на рисунке.

В Burner_1_Analysis_Delay подсистемы используйте блок выбора шины для извлечения сигналов в шине. Используйте тот же метод, что и в Burner_1_Analysis подсистемы.
Блок «Для каждой подсистемы» разделяет входной сигнал и последовательно выполняет алгоритм для каждого раздела. Например, если вход в подсистему представляет собой массив из шести сигналов, можно настроить подсистему на выполнение одного и того же алгоритма для каждого из шести сигналов.
Для итеративного повторения алгоритма можно использовать подсистемы Для каждой (For Each). Этот подход улучшает удобочитаемость модели и облегчает изменение повторяющегося алгоритма.
Добавьте в модель два блока «Для каждой подсистемы». Назовите одну из подсистем Burner_Analysis. Назовите другую подсистему Burner_Analysis_Delay.
Скопируйте содержимое Burner_1_Analysis подсистемы в Burner_Analysis подсистемы. Перед вставкой блоков удалите блоки Inport и Outport в подсистеме For Each.
В диалоговом окне «Для каждого блока» подсистемы Burner_Analysis установите флажок для секционирования входных данных. In1.
Скопируйте содержимое Burner_1_Analysis_Delay подсистемы в Burner_Analysis_Delay подсистемы.
В диалоговом окне «Для каждого блока» подсистемы Burner_Analysis_Delay установите флажок для секционирования входных данных. In1.
На верхнем уровне модели удалите подсистемы Burner_1_Analysis и Burner_1_Analysis_Delay. Подключите новые блоки «Для каждой подсистемы» на их месте.
На вкладке Signal Attributes Burner_1_Sensor1 Inport блокируют диалоговое окно, устанавливают размеры Порта в 3.
Блочный выход представляет собой трехэлементный массив шин. Подсистемы For Each в модели повторяют алгоритм для каждой из трех шин в массиве.
Создать Simulink.SimulationData.Dataset объект, который блок Inport может использовать для импорта данных моделирования. Этот код можно использовать для создания объекта и сохранения его в переменной SensorsInput.
% First, create an array of structures whose field values are % timeseries objects for i = 1:3 % Burner number % Sensor 1 eval(['tempInput(1,' num2str(i) ').sensor1 = ' ... 'timeseries(SensorsInput(:,' num2str(3*(i-1)+1) '),t);']) % Sensor 2 eval(['tempInput(1,' num2str(i) ').sensor2 = ' ... 'timeseries(SensorsInput(:,' num2str(3*(i-1)+2) '),t);']) % Sensor 3 eval(['tempInput(1,' num2str(i) ').sensor3 = ' ... 'timeseries(SensorsInput(:,' num2str(3*(i-1)+3) '),t);']) end % Create the Dataset object. SensorsInput = Simulink.SimulationData.Dataset; SensorsInput = addElement(SensorsInput,tempInput,'element1'); clear tempInput t i
Код сначала создает переменную tempInput содержит массив из трех структур. Каждая структура имеет три поля, которые соответствуют сигнальным элементам в типе шины SensorData, и в каждом поле хранится MATLAB
®timeseries объект. Каждый timeseries объект хранит один из девяти столбцов данных из переменной SensorsInput, который хранит входные данные моделирования для каждого из датчиков.
Код затем перезаписывается SensorsInput с новым Simulink.SimulationData.Dataset объект и добавляет tempInput как элемент объекта.
Задайте для параметра конфигурации Input значение SensorsInput.
С тех пор SensorsInput обеспечивает моделирование входных данных в виде timeseries , нет необходимости указывать переменную, содержащую временные данные.
Создайте массив структур, инициализирующий оставшийся блок памяти, и сохраните массив в переменной initForDelay. Укажите поля структуры со значениями существующих переменных инициализации, например initDelay_1_sensor1.
for i = 1:3 % Burner number % Sensor 1 eval(['initForDelay(' num2str(i) ').sensor1 = ' ... 'initDelay_' num2str(i) '_sensor1;']) % Sensor 2 eval(['initForDelay(' num2str(i) ').sensor2 = ' ... 'initDelay_' num2str(i) '_sensor2;']) % Sensor 3 eval(['initForDelay(' num2str(i) ').sensor3 = ' ... 'initDelay_' num2str(i) '_sensor3;']) end
Просмотр содержимого новой переменной initForDelayдважды щелкните имя переменной в базовой рабочей области. Переменная содержит массив из трех структур, каждая из которых имеет три поля: sensor1, sensor2, и sensor3.

В диалоговом окне «Блок памяти» установите для параметра «Начальное условие» значение initForDelay.
Вывод блока памяти представляет собой массив шин, требующих инициализации. Каждый элемент сигнала в массиве шин получает начальное значение из соответствующего поля в массиве структур.
Базовое рабочее пространство содержит множество переменных, которые модель примера использует для параметров блока. Чтобы уменьшить количество переменных рабочей области, упаковывайте их в массивы структур и используйте отдельные поля структуры для задания параметров блоков.
Блок «Для каждой подсистемы» может разделять массив значений, указанных в качестве параметра маски. Каждая итерация подсистемы использует один раздел массива для задания параметров блока. Если параметр указан как массив структур, каждая итерация подсистемы может использовать одну из структур в массиве.
Создайте множество структур, которое параметризует Burner_Analysis
Для Каждой подсистемы, и сохраните множество в переменной paramsNormal. Укажите поля структуры, используя значения существующих переменных параметров, таких как gainNormal_1, offsetNormal_1, и initDelayed_1.
for i = 1:3 eval(['paramsNormal(' num2str(i) ').gain = gainNormal_' num2str(i) ';']) eval(['paramsNormal(' num2str(i) ').offset = offsetNormal_' num2str(i) ';']) eval(['paramsNormal(' num2str(i) ').init = initNormal_' num2str(i) ';']) end
Переменная содержит массив из трех структур, каждая из которых имеет три поля: gain, offset, и init.
В модели щелкните правой кнопкой мыши по Burner_Analysis Для Каждой подсистемы и выберите Маску>, Создают Маску.
На панели «Параметры и диалоговое окно» диалогового окна в разделе «Параметр» нажмите кнопку «Изменить». Для нового параметра маски установите для параметра «Запрос» значение Parameter structure и имя для paramStruct. Нажмите кнопку ОК.
В маске для подсистемы Burner_Analysis установите для свойства Parameter structure значение paramsNormal.
Откройте подсистему. В диалоговом окне «Для каждого блока» на панели «Раздел параметров» установите флажок для секционирования параметра. paramStruct. Задать для размера секции значение 2.
Для блоков в подсистеме задайте эти параметры.
| Блок | Имя параметра | Значение параметра |
|---|---|---|
| Выгода | Выгода | paramStruct.gain |
| Интегратор дискретного времени | Исходное состояние | paramStruct.init |
| Постоянный | Постоянное значение | paramStruct.offset |
Создайте множество структур, которое параметризует Burner_Analysis_Delay
Для Каждой подсистемы, и сохраните множество в переменной paramsForDelay.
for i = 1:3 eval(['paramsForDelay(' num2str(i) ').gain = gainDelayed_' num2str(i) ';']) eval(['paramsForDelay(' num2str(i) ').offset = offsetDelayed_' num2str(i) ';']) eval(['paramsForDelay(' num2str(i) ').init = initDelayed_' num2str(i) ';']) end
На высшем уровне модели щелкните правой кнопкой мыши по Burner_Analysis_Delay Для Каждой подсистемы и выберите Маску>, Создают Маску.
На панели «Параметры и диалоговое окно» диалогового окна в разделе «Параметр» нажмите кнопку «Изменить». Для нового параметра маски установите для параметра «Запрос» значение Parameter structure и имя для paramStruct. Нажмите кнопку ОК.
В маске для блока «Для каждой подсистемы» задайте для параметра «Структура параметров» значение paramsForDelay.
Откройте подсистему. В диалоговом окне «Для каждого блока» на панели «Раздел параметров» установите флажок для секционирования параметра. paramStruct. Задать для размера секции значение 2.
Для блоков в подсистеме задайте эти параметры.
| Блок | Имя параметра | Значение параметра |
|---|---|---|
| Выгода | Выгода | paramStruct.gain |
| Интегратор дискретного времени | Исходное состояние | paramStruct.init |
| Постоянный | Постоянное значение | paramStruct.offset |
Удалите ненужные переменные из базовой рабочей области.
% Clear the old parameter variables that you replaced % with arrays of structures clear -regexp _ % Clear the iteration variables clear i
Для модели требуется несколько переменных в базовой рабочей области.
Для просмотра новой организации сигналов и подсистем обновите схему.

Входной сигнал модели представляет собой массив из трех шин. Модель использует две подсистемы For Each для выполнения двух алгоритмов на каждой из трех шин входного массива.
В базовой рабочей области массивы структур заменяют множество переменных, используемых моделью. Математически измененная модель ведет себя так же, как и при запуске, поскольку массивы структур содержат значения всех старых переменных.
Совет
В подсистеме For Each можно регистрировать сигналы, не связанные с шиной. Однако нельзя использовать регистрацию сигналов для шин или массивов шин из подсистемы «Для каждой». Используйте блок выбора шины для выбора сигналов элементов шины, которые требуется зарегистрировать, или добавьте блок исходящего порта за пределами подсистемы, а затем зарегистрируйте этот сигнал. Дополнительные сведения см. в разделе Регистрация сигналов в разделе Для каждой подсистемы.
В этом примере показано, как упростить моделирование векторизированных алгоритмов. Использование блоков для каждой подсистемы упрощает модель, в которой три входных сигнала фильтруются тремя идентичными блоками Transfer Fcn. В этом примере также показано, как добавить дополнительные элементы управления к фильтрам путем изменения их коэффициентов для каждой итерации подсистемы.
Эта модель использует идентичные блоки Transfer Fcn для независимой обработки каждого элемента входного синусоидального сигнала. Блок векторной конкатенации объединяет результирующие выходные сигналы. Этот повторяющийся процесс является графически сложным и трудным в обслуживании. Добавление еще одного элемента в сигнал также требует существенной переработки модели.

Эту модель можно упростить, заменив повторяющиеся операции одним блоком «Для каждой подсистемы».

Блок подсистемы For Each содержит блок For Each и модель, представляющую алгоритм трех блоков, которые он заменяет посредством блока Transfer Fcn. Блок «Для каждого» определяет, как разделить вектор входного сигнала на отдельные элементы и как объединить обработанные сигналы для формирования вектора выходного сигнала. Каждый блок, который имеет состояние, поддерживает отдельный набор состояний для каждого входного элемента, обрабатываемого на данном этапе выполнения.

В этом примере входной сигнал выбирается для разделения. Параметры «Размер секции» и «Ширина секции» блока «Для каждого» имеют значение 1 для ввода.

Этот подход можно масштабировать для добавления дополнительных сигналов без необходимости значительного изменения модели. Этот подход легко масштабируем и графически проще.
Изменение параметра модели без изменения структуры модели. В этом примере показано, как моделировать изменение параметров в алгоритме. Он использует модель секционирования для каждой подсистемы из приведенного выше примера и создает различные фильтры для каждого входного сигнала, сохраняя простоту модели. Массив коэффициентов фильтра подается в блок подсистемы For Each в качестве параметра маски, отмеченного для секционирования. В каждой итерации блока подсистемы «Для каждого» разбиение массива коэффициентов фильтра подается в блок Transfer Fcn.
Откройте ex_ForEachSubsystem_Partitioning модели. Создайте маску для блока «Для каждой подсистемы» и добавьте редактируемый параметр маски. Задайте для имени значение FilterCoeffs и подсказку для Filter Coefficient Matrix. Дополнительные сведения о добавлении параметра маски см. в разделе Создание простой маски.

Откройте блок «Для каждой подсистемы». В подсистеме откройте диалоговое окно «Для каждого блока».
На вкладке «Раздел параметров» установите флажок рядом с параметром FilterCoeffs, чтобы включить секционирование этого параметра. Параметры Ширина раздела (Partition Width) и Размер раздела (Partition Dimension) должны иметь значение по умолчанию 1.

Дважды щелкните по блоку «Для каждой подсистемы» и введите матрицу коэффициентов фильтра, имеющую одну строку коэффициентов фильтра для каждого входного сигнала. Например, введите [0.0284 0.2370 0.4692 0.2370 0.0284; -0.0651 0 0.8698 0 -0.0651; 0.0284 -0.2370 0.4692 -0.2370 0.0284] для реализации различных фильтров четвертого порядка для каждого входного сигнала.
В блоке «Для каждой подсистемы» дважды щелкните по блоку «Transfer Fcn» и введите FilterCoeffs для параметра Коэффициенты знаменателя. Этот параметр заставляет блок получать свои коэффициенты из параметра маски.
Блок «Для каждой подсистемы» разделяет входной параметр на горизонтальные секции шириной 1, что эквивалентно одной строке коэффициентов. Параметр коэффициентов преобразуется из одного массива

на три строки параметров:

Улучшенное повторное использование кода с использованием для каждой подсистемы. В этом примере показано, как можно улучшить повторное использование кода при наличии двух или более идентичных блоков для каждой подсистемы. Рассмотрим следующую модель, rtwdemo_foreachreuse.

Цель состоит в том, чтобы три подсистемы - Vector SS1, Vector SS2 и Vector SS3 - применили одинаковую обработку к каждому скалярному элементу векторного сигнала на своих соответствующих входах. Поскольку эти три подсистемы выполняют одну и ту же обработку, для них желательно создать одну общую функцию вывода (и обновления) для всех трех подсистем в коде, сгенерированном для этой модели. Например, подсистема Vector SS3 содержит эти блоки.

Чтобы создать одну общую функцию для трех подсистем, конфигурация разделения, которое они выполняют для своих входных сигналов, должна быть одинаковой. Для Vector SS1 и Vector SS3 эта конфигурация проста, поскольку можно задать размер и ширину секционирования равным 1. Однако для того, чтобы вектор SS2 также разделил свой входной сигнал вдоль размера 1, необходимо вставить блок Математическая функция (Math Function), чтобы перенести вектор строки 1 на 8 в вектор столбца 8 на 1. Затем можно преобразовать выходные данные подсистемы обратно в вектор строк 1 на 8, используя второй блок математической функции, установленный в transpose оператор.
Если для создания кода нажать клавиши Ctrl + B, то результирующий код использует одну функцию вывода. Эта функция используется всеми тремя экземплярами для каждой подсистемы.
/*
* Output and update for iterator system:
* '<Root>/Vector SS1'
* '<Root>/Vector SS2'
* '<Root>/Vector SS3'
*/
void VectorProcessing(int32_T NumIters, const real_T rtu_In1[],
real_T rty_Out1[],
rtDW_VectorProcessing *localDW)Функция имеет входной параметр NumIters указывает количество независимых скаляров, которые каждый для каждой подсистемы должен обрабатывать. Эта функция вызывается трижды с параметром NumIters установите значения 10, 8 и 7 соответственно.
Остальные две подсистемы в этой модели показывают, как повторно используемый код может быть также сгенерирован для матричных сигналов, которые обрабатываются с использованием блока «Для каждой подсистемы». Опять же, нажатие клавиш Ctrl + B для создания кода обеспечивает повторное использование кода одной функции.