AnyMath 文档

Engee Function

在模型中使用Julia代码。

模块类型: EngeeFunction

库中的路径:

/Basic/User-Defined Functions/Engee Function

资料描述

Engee Function 允许在模型中使用Julia代码 AnyMath .

在页面上阅读更多关于Julia编程语言的信息 编程.
在街区里 Engee Function 支持大多数Julia语言功能。 但是,不提供在块中使用*Pkg*包管理器。

使用

将Julia代码集成到模型中 AnyMath 必要:

  1. 向模型添加块 Engee Function 从该组 Basic/User-Defined Functions 块库 blocks library icon;

  2. 设置窗口 debug article icon 1 在标签上 Main 街区 Engee Function 按下按钮 编辑源代码 打开源代码编辑器(EngeeFunctionCode):

    engee function code editor

源代码单元格

_EngeeFunctionCode_源代码编辑器由带有Julia代码的功能单元组成。 默认情况下,有三个单元格可用:辅助(不可编辑), Component struct codeStep method code (单元格可以隐藏):

engee function all start cell

要连接其他源代码文件,您可以使用该函数 包括() 在牢房里 Common code (有关单元格的描述,请参阅 下文):

include("/user/engeefunction/source.jl")
整个块代码 Engee Function 您可以在单元格中写入 Common code 通过获得对组件结构,签名和功能数量的完全控制。

要添加/删除其他功能单元格,请单击 «方法管理» engee function all methods 并选中/取消选中相应的单元格。:

engee function choose methodsengee function choose methods 1

每个单元负责块的独特功能 Engee Function . 下面给出每个小区的详细描述。

信息单元格(不可编辑)

Details

自动显示块变量 Engee Function ,输入和输出信号的属性(尺寸,类型,离散度)和其他用户定义的参数。 其内容根据块设置动态更新。 单元格始终处于活动状态,但未在"方法管理"菜单中选择该单元格。 engee function all methods. 它包含带有提示的半透明文本。

默认单元格代码:

