Привожу обещанный модуль расчета остывания.
Принцип расчета
Практический результат
Скрипт
Вот функции, реализующие этот алгоритм:
Скрипт симуляции:
- Код: Выделить всё
------------------------------------------------------------
require "Assets/.../Util_Script.out"
require "Assets/.../[...]_telemetry_script.out"
------------------------------------------------------------
-- Setup
--
function Setup ()
prevST = 0
interval = 0 -- Время в секундах, прошедшее с прошлого прохода скрипта.
SetupTelemetry()
Timer ("0.2s", 0.2) -- запуск таймера с интервалом в 0.2 сек.
Call( "BeginUpdate" )
end
------------------------------------------------------------
-- Update
--
function Update (interval)
local simulationTime = Call( "*:GetSimulationTime")
if simulationTime - prevST < 0.001 then
return
end
prevST = simulationTime
--- Процессы с интервалом 0.2 секунды------------------------------------------------------------------------------
if Timer ("0.2s") then -- функция возвращает true по окончании выдержки
UpdateTelemetry(0.2) -- передача интервала в функцию.
Timer ("0.2s", 0.2) -- перезапуск таймера на новый отсчет
end
--------------------------------------------------------------------------------------------------------------------
-- Блок вызова тактируемых функций
if interval > 0.001 then
Timer (interval) -- тактирование таймера
end
end -- Update
-----------------------------------------------------------------------------------------------------------------------
Обработка системы охлаждения прописана в отдельном скрипте телеметрии.
Скрипт телеметрии:
- Код: Выделить всё
function SetupTelemetry()
--0 весна 1 лето 2 осень 3 зима
Season = SysCall("ScenarioManager:GetSeason")
OilTemp = 60 -- стартовое значение температуры масла
WaterTemp = 60 -- стартовое значение температуры воды
HeatLossOil = 0 -- потери тепла масла за минуту
HeatLossWater = 0 -- потери тепла воды заминуту
DailyDataTemperature = { -- таблица почасовой температуры воздуха для 4 сезонов
[0] = { 15, 12, 14, 13, 13, 12, 11, 11, 12, 11, 11, 14, 16, 16, 14, 13, 14, 13, 14, 14, 13, 13, 12, 14},-- апрель
[1] = { 25, 25, 24, 22, 20, 19, 19, 23, 24, 26, 27, 28, 29, 30, 31, 31, 31, 31, 30, 29, 28, 26, 25, 24},-- июль
[2] = { 5, 4, 3, 3, 3, 2, 2, 3, 4, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5},-- октябрь
[3] = {-12,-10, -9, -8, -8, -9, -9,-10, -8, -7, -7, -6, -4, -2, -1, -3, -4, -6, -6, -7, -8, -9,-10,-11}}-- январь
Timer ("TimeOfDay", 3600) -- Почасовой перерасчет таблицы теплопотерь
Timer ("HeatLoss", 0.1) -- Перерасчет теплопотерь. Первый расчет сразу после старта -0.1 сек на переходные процессы
Timer ("UpdateTemperatupe", 0.5)-- Обновление показаний приборов.
CreationDynamicsCooling () -- Первое построение таблицы теплопотерь
end
function UpdateTelemetry(time)
--------------------------------------------------------------------------------------------------------------------
if Timer ("HeatLoss") then
local key = "none"
local difference, prev_difference = 120, 120
for k, v in pairs(TabDiffTempOil) do -- перебор таблицы теплопотерь масла
difference = math.min(difference, math.abs(k - OilTemp)) -- выбор меньшего значения разности текущей температуры и табличного значения
key = difference ~= prev_difference and k or key -- если есть обновление разности, запоминаем эту ячейку
prev_difference = difference
end -- в результате перебора таблицы в переменной key будет значение ячейки, температура которой максимально близка к текущему значению
HeatLossOil = TabDiffTempOil[key] -- считываем значение теплопотери из этой ячейки
key = "none" -- подготовка переменных для аналогичного перебора таблицы теплопотерь воды
difference, prev_difference = 120, 120
for k, v in pairs(TabDiffTempWater) do
difference = math.min(difference, math.abs(k - WaterTemp))
key = difference ~= prev_difference and k or key
prev_difference = difference
end
HeatLossWater = TabDiffTempWater[key]
Timer ("HeatLoss", 121 - WaterTemp) -- чем выше температура воды, тем чаще будет происходить перерасчет значения теплопотерь
end
if Timer ("UpdateTemperatupe") then
local warming_oil = 0 -- здесь должен быть расчет нагрева масла
OilTemp = OilTemp + warming_oil - HeatLossOil/4 -- так как итерация происходит 4 раза в минуту, делим на 4
local warming_water = 0 -- здесь должен быть расчет нагрева воды
WaterTemp = WaterTemp + warming_water - HeatLossWater/4 -- так как итерация происходит 4 раза в минуту, делим на 4
Call("*:SetControlValue", "ndl_toil1", 0, OilTemp)
Call("*:SetControlValue", "ndl_twater1", 0, WaterTemp)
Timer ("UpdateTemperatupe", 15) -- новая итерация будет через 15 секунд
end
if Timer ("TimeOfDay") then -- Если прошло 3600 секунд
CreationDynamicsCooling () -- Перерасчет таблицы теплопотерь
Timer ("TimeOfDay", 3600) -- Заводим таймер на новый отсчет
end
--------------------------------------------------------------------------------------------------------------------
end
function CreationDynamicsCooling ()
-- Расчет константы теплопотерь
local TimeOfDay = math.floor(SysCall("ScenarioManager:GetTimeOfDay")/3600) + 1 -- загрузка текущего количества часов (1...24)
AmbientTemp = DailyDataTemperature[Season][TimeOfDay] -- считывание температуры окружающей среды с учетом времени и сезона
local pTempWater = 122.9790137 -- опорные значения температуры воды - начальное
local TempWater = 119.5272072 -- и через минуту. Разница используется для расчета таблицы теплопотерь воды
local pTempOil = 122.5489382 -- опорные значения температуры масла - начальное
local TempOil = 119.6926089 -- и через минуту. Разница используется для расчета таблицы теплопотерь масла
TabDiffTempWater = {} -- таблица теплопотерь воды
TabDiffTempOil = {} -- таблица теплопотерь масла
-- таблицы будут построены в диапазоне от опорной температуры до температуры окружающей среды + поправка (1 градус)
-- чем больше поправка, тем короче таблица.
-- Если температура воды/масла опустится ниже минимального предела таблицы, значение теплопотери перестанет обновляться
while TempOil > AmbientTemp + 1 do
pTempOil, TempOil = TempOil, AmbientTemp + (TempOil - AmbientTemp)^2/(pTempOil - AmbientTemp)
TabDiffTempOil[pTempOil] = pTempOil - TempOil
end
while TempWater > AmbientTemp + 1 do
pTempWater, TempWater = TempWater, AmbientTemp + (TempWater - AmbientTemp)^2/(pTempWater - AmbientTemp)
TabDiffTempWater[pTempWater] = pTempWater - TempWater
end
end
-----------------------------------------------------------------------------------------------------------------------
В скрипте использована функция Timer, описанная мной ранее.
Описание достаточно сжатое, так как мне проще ответить на конкретные вопросы, если они у кого-нибудь возникнут, чем пытаться построчно объяснить весь процесс