Применение программного управления моделью

Данный пример демонстрирует один из инструментов управления моделью - программное управление.

Программное управление позволяет создавать, запускать и сохранять модели, а также изменять их параметры в редакторе скриптов с помощью специальных команд.

cd( @__DIR__ ) # Переместимся в каталог, где лежит текущий скрипт
homePath = string(@__DIR__)
"/user/start/examples/base_simulation/command_control"

Создание и сохранение модели

# Для повторного запуска команды create
if "model" in [m.name for m in engee.get_all_models()]
    engee.close("model", force=true)
end
Model(
	name: newmodel_1
	id: 44f96846-5a38-40ef-bb8a-53aed569e391
)

Создание модели:

engee.create("model")
Model(
	name: model
	id: b1ef1997-a2a6-4c65-8f4d-8c251ab2e2c0
)

Просмотр имени открытой модели осуществляется функцией:

    engee.get_current_model()::Model
    engee.gcm()::Model
m = engee.gcm()
Model(
	name: model
	id: b1ef1997-a2a6-4c65-8f4d-8c251ab2e2c0
)

Сохранение модели с помощью функции save()

engee.save( "model", "$homePath/model.engee"; force=true )
Model(
	name: model
	id: b1ef1997-a2a6-4c65-8f4d-8c251ab2e2c0
)

Модель была сохранена по указанному пути:

image.png

Просмотр списка открытых моделей можно произвести с помощью функции get_all_models():

engee.get_all_models()
3-element Vector{Engee.Types.Model}:
 Model(
	name: model
	id: b1ef1997-a2a6-4c65-8f4d-8c251ab2e2c0
)

 Model(
	name: newmodel_1
	id: 44f96846-5a38-40ef-bb8a-53aed569e391
)

 Model(
	name: program_control_model
	id: b27bcfc6-48bb-4546-b400-dc7fa3e7c3ad
)

Загрузка модели и изменение параметров моделирования

image1.png

Если модель еще не открыта в редакторе, то мы загружаем модель с помощью функции load(). Если уже открыта, то нужно пользоваться функцией open(). Затем получаем параметры моделирования с помощью команды get_param():

if "program_control_model" in [m.name for m in engee.get_all_models()]
    m = engee.open( "program_control_model" ) # загрузка модели
else
    m = engee.load( "$homePath/program_control_model.engee" ) # если модель уже открыта, выполните эту строчку
end

m_param = engee.get_param( "program_control_model" ) # получение параметров моделирования
ModelParameters(
  :EnableMultiTasking => false
  :GenerateComments => true

  #Параметры интегратора:
  :StartTime => 0.0
  :StopTime => 10
  :SolverName => Tsit5
  :SolverType => variable-step
  :MaxStep => auto
  :MinStep => auto
  :InitialStep => auto
  :RelTol => auto
  :AbsTol => auto
  :OutputOption => true
  :OutputTimes => 1e-2
)

Параметры моделирования можно изменить с помощью функции set_param!():

engee.set_param!("program_control_model", "SolverName" => "Tsit5", "SolverType" => "variable-step") #= меняем постоянный шаг решателя
                                                                  на переменный и изменяем сам решатель =#
engee.get_param("program_control_model") # выводим параметры с внесёнными изменениями
ModelParameters(
  :EnableMultiTasking => false
  :GenerateComments => true

  #Параметры интегратора:
  :StartTime => 0.0
  :StopTime => 10
  :SolverName => Tsit5
  :SolverType => variable-step
  :MaxStep => auto
  :MinStep => auto
  :InitialStep => auto
  :RelTol => auto
  :AbsTol => auto
  :OutputOption => true
  :OutputTimes => 1e-2
)
engee.set_param!("program_control_model", "MinStep" => "auto", "MaxStep" => "auto") #= меняем постоянный шаг решателя
                                                                  на переменный и изменяем сам решатель =#
engee.get_param("program_control_model") # выводим параметры с внесёнными изменениями
ModelParameters(
  :EnableMultiTasking => false
  :GenerateComments => true

  #Параметры интегратора:
  :StartTime => 0.0
  :StopTime => 10
  :SolverName => Tsit5
  :SolverType => variable-step
  :MaxStep => auto
  :MinStep => auto
  :InitialStep => auto
  :RelTol => auto
  :AbsTol => auto
  :OutputOption => true
  :OutputTimes => 1e-2
)

Запуск симуляции

    run([m::Model]; verbose=false)

Запускает исполнение модели. Если модель не указана, запускает симуляцию текущей модели. Если модель не открыта, то бросается исключение NoModelOpenedException.