START_TIME = 0.0
STOP_TIME = 10
BLOCK_NAME = "Engee Function-1"
INPUT_SIGNAL_ATTRIBUTES[1] = (dimensions = -1, type = Inherit, sample_time = (period = -1.0, offset = 0.0), direct_feedthroughs = true)
OUTPUT_SIGNAL_ATTRIBUTES[1] = (dimensions = -1, type = Float64, sample_time = (period = -1.0, offset = 0.0))
gain = 2
const Dimensions = NTuple{N, Int} where N
const SampleTime = NamedTuple{(:period, :offset, :mode), Tuple{Rational{Int64}, Rational{Int64}, Symbol}}
const SAMPLE_TIME = (period = -1//1, offset = 0//1, mode = :Unknown)
更改块参数不仅会影响信息单元格的内容,还会影响其他单元格中的提示,这些提示也会以半透明文本显示。

Define component struct

Details

添加单元格 Component struct code ,它定义了块组件的结构 Engee Function (继承自类型 AbstractCausalComponent). 结构的字段在不可编辑的行之间定义 结构块<:AbstractCausalComponent结束. 默认情况下,将创建参数 g,由块值初始化 增益,以及构造函数 座() 它不接受论点。

默认单元格代码:

struct Block <: AbstractCausalComponent
# Для того, чтобы создать свой блок, определите структуру, наследуемую от
# `AbstractCausalComponent`. Конструктор не должен принимать аргументов.
# Параметр структуры `g` инициализируется значением параметра блока `gain`.
    g::Real
    function Block()
        new(gain)
    end
end

Use common code

Details

添加单元格 Common code ,其中代码以自由形式编写。 默认情况下,单元格为空。 例如,如果标准结构在 Component struct code 不适合(由于不可编辑 结构块<:AbstractCausalComponent),那么你可以禁用 Define component struct 删除单元格,并在 Common code . 这同样适用于方法管理菜单中的任何功能。 engee function all methods -而不是标准的单元格,你可以编写自己的代码 Common code .

engee function common code

声明一个组件和一个函子是需要工作的。 Engee Function . 如果 Define component struct 和*定义步骤方法*被禁用,那么它们的代码必须设置在 Common code ,否则该块将无法工作。
要重新定义继承函数(Override,见下文),您首先需要包含相应的单元格,擦除其内容,然后在 Common code .

Define step method

Details

添加单元格 Step method code ,其中指定了方法 步骤,其中计算块的输出信号 Engee Function . 方法签名是根据相应标签的值自动生成的(Label)选项卡上的端口 Ports . 该方法表示为函子(有关详细信息,请参阅 这里)并且在模拟的每个步骤中被调用。 字段在不可编辑的行之间定义 函数(c::块)(t::实,in1)结束. 第一个论点 真的 -仿真时间,然后输入信号变量被发送。 通过关键字返回计算的输出值 回来吧.

默认单元格代码:

function (c::Block)(t::Real, in1)
# Функция для вычисления значений выходных сигналов блока.
# Первый аргумент `t` - время, остальные - значения входных сигналов.
# В данном примере выходом блока является результат умножения
# входного сигнала на внутренний параметр структуры `g`.
    return c.g .* in1
end

Define update method

Details

添加单元格 Update method code ,其中方法 更新! 更新块的内部状态 Engee Function 在模拟的每一步。 第一个论点 c::座 -块结构,第二 真的 -仿真时间,然后输入信号被发送。 如果块没有内部状态,那么该方法可以保持为空并简单地返回 c.

默认单元格代码:

function update!(c::Block, t::Real, in1)
# В случае, если блок имеет внутреннее состояние, необходимо определить метод
# `update!`. Первый аргумент - структура блока, второй - время, остальные - значения
# входных сигналов. В данном случае блок не имеет внутреннего состояния и
# метод не имеет эффектов.
    return c
end
如果需要定义多个方法 更新! 或者设置一个具有不同签名的方法,然后是一个单元格 Update method code 您可以禁用它并在单元格中编写代码 Common code . 编译器将自动检测方法的存在 更新! 并将其用于仿真。

Define terminate method code

Details

添加单元格 Terminate method code ,在块模拟结束时执行 Engee Function (使用方法 终止!). 第一个论点 c::座 -块结构。 默认情况下,该方法不执行任何其他操作,只需返回 c.

默认单元格代码:

function terminate!(c::Block)
    return c
end

Override type inheritance method

Details

添加单元格 Types inheritance method ,复盖类型继承方法。

如果复选框 *Override type inheritance method 禁用(默认情况下)-输入/输出端口类型根据输入/输出端口描述中指定的规则继承。

如果复选框 *Override type inheritance method 已安装-输入/输出端口类型根据函数中指定的规则继承 传播_类型 细胞 Types inheritance method 在源代码中。 功能 传播_类型 接受一个参数,一个类型的向量,每个输入信号一个类型,并返回一个输出类型的向量。

默认单元格代码:

function propagate_types(inputs_types::Vector{DataType})::Vector{DataType}
# Функция, возвращающая массив типов сигналов на выходе.
# Игнорируется, если используется алгоритм по умолчанию.
# В данном случае учитываются тип входного сигнала и тип
# параметра блока `gain`.
    input_type = first(inputs_types)
    # promote_type возвращает тип, к которому приводятся типы-аргументы
    # при арифметических операциях с объектами этих типов.
    output_type = promote_type(input_type, eltype(gain))
    return [output_type]
end

这里,输入信号的公共元素和Parameters选项卡上的块设置中的参数集的元素被取为继承类型。

Override dimensions inheritance method

Details

添加单元格 Dimensions inheritance method ,它重新定义了维度的继承方法。

如果复选框 *Override dimensions inheritance method 禁用(默认情况下)-输入/输出端口的尺寸根据输入/输出端口描述中指定的规则继承。

如果复选框 *Override dimensions inheritance method set-输入/输出端口的尺寸根据函数中指定的规则继承 传播_dimensions 细胞 Dimensions inheritance method 在源代码中。 功能 传播_dimensions 接受每个输入信号的元组(维度)数组,并在输出端返回维度数组。

默认单元格代码:

function propagate_dimensions(inputs_dimensions::Vector{<:Dimensions})::Vector{<:Dimensions}
# Функция, возвращающая массив размерностей сигналов на выходе.
# Игнорируется, если используется алгоритм по умолчанию.
# В данном случае учитываются размерности входного сигнала и
# параметра блока `gain`.
    input_dimensions = first(inputs_dimensions)
    mock_input = zeros(input_dimensions)
    mock_output = mock_input .* gain
    return [size(mock_output)]
end

在这里,一个具有所需维度的数组被用来继承维度(模拟输入),由零组成。 它乘以Parameters选项卡上的块设置中的参数集的元素,之后取其维度。

Use common method for types and dimensions inheritance

Details

添加单元格 Common types and dimensions inheritance method ,它使用一个通用的方法在同一时间重新定义类型和维度的继承。 与类型的特定方法相反( Types inheritance method)或尺寸(Dimensions inheritance method ),一般方法包括两种类型和尺寸在同一时间:

如果复选框 *Use common method for types and dimensions inheritance 禁用(默认情况下)-忽略常规方法,输入/输出端口的尺寸和类型根据输入/输出端口描述或继承方法中指定的规则继承。 Override type inheritance method (如果启用)和 Override dimensions inheritance method (如果启用)。

如果复选框 *Use common method for types and dimensions inheritance set-输入/输出端口的尺寸和类型根据函数中指定的规则继承 传播_types_and_dimensions 细胞 Common types and dimensions inheritance method 在源代码中。

默认单元格代码:

function propagate_types_and_dimensions(inputs_types::Vector{DataType}, inputs_dimensions::Vector{<:Dimensions})::Tuple{Vector{DataType}, Vector{<:Dimensions}}
# Функция, возвращающая массив типов сигналов и массив
# размерностей сигналов на выходе. Эту функцию можно использовать
# если необходимо одновременно переопределить и алгоритм наследования
# типов сигналов, и алгоритм наследования размерностей.
    outputs_types = propagate_types(inputs_types)
    outputs_dimensions = propagate_dimensions(inputs_dimensions)
    return outputs_types, outputs_dimensions
end

依赖关系

要使用此单元格,请选中方法框 Override type inheritance methodOverride dimensions inheritance method .

Override sample time inheritance method

Details

添加单元格 Sample times inheritance method ,其重新定义了计算步骤的继承方法。

计算步骤的结构代码 采样时间 和功能 传播_sample_times 它们不会自动添加到旧型号的_EngeeFunctionCode_源代码中。 AnyMath . 要细化旧模型,请添加计算步骤结构和功能。

如果复选框 *Override sample time inheritance method 已禁用(默认情况下)—使用计算步骤的预设继承方法(默认情况下 Default)从参数 Sample time inheritance method 标签 Advanced . 在参数说明中阅读有关预设方法的更多信息。 Sample time inheritance method .

如果复选框 *Override sample time inheritance method 已安装-预设选项卡方法 Advanced 被忽略(参数不可用),使用单元格继承方法 Sample times inheritance method 在_EngeeFunctionCode_的源代码中。

为了使继承方法起作用,您需要从单元格中查找函数字符串。 传播_sample_times 并手动设置所需的计算步骤。

默认单元格代码:

function propagate_sample_times(inputs_sample_times::Vector{SampleTime}, fixed_solver::Bool)::SampleTime
# Функция, возвращающая время дискретизации блока.
# Используется только в режиме наследования `Custom`.
# Параметр fixed_solver говорит о том, используется решатель
# с постоянным шагом (true) или с переменным (false).
# Более сложный пример работы с наследованием времени
# дискретизации блока можно посмотреть в документации.
    return first(inputs_sample_times)
end

其中计算步骤具有形式:

const SampleTime = NamedTuple{(:period, :offset, :mode), Tuple{Rational{Int64}, Rational{Int64}, Symbol}}

Override direct feedthrough setting method

Details

添加单元格 Direct feedthrough setting method ,它定义了直接的端到端连接。

如果复选框 *Override direct feedthrough setting method 禁用(默认情况下),直接端到端连接由参数值决定 Direct feedthrough .

*如果复选框 *Override direct feedthrough setting method 如果已安装,则可使用直接的端到端连接。 这意味着输出信号直接由输入端口的值控制。

默认单元格代码:

function direct_feedthroughs()::Vector{Bool}
# Функция, возвращающая массив булевых значений, определяющих,
# сквозные соединения. Если i-ый элемент массива равен true,
# то i-ый порт имеет сквозное соединение.
# Игнорируется, если используется алгоритм по умолчанию.
    return [true]
end

例如_:

function direct_feedthroughs()::Vector{Bool}
    if gain == 2
        return [false]
    else
        return [true]
    end
end

获取属性的常量和函数

要找出块的可执行代码中的类型,大小和其他辅助信息,请在代码中使用以下常量 Engee Function :

  • 块名 -块的名称。 对于添加到画布的每个块 AnyMath ,有一个名字可以通过这个常量访问。 例如,您可以参考 块名 在错误初始化期间,要在其中打印块名称。

  • 开始时间 -从模型设置开始模拟。

  • 停止时间 -结束模拟从模型设置。

  • 输入_SIGNAL_ATTRIBUTES -每个输入端口的属性列表。 例如,要找出第一个输入信号的属性,使用 输入_SIGNAL_ATTRIBUTES[1],在哪里 1 -单元的第一输入端口 Engee Function .

  • 输出_SIGNAL_ATTRIBUTES -每个输出端口的属性列表。 例如,要找出第一输出信号的属性,使用 输出_SIGNAL_ATTRIBUTES[1],在哪里 1 -单元的第一输出端口 Engee Function .

变量 开始时间停止时间 可在所有源代码单元中使用 Engee Function (包括_override_继承方法)。 它们包含模型设置中模拟集的开始和结束时间。 常见使用场景:

*模拟持续时间的计算 STOP_TIME-START_TIME. *在第一/最后一步执行操作(初始化/完成)。 *将离散步骤设置为总持续时间的一小部分(例如,获取 N 间隔上的点)。

要了解有关特定块端口的更多信息,您可以通过添加点来参考其信号的属性 . 常数之后 输入_SIGNAL_ATTRIBUTES[i],在哪里 [i] -输入端口的编号,以及 输出_SIGNAL_ATTRIBUTES[i],在哪里 [i] -分别输出端口的编号。 可通过以下联系人功能获取其他信息:

  • 尺寸 -信号的维度。 可缩短至 暗淡无光.

  • 类型 -信号的类型。 可缩短至 tp.

  • 采样时间 -计算步骤。 它是一种类似于信号属性的结构,可以通过点访问。 .. 提供两种转换功能:

    • 期间 -计算步骤的周期。 全转换功能 — sample_time.期间. 可缩短至 圣.p.

    • 偏移量 -计算步骤的偏移。 全转换功能 — sample_time.偏移量. 可缩短至 圣.o.

  • direct_feedthrough -确定端口是否具有直接的端到端连接。 它仅用于输入端口(仅检查输入端口的属性)。 可缩短至 df.

具有所有常量和转换函数的模型示例

Details

一个模型的例子 Engee Function 具有所有常量和处理函数:

engee function constants

struct Block <: AbstractCausalComponent end

function (c::Block)(t::Real, x1, x2)
    y1 = [START_TIME, STOP_TIME]
    y2 = collect(INPUT_SIGNAL_ATTRIBUTES[1].dimensions)
    y3 = OUTPUT_SIGNAL_ATTRIBUTES[1].dims[1]
    y4 = (INPUT_SIGNAL_ATTRIBUTES[2].type == Int64)
    y5 = (OUTPUT_SIGNAL_ATTRIBUTES[4].tp == Bool)
    y6 = INPUT_SIGNAL_ATTRIBUTES[1].sample_time.period
    y7 = OUTPUT_SIGNAL_ATTRIBUTES[1].st.p
    y8 = INPUT_SIGNAL_ATTRIBUTES[1].sample_time.offset
    y9 = OUTPUT_SIGNAL_ATTRIBUTES[2].st.o
    y10 = INPUT_SIGNAL_ATTRIBUTES[1].direct_feedthrough
    y11 = INPUT_SIGNAL_ATTRIBUTES[2].df
    return (y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11)
end

使用参数作为变量

变量窗口中可用的全局变量 AnyMath variables icon,可以在*Parameters*选项卡上设置,以便插入块源代码 Engee Function . 如果参数的名称和全局变量匹配,参数值将自动从全局变量中替换。

区分块参数(在选项卡上设置)非常重要 Parameters 并且是源代码中的全局变量 Engee Function)来自全局变量 AnyMath 在变量窗口中 variables icon. 虽然可以在块参数中使用全局变量的值和名称。 AnyMath ,这些实体是完全不同的。 全局变量无法控制。 AnyMath 通过块参数或从其源代码。 但是,对于源代码,块参数(来自选项卡 Parameters)是全局变量,可以在它的任何部分中使用,而不引用特定的函数或代码块。

