Дуговая сталеплавильная печь
作者
using FFTW, JLD2
"""___________________________________________________________________________________
___________________________________________________________________________________"""
function get_sim_results(источник::String, example_path::String)
if occursin(".engee", источник)
name = filter(x->occursin(".engee", x), readdir(example_path))[1]
try
engee.close(split(name, '.')[1], force=true) # закрытие модели
catch err # в случае, если нет модели, которую нужно закрыть и engee.close() не выполняется, то будет выполнена её загрузка после catch
m = engee.load(joinpath(example_path, name)) # загрузка модели
end;
try
engee.run(m) # запуск модели
catch err # в случае, если модель не загружена и engee.run() не выполняется, то будут выполнены две нижние строки после catch
m = engee.load(joinpath(example_path, name)) # загрузка модели
engee.run(m) # запуск модели
end
else
name = filter(x->occursin(".jld2", x), readdir(example_path))[1]
return load(name)["simout"]
end
end
"""___________________________________________________________________________________
`get_sim_data(simout::SimulationResult, signal::String, pos::Int64, data::String)::Vector{Float64}`
Извлекает заданный параметр из `simout`
Параметры
- `signal`: имя записываемого сигнала
- `pos`: его местонахождение в векторе
- `data`: тип возвращаемых данных time или value
Возвращает вектор значений из `simout`
___________________________________________________________________________________"""
function get_sim_data(simout::SimulationResult, signal::String, pos::Int64, data::String)::Vector{Float64}
sim_data::Vector{Float64}=[]
if data=="value"
for i in collect(simout[signal]).value
push!(sim_data, i[pos])
end
return sim_data
elseif data=="time"
sim_data = collect(simout[signal]).time
return sim_data
else
println("Допустимые значения параметра data: value, time")
end
end
"""___________________________________________________________________________________
`analyze_harmonics(signal::Vector{Float64}, fs::Int, f0::Float64=50.0)`
Вычисляет амплитуды и фазы гармоник в сигнале.
Параметры:
- `signal`: входной сигнал (вектор напряжений)
- `fs`: частота дискретизации (в Гц)
- `f0`: базовая частота (по умолчанию 50 Гц)
Возвращает:
- `harmonics`: словарь с номером гармоники => (амплитуда, фаза)
___________________________________________________________________________________"""
function analyze_harmonics(signal::Vector{Float64}, fs::Int, f0::Float64=50.0)
N = length(signal)
# Вычисляем FFT и нормируем результат
fft_result = fft(signal)
fft_norm = fft_result / N
# Выделяем спектр для положительных частот
freq_range = (0:(N-1)) .* (fs / N)
mask = freq_range .<= fs/2
pos_freq = freq_range[mask]
pos_spectrum = fft_norm[mask]
# Находим максимально возможный номер гармоники
max_harm = floor(Int, fs/(2*f0))
harmonics = Dict{Int, Tuple{Float64, Float64}}()
for k in 1:max_harm
target_freq = k * f0
# Находим ближайшую частоту в спектре
idx = argmin(abs.(pos_freq .- target_freq))
freq_diff = abs(pos_freq[idx] - target_freq)
# Проверяем точность совпадения частот
if freq_diff > fs/(2N)
@warn "Гармоника $k*$(f0) Гц не точно соответствует сетке частот. Расхождение: $freq_diff Гц"
sleep(1)
end
# Извлекаем комплексную амплитуду
Z = pos_spectrum[idx]
# Корректируем амплитуду (кроме DC и Найквиста)
amplitude = k * f0 == fs/2 ? abs(Z) : 2abs(Z)
phase = angle(Z)
harmonics[k] = (amplitude, phase)
end
sorted = sort(collect(harmonics))
return sorted
end
"""___________________________________________________________________________________
`get_harmonics_data(results::Vector{Pair{Int64, Tuple{Float64, Float64}}})`
Извлекает номера гармоник, амплитуды и фазы из результатов гармонического анализа
Параметры:
- `results`: отсортированный словарь результатов гармонического анализа в функции `analyze_harmonics()`
Возвращает:
Кортеж векторов:
- `k`: номера гармоник
- `A`: амплитуды гармоник
- `ph`: фазы гармоник
___________________________________________________________________________________"""
function get_harmonics_data(results::Vector{Pair{Int64, Tuple{Float64, Float64}}})
A::Vector{Float64}=[]
ph::Vector{Float64}=[]
base_ph = results[1][2][2]
base_amp = results[1][1]
k = Vector(keys(results))
for (_, value) in results push!(ph,round(value[2]-base_ph)) end
for (_, value) in results push!(A,round(value[1])) end
return k, A, ph
end
"""___________________________________________________________________________________
`get_sequences(results, n)`
Извлекает последовательности из анализа гармоник
Параметры:
- `results`: отсортированный словарь результатов гармонического анализа в функции `analyze_harmonics()`
- `n`: номера гармоник
Возвращает:
Кортеж векторов:
- `harm`: вектор прямой последовательности - номера, амплитуды, фазы гармоник
- `harm2`: вектор обратной последовательности - номера, амплитуды, фазы гармоник
- `harm3`: вектор тройной последовательности - номера, амплитуды, фазы гармоник
___________________________________________________________________________________"""
function get_sequences(results, n)
n2 = filter(x -> x%2 == 0, n);
n = setdiff(n, n2);
n3 = filter(x -> x%3 == 0, n);
n = setdiff(n, n3);
v = map(x -> results[x][2], n);
A = map(x -> x[1], v); Ph = map(x -> x[2], v)
v2 = map(x -> results[x][2], n2);
A2 = map(x -> x[1], v2); Ph2 = map(x -> x[2], v2)
v3 = map(x -> results[x][2], n3);
A3 = map(x -> x[1], v3); Ph3 = map(x -> x[2], v3)
harm = [n, A, Ph]
harm2 = [n2, A2, Ph2]
harm3 = [n3, A3, Ph3]
return harm, harm2, harm3
end