主要内容

使用For-Each子系统重复一个算法

要重复一个算法,可以在分组到数组和结构中的信号、子系统和参数上迭代该算法。本页给出了如何将低效的复杂重复算法转换为更容易管理的紧凑形式的示例。

如果您通过复制和粘贴块和子系统来重复图中的算法,那么维护模型就会变得困难。单独的信号线和子系统会使图表变得拥挤不堪,降低了可读性,使简单的更改变得困难。变量也会挤占工作空间,降低模型的可移植性。随着时间的推移,当您添加到设计中时,模型可能会产生这些效率问题。

探索范例模型

该模型ex_repeat_algorithm处理和分析来自三个燃烧器的传感器数据,每个燃烧器包含三个传感器,在不同的、相同的子系统中对每个燃烧器使用相同的算法。使用for-each子系统可以简化模型。

  1. 打开示例模型ex_repeat_algorithm.该模型在基本工作区中创建了大约30个变量。

  2. 检查命名为Burner_1_Analysis.该子系统通过使用基本工作区变量作为块中的参数来执行算法,例如常数而且离散时间积分器块。

  3. 检查命名为Burner_2_Analysis而且Burner_3_Analysis.所有三个子系统执行相同的算法,但使用不同的工作空间变量来参数化块。

  4. 检查三个Analysis_Delay子系统。这些子系统重复不同的算法分析子系统。

  5. 返回到模型的顶层。的内存块在输入信号进入Analysis_Delay子系统。

  6. 看看数据导入/导出窗格中的“配置参数”对话框。该模型使用变量SensorsInput而且t作为模拟输入。

    在模拟过程中,每个矩阵中的九列变量SensorsInput类的输入数据轮廓尺寸块在模型的顶层。

减少总线的信号线密度

您可以使用总线将相关信号分组为单个结构化信号,降低线路密度并提高模型的可读性。

示例模型中的每个子系统都需要三个信号输入。你可以把每组三个信号组合成一个总线。

您可以修改示例模型中的所有子系统以使用总线。但是,由于有些子系统是相同的,您可以删除它们,然后将它们替换为每个子系统块。

  1. 打开类型编辑器。

    typeeditor

  2. 创建一个金宝app仿真软件。公共汽车命名为SensorData有三个要素:sensor1sensor2,sensor3

    类型编辑器中名为SensorData的总线对象

  3. 如图所示,删除block。只保留命名的块Burner_1_Sensor1而且Burner_1_Delay1作为其余两个子系统的输入。

    简化模型包含六个块:Burner_1_Sensor1、Burner_1_Analysis、Out1、Burner_1_Delay1、Burner_1_Analysis_Delay和Out4。

  4. 信号的属性的标签。Burner_1_Sensor1轮廓尺寸块对话框,设置数据类型总线:SensorData

    该块的输出是一个包含三个信号元素的总线sensor1sensor2,sensor3

  5. 打开命名为Burner_1_Analysis.删除三者的信号输出线轮廓尺寸块。删除轮廓尺寸块命名In2而且In3

  6. 添加一个总线选择器块的右边轮廓尺寸块命名三机一体.连接轮廓尺寸块输出到总线选择器块。

  7. 总线选择器方块对话框中,选择信号sensor1sensor2,sensor3

    “块参数”对话框

    总线选择器Block从输入总线中提取三个信号元素。模型中的其他块可以使用提取的信号元素。

  8. 在子系统中,如图所示连接块。

    sensor1连接到Product块,sensor2连接到Sum块,sensor3连接到Discrete-Time Integrator块。

  9. 在命名为Burner_1_Analysis_Delay,使用总线选择器块来提取总线中的信号。使用与在named子系统中使用的相同的技术Burner_1_Analysis

重复算法

一个每个子系统Block对输入信号进行分区,并在每个分区上依次执行算法。例如,如果子系统的输入是一个由六个信号组成的数组,您可以配置子系统对这六个信号中的每一个执行相同的算法。