使用参数作为变量的示例

Details

让我们考虑全局变量完全对应于源代码中的变量的情况。 例如,设置了三个全局变量 a, b, c 与价值观 1, 2, 3 相应地。 所有三个全局变量都用作块参数。 Engee Function :

engee function param explain 1

然后添加参数的源代码将如下所示:

struct Block <: AbstractCausalComponent
    a::Real
    b::Real
    c::Real

    function Block()
        new(a_param, b_param, c_param)
    end
end

function (c::Block)(t::Real, x::Vector{<:Real})
    return (c.a .* x .+ c.b) ./ c.c
end

此代码定义了结构 ,从而调整组件的行为。 该示例使用块参数的名称。 a_param, b_帕拉姆c_param 设置结构参数 a, bc 相应地。 代码还定义了一个方法 function(c::Block)(t::Real,x::Vector{<:Real}),其中缩放向量的每个元素 x 到块参数 a,补充 b 并将结果除以 c. 这允许您灵活地更改和规范化矢量。 x 据块参数的值。

让我们考虑一下只使用tab参数的情况。 Parameters :

struct Block <: AbstractCausalComponent end

function (c::Block)(t::Real, x::Vector{<:Real})
    return (a_param .* x .+ b_param) ./ c_param
end

这些参数将是块代码中的全局变量。 这意味着它们将始终在块代码的任何部分中可用,而不必在每个函数或代码块中重复定义它们。 这大大简化了代码,并可以轻松更改选项卡上的设置。 Parameters 不影响源代码。

让我们考虑参数与源代码不完全匹配的情况。 例如,有一个参数 a_param,等于 100. 源代码中有一个结构字段 a:

struct Block <: AbstractCausalComponent
    a::Real

    function Block()
        new(a_param/10)
    end
end

function (c::Block)(t::Real, x::Vector{<:Real})
    c.a
end

在这段代码中,参数 a_param 用于初始化字段 a 结构 结构块 通过它的构造函数,它将参数值划分为 10. 在这种情况下,该字段在块的函子中返回 a.

变量可以在源代码中全局化。:

a = 1;
b = 2;
с = 3;

struct Block<:AbstractCausalComponent;end

function(c::Block)(t::Real,x::Vector{<:Real})
    返回(a。*x.+b)。/c
结束

在代码中创建一个结构 定义了一个函数,它用全局变量执行数学运算。 a, bc 通过将它们应用于变量 x.

如果您*不想*要使用选项卡中的选项 Parameters ,那么就可以直接在源代码中初始化变量了。:

struct Block <: AbstractCausalComponent; end

function (c::Block)(t::Real, x)
    a = 1;
    b = 2;
    c = 3;
    return (a .* x .+ b) ./ c
end

在代码中创建一个结构 ,定义对局部变量进行数学运算的函数 a, bc 通过将它们应用于变量 x.

让我们考虑最有效和正确的方法。 阻止 Engee Function 工作正常,选中该选项的复选框 Use external cache for non-scalar output 在块的主选项卡上 Engee Function . 源代码将如下所示:

struct Block{Ta, Tb, Tc} <: AbstractCausalComponent
    a::Ta
    b::Tb
    c::Tc

    function Block()
        Ta = typeof(a_param); Tb = typeof(b_param); Tc = typeof(c_param)
        all(isreal, (a_param, b_param, c_param)) ||
          error("Параметры блока должны быть вещественными")
        all(x->isempty(size(x)), (a_param, b_param, c_param)) ||
          error("Параметры блока должны быть 标量ами")
        new{Ta, Tb, Tc}(a_param, b_param, c_param)
    end
end

function (c::Block)(t::Real, cache::Vector{<:Real}, x::Vector{<:Real})
    cache .= (c.a .* x .+ c.b) ./ c.c
    nothing
end
此代码只能在单元格中编写。 Common code ,因为标准单元格不允许编辑组件结构的定义和函子的签名。

字段 a, bc 结构是在构造函数中严格检查类型的块参数。 这些参数中的每一个都必须是一个真正的标量(真实的),从而保证了执行过程中计算的准确性。

