使用For-Each子系统重复一个算法
要重复一个算法,可以在分组到数组和结构中的信号、子系统和参数上迭代该算法。本页给出了如何将低效的复杂重复算法转换为更容易管理的紧凑形式的示例。
如果您通过复制和粘贴块和子系统来重复图中的算法,那么维护模型就会变得困难。单独的信号线和子系统会使图表变得拥挤不堪,降低了可读性,使简单的更改变得困难。变量也会挤占工作空间,降低模型的可移植性。随着时间的推移,当您添加到设计中时,模型可能会产生这些效率问题。
探索范例模型
该模型ex_repeat_algorithm
处理和分析来自三个燃烧器的传感器数据,每个燃烧器包含三个传感器,在不同的、相同的子系统中对每个燃烧器使用相同的算法。使用for-each子系统可以简化模型。
打开示例模型
ex_repeat_algorithm
.该模型在基本工作区中创建了大约30个变量。检查命名为
Burner_1_Analysis
.该子系统通过使用基本工作区变量作为块中的参数来执行算法,例如常数而且离散时间积分器块。检查命名为
Burner_2_Analysis
而且Burner_3_Analysis
.所有三个子系统执行相同的算法,但使用不同的工作空间变量来参数化块。检查三个
Analysis_Delay
子系统。这些子系统重复不同的算法分析
子系统。返回到模型的顶层。的内存块在输入信号进入
Analysis_Delay
子系统。看看数据导入/导出窗格中的“配置参数”对话框。该模型使用变量
SensorsInput
而且t
作为模拟输入。在模拟过程中,每个矩阵中的九列变量
SensorsInput
类的输入数据轮廓尺寸块在模型的顶层。
减少总线的信号线密度
您可以使用总线将相关信号分组为单个结构化信号,降低线路密度并提高模型的可读性。
示例模型中的每个子系统都需要三个信号输入。你可以把每组三个信号组合成一个总线。
您可以修改示例模型中的所有子系统以使用总线。但是,由于有些子系统是相同的,您可以删除它们,然后将它们替换为每个子系统块。
打开类型编辑器。
typeeditor
创建一个
金宝app仿真软件。公共汽车
命名为SensorData
有三个要素:sensor1
,sensor2
,sensor3
.如图所示,删除block。只保留命名的块
Burner_1_Sensor1
而且Burner_1_Delay1
作为其余两个子系统的输入。在信号的属性的标签。
Burner_1_Sensor1
轮廓尺寸块对话框,设置数据类型来总线:SensorData
.该块的输出是一个包含三个信号元素的总线
sensor1
,sensor2
,sensor3
.打开命名为
Burner_1_Analysis
.删除三者的信号输出线轮廓尺寸块。删除轮廓尺寸块命名In2
而且In3
.添加一个总线选择器块的右边轮廓尺寸块命名
三机一体
.连接轮廓尺寸块输出到总线选择器块。在总线选择器方块对话框中,选择信号
sensor1
,sensor2
,sensor3
.的总线选择器Block从输入总线中提取三个信号元素。模型中的其他块可以使用提取的信号元素。
在子系统中,如图所示连接块。
在命名为
Burner_1_Analysis_Delay
,使用总线选择器块来提取总线中的信号。使用与在named子系统中使用的相同的技术Burner_1_Analysis
.
重复算法
一个每个子系统Block对输入信号进行分区,并在每个分区上依次执行算法。例如,如果子系统的输入是一个由六个信号组成的数组,您可以配置子系统对这六个信号中的每一个执行相同的算法。
您可以使用for-each子系统以迭代的方式重复算法。该方法提高了模型的可读性,便于重复算法的修改。
添加两个每个子系统块到模型。说出其中一个子系统
Burner_Analysis
.命名另一个子系统Burner_Analysis_Delay
.复制命名的子系统的内容
Burner_1_Analysis
进入命名为Burner_Analysis
.在粘贴块之前,删除轮廓尺寸而且外港for-each子系统中的块。在为每一个块对话框中的
Burner_Analysis
子系统,选中复选框对输入进行分区三机一体
.复制命名的子系统的内容
Burner_1_Analysis_Delay
进入命名为Burner_Analysis_Delay
.在为每一个块对话框中的
Burner_Analysis_Delay
子系统,选中复选框对输入进行分区三机一体
.在模型的顶层,删除已命名的子系统
Burner_1_Analysis
而且Burner_1_Analysis_Delay
.连接新每个子系统在他们的地方。在信号的属性的标签。
Burner_1_Sensor1
轮廓尺寸块对话框,设置港维来3.
.块输出是一个三元素的总线数组。模型中的for-each子系统为数组中的三个总线中的每一个重复一种算法。
创建一个
金宝appSimulink.SimulationData.Dataset
对象的轮廓尺寸块可以用来导入仿真数据。您可以使用此代码创建对象并将其存储在变量中SensorsInput
.首先,创建一个结构数组,其字段值为%时间序列对象。为I = 1:3%燃烧器数%传感器1eval ([“tempInput(1)”num2str(我)”)。Sensor1 = '...timeseries (SensorsInput (:,num2str(3 *(张)+ 1)”),t),“])%传感器2eval ([“tempInput(1)”num2str(我)”)。Sensor2 = '...timeseries (SensorsInput (:,num2str(3 *(张)+ 2)”),t),“])%传感器3eval ([“tempInput(1)”num2str(我)”)。Sensor3 = '...timeseries (SensorsInput (:,num2str(3 *(张)+ 3)”),t),“])结束创建数据集对象。SensorsInput = 金宝appSimulink.SimulationData.Dataset;SensorsInput = addElement(SensorsInput,tempInput,element1的);清晰的tempInputt我
代码首先创建一个变量
tempInput
包含三个结构的数组。每个结构都有三个字段,分别对应于总线类型中的信号元素SensorData
,每个字段存储一个MATLAB®timeseries
对象。每一个timeseries
对象存储来自变量的九列数据中的一列SensorsInput
,用于存储每个传感器的模拟输入数据。然后重写代码
SensorsInput
用一个新的金宝appSimulink.SimulationData.Dataset
对象并添加tempInput
作为对象的一个元素。设置输入配置参数为
SensorsInput
.自
SensorsInput
的形式提供模拟输入数据timeseries
对象时,不需要指定包含时间数据的变量。创建一个初始化其余结构的数组内存块,并将数组存储在变量中
initForDelay
.使用现有初始化变量的值指定结构字段,例如initDelay_1_sensor1
.为I = 1:3%燃烧器数%传感器1eval ([“initForDelay(”num2str(我)”)。Sensor1 = '...“initDelay_”num2str(我)“_sensor1;”])%传感器2eval ([“initForDelay(”num2str(我)”)。Sensor2 = '...“initDelay_”num2str(我)“_sensor2;”])%传感器3eval ([“initForDelay(”num2str(我)”)。Sensor3 = '...“initDelay_”num2str(我)“_sensor3;”])结束
查看新变量的内容
initForDelay
,在基本工作区中双击变量名。变量包含三个结构的数组,每个结构有三个字段:sensor1
,sensor2
,sensor3
.在内存块对话框,设置初始条件来
initForDelay
.的内存块输出是一个需要初始化的总线数组。总线数组中的每个信号元素从结构数组中的对应字段中获取一个初始值。
将参数组织到结构数组中
基本工作空间包含示例模型用于块参数的许多变量。要减少工作空间变量的数量,请将它们打包到结构数组中,并使用各个结构字段指定块参数。
一个每个子系统块可以对指定为掩码参数的值数组进行分区。子系统的每次迭代都使用数组的单个分区来指定块参数。如果您将参数指定为一个结构数组,子系统的每次迭代都可以使用数组中的一个结构。
属性参数化的结构数组每个子系统块命名
Burner_Analysis
,并将数组存储在变量中paramsNormal
.使用现有参数变量的值指定结构字段,例如gainNormal_1
,offsetNormal_1
,initDelayed_1
.为I = 1:3 eval([“paramsNormal(”num2str(我)”)。gain = gainNormal_'num2str(我)“;”eval ()) (“paramsNormal(”num2str(我)”)。offset = offsetNormal_'num2str(我)“;”eval ()) (“paramsNormal(”num2str(我)”)。我nit = initNormal_'num2str(我)“;”])结束
变量包含三个结构的数组,每个结构有三个字段:
获得
,抵消
,初始化
.在模型中,右键单击
Burner_Analysis
为每个子系统,并选择面具>创建面具.在参数&对话框窗格下的对话框参数,点击编辑.对于新的掩码参数,请设置提示来
参数结构
而且的名字来paramStruct
.点击好吧.在蒙版中为
Burner_Analysis
子系统,参数结构来paramsNormal
.打开子系统。在为每一个块对话框,在参数分区窗格中,选中复选框以对参数进行分区
paramStruct
.集分区维度来2
.对于子系统中的块,需要设置这些参数。
块 参数名称 参数值 获得 获得 paramStruct.gain
离散时间积分器 初始条件 paramStruct.init
常数 恒定值 paramStruct.offset
属性参数化的结构数组
Burner_Analysis_Delay
,并将数组存储在变量中paramsForDelay
.为I = 1:3 eval([“paramsForDelay(”num2str(我)”)。gain = gainDelayed_'num2str(我)“;”eval ()) (“paramsForDelay(”num2str(我)”)。offset = offsetDelayed_'num2str(我)“;”eval ()) (“paramsForDelay(”num2str(我)”)。我nit = initDelayed_'num2str(我)“;”])结束
在模型的顶层,右键单击
Burner_Analysis_Delay
为每个子系统,并选择面具>创建面具.在参数&对话框窗格下的对话框参数,点击编辑.对于新的掩码参数,请设置提示来
参数结构
而且的名字来paramStruct
.点击好吧.在蒙版中为每个子系统块,设置参数结构来
paramsForDelay
.打开子系统。在为每一个块对话框,在参数分区窗格中,选中复选框以对参数进行分区
paramStruct
.集分区维度来2
.对于子系统中的块,需要设置这些参数。
块 参数名称 参数值 获得 获得 paramStruct.gain
离散时间积分器 初始条件 paramStruct.init
常数 恒定值 paramStruct.offset
清除基本工作区中不必要的变量。
清除替换的旧参数变量。%使用结构数组清晰的正则表达式_清除迭代变量清晰的我
该模型在基本工作空间中只需要很少的变量。
检查转换模型
要查看新的信号和子系统组织,请更新图表。
模型输入是一个由三个总线组成的数组。该模型使用两个for-each子系统在输入数组中的三个总线中的每一个上执行两个算法。
在基本工作空间中,结构数组取代了模型使用的许多变量。从数学上讲,修改后的模型的行为与开始时相同,因为结构数组包含了所有旧变量的值。
提示
您可以在for-each子系统中记录非总线信号。但是,您不能从for-each子系统中为总线或总线阵列使用信号记录。或者使用总线选择器块来选择要记录或添加的总线元素信号外港在子系统外阻塞,然后记录那个信号。详细信息请参见每个子系统的日志信号.
使用For-Each子系统的其他示例
使用For-Each子系统的向量化算法
这个例子展示了如何简化向量化算法的建模。使用每个子系统Blocks简化了一个模型,其中三个输入信号被三个相同的信号过滤转移Fcn块。这个示例还展示了如何通过为子系统的每次迭代更改它们的系数来为过滤器添加更多的控制。
这个模型使用相同的转移Fcn块来独立处理每个信号。一个向量连接块连接产生的输出信号。这个重复的过程在图形上很复杂,很难维护。添加另一个信号也需要对模型进行重大的重做。
您可以通过将重复操作替换为单个操作来简化此模型每个子系统块。
的每个子系统块包含为每一个块和一个表示算法的模型的三个块,它取代的方式转移Fcn块。的为每一个Block指定如何将输入信号向量划分为单独的元素,以及如何将处理过的信号连接起来形成输出信号向量。每个具有状态的块都为在给定执行步骤中处理的每个输入元素维护一组单独的状态。
在本例中,选择输入信号进行分区。的分区维度而且分区宽度For Each块上的参数都设置为1
对于输入。
您可以扩展这种方法来添加更多的信号,而不必对模型进行重大更改。这种方法易于扩展,在图形上也更简单。
不改变模型结构的模型参数变化。这个例子展示了如何在一个算法中建模参数变化。它使用前面示例中的for-each子系统分区模型,并为每个输入信号创建不同的过滤器,同时保持模型的简单性。一个滤波器系数数组被馈送到每个子系统块作为用于分区的掩码参数。在每次迭代中每个子系统块,一个划分的滤波器系数数组被馈送到转移Fcn块。
对象创建掩码每个子系统块并添加一个可编辑的掩码参数。将名称设置为
FilterCoeffs
提示符是滤波系数矩阵
.有关如何添加掩码参数的信息,请参见创建一个简单的蒙版.打开每个子系统块。在子系统内部,打开为每一个对话框。
在参数分区选项卡上,选中FilterCoeffs参数以启用此参数的分区。保持分区宽度而且分区维度参数,默认值为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]
为每个输入信号实现不同的四阶滤波器。在每个子系统块,双击转移Fcn方块并进入
FilterCoeffs
为分母系数参数。此设置使块从mask参数获取其系数。
的每个子系统Block将输入参数切片为宽度为1的水平分区,这相当于一行系数。系数的参数从一个数组开始。
它将单个数组转换为三行参数。
使用For-Each子系统改进了代码重用
这个例子展示了当您有两个或多个相同的模型时,如何设计模型来提高代码重用每个子系统块。考虑到ForEachReuse
模型。
目的是为三个子系统向量魔法石,第1章
,SS2向量
,向量SS3
-将相同的处理应用于矢量信号在各自输入处的每个标量元素。因为这三个子系统执行相同的处理,所以它们在为该模型生成的代码中为所有三个子系统生成一个共享的Output(和Update)函数是可取的。例如,向量SS3
子系统包含这些块。
要为三个子系统生成单一的共享函数,它们在输入信号上执行的分区配置必须相同。为向量魔法石,第1章
而且向量SS3
,此配置很简单,因为您可以将分区尺寸和宽度设置为1。然而,为了SS2向量
为了也沿着维1划分它的输入信号,插入a数学函数块,将1 × 8的行向量转置为8 × 1的列向量。使用秒将子系统的输出转换回1 × 8的行向量数学函数块设置为转置
操作符。还可以为其余两个处理矩阵信号的子系统生成可重用的共享函数。有关为模型生成C代码的更多信息,请参见为每个子系统生成可重用的代码(金宝app仿真软件编码器).
For-Each子系统的限制
的每个子系统Block有这些限制和变通方法。
限制 | 解决方案 |
---|---|
您不能在for-each子系统中直接记录总线或总线数组。 |
使用以下方法中的一种:
|
如果存在以下任何一种情况,则不能在for-each子系统中的引用模型中记录信号:
|
对于第一种情况,使用加速模式。 对于第二种情况,使用正常或快速加速模式。 |
您不能在for-each子系统中记录块的状态。 |
保存并恢复模拟状态。 |
不能使用普通模式模拟模型块在for-each子系统内。 |
使用加速或快速加速模式。 |
如果它们的输入和输出信号是向量(1-D或2-D行或列向量),则为具有相同内容的两个for-each子系统生成可重用代码。对于n-D输入和输出信号,只有当信号被划分的维度是最高维度时,才会生成可重用代码。 |
排列信号维数,将划分维数和连接维数转换为n-D信号的最高非单维数。 |
的每个子系统Block不支持以下特性:金宝app
你不能在for-each子系统中包含这些块或s函数:
数据存储内存,数据存储读取,或数据存储写块
的从工作空间方法时,则阻塞
时间结构
格式,并有一个空的时间字段到文件块
转到而且从跨越子系统边界的块
参考模型,仿真模式设置为正常
影子港口
ERT S-functions
要获得支持每个子系统的块的完整列表,请输入金宝app
showblockdatatypetable
在MATLAB命令窗口中。
你不能使用这些类型的信号:
在系统内部使用外部存储类的信号
子系统输入和输出边界上的帧信号
超过一维的可变大小信号
在子系统内部创建线性化点
为子系统内的块传播雅可比矩阵标志。你可以用MATLAB来检验这个条件
J.Mi.BlockAnalyticFlags.jacobian
,在那里J
是雅可比矩阵。来验证雅可比矩阵的正确性每个子系统布洛克:看看for-each子系统雅可比矩阵的标记。如果是的话
“not_金宝appsupported”
,则雅可比矩阵不正确。将每个块移出for-each子系统并计算其雅可比矩阵。如果任何块是
“not_金宝appsupported”
或有警告标记,则for-each子系统的雅可比矩阵是不正确的。
你不能执行这些类型的代码生成:
一代金宝app®编码器™功能目标
金宝app仿真软件编码器以下两种情况下的代码生成:
一个Stateflow®或MATLAB函数块驻留在子系统中。
此块尝试访问子系统外部的全局数据,例如数据存储内存块或
金宝app仿真软件。信号
的对象ExportedGlobal
存储类。
PLC代码生成
在某些情况下,使用for-each子系统的模型在正常模式下的模拟时间可能比使用单独子系统实现模型所需的时间要长。