您可以使用for-each子系统以迭代的方式重复算法。该方法提高了模型的可读性,便于重复算法的修改。

  1. 添加两个每个子系统块到模型。说出其中一个子系统Burner_Analysis.命名另一个子系统Burner_Analysis_Delay

  2. 复制命名的子系统的内容Burner_1_Analysis进入命名为Burner_Analysis.在粘贴块之前,删除轮廓尺寸而且外港for-each子系统中的块。

  3. 为每一个块对话框中的Burner_Analysis子系统,选中复选框对输入进行分区三机一体

  4. 复制命名的子系统的内容Burner_1_Analysis_Delay进入命名为Burner_Analysis_Delay

  5. 为每一个块对话框中的Burner_Analysis_Delay子系统,选中复选框对输入进行分区三机一体

  6. 在模型的顶层,删除已命名的子系统Burner_1_Analysis而且Burner_1_Analysis_Delay.连接新每个子系统在他们的地方。

  7. 信号的属性的标签。Burner_1_Sensor1轮廓尺寸块对话框,设置港维3.

    块输出是一个三元素的总线数组。模型中的for-each子系统为数组中的三个总线中的每一个重复一种算法。

  8. 创建一个金宝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作为对象的一个元素。

  9. 设置输入配置参数为SensorsInput

    SensorsInput的形式提供模拟输入数据timeseries对象时,不需要指定包含时间数据的变量。

  10. 创建一个初始化其余结构的数组内存块,并将数组存储在变量中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,在基本工作区中双击变量名。变量包含三个结构的数组,每个结构有三个字段:sensor1sensor2,sensor3

    带有三个字段的initForDelay 1x3结构

  11. 内存块对话框,设置初始条件initForDelay

    内存块输出是一个需要初始化的总线数组。总线数组中的每个信号元素从结构数组中的对应字段中获取一个初始值。

将参数组织到结构数组中

基本工作空间包含示例模型用于块参数的许多变量。要减少工作空间变量的数量,请将它们打包到结构数组中,并使用各个结构字段指定块参数。

一个每个子系统块可以对指定为掩码参数的值数组进行分区。子系统的每次迭代都使用数组的单个分区来指定块参数。如果您将参数指定为一个结构数组,子系统的每次迭代都可以使用数组中的一个结构。

  1. 属性参数化的结构数组每个子系统块命名Burner_Analysis,并将数组存储在变量中paramsNormal.使用现有参数变量的值指定结构字段,例如gainNormal_1offsetNormal_1,initDelayed_1

    I = 1:3 eval([“paramsNormal(”num2str(我)”)。gain = gainNormal_'num2str(我)“;”eval ()) (“paramsNormal(”num2str(我)”)。offset = offsetNormal_'num2str(我)“;”eval ()) (“paramsNormal(”num2str(我)”)。我nit = initNormal_'num2str(我)“;”])结束

    变量包含三个结构的数组,每个结构有三个字段:获得抵消,初始化

  2. 在模型中,右键单击Burner_Analysis为每个子系统,并选择面具>创建面具

  3. 参数&对话框窗格下的对话框参数,点击编辑.对于新的掩码参数,请设置提示参数结构而且的名字paramStruct.点击好吧

  4. 在蒙版中为Burner_Analysis子系统,参数结构paramsNormal

  5. 打开子系统。在为每一个块对话框,在参数分区窗格中,选中复选框以对参数进行分区paramStruct.集分区维度2

  6. 对于子系统中的块,需要设置这些参数。

    参数名称 参数值
    获得 获得 paramStruct.gain
    离散时间积分器 初始条件 paramStruct.init
    常数 恒定值 paramStruct.offset

  7. 属性参数化的结构数组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(我)“;”])结束

  8. 在模型的顶层,右键单击Burner_Analysis_Delay为每个子系统,并选择面具>创建面具

  9. 参数&对话框窗格下的对话框参数,点击编辑.对于新的掩码参数,请设置提示参数结构而且的名字paramStruct.点击好吧

  10. 在蒙版中为每个子系统块,设置参数结构paramsForDelay

  11. 打开子系统。在为每一个块对话框,在参数分区窗格中,选中复选框以对参数进行分区paramStruct.集分区维度2

  12. 对于子系统中的块,需要设置这些参数。

    参数名称 参数值
    获得 获得 paramStruct.gain
    离散时间积分器 初始条件 paramStruct.init
    常数 恒定值 paramStruct.offset

  13. 清除基本工作区中不必要的变量。

    清除替换的旧参数变量。%使用结构数组清晰的正则表达式_清除迭代变量清晰的

    该模型在基本工作空间中只需要很少的变量。

检查转换模型

要查看新的信号和子系统组织,请更新图表。

更新了ex_repeat_algorithm模型

模型输入是一个由三个总线组成的数组。该模型使用两个for-each子系统在输入数组中的三个总线中的每一个上执行两个算法。

在基本工作空间中,结构数组取代了模型使用的许多变量。从数学上讲,修改后的模型的行为与开始时相同,因为结构数组包含了所有旧变量的值。

提示

您可以在for-each子系统中记录非总线信号。但是,您不能从for-each子系统中为总线或总线阵列使用信号记录。或者使用总线选择器块来选择要记录或添加的总线元素信号外港在子系统外阻塞,然后记录那个信号。详细信息请参见每个子系统的日志信号

使用For-Each子系统的其他示例

使用For-Each子系统的向量化算法