设计师 座() 检查传递参数的类型 , . 如果其中至少有一个不是真正的标量或具有不适当的维度(它们必须是标量),则构造函数会生成带有相应消息的错误。 验证后,构造函数使用值初始化结构的字段 , 指定的类型 Ta, 结核病Tc技术.

为块实例定义的计算函数需要时间 t,外部缓存和矢量 x 实数。 字段用于此函数 a, bc 结构 计算值,然后将其写入缓存。 这通过重用提供的缓存来避免不必要的内存分配。

因此,结构 通过使用外部缓存来存储计算结果,提供对数据类型的严格管理和资源的有效使用。

如果要更改块参数,则必须使用 可变的 的结构。 考虑一个例子:

mutable struct Counter{T} <: AbstractCausalComponent
    limit::T
    iter::T

    function Counter()
      isempty(size(limit)) || error("Предел блока $BLOCK_NAME должен быть 标量ом")
      isreal(limit) || error("Предел блока $BLOCK_NAME должен быть вещественным числом")
      T = typeof(limit)
      iter = zero(T)
      new{T}(limit, iter)
    end
end

function (c::Counter)(t::Real)
    return c.iter
end

function update!(c::Counter, t::Real)
  c.iter += 1
  if c.iter > c.limit
    c.iter = zero(c.iter)
  end
  c
end

结构 柜台 -这是 可变的 用于计算具有指定限制的迭代的数据类型。 它是强类型的。 字段 限额伊特尔 结构表示块参数:

  • 限额 -这是计数器的极限值;

  • 伊特尔 -计数器的当前值。

在结构构造函数中检查该参数。 限额 -它必须是标量并具有真实的数据类型。 之后,该字段被初始化 伊特尔 具有相应类型的零值 T. 功能 更新! 更新标签状态 c,增加价值 伊特尔 每个电话一个。 如果当前值为 伊特尔 超过 限额,然后将其重置为零,这允许计数器循环回到其初始状态。

块的源代码中 Engee Function 可以使用 包括,参考外部代码。 这允许您从源代码中的外部代码(如果有的话)初始化变量。
实际的数据类型以及对可能的数据类型的支持取决于块内的用户代码。

港口

入口处

输入端口 — 输入端口

+ 标量,标量 | 向量资料 | 矩阵 | 阵列

Details

指定为标量、矢量、矩阵或数组的输入信号。

输入端口的数量在参数中设置 Number of input ports .

对于每个输入端口,您可以配置选项卡上的设置 Ports . 有关详细信息,请参阅输入端口

出口;出口

输出端口 — 输出端口

+ 标量,标量 | 向量资料 | 矩阵 | 阵列

Details

作为标量、矢量、矩阵或数组返回的输出信号。

输出端口的数量在参数中设置 Number of output ports .

对于每个输出端口,您可以配置选项卡上的设置 Ports . 有关详细信息,请参阅输出端口

参数

Main

Number of input ports — 输入端口数

+ 整数

Details

指定块中的输入端口数。

默认值

通行证:[1]

编程使用的名称

输入 可配置::无 计算::是

Number of output ports — 输出端口数

+ 整数

Details

指定块的输出端口数。

默认值

通行证:[1]

编程使用的名称

产出 可配置::无 计算::是

Sample time — 计算步骤之间的间隔

+ SampleTime(实数/两个实数的向量)

Details

将计算步骤之间的间隔指定为非负数。 要继承计算步骤,请将此参数设置为 −1.

默认值

通行证:[-1]

编程使用的名称

采样时间 可配置::无 计算::是

Parameters

参数数量 — 参数的数量

+ 整数

Details

指定块中使用的参数数量。

默认值

通行证:[1]

编程使用的名称

参数 可配置::无 计算::是

Name — 参数名称

+ 字符串

Details

指定要在块源代码中使用的参数名称。 Engee Function .

第一个参数的名称(默认存在) — 增益,其值为 2. 新参数被调用 参数2 然后上升。 新参数的默认值为 0.

有关详细信息,请参阅参数

默认值

通行证:[增益]

编程使用的名称

参数1名 可配置::无 计算::无

Value — 参数的值

+ 任意类型

Details

使用名称指定参数的值 Name . 任何Julia表达式都可以设置为值。

要设置总线参数,请为参数设置 价值 命名元组形式的总线值,例如 (s1=5,s2=4).

有关详细信息,请参阅参数

Advanced

Use external cache for non-scalar output — 用于非标量输出信号的外部缓存

+ 合乎逻辑的

Details

选中复选框以将外部缓存用于非标量(多维)输出信号以保存RAM。 AnyMath . 使用,如果块有 Engee Function 只有一个输出端口:

*如果未选中复选框(默认情况下),则不使用外部缓存。

如果复选框被选中,输出信号可以接受一个额外的参数。 缓存,在_EngeeFunctionCode_的源代码中必须考虑到这一点。 如果单元具有一个输出端口,则在单元 *Step method code 论点 缓存 它会自动添加到函数参数列表中,除非将端口维度显式指定为 () (标量)。 在源代码中,有必要根据输出信号的维度定义函子。 函数可以在单元格中定义 Common code :

**如果输出信号是标量的:

+

function (c::Block)(t::Real, x)
    return c.g * x
end

**如果输出信号是非标量的:

+

function (c::Block)(t::Real, cache, x)
    cache .= c.g .* x
    nothing
end

+ 哪里 t -时间, x -参数(来自输入端口的信息)。 必须指定time参数,即使它不包含在块参数中。

默认值

通行证:[错误(禁用)]

编程使用的名称

[医]使用 可配置::无 计算::无

Sample time inheritance method — 计算步骤的继承方法

+ Default | Discrete | Continuous

Details
定制化 Sample time inheritance method 从选项卡中消失 Advanced 如果在_engeefunctioncode的源代码中选中了复选框_ Override sample time inheritance method . 在这种情况下,计算步骤的继承方法由功能单元的代码确定。 Sample times inheritance method .

根据所选值定义计算步骤的继承方法:

  • Default -计算步骤的默认继承方法。 继承的方法 Default 块时使用 Engee Function 它不是离散或连续的。 它允许任何类型的计算步骤。 选择此方法时,块 Engee Function 将根据以下原则继承计算步骤:

    如果单元没有输入端口,则输出端有一个连续的计算步骤。 如果输入处的所有计算步骤相同,则输出处的计算步骤与输入相同。 如果输入步骤中有连续的计算步骤,则输出处也有连续的计算步骤。 如果输入计算步骤中存在固定小调(FiM,Fixed-In-Minor),则不存在连续计算步骤和 求解器与可变间距-输出是一个固定的小一个。 **如果在输入处没有连续和固定的小计算步骤并且并非所有计算步骤都相等,则只考虑输入处的离散计算步骤,对于其中一个选项是有效的:

    *如果离散计算步骤的最大公约数与输入计算步骤之一重合或使用恒定步长求解器,则输出是具有最大公约数的步长的离散计算步骤。 *如果可变步长求解器和输入离散计算步骤的最大公约数与任何输入计算步骤不匹配,则输出为固定小的。

  • Discrete -种获得离散计算步骤的继承方法。 选择此方法时,块 Engee Function 将根据以下原则继承计算步骤:

    如果输入端有一个连续的或固定的小计算步长,则输出是一个带有求解器步长的离散计算步长(即使求解器带有可变步长)。 如果在输入处存在离散计算步骤,则输出是与输入离散计算步骤具有最大公约数的离散计算步骤。

  • Continuous —种用于获得与输入计算步骤无关的连续计算步骤的继承方法。

