AnyMath 文档
Notebook

管道几何优化

在这个项目中,我们优化了管道几何的参数,以达到所需的流动参数。

让我们考虑一个简单的模型,其中在管道中发生T形分支,然后是两个弯曲的管道。 通过在从0到120度的范围内改变它们的弯曲角度,我们将通过系统的每个分支实现给定的成本差异。

模型描述

下载几个库:

In [ ]:
Pkg.add("Optim")
using DataFrames, CSV, Optim

让我们打开我们的模型。

In [ ]:
engee.open( "$(@__DIR__)/" * "pipe_circuit_optimization.engee");
image.png

当两个管道的弯曲相同时,每个管道具有相同的液体流速,等于入口流量的一半。

模型参数优化

让我们以一种相当简单的方式来解决这个问题:我们预先推出了一个模型,其中管道的弯曲等于30和60度。 我们将获得的值设置为目标优化标准(消耗150.6和136.6kg/s),并将每个管道的初始弯曲值设置为90度。

优化任务将需要定义自由变量("独立"变量,我们将逐渐改变其值)和因变量(具有目标值)。

自由变量是一些具有目标值和物理约束的块的一些内部属性。

In [ ]:
cd( @__DIR__ )
adj = CSV.read("adjustable_parameters.csv", DataFrame)
Out[0]:
2×6 DataFrame
Rowblocksparametersunitsx0lowerupper
StringString15String3Float64Float64Float64
1pipe_circuit_optimization/Изгиб трубы (ИЖ)bend_angledeg90.00.0120.0
2pipe_circuit_optimization/Изгиб трубы (ИЖ)-1bend_angledeg90.00.0120.0

因变量是某些信号在最后时刻的期望值。

In [ ]:
tgt = CSV.read("target_parameters.csv", DataFrame)
Out[0]:
2×2 DataFrame
Rownamesvalues
String7Float64
1Outlet1150.6
2Outlet2136.6

让我们开始优化过程,在此期间我们将搜索自由参数的值。 adj (可调节),允许您实现相关参数的所需值 tgt (目标)。

In [ ]:
using Optim

function f(x)
    # 我们将设置块参数(自由变量)的值
    for (i, (block, param, unit, _)) in enumerate(eachrow(adj))
        engee.set_param!( String(block), String(param) => Dict("value" => string(x[i]), "unit" => String(unit)) )
    end
    # 让我们使用新参数运行模型
    data = engee.run("pipe_circuit_optimization");
    # 我们将在最后时刻获取因变量的值
    out_vector = [data[String(name)].value[end] for name in tgt.names]
    # 我们来计算优化准则
    return sum((out_vector .- tgt.values) .^ 2)
end

# 边界条件优化器
inner_optimizer = GradientDescent()

# 优化过程的常规设置
options = Optim.Options(iterations = 4, outer_iterations = 4,
                        x_abstol = 5.0, outer_x_abstol = 5.0,
                        store_trace=true, trace_simplex=true, extended_trace=true )

# 启动优化
result = optimize(f, adj.lower, adj.upper, adj.x0, Fminbox(inner_optimizer), options)
Out[0]:
 * Status: success

 * Candidate solution
    Final objective value:     3.838696e-01

 * Found with
    Algorithm:     Fminbox with Gradient Descent

 * Convergence measures
    |x - x'|               = 3.83e+00 ≤ 5.0e+00
    |x - x'|/|x'|          = 6.26e-02 ≰ 0.0e+00
    |f(x) - f(x')|         = 2.61e+00 ≰ 0.0e+00
    |f(x) - f(x')|/|f(x')| = 6.80e+00 ≰ 0.0e+00
    |g(x)|                 = 6.09e+01 ≰ 1.0e-08

 * Work counters
    Seconds run:   189  (vs limit Inf)
    Iterations:    2
    f(x) calls:    10
    ∇f(x) calls:   10
    ∇f(x)ᵀv calls: 0
model_optimization.gif

最后,让我们确保寻找解决方案确实朝着正确的方向发展。:

In [ ]:
gr()
loss_value = getfield.( result.trace, :value )
xs = first.( trace_point.metadata["x"] for trace_point in Optim.trace(result) );
ys = last.( trace_point.metadata["x"] for trace_point in Optim.trace(result) );
plot(
    plot(loss_value, c=:Black, left_margin=10Plots.mm, bottom_margin=10Plots.mm, xlabel="迭代", ylabel="优化标准", title="优化进度图(标准)"),
    plot( xs, ys, c=:Black, markershape=:+, mc=:Red, bottom_margin=10Plots.mm, xlabel=adj.blocks[1], ylabel=adj.blocks[2], title="优化过程的轨迹" ),
    leg=false, size=(900,300), guidefont=font(6), titlefont=font(9)
)
Out[0]:
No description has been provided for this image

结论

我们已经研究了如何将模型包装在高级优化函数中,现在我们可以遍历变量进行优化并选择优化器。