这个例子展示了如何简化向量化算法的建模。使用每个子系统Blocks简化了一个模型,其中三个输入信号被三个相同的信号过滤转移Fcn块。这个示例还展示了如何通过为子系统的每次迭代更改它们的系数来为过滤器添加更多的控制。

这个模型使用相同的转移Fcn块来独立处理每个信号。一个向量连接块连接产生的输出信号。这个重复的过程在图形上很复杂,很难维护。添加另一个信号也需要对模型进行重大的重做。

对三个信号进行独立但相同的处理。

您可以通过将重复操作替换为单个操作来简化此模型每个子系统块。

对三个信号进行迭代处理的模型。

每个子系统块包含为每一个块和一个表示算法的模型的三个块,它取代的方式转移Fcn块。的为每一个Block指定如何将输入信号向量划分为单独的元素,以及如何将处理过的信号连接起来形成输出信号向量。每个具有状态的块都为在给定执行步骤中处理的每个输入元素维护一组单独的状态。

每个子系统的内容

在本例中,选择输入信号进行分区。的分区维度而且分区宽度For Each块上的参数都设置为1对于输入。

“每个块”对话框的“块参数”页签

您可以扩展这种方法来添加更多的信号,而不必对模型进行重大更改。这种方法易于扩展,在图形上也更简单。

不改变模型结构的模型参数变化。这个例子展示了如何在一个算法中建模参数变化。它使用前面示例中的for-each子系统分区模型,并为每个输入信号创建不同的过滤器,同时保持模型的简单性。一个滤波器系数数组被馈送到每个子系统块作为用于分区的掩码参数。在每次迭代中每个子系统块,一个划分的滤波器系数数组被馈送到转移Fcn块。

  1. 打开模型ex_ForEachSubsystem_Partitioning

  2. 对象创建掩码每个子系统块并添加一个可编辑的掩码参数。将名称设置为FilterCoeffs提示符是滤波系数矩阵.有关如何添加掩码参数的信息,请参见创建一个简单的蒙版

    掩码编辑器对话框

  3. 打开每个子系统块。在子系统内部,打开为每一个对话框。

  4. 参数分区选项卡上,选中FilterCoeffs参数以启用此参数的分区。保持分区宽度而且分区维度参数,默认值为1。

    “对于每个块”对话框的“块参数”页签

  5. 双击每个子系统块并输入您的滤波系数矩阵,每个输入信号都有一行滤波系数。例如,输入[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]为每个输入信号实现不同的四阶滤波器。

  6. 每个子系统块,双击转移Fcn方块并进入FilterCoeffs分母系数参数。此设置使块从mask参数获取其系数。

每个子系统Block将输入参数切片为宽度为1的水平分区,这相当于一行系数。系数的参数从一个数组开始。

系数参数为单列

它将单个数组转换为三行参数。

参数的系数作为三行参数

使用For-Each子系统改进了代码重用

这个例子展示了当您有两个或多个相同的模型时,如何设计模型来提高代码重用每个子系统块。考虑到ForEachReuse模型。

ForEachReuse模型

目的是为三个子系统向量魔法石,第1章SS2向量,向量SS3-将相同的处理应用于矢量信号在各自输入处的每个标量元素。因为这三个子系统执行相同的处理,所以它们在为该模型生成的代码中为所有三个子系统生成一个共享的Output(和Update)函数是可取的。例如,向量SS3子系统包含这些块。

向量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子系统处于以快速加速器模式进行模拟的模型中。

  • for-each子系统本身位于一个模型中模型块在加速模式。

对于第一种情况,使用加速模式。

对于第二种情况,使用正常或快速加速模式。

您不能在for-each子系统中记录块的状态。

保存并恢复模拟状态。

不能使用普通模式模拟模型块在for-each子系统内。

使用加速或快速加速模式。

如果它们的输入和输出信号是向量(1-D或2-D行或列向量),则为具有相同内容的两个for-each子系统生成可重用代码。对于n-D输入和输出信号,只有当信号被划分的维度是最高维度时,才会生成可重用代码。

排列信号维数,将划分维数和连接维数转换为n-D信号的最高非单维数。

每个子系统Block不支持以下特性:金宝app

  • 你不能在for-each子系统中包含这些块或s函数:

    • 数据存储内存数据存储读取,或数据存储写

    • 从工作空间方法时,则阻塞时间结构格式,并有一个空的时间字段

    • 到文件

    • 转到而且跨越子系统边界的块

    • 参考模型,仿真模式设置为正常

    • 影子港口

    • ERT S-functions

    要获得支持每个子系统的块的完整列表,请输入金宝appshowblockdatatypetable在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子系统的模型在正常模式下的模拟时间可能比使用单独子系统实现模型所需的时间要长。

另请参阅

对象

相关的话题