如果在现场 Sample time 值指定 −1,则根据字段中指定的方法继承计算步骤 Sample time inheritance method 取决于所选值(Default, Discrete, Continuous). 在所有其他情况下( Sample time 不等于 −1Sample time 大于或等于 0)-区块 Engee Function 使用指定的字段值 Sample time ,忽略 Sample time inheritance method .

一个重新定义函数的例子 传播_sample_times 具有类似于继承方法的作业 Default:

function propagate_sample_times(inputs_sample_times::Vector{SampleTime}, fixed_solver::Bool)::SampleTime
    nonnegative_sample_times = filter(
        st -> st.period >= 0,
        collect(values(inputs_sample_times)),
    )
    finite_periods = filter(
        st -> !isinf(st.period),
        nonnegative_sample_times,
    ) .|> (st -> st.period)
    output_sample_time = if !isempty(nonnegative_sample_times)
        if allequal(nonnegative_sample_times)
            first(nonnegative_sample_times)
        elseif any(st -> st.period == 0 // 1 && st.mode == :Continuous, nonnegative_sample_times)
            (period = 0 // 1, offset = 0 // 1, mode = :Continuous)
        elseif any(st -> st.mode == :FiM, nonnegative_sample_times) && !fixed_solver
            (period = 0 // 1, offset = 0 // 1, mode = :FiM)
        elseif (
            all(x -> x.period > 0 // 1, nonnegative_sample_times) &&
            (fixed_solver || gcd(finite_periods) in finite_periods)
            )
            (period = gcd(finite_periods), offset = 0 // 1, mode = :Discrete)
        else
            (period = 0 // 1, offset = 0 // 1, mode = :FiM)
        end
    else
        (period = 0 // 1, offset = 0 // 1, mode = :Continuous)
    end
    return output_sample_time
end
如果功能 传播_sample_times 申报表 (周期=0//1,偏移=0//1,模式=:离散),那么这样的计算步骤将被视为具有求解器步骤的离散。
价值

违约情况 | 离散的,离散的 | 连续不断

默认值

通过:[默认]

编程使用的名称

[医]样品,样品 可配置::无 计算::无

Ports

输入端口

Label — 输入端口的名称

+ 字符串

Details

指定输入端口的名称。

默认值

通行证:[—]

编程使用的名称

输入端口1label 可配置::无 计算::无

Type — 输入数据类型

+ 继承 | 漂浮64 | 漂浮物32 | 漂浮物16 | 复杂的f64 | 复杂的32 | 布尔 | Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Int128 | UInt128 | N.公共标志

Details

选择其中一个选项:

*某一类型(除 Inherit)-检查某种类型的信号正在发送到输入端口。 为输入端口选择特定的数据类型。

  • Inherit (默认情况下)—从关联块继承数据类型。 它可以是任何类型的数据。

价值

继承 | 漂浮64 | 漂浮物32 | 漂浮物16 | 复杂的f64 | 复杂的32 | 布尔 | Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Int128 | UInt128 | N.公共标志

默认值

通行证:[继承]

编程使用的名称

输入端口1类型 可配置::无 计算::无

Output bus type — 输入总线类型

+ 数据类型

Details

输入总线类型。 阻止 Engee Function 我明白了哪辆公共汽车会来到入口处,安装就足够了 Type 在值 Inherit. 显式类型指示仅对输出信号是必要的。

Engee Function 不继承输出端口上的总线,尽管它可以在输入端接收它们。 要继承输出端口上的总线(用于传输到其他块),必须在参数中显式指定总线类型 Output bus type .

依赖关系

若要使用此参数,请为参数设置 Type 价值 BusSignal.

默认值

通行证:[BusSignal((), (), (), :EngeeFunctionInput1BusType)]

编程使用的名称

输入端口1bustype 可配置::无 计算::是

尺寸 — 输入信号的维度

+ Int64或int64的元组

Details

输入信号的维度可以设置为:

  • −1 (默认情况下)—继承施加到输入端口的信号的维度(信号可以具有任何维度)。

*整数或整数元组-输入信号必须具有指定数量的元素。 Dimensions以Julia表示法指定,例如, () 对于标量, (2,) 为由两个元素组成的一维信号,或 (2, 3, 4) 对于多维。

*整数元组和 −1 -某些维度的继承。 例如, (-1, 2) -第一个维度是继承的,第二个维度是显式设置的。

默认值

通行证:[-1]

编程使用的名称

输入端口1大小 可配置::无 计算::是

Direct feedthrough — 直接端到端连接

+ 合乎逻辑的

Details

定义直接的端到端连接:

*如果选中该复选框(默认情况下),则直接端到端连接可用。 这意味着输出信号直接由输入端口的值控制。

*如果未选中,则直接端到端连接不可用。 这意味着输出信号将不受输入端口的值控制,这允许单元开环。

默认值

通过:[真(启用)]

编程使用的名称

输入端口1directfeedthrough 可配置::无 计算::无

输出端口

Label — 输出端口的名称

+ 字符串

Details

指定输出端口的名称。

默认值

通行证:[—]

编程使用的名称

输出端口1label 可配置::无 计算::无

Type — 输出数据的类型

+ 继承 | 漂浮64 | 漂浮物32 | 漂浮物16 | 复杂的f64 | 复杂的32 | 布尔 | Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Int128 | UInt128 | N.公共标志

Details

选择其中一个选项:

*某一类型(除 Inherit)是输出信号的特定数据类型。

  • Inherit (默认情况下)-继承输出信号的数据类型。 当有多个不同类型的输入信号时,计算最小的公共类型。 它可以是任何类型的数据。

价值

继承 | 漂浮64 | 漂浮物32 | 漂浮物16 | 复杂的f64 | 复杂的32 | 布尔 | Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Int128 | UInt128 | N.公共标志

默认值

通行证:[Float64]

编程使用的名称

输出端口1类型 可配置::无 计算::无

Output bus type — 输出总线类型

+ 数据类型

Details

型的输出总线。 阻止 Engee Function 当轮胎到达出口时,有必要明确指定其类型。

依赖关系

若要使用此参数,请为参数设置 Type 价值 BusSignal.

默认值

通行证:[BusSignal((), (), (), :EngeeFunctionOutput1BusType)]

编程使用的名称

输出端口1类型 可配置::无 计算::是

尺寸 — 输出信号的维度

+ Int64或int64的元组

Details

输出信号的维度可以设置为:

  • −1 (默认情况下)—继承发送到输入端口的信号的维度。 如果有多个输入信号,则维度继承遵循规则 广播。 特殊情况:

**如果输入信号具有相同的尺寸,则输出端口将继承它。;

**如果输入信号是具有相同维度的标量和非标量(向量、矩阵或多维数组),则它被继承。;

**如果广播不能应用于输入信号(例如,输入信号是不同长度的向量),那么自动维度继承是不可能的。 在这种情况下,您将需要显式设置输出信号维度。

*整数或整数元组-输出信号必须具有指定数量的元素。 Dimensions以Julia表示法指定,例如, () 对于标量, (2,) 为由两个元素组成的一维信号,或 (2, 3, 4) 对于多维。

*整数元组和 −1 -某些维度的继承。 例如, (-1, 2) -第一个维度是继承的,第二个维度是显式设置的。

默认值

通行证:[-1]

编程使用的名称

输出端口1大小 可配置::无 计算::是

使用固定点和自定义总线

Engee Function ,以及 命令提示符 img 41 1 2 AnyMath 支持定点操作(固定)和定制轮胎类型(N.公共标志). 这些构造有助于控制处理整数、实数、固定和复杂数据类型时的操作行为。

定点类型和功能(定点)

Details

在文章中 定点算术在 AnyMath 描述如何使用固定点在 AnyMath . 文章中给出的构造对块也有效 Engee Function ,所以块支持:

  • 固定点,固定点 -所有固定数字的抽象类型;

  • 固定 -一种特定类型的固定数字,它是手动创建的,带有位表示的指示;

  • 菲(。..) -创建类型值 固定 使用数值和表示参数;

  • fixdt(。..) -创建固定类型,并指示符号、宽度和小数位数。

例如:

a = fi(5, 1, 16, 4)     # Знаковое число, 16 бит, 4 дробных
b = fi(10, 0, 8, 0)     # Беззнаковое целое 8 бит
T = fixdt(1, 24, 8)     # Тип Fixed с 24 битами, 8 из них — дробные
c = Fixed(0x01ff, T)    # Создание фиксированного числа напрямую по битовому представлению

定点数在 Engee Function 你可以:

作为参数传输; *在组件结构(细胞)中的使用 *Component struct code); 通过它们执行算术运算 emul, 埃苏姆, 伊迪夫 在牢房里 *Step method code (有关详细信息,请参阅[数字转换]); *适用于计算 propagate_types(…​), propagate_dimensions(。..).

使用自定义轮胎类型(N.公共标志)

Details

自定义总线类型允许您以结构化元组的形式指定输入和输出信号的类型(命名的,命名的)与里面的名称,类型和尺寸的描述 Engee Function . 可用功能:

  • BusSignal{名称,类型,尺寸,:BusName} -带有信号名称的总线(姓名),基本类型(基本类型),尺寸(暗淡无光)及巴士名称(总线名称);

  • get_bus_names(类型) -获取信号名称列表;

  • get_bus_types(类型) -获取信号的类型;

  • get_bus_dimensions(类型) -获取信号的尺寸;

  • get_names_types_dims(类型) -立即得到一切;

  • get_bus_signal_type(::NamedTuple) -识别类型 N.公共标志 按价值计算。

一个确定和分析轮胎类型的例子:

bus_type = BusSignal{(:s1, :s2, :s3), Tuple{Int64, Float64, Int8}, ((), (2,), (2, 2)), :MyBus}
get_names_types_dims(bus_type)  # => ((:s1, :s2, :s3), (Int64, Float64, Int8), ((), (2,), (2, 2)))

get_bus_names(bus_type)       # => (:s1, :s2, :s3)
get_bus_types(bus_type)       # => (Int64, Float64, Int8)
get_bus_dimensions(bus_type)  # => ((), (2,), (2, 2))

你可以明确地描述轮胎:

bus_obj = BusSignal{(:a, :b), Tuple{Int, Float64}, ((), (3,)), :MyBus}((a=1, b=[1.0, 2.0, 3.0]))

还支持嵌套总线。:

Inner = BusSignal{(:x, :y), Tuple{Int, Int}, ((), ()), :InnerBus}
Outer = BusSignal{(:a, :b), Tuple{Float64, Inner}, ((), ()), :OuterBus}

块中的用法 Engee Function

Details

类别 固定N.公共标志 它可以用于块的不同部分。 Engee Function :

在块参数中,您可以通过以下方式设置固定点值 菲(。..),以及转移总线结构 BusSignal{…​}. *在牢房里 *Common code -可以定义数据类型(固定, BusSignal{…​}),组件结构(结构块),创建辅助函数或初始化值。 如果禁用,您也可以在此处移动主逻辑 Step method codeComponent struct code . 在牢房里 *Component struct code -描述结构的字段时,可以使用如下值 固定,以及类型 N.公共标志 如果字段是复合信号。 在牢房里 *Step method code -块的主要逻辑实现。 在这里,固定数字和总线信号可以参与计算、比较和结构处理。 在牢房里 *Types inheritance method -类型可以使用 固定N.公共标志 分析输入并指定组件的输出类型。 在牢房里 *Dimensions inheritance method -数据可以使用 固定 和来自总线的值来确定输出信号的尺寸。 在牢房里 *Update method code -如果块具有内部状态,则字段如下 固定N.公共标志 它可用于在仿真的每个步骤存储或更改此状态。 在牢房里 *Terminate method code -如果结构包含适当的字段,这些类型可用于记录最终状态。 在牢房里 *Common types and dimensions inheritance method -如果需要同时处理两种类型和尺寸, 固定N.公共标志 他们也可以参与计算逻辑。

因此, 固定, 菲(。..), fixdt(。..), N.公共标志get_总线 这些功能适用于机组配置和操作的各个方面. Engee Function -在信号的类型和维度的执行阶段和生成阶段。 它们可以在所有单元格的参数和源代码中自由使用(取决于它们的操作规则)。

说明

注释在 Engee Function 允许您在模型中直接在其名称下显示块参数。 要添加它们,请打开 设置窗口 debug article icon 1 街区 Engee Function 并转到*Annotation*选项卡。 选择所需的块属性标记并将其添加到文本编辑器中。

engee function annotations

在这个标签上:

*左侧显示可用选项列表(隐藏选项除外)。 *右侧有一个文本编辑器,您可以在其中设置带有格式标记的注释 %<参数名称>. *参数可以手动传输,通过自动完成,或使用按钮 engee function annotations 1.

退出编辑器后(例如,在其外部单击时),将应用注释:标记将自动替换为实际参数值,最终文本显示在块名称下(或在其上方,如果名称放在顶部)。

要删除批注,必须在编辑器中删除相应的标记。

可用标记

属性标记将自动替换为当前参数值。 以下标记可用:

港口*: %<输入>, %<输出> -输入输出端口数; %<输入端口1类型>, %<输出端口1类型>, %<输入端口1大小>, %<输出端口1大小> -数据的类型和信号的维度。 临时特性*: %<采样时间> -离散化; %<采样时间> -离散继承的方法。 代码单元格*: %<组件结构码>, %<StepMethodCode> -步骤结构和方法的代码。 参数*: %<参数>, %<参数名称>, %<参数1值> -参数的名称和值。 启用标志*: %<定义组件结构>, %<UseCommonCode>, %<DefineStepMethod>, %<DefineUpdateMethod>, %<DefineTerminateMethod> -纳入守则的有关部分。 重新定义方法*: %<超负荷类型>, %<OverrideDimsInhMethod>, %<重写时间> -类型继承设置。 *其他: %<UseExternalCache> -使用外部缓存。

转换函数和类型化算术运算: [医]经济型, 埃苏姆, emul, 伊迪夫

在街区里 Engee Function ,以及在 命令行 img 41 1 2 AnyMath 可用的函数允许您执行指定输出类型的算术运算,在具有舍入和溢出控制的类型之间转换值,并使用专门的规则预先确定结果类型(_promote_类型). 这些函数用于逻辑 Engee Function 写在源代码的单元格中 Step method code , Common code 和其他人。

可用功能:

  • [医]经济型 -类型之间的值转换;

  • 埃苏姆, [医]esub, emul, 伊迪夫 -输出类型赋值的算术运算;

  • 艾缪尔! -带有结果缓存的矩阵乘法;

  • *_promote_type -基于输入类型的输出功能。

这些函数可以应用于标量和数组。 结果总是以用户显式指定的类型返回(或自动输出),这使得块行为稳定和预期。

支持的类型

Details

此集合中的所有函数都适用于以下类型:

*物理: 漂浮物16, 漂浮物32, 漂浮64; *整数: Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128; *逻辑: 布尔; *固定: 固定 (通过创建 菲(。..)fixdt(。..)); *复杂: 综合体{T},在哪里 T -任何上述类型。

函数也可以使用点语法与数组和矢量化表达式一起使用(.). 接下来,让我们更详细地看一下这些功能。

使用 [医]经济型

Details

功能 [医]经济型 允许您通过指定舍入方法和溢出处理方法将值转换为指定类型。:

econvert(type::Type{T1}, var::T2; rounding_mode::RoundingMode=RoundDown, overflow::Bool=true)

这里:

  • 类型 -要将值转换为的类型。 如果 瓦尔 -一个复数,基本实数表示。 例如, 经济型(Float32,综合大楼){Int16}(1+2im)) 它会回来的 综合体{Float32};

  • 瓦尔 -转换价值;

  • 圆角/圆角 -舍入法(四舍五入, 综述, RoundNearest拢潞, 往返旅行, 圆托泽罗);

  • 溢出 -如果 真的,则使用溢出行为(wrap);如果 错误 饱和启用-值受类型范围限制。

功能 [医]经济型 它可用于比较前的类型转换,在算术表达式内部,在条件和其他场景中处理信号时。

算术与类型控制使用 埃苏姆, [医]esub, emul, 伊迪夫, 艾缪尔!

Details

类型化算术运算的函数 埃苏姆, [医]esub, emul, 伊迪夫, 艾缪尔! 他们有相同的接口:

esum(x1, x2, out_type, overflow=true, rm=RoundDown)
esub(x1, x2, out_type, overflow=true, rm=RoundDown)
emul(x1, x2, out_type, overflow=true, rm=RoundDown)
ediv(x1, x2, out_type, overflow=true, rm=RoundDown)
emul!(cache, x1, x2, out_type, overflow=true, rm=RoundDown)

争论:

  • x1, x2 -操作参数(标量或数组);

  • out_type -生成和返回结果的类型;

  • 溢出 -启用溢出(真的)或饱和度(错误);

  • rm -舍入方法(见上面的列表)。

功能 埃苏姆, [医]esub, emul, 伊迪夫 返回与指定的值对应的值 out_type.

功能 艾缪尔! 它用于在处理矩阵时加快速度:它不会创建新数组,而是将结果写入已经分配的数组。 缓存. 重要的是 eltype(缓存) 恰逢 out_type.

结果取决于类型 out_type:它不仅影响最终结果,还影响中间计算的行为—这对于 固定综合体.

使用以下方法推断结果的类型 *_promote_type

Details

如果块参数(例如, [医]相类型多类型,多类型)被设置为字符串 "继承",结果的类型是根据使用函数的输入数据类型自动确定的 *_promote_type.

如果您需要计算操作的结果类型,请使用列出的函数:

*定义添加时的输出类型 n 相同类型的值 T:

+

sum_promote_type(::Type{T}, n::Integer=1, hdlsetup::Bool=false)

*定义两个不同类型加在一起时的输出类型 T1T2n 价值:

+

sum_promote_type(::Type{T1}, ::Type{T2}, n::Integer=1, hdlsetup::Bool=false)

*在添加任意数量的具有不同类型的参数时定义输出类型。:

+

sum_promote_type_from_inputs(types::Type...; hdlsetup::Bool=false)

*确定添加时的电池类型 n 相同类型的值 T:

+

sum_accumulator_promote_type(::Type{T}, n::Integer=1, hdlsetup::Bool=false)

*当两种不同类型的电池加在一起时,确定电池的类型 T1T2n 价值:

+

sum_accumulator_promote_type(::Type{T1}, ::Type{T2}, n::Integer=1, hdlsetup::Bool=false)

*在添加任意数量的具有不同类型的参数时确定累加器的类型。:

+

sum_accumulator_promote_type_from_inputs(types::Type...; hdlsetup::Bool=false)

*在乘以相同类型的值时定义输出类型 T:

+

mul_promote_type(::Type{T}, hdlsetup::Bool=false)

*定义两种不同类型相乘时的输出类型 T1T2:

+

mul_promote_type(::Type{T1}, ::Type{T2}, hdlsetup::Bool=false)

*在划分单个类型值时定义输出类型 T:

+

div_promote_type(::Type{T}, hdlsetup::Bool=false)

*在划分类型值时定义输出类型 T1 在类型值上 T2:

+

div_promote_type(::Type{T1}, ::Type{T2}, hdlsetup::Bool=false)

+ 这里 hdlsetup -一个逻辑参数,决定是否考虑到硬件平台的细节(目标软件). 默认情况下:

+

hdlsetup = TargetHardware == "C" ? false : true

这些功能在单元格中使用很方便 Types inheritance method 根据输入和参数准确确定输出块类型。

使用示例

Details

下面是实现表达式的组件的示例 a*x+b. 使用参数设置中间乘法和最终加法的类型 多类型,多类型[医]相类型. 如果指定 "继承",然后自动输出该类型。

engee function example 3

参数 Engee Function :

a = fi(5, 1, 16, 4)
b = fi(11, 1, 24, 7)
MulType = "Inherit"
SumType = "Inherit"

块代码(在单元格中 Common code , Dimensions inheritance methodTypes inheritance method):

细胞 *Common code :

+

struct Block{SumType, MulType, aType, bType} <: AbstractCausalComponent
    a::aType
    b::bType
    function Block()
        sum_type = OUTPUT_SIGNAL_ATTRIBUTES[1].type
        mul_type = if MulType == "Inherit"
            mul_promote_type(INPUT_SIGNAL_ATTRIBUTES[1].type, eltype(a))
        else
            MulType
        end
        new{sum_type, mul_type, typeof(a), typeof(b)}(a, b)
    end
end

细胞 *Dimensions inheritance method :

+

function propagate_dimensions(inputs_dimensions::Vector{<:Dimensions})::Vector{<:Dimensions}
    input_dimensions = first(inputs_dimensions)
    mock_input = zeros(input_dimensions)
    mock_output = mock_input .* a .* b
    return [size(mock_output)]
end

细胞 *Types inheritance method :

+

function propagate_types(inputs_types::Vector{DataType})::Vector{DataType}
    mul_type = if MulType == "Inherit"
        mul_promote_type(inputs_types[1], eltype(a))
    else
        MulType
    end
    sum_type = if SumType == "Inherit"
        sum_promote_type(mul_type, eltype(b))
    else
        SumType
    end
    return [sum_type]
end

因此,功能 [医]经济型, 埃苏姆, emul, 伊迪夫 和规则 promote_type 它们允许您控制块内计算的类型和行为。 Engee Function . 它们支持所有主要的数值类型,包括固定点和复杂值,并可用于计算、比较、继承逻辑和使用块的组件行为调整。 Engee Function .

诊断功能 警告, 停止模拟, 暂停模拟, 资料

块的源代码中 Engee Function 功能也可用 警告, 停止模拟, 暂停模拟资料,允许您在模拟阶段与模型诊断系统交互,并将消息输出到 诊断窗口 model diagnosis main. 这些函数可以在以下源代码单元中使用:

  • Component struct code

  • Step method code

  • Update method code

  • Terminate method code

  • Common code

功能 警告, 停止模拟, 暂停模拟, 资料 它只能用于在模型仿真期间执行的代码的那些部分。

所以,尽管这些函数在单元格中正式有效 Component struct code ,在实践中,它们在那里的位置没有意义:此单元格仅用于描述块结构,而不是用于可执行逻辑。 为了使诊断功能正常工作,必须将它们放在支持的仿真方法中。: Step method code , Update method code , Terminate method code 或在 Common code 如果相应的方法在那里重新定义。 正确放置的例子:

  • Component struct code :

    #
    struct Block <: AbstractCausalComponent
        g::Real
        function Block()
            new(gain)
        end
    end
  • Common code ,函子 函数(c::块)(t::实,in1) 取自 Step method code ,方法本身被禁用:

    function (c::Block)(t::Real, in1)
        if t == 5.0
            warning("time == $t")
        end
        return c.g .* in1
    end

通过类推,您可以复盖在模拟期间调用的任何受支持的方法(例如, 更新!, 终止;终止, 步骤),在细胞中 Common code 手动,如果禁用相应的标准单元格(例如, Define update method ,*定义步骤方法*等。).

为了在细胞中正确操作 Common code 功能 警告, 停止模拟, 暂停模拟资料 可以使用:

内部函数,重新定义负责执行模型的方法的行为,例如 步骤, 更新!, 终止!. 例如,如果函子通常在单元格中指定 *Step method code ,定义于 Common code ,那么它里面的诊断功能将正常工作。

内部从负责执行模型的方法调用的辅助函数。 也就是说,如果辅助函数定义在 *Common code 并用于,例如,在 步骤,那么对其内部诊断函数的调用也将正确执行。

+

重新定义 更新! 或其他方法不替换所要求的实现。 步骤 (函数(c::块)(t,in…​)). AnyMath 需要此功能作为模拟的入口点。

正确重新定义的一个例子 更新!Common code :

# Структура с Component struct code (если отключена, то должна быть обязательно вынесена в Common code)
struct Block <: AbstractCausalComponent
    g::Real
    function Block()
        new(gain)
    end
end

# Step method (обязательный метод, вызываемый на каждом шаге симуляции)
function (c::Block)(t::Real, in1)
    c = update!(c, t, in1)
    return c.g .* in1
end

# Переопределенный метод update!
function update!(c::Block, t::Real, in1)
    if t == 5.0
        info("update triggered at t = $t")  # диагностическое сообщение
    end
    return c
end

因此,将在模型的诊断窗口中收到以下消息:

engee function continue 1

接下来,让我们仔细看看诊断功能本身。:

  • 警告 -功能 警告(msg::String) 显示警告消息。 模拟继续进行。 这对于指出需要注意但不会停止执行的非关键问题或条件非常有用。 例子::

    if t == 5.0 || t == 7.5
        warning("time == $t")
    end
  • 停止模拟 -功能 stop_simulation(msg::String) 立即结束模拟并显示完成消息。 它用于指示一个临界条件,在该条件下继续建模是不可能的或不希望的。 例子::

    if t == 5.0
        stop_simulation("time == $t")
    end
  • 暂停模拟 -功能 pause_simulation(msg::String) 暂停模拟并显示指定的暂停消息。 可以使用按钮手动恢复模拟 继续 :

    engee function continue

    此函数对于分析给定时间的模型状态非常有用。 例子::

    if t == 5.0
        pause_simulation("time == $t")
    end
  • 资料 -功能 信息(msg::字符串) 显示信息消息。 它用于在不影响仿真执行的情况下显示中间值。 例子::

    if t == 5.0 || t == 7.5
        info("time == $t")
    end

示例代码

该示例示出了块的简化实现。 Discrete-Time Integrator 基于Julia代码集成到模型中 AnyMath . 选择直接欧拉法作为积分法。 在标签上 Advanced 街区 Engee Function 设置值 Discrete 为参数 Sample time inheritance method . 接下来,填写源代码单元格,如下所示:

在牢房里 *Common code :

+

mutable struct Block{T} <: AbstractCausalComponent
    const dt::Float64
    state::T
    gain::Float64

    function Block()
        dt = OUTPUT_SIGNAL_ATTRIBUTES[1].sample_time.period
        state = initial_condition
        gain = k
        new{typeof(state)}(dt, state, gain)
    end
end

在牢房里 *Step method code :

+

    return c.state

在牢房里 *Update method code :

+

    c.state += in1 * c.dt * c.gain
    return c

因此,将获得以下源代码:

engee function example 1

参数 初始化_条件k 它们在块设置的*参数*选项卡上初始化 Engee Function :

engee function example 2

在模型仿真的第一步,块的内部状态为 c.国家 由参数值初始化 初始化_条件.

然后,在每个计算步骤,块返回内部状态。 c.国家 作为输出信号并重新计算其值的方法 更新!.

组件结构在单元格中重新定义 Common code ,而不是在 Component struct code ,因为需要更灵活的定义:结构必须是可变的,并且由与状态类型对应的类型*T*参数化。 标准定义在 Component struct code 仅适用于不可变和非参数化结构。

高级用法

Engee Function 允许您使用自己的代码设置组件的行为,而无需从现成的块组装它。 这使得可以手动控制输出信号的类型和尺寸,使用缓存来提高性能,禁用输入到输出的直接传输,并设置自己的数据更新周期。

所以,在发布的页面上 社区 AnyMath链接提供了块的高级用法的实际示例 Engee Function :

通过重新定义输出参数将输入数据转换为矢量; *使用缓存和强类型结构来提高性能; *没有直接传输的块的实现( *Direct feedthrough)用于打破代数循环; *设置输出信号的用户采样周期。