Аргументы:

  • verbose: выводить ли прогресс на печать, по умолчанию verbose=false.

  • m::Model: модель, относительно которой выполняется операция, по умолчанию текущая модель.

    Пример:

        engee> m = engee.load("start/examples/powersystems/models/power_line_apv.engee")
        engee> engee.run(m)
        Dict{String, DataFrame} with 6 entries:
           "Va" => 40001×2 DataFrame…
           "Ia" => 40001×2 DataFrame…
           "Ib" => 40001×2 DataFrame…
           "Ic" => 40001×2 DataFrame…
           "Vc" => 40001×2 DataFrame…
           "Vb" => 40001×2 DataFrame…

Запуск модели с выводом прогресса симуляции:

engee.run(m, verbose=true)
Building...
Progress 100%
Dict{String, DataFrames.DataFrame} with 3 entries:
  "Add.1"         => 1001×2 DataFrame…
  "Sine Wave-1.1" => 1001×2 DataFrame…
  "Sine Wave.1"   => 1001×2 DataFrame…

Просмотр результатов симуляции

Результаты симуляции можно получить с помощью функции get_results():

    engee.get_results(model_name::String)
    engee.get_results(model::Model)
    engee.get_results()

Возвращает результаты последней симуляции модели в виде словаря Dict{String, DataFrame}, где ключ - имя отслеживаемого порта.

Если модель не открыта, то выводится исключение NoModelOpenedException.

Если симуляция не запущена, то выводится исключение ModelIsNotRunningException.

Аргументы:

  • m::Model: модель, относительно которой выполняется операция, по-умолчанию, текущая модель.

    Пример:

        engee> m = engee.load("start/examples/powersystems/models/power_line_apv.engee")
        engee> results1 = engee.run(m);
        engee> results2 = engee.get_results(m)
        Dict{String, DataFrame} with 6 entries:
          "Va" => 40001×2 DataFrame…
          "Ia" => 40001×2 DataFrame…
          "Ib" => 40001×2 DataFrame…
          "Ic" => 40001×2 DataFrame…
          "Vc" => 40001×2 DataFrame…
          "Vb" => 40001×2 DataFrame…
        engee> results1 == results2
        true

Отображение результатов, полученных в ходе симуляции:

results = engee.get_results( "program_control_model" )
Dict{String, DataFrames.DataFrame} with 3 entries:
  "Add.1"         => 1001×2 DataFrame…
  "Sine Wave-1.1" => 1001×2 DataFrame…
  "Sine Wave.1"   => 1001×2 DataFrame…

Запись результатов моделирования в переменные и вывод итоговой таблицы с результатами:

sin1 = engee.get_results("program_control_model")["Sine Wave.1"]
sin2 = engee.get_results("program_control_model")["Sine Wave-1.1"]
sum_signal = engee.get_results("program_control_model")["Add.1"]
table = hcat(hcat(sin1, sin2[:,2], makeunique=true), sum_signal[:,2], makeunique=true) # используя сложение массивов по горизонтали (hcat()), составляем таблицу
first(table, 10) # выводим первые 10 значений получившейся таблицы
10×4 DataFrame
 Row │ time     value       x1        x1_1
     │ Float64  Float64     Float64   Float64
─────┼─────────────────────────────────────────
   1 │    0.0   0.0         0.841471  0.841471
   2 │    0.01  0.00999983  0.846832  0.856832
   3 │    0.02  0.0199987   0.852108  0.872107
   4 │    0.03  0.0299955   0.857299  0.887294
   5 │    0.04  0.0399893   0.862404  0.902394
   6 │    0.05  0.0499792   0.867423  0.917402
   7 │    0.06  0.059964    0.872355  0.932319
   8 │    0.07  0.0699428   0.877201  0.947143
   9 │    0.08  0.0799147   0.881958  0.961873
  10 │    0.09  0.0898785   0.886627  0.976505

Строим график изменения величин, полученных в результате симуляции:

using Plots
plot(table[:,1], table[:,2])
plot!(table[:,1], table[:,3])
plot!(table[:,1], table[:,4])

interactive-scripts/images/base_simulation_program_control_demo/cb847fef0830ef00695920dbe54d41f0d4e85ddd

Вывод

В данном примере было продемонстрировано применение программного управления моделью для запуска симуляции из скрипта.

В ходе выполнения кода, была создана и сохранена новая модель, загружена готовая модель, изменены параметры симуляции, а также, с помощью графической библиотеки, были выведены результаты моделирования и преобразованы в удобный вид.