Engee Function
Использование кода Julia в моделях.
Описание
Блок Engee Function позволяет использовать код на языке Julia в моделях Engee.
Подробнее про язык программирования Julia читайте на странице Программирование. |
В блоке Engee Function допустимо использовать большую часть возможностей языка Julia. При этом использование в блоке пакетного менеджера Pkg не предусматривается. |
Использование
Для интеграции кода на Julia в модель Engee необходимо:
-
Добавить в модель блок Engee Function из раздела Базовые/Пользовательские функции библиотеки блоков
;
-
В окне настроек
на вкладке Main блока Engee Function нажать на кнопку Редактировать исходный код для открытия редактора исходного кода (EngeeFunctionCode):
Ячейки исходного кода
Редактор исходного кода EngeeFunctionCode состоит из функциональных ячеек с кодом Julia. По умолчанию доступны три ячейки: вспомогательная (нередактируемая), Component struct code и Step method code (ячейки можно скрыть):
Для подключения дополнительных файлов исходного кода можно использовать функцию
|
Весь код блока Engee Function можно написать в ячейке Common code, получив полный контроль над структурой компонента, сигнатурами и количеством функций. |
Для добавления/удаления других функциональных ячеек нажмите на кнопку «Управление методами» и установите/уберите флажки на нужных ячейках:
→
Каждая ячейка отвечает за уникальный функционал блока Engee Function. Рассмотрим их подробнее:
-
Информационная ячейка (нередактируемая) — автоматически отображает переменные блока Engee Function, атрибуты входных и выходных сигналов (размерность, тип, дискретность) и другие параметры, заданные пользователем. Ее содержимое обновляется динамически в зависимости от настроек блока. Ячейка всегда активна, но не выбирается в меню управления методами
. Имеет полупрозрачный текст, которым отображаются подсказки.
Изменение параметров блока влияет не только на содержимое информационной ячейки, но и на подсказки в других ячейках, которые также отображаются полупрозрачным текстом. -
Define component struct — добавляет ячейку Component struct code, в которой задается структура компонента блока Engee Function (наследуемая от типа
AbstractCausalComponent
). Поля структуры определяются между нередактируемыми строкамиstruct Block <: AbstractCausalComponent
иend
. По умолчанию создается параметрg
, инициализируемый значением блокаgain
, а конструкторBlock()
не принимает аргументов.
-
Use common code — добавляет ячейку Common code, в которой пишется код в свободной форме. По умолчанию ячейка пуста. Например, если стандартное объявление структуры в Component struct code не подходит (из-за нередактируемости
struct Block <: AbstractCausalComponent
), то можно отключить Define component struct, чтобы удалить ячейку, и определить структуру компонента вручную в Common code. То же самое касается любых функций из меню управления методами— вместо стандартных ячеек можно писать свой код в Common code.
Объявление компонента и функтора обязательно для работы Engee Function. Если Define component struct и Define step method отключены, то их код необходимо задать в Common code, иначе блок не будет работать. Для переопределения функций наследования (Override, см. ниже) сначала нужно включить соответствующую ячейку, стереть ее содержимое, а затем написать новый код в Common code. -
Define step method — добавляет ячейку Step method code, в которой задается метод Step, вычисляющий выходные сигналы блока Engee Function. Сигнатура метода генерируется автоматически в зависимости от значений соответствующих меток (Label) портов во вкладке Ports. Метод представлен в виде функтора (подробнее см. здесь) и вызывается на каждом шаге симуляции. Поля определяются между нередактируемыми строками
function (c::Block)(t::Real, in1)
иend
. Первый аргументt::Real
— время симуляции, далее передаются переменные входных сигналов. Вычисленные значения выходов возвращаются через ключевое словоreturn
. -
Define update method — добавляет ячейку Update method code, в которой метод
update!
обновляет внутреннее состояние блока Engee Function на каждом шаге симуляции. Первый аргументc::Block
— структура блока, второйt::Real
— время симуляции, далее передаются входные сигналы. Если блок не имеет внутреннего состояния, то метод может оставаться пустым и просто возвращатьc
.Если требуется определить несколько методов update!
или задать метод с другой сигнатурой, то ячейку Update method code можно отключить и написать код в ячейке Common code. Компилятор автоматически определит наличие методаupdate!
и использует его для симуляции. -
Define terminate method code — добавляет ячейку Terminate method code, которая выполняется при завершении симуляции блока Engee Function (с помощью метода
terminate!
). Первый аргументc::Block
— структура блока. По умолчанию метод не выполняет дополнительных действий и просто возвращаетc
. -
Override type inheritance method — добавляет ячейку Types inheritance method, которая переопределяет метод наследования типов.
-
Override dimensions inheritance method — добавляет ячейку Dimensions inheritance method, которая переопределяет метод наследования размерностей.
-
Use common method for types and dimensions inheritance — добавляет ячейку Common types and dimensions inheritance method, которая использует общий метод для переопределения наследования типов и размерностей одновременно.
-
Override sample time inheritance method — добавляет ячейку Sample times inheritance method, которая переопределяет метод наследования шага расчета.
-
Override direct feedthrough setting method — добавляет ячейку Direct feedthrough setting method, которая определяет прямое сквозное соединение.
Константы и функции получения атрибутов
Для того чтобы узнать типы, размеры и другую вспомогательную информацию в исполняемом коде блока, используйте следующие константы внутри вашего кода Engee Function:
-
BLOCK_NAME
— имя блока. У каждого блока, добавленного на холст Engee, есть имя, по которому можно обратиться через эту константу. Например, можно обратиться к BLOCK_NAME во время инициализации ошибки, чтобы вывести в ней имя блока. -
START_TIME
— начало симуляции из настроек модели. -
END_TIME
— конец симуляции из настроек модели. -
INPUT_SIGNAL_ATTRIBUTES
— списки из атрибутов по каждому входному порту. Например, чтобы узнать атрибуты первого входного сигнала — используйтеINPUT_SIGNAL_ATTRIBUTES[1]
, где1
— первый входной порт блока Engee Function. -
OUTPUT_SIGNAL_ATTRIBUTES
— списки из атрибутов по каждому выходному порту. Например, чтобы узнать атрибуты первого выходного сигнала — используйтеOUTPUT_SIGNAL_ATTRIBUTES[1]
, где1
— первый выходной порт блока Engee Function.
Чтобы узнать дополнительную информацию конкретного порта блока, можно обратиться к атрибутам его сигнала, добавив точку . после константы INPUT_SIGNAL_ATTRIBUTES[i]
, где [i]
— номер входного порта, и OUTPUT_SIGNAL_ATTRIBUTES[i]
, где [i]
— номер выходного порта соответственно. Можно узнать дополнительную информацию через следующие функции обращения:
-
dimensions
— размерность сигнала. Можно сократить доdims
. -
type
— тип сигнала. Можно сократить доtp
. -
sample_time
— шаг расчета. Представляет собой структуру по аналогии с атрибутами сигналов, к которой можно обращаться через точку .. Доступны две функции обращения:-
period
— период шага расчета. Полная функция обращения —sample_time.period
. Можно сократить доst.p
. -
offset
— смещение шага расчета. Полная функция обращения —sample_time.offset
. Можно сократить доst.o
.
-
-
direct_feedthrough
— указывает, размыкает ли порт петли. Используется только для входных портов (проверяет атрибуты только для входного порта). Можно сократить доdf
.
Пример модели Engee Function со всеми константами и функциями обращения:
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
julia
Настройка параметров
В исходном коде блока Engee Function можно использовать include , ссылающийся на внешний код. Это позволяет инициализировать переменные из внешнего кода (при их наличии) в исходном коде.
|
Фактический тип данных, как и поддержка возможных типов данных, зависит от пользовательского кода внутри блока. |
Пример кода
В данном примере представлена упрощенная реализация блока Дискретный интегратор, основанная на интеграции кода Julia в модель Engee. В качестве метода интегрирования выбран прямой метод Эйлера. На вкладке 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
julia -
В ячейке Step method code:
return c.state
julia -
В ячейке Update method code:
c.state += in1 * c.dt * c.gain return c
julia
В итоге будет получен следующий исходный код:
Параметры initial_condition
и k
инициализируются во вкладке Parameters настроек блока Engee Function:
На первом шаге симуляции модели внутреннее состояние блока c.state
инициализируется значением параметра initial_condition
.
После чего на каждом шаге расчета блок возвращает внутреннее состояние c.state
в качестве выходного сигнала и пересчитывает его значение в методе update!
.
Структура компонента переопределяется в ячейке Common code, а не в Component struct code, так как требуется более гибкое определение: структура должна быть изменяемой (mutable) и параметризованной типом T, соответствующим типу состояния. Стандартное определение в Component struct code подходит только для неизменяемых (immutable) и непараметризованных структур. |
Аннотации
Аннотации в Engee Function позволяют отображать параметры блока прямо под его названием в модели. Для их добавления откройте окно настроек блока Engee Function и перейдите на вкладку Аннотация. Выберите нужные маркеры свойств блока и добавьте их в текстовый редактор.
На этой вкладке:
-
Слева отображается список доступных параметров (кроме скрытых).
-
Справа находится текстовый редактор, где можно задать аннотацию с маркерами в формате
%<ИмяПараметра>
. -
Перенос параметров возможен вручную, через автодополнение или с помощью кнопки
.
После выхода из редактора (например, при клике вне его) аннотация применяется: маркеры автоматически заменяются на фактические значения параметров, и итоговый текст отображается под названием блока (или над ним, если название размещено сверху).
Для удаления аннотаций необходимо удалить соответствующий маркер в редакторе.
Доступные маркеры
Маркер свойств автоматически заменяется на актуальное значение параметра. Доступны следующие маркеры:
-
Порты:
%<Inputs>
,%<Outputs>
— количество входных и выходных портов;%<InputPort1Type>
,%<OutputPort1Type>
,%<InputPort1Size>
,%<OutputPort1Size>
— тип данных и размерность сигналов. -
Временные характеристики:
%<SampleTime>
— дискретность;%<SampleTimeInheritanceMethod>
— метод наследования дискретности. -
Кодовые блоки:
%<ComponentStructCode>
,%<StepMethodCode>
— код структуры и метода шага. -
Параметры:
%<Parameters>
,%<Parameter1Name>
,%<Parameter1Value>
— названия и значения параметров. -
Флаги включения:
%<DefineComponentStruct>
,%<UseCommonCode>
,%<DefineStepMethod>
,%<DefineUpdateMethod>
,%<DefineTerminateMethod>
— включение соответствующих секций кода. -
Методы переопределения:
%<OverrideTypesInhMethod>
,%<OverrideDimsInhMethod>
,%<OverrideSampleTimeInhMethod>
— настройки наследования типов. -
Прочее:
%<UseExternalCache>
— использование внешнего кэша.