Моделирование химико-технологической системы (ХТС)
Моделирование ХТС (часть 2: смесители и разделители потока)
В предыдущей части мы рассмотрели, как задаются многокомпонентные паро-жидкостные потоки.
В данном примере мы рассмотрим пару базовых компонентов для создания ХТС: это разделители потока и смесители.
Для начала нам необходимо подключить предыдущий документ, для того чтобы мы могли использовать определенные ранее функции:
engee.script.@include("/user/myHysys/part1.ngscript")
Разделители потока
Разделитель потока делит поток на две части. Обе части потока будут иметь такие же термодинамические свойства, что и исходный поток.
Для начала создадим функции, которые будут в дальнейшем часто использоваться. Свойства выходящих потоков будут такими же как и входящего, будет изменяться только расход. Поэтому сделаем функцию, которая будет клонировать материальный поток:
function material_stream_copy(s::MaterialStream)
return MaterialStream(s.N, s.T, s.p, s.x, s.y, s.Q, s.model)
end
Делим поток по долям
На вход функции подается материальный поток и какая доля этого потока будет выходить с первым потоком, остаток будет выходить со вторым потоком. Также для адекватного поведения была добавлена проверка, чтобы доля потока была в диапазоне от 0 до 1. На выходе функция вернет два материальных потока.
function splitter_dol(ms_in::MaterialStream, dol::Float64)
if dol >= 0 && dol <= 1
ms_out1 = material_stream_copy(ms_in)
ms_out1.N = ms_in.N * dol
ms_out2 = material_stream_copy(ms_in)
ms_out2.N = ms_in.N - ms_out1.N
return ms_out1, ms_out2
else
println("Доля должна быть в диапазоне от 0 до 1")
end
end
Пример применения зададим поток для системы из первого примера и разделим его пополам:
stream_a = mstream_TpA(12.0, 310.0, 5.0*10.0^5, [0.1, 0.9], sys) #создаем поток
splitter_dol(stream_a, 0.5)
Делим поток с заданным расходом
В случае если выходящий поток должен быть фиксированным, можно использовать следующую функцию. В ней также осуществляется проверка, чтоб выходящий поток не должен превышать входящий:
function splitter_N(ms_in::MaterialStream, N1::Float64)
if 0 < N1 <= ms_in.N
ms_out1 = material_stream_copy(ms_in)
ms_out1.N = N1
ms_out2 = material_stream_copy(ms_in)
ms_out2.N = ms_in.N - ms_out1.N
return ms_out1, ms_out2
else
println("Расход выходящего потока должен быть меньше входящего расхода и больше нуля")
end
end
В качестве примера также разделим поток stream_a чтобы расход первого потока был 8.5 моль/с
splitter_N(stream_a, 8.5)
Делим поток на фазы
Достаточно часто в ХТС используется сепаратор - аппарат в котором исходная смесь разделяется по фазам. Для моделирования парожидкостного сепаратора нам необходимо разделять потоки по фазам:
function splitter_phase(ms_in::MaterialStream)
#паровая фаза
ms_out_v = material_stream_copy(ms_in)
ms_out_v.N = ms_in.N * ms_in.Q
ms_out_v.Q = 1.0
ms_out_v.x = zeros(Float64, length(ms_in.x))
#жидкая фаза
ms_out_l = material_stream_copy(ms_in)
ms_out_l.N = ms_in.N * (1.0 - ms_in.Q)
ms_out_l.Q = 0.0
ms_out_l.y = zeros(Float64, length(ms_in.y))
return ms_out1, ms_out2
end
Удельная энтальпия потока при разной температуре
В отличие от разветвителя, смесителем нельзя управлять и свойства выходящего потока будут зависеть только от свойств входящих потоков.
Температуры смешиваемых потоков могут быть разными и тут нам понадобится функция, вычисляющая энтальпию потока в зависимости от температуры. Данная функция также будет полезна в дальнейшем при описании теплообменных процессов.
Удельная энтальпия паровой и жидкой фазы существенно отличается. И при варьировании температуры требуется сначала определить фазовый состав исходной смеси с использованием функции [mstream_TpA](ссылка на первую часть). Удельная мольная энтальпия величина аддитивная, и в случае двухфазного потока складывается из суммы энтальпии паровой и жидкой фаз: .
:liquid или :vapor
В библиотеке Clapeyron не всегда алгоритмы правильно определяют фазовый состав. Корректно определяется для случая описания фазового равновесия через уравнения состояния. В случае использования коэффициентов активности лучше в явном виде задавать начальное приближение от которого будет отсчитываться состояние чистых веществ.
function mstream_H_T(s::MaterialStream, T)
A = @. s.Q * s.y + (1.0-s.Q) * s.x #расчет суммарной доли по фазам
ins = mstream_TpA(s.N, T, s.p, A, s.model) #температура заменена
if 0.0 < ins.Q < 1.0 #двухфазная система
hl = enthalpy(ins.model, ins.p, ins.T, ins.x, phase=:liquid)
hv = enthalpy(ins.model, ins.p, ins.T, ins.y, phase=:vapor)
return ins.Q * hv + (1.0-ins.Q) * hl
elseif ins.Q == 0.0
return enthalpy(ins.model, ins.p, ins.T, ins.x, phase=:liquid)
elseif ins.Q == 1.0
return enthalpy(ins.model, ins.p, ins.T, ins.y, phase=:vapor)
end
end
Смеситель потока
С точки зрения гидравлики поток не может идти из зоны пониженного давления в зону повышенного. Для статического моделирования это означает, что в смесителе давление на входящих и выходящем потоках должно быть одинаковым. В случае, если давление исходных потоков разное, то требуется воспользоваться блоком изменения давления (рассмотрим чуть позже).
При смешении двух потоков материальный баланс выглядит следующим образом:
где - мольный поток. В нашей модели мы учитываем, что потоки могут находится в разных фазах. Поэтому - суммарная доля компонентов в обеих возможных фазах:
В итоге доля компонента в выходящей смеси будет определяться выражением:
Тепловой баланс смесителя:
расписывая через удельную энтельпию:
откуда можно найти энтальпию выходящего потока, а через нее уже и температуру потока.
Можно использовать энтальпию
Одним из вариантов задания степени свободы (структуры со свойствами потока) является заменить температуру на энтельпию. В данном случае например не пришлось бы численно решать уравение для определения выходящей температуры.
function mixer(ms_in1::MaterialStream, ms_in2::MaterialStream)
if ms_in1.p == ms_in2.p
a1 = @. ms_in1.Q * ms_in1.y + (1.0-ms_in1.Q) * ms_in1.x #суммарны доли компонентов в фазах
a2 = @. ms_in2.Q * ms_in2.y + (1.0-ms_in2.Q) * ms_in2.x
aout = @. (a1 * ms_in1.N + a2 * ms_in2.N) / (ms_in1.N + ms_in2.N)
h_in1 = mstream_H_T(ms_in1, ms_in1.T) #энтельпия первого потока
h_in2 = mstream_H_T(ms_in2, ms_in2.T) #энтальпия второго потока
h_out = (ms_in1.N * h_in1 + ms_in2.N * h_in2)/(ms_in1.N + ms_in2.N) #удельная энтальпия выходящего потока
Tinit = (ms_in1.T * ms_in1.N + ms_in2.T * ms_in2.N) / (ms_in1.N + ms_in2.N) #начальное приближение для температуры
ms_out = mstream_TpA(ms_in1.N + ms_in2.N, ms_in1.T, ms_in1.p, aout, ms_in1.model) #определяется поток без заданной температуры
Troot = find_zero(T -> mstream_H_T(ms_out, T) - h_out, Tinit) #определяем конечную температуру
return mstream_TpA(ms_in1.N + ms_in2.N, Troot, ms_in1.p, aout, ms_in1.model) #подставляем найденное значение и определяем состояние выходящего потока
else
println("Давление входящих потоков должно быть одинаковым")
end
end
stream_a = mstream_TpA(6.0, 410.0, 5.0*10.0^5, [0.1, 0.9], sys) #создаем поток
stream_b = mstream_TpA(32.0, 320.0, 5.0*10.0^5, [0.5, 0.5], sys) #создаем поток
mixer(stream_b, stream_a)