SolorControl — 导热油单相流动管道建模教学文档

1. 文档定位

本文件面向 Modelica 教学,聚焦 SolorControl 库中 Pipe 子包里的 DynamicOnePhaseFlowPipe_Oil 管道模型及其测试案例 Test1,涵盖:

  • 管道模型的物理假设与数学方程
  • 自定义导热油物性介质(Therminol VP1)的构建与调用
  • 专用边界组件(入口质量流源 / 出口压力汇)的设计
  • 测试案例搭建与仿真分析方法
  • 可扩展方向与教学建议

前置文档 教学文档.md 已覆盖太阳能跟踪系统整体架构(集热器光学、控制器、Plant 封装等),本文档是其 Pipe 侧的有力补充,对应库目录 Pipe/Boundary/Media/DemoTest/Test1.mo


2. 库结构一览

SolorControl/
├── Media/                          # 导热油物性介质
│   ├── Interfaces/
│   │   └── PartialOilMedium.mo     # 介质接口(6 个偏函数签名)
│   └── Oil_TherminolVP1/           # Therminol VP1 实现
│       ├── TherminolVP1_Data.mo    # 介质数据记录(温度范围、参考状态)
│       ├── Enthalpy_T.mo           # h = f(T),4 次多项式,含反函数 T = f(h)
│       ├── Temperature_h.mo        # T = f(h),4 次多项式
│       ├── Density_T.mo            # ρ = f(T),4 次多项式
│       ├── SpecificHeatCp_T.mo     # cp = f(T),4 次多项式
│       ├── DynamicViscosity_T.mo   # μ = f(T),含 T⁻¹/T⁻² 项的多项式
│       └── ThermalConductivity_T.mo# k = f(T),4 次多项式
├── Boundary/                       # 专用流体边界
│   ├── OilMassFlowSource_h.mo      # 定质量流量 + 定入口温度(焓)
│   └── OilPressureSink_h.mo        # 定出口压力 + 反向流动参考温度
├── Pipe/                           # 管道模型
│   └── DynamicOnePhaseFlowPipe_Oil.mo  # ★ 本文档核心
├── DemoTest/
│   └── Test1.mo                    # ★ 管道模型的测试案例
├── Plants/                         # 集热器、机械等(由教学文档.md 覆盖)
├── Control/                        # 跟踪控制器
├── ThreeDDemo/                     # 三维可视化
└── FUNTIONS/                       # 辅助函数

3. 介质层:Therminol VP1 导热油物性

3.1 设计理念

Modelica 流体库(Modelica.Fluid)要求每个流体组件声明一个 Medium 包,用于提供密度、焓、黏度等物性。标准做法是:

  1. 定义接口PartialOilMedium):声明 6 个偏函数签名,约束所有"导热油介质"必须实现这些函数
  2. 实现介质Oil_TherminolVP1):继承接口,用多项式拟合厂家数据表,提供具体计算

3.2 接口定义:PartialOilMedium

partial package PartialOilMedium
  partial function Enthalpy_T "比焓关于温度的函数接口"
    input  Temperature temp;  output SpecificEnthalpy h;
  end Enthalpy_T;
  partial function Temperature_h "温度关于比焓的函数接口"
    input  SpecificEnthalpy h;  output Temperature temp;
  end Temperature_h;
  partial function Density_T ...
  partial function SpecificHeatCp_T ...
  partial function DynamicViscosity_T ...
  partial function ThermalConductivity_T ...
end PartialOilMedium;

教学要点

  • partial 关键字表示这些函数只有声明没有实现体,相当于 C++ 的虚函数
  • input/output 类型均使用 Modelica.SIunits 量纲(TemperatureSpecificEnthalpy 等),自带量纲检查
  • Enthalpy_TTemperature_h 互为反函数,Modelica 可利用 inverse annotation 自动求逆

3.3 Therminol VP1 物性实现

Enthalpy_T 为例:

function Enthalpy_T
  input  Temperature temp;
  output SpecificEnthalpy h;
protected
  constant Real c0 = -293286.37;
  constant Real c1 = 431.97;
  constant Real c2 = 2.498;
  constant Real c3 = -0.001703;
  constant Real c4 = 9.291e-7;
algorithm
  h := c0 + c1*temp + c2*temp^2 + c3*temp^3 + c4*temp^4;
  annotation(derivative = Enthalpy_derT, inverse(temp = Temperature_h(h)));
end Enthalpy_T;

教学要点

特性 说明
algorithm 使用顺序赋值(非 equation),适合多项式计算
derivative annotation 提供解析导数函数,加速 Newton 求解
inverse annotation 声明反函数,解析求解 T(h) 而非数值迭代
常数用 protected 外部不可见,避免命名污染
多项式阶数 4 阶足够拟合厂家数据的非线性

其他物性函数结构相同,参数来自制造商数据表拟合:

物性 函数名 温度 560K 典型值 量纲
密度 Density_T ~870 kg/m³ kg/m³
比热容 SpecificHeatCp_T ~2290 J/(kg·K) J/(kg·K)
动力黏度 DynamicViscosity_T ~3.1×10⁻⁴ Pa·s Pa·s
导热系数 ThermalConductivity_T ~0.11 W/(m·K) W/(m·K)
比焓 Enthalpy_T ~5.64×10⁵ J/kg J/kg

黏度公式的特殊性DynamicViscosity_T 使用了 T⁻¹、T⁻² 负幂次项,因为液体黏度随温度升高呈指数衰减,纯多项式拟合效果差。这是工业介质物性建模的常见技巧。

3.4 TherminolVP1_Data 记录

record TherminolVP1_Data
  String mediumName = "TherminolVP1";
  Temperature maximum_temperature = 405 + 273.15;  // 678 K
  Temperature minimum_temperature = 15 + 273.15;   // 288 K
  // 参考状态、默认初始化值 ...
end TherminolVP1_Data;

作用:集中存储介质标识、温度上下限、参考压力和默认初始化值,供管道和边界组件统一引用。

3.5 介质在组件中的声明方式

管道模型中通过双 replaceable package 声明两种介质角色:

replaceable package Medium =
  Modelica.Media.Interfaces.PartialMedium          // ① 流体端口类型声明
  annotation(choicesAllMatching = true);
replaceable package OilMedium =
  Media.Oil_TherminolVP1
  constrainedby SolorControl.Media.Interfaces.PartialOilMedium  // ② 物性计算函数包
  annotation(choicesAllMatching = true);
角色 包名 用途
Medium Modelica.Media.Interfaces.PartialMedium 继承标准流体端口(FluidPort_a/b),端口内声明介质类型,匹配 Modelica.Fluid 连接规范
OilMedium SolorControl.Media.Interfaces.PartialOilMedium 提供 h(T)T(h)ρ(T)cp(T)μ(T)k(T) 等物性计算函数

可扩展性:如需换用其他导热油(如 Therminol 66、Dowtherm A),只需:

  1. 仿照 Oil_TherminolVP1 结构创建新的介质包
  2. 实现 PartialOilMedium 的 6 个函数
  3. 在管道/边界中通过 redeclare package OilMedium = MyNewOil; 切换

4. 边界组件

4.1 OilMassFlowSource_h:定质量流量入口

model OilMassFlowSource_h
  replaceable package Medium = Modelica.Media.Interfaces.PartialMedium;
  replaceable package OilMedium = Media.Oil_TherminolVP1
    constrainedby SolorControl.Media.Interfaces.PartialOilMedium;

  parameter MassFlowRate m_flow0 = 1;       // 质量流量,kg/s
  parameter Temperature  T_in    = 560;      // 入口温度,K
  parameter SpecificEnthalpy h_in = OilMedium.Enthalpy_T(temp=T_in);  // 自动换算焓

equation
  port.m_flow   = -m_flow0;   // 约定:源的 outflow = 管道的 inflow
  port.h_outflow = h_in;
end OilMassFlowSource_h;

关键约定

  • port.m_flow = -m_flow0:Modelica Fluid 规定 port.m_flow > 0 表示流入组件。对入口源而言,流体从源流出进入管道,所以源端口的 m_flow 应为负值
  • port.h_outflow:声明"如果流体从本组件流出,携带的焓值是多少"。正向流动时,这个焓进入管道

4.2 OilPressureSink_h:定出口压力汇

model OilPressureSink_h
  parameter Pressure   p0        = 1e5;      // 出口背压,Pa
  parameter Temperature T_reverse = 560;      // 反流参考温度,K

equation
  port.p = p0;
  port.h_outflow = OilMedium.Enthalpy_T(temp=T_reverse);
end OilPressureSink_h;

关键约定

  • port.p = p0:只固定压力,不固定流量(流量由上游源 + 管道阻力共同决定)
  • T_reverse:反向流动时的参考温度(如泵停转后下游高温油回流)

4.3 为什么自己写边界而不是用 Modelica 标准库?

自定义 标准库 Boundary_pT / Boundary_m_flow
直接调用 OilMedium 物性函数 依赖 Medium 标准接口(需实现全套 PartialMedium)
参数少、语义明确 参数繁多、通用但冗余
学生容易理解 初学者易迷失
便于逐步扩展 耦合深、改动大

5. 核心组件:DynamicOnePhaseFlowPipe_Oil

5.1 模型定位

这是一个一维、有限体积、单相、动态焓 + 准稳态质量/动量的管道模型,专为槽式太阳能集热器吸热管设计。它通过热端口数组 heatPorts[Ns] 接收来自集热器光学模型(SolarCollector)分段计算出的壁面热流,计算导热油沿管长的温度演变。

5.2 参数一览

参数 默认值 含义
L 10 m 管道长度
D 0.2 m 管道内径
rugosrel 0.0007 相对粗糙度(摩擦系数用)
ntubes 1 并联管道数
z1, z2 0, 0 入口/出口高度(重力压降)
Ns 10 热节点分段数(水力节点数 = Ns+1)
steady_state true true=从稳态初值启动;false=按指定 T0/h0 初始化
option_temperature 1 1=按初始温度;2=按初始焓
T0[Ns] fill(290, Ns) 流体初始温度(每段)
advection false 是否启用对流加速压降项
continuous_flow_reversal true 是否连续处理流向反转
dpfCorr 1.0 摩擦压降修正系数
hcCorr 1.0 换热系数修正系数

5.3 离散方案

管道总长 L,分段数 Ns
  ├── 热节点:N = Ns + 1 个边界点(含端点)
  │   每个热节点长度 dx1 = L / (Ns-1)
  │   位置:i = 1, 2, ..., Ns(center-aligned)
  │   方程:能量守恒(动态焓)、质量守恒(准稳态)
  │
  └── 水力节点:N 个(等于 Ns+1)
      每个水力节点长度 dx2 = L / N
      位置:i = 1, 2, ..., N(staggered grid)
      方程:动量守恒(准稳态压降)

交错网格(staggered grid):热节点和水力节点在空间上错开,类似于 CFD 中的 MAC 网格,避免压力-速度解耦。

5.4 端口定义

// 流体端口 — 使用 Modelica.Fluid 标准接口
Modelica.Fluid.Interfaces.FluidPort_a port_a;
Modelica.Fluid.Interfaces.FluidPort_b port_b;

// 热端口数组 — 每段与集热器对应分段热端口连接
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPorts[Ns];

heatPorts[i] 提供两个变量:

  • heatPorts[i].T:管壁温度 Tp[i](由 SolarCollector 计算)
  • heatPorts[i].Q_flow:壁面→油的热流 dW1[i]

5.5 初始化策略

initial equation
  if steady_state then
    for i in 2:N loop
      der(h[i]) = 0;           // 强制所有内部节点焓值导数为零
    end for;
  else
    if (option_temperature == 1) then
      for i in 2:N loop
        h[i] = OilMedium.Enthalpy_T(temp = T0[i-1]);  // 由 T0 反算初始焓
      end for;
    elseif (option_temperature == 2) then
      for i in 2:N loop
        h[i] = h0[i-1];                                // 直接指定初始焓
      end for;
    end if;
  end if;
模式 steady_state option_temperature 效果
稳态启动 true 忽略 der(h)=0,从定常解开始
瞬态启动-温度给定 false 1 每段按 T0[i] 初始化焓
瞬态启动-焓值给定 false 2 每段按 h0[i] 初始化焓

教学建议:先用 steady_state=true 获得稳态结果,再切换 false 观察动态响应。

5.6 核心方程详解

(a) 端口压力映射

P[1]     = port_a.p;      // 第一边界点 = 入口压力
P[N+1]   = port_b.p;      // 最后边界点 = 出口压力

(b) 质量流量映射(注意符号)

Q[1] = port_a.m_flow;     // Modelica 约定:m_flow>0 为流入组件
Q[N] = -port_b.m_flow;    // 出口流出→管道内部为正值,所以取反

(c) 焓值回流定义

port_a.h_outflow = h[2];           // 从入口反向流出的液体携带节点 2 的焓
port_b.h_outflow = h[N];           // 从出口正向流出的液体携带节点 N 的焓
h[1]   = inStream(port_a.h_outflow);  // 上游流入焓(来自入口源)
h[N+1] = inStream(port_b.h_outflow);  // 下游反流焓(来自出口压力汇)

inStream() 是 Modelica 流变量语义的核心函数,用于从连接网络获取"对面组件提供的值"。

(d) 热节点 — 能量守恒(★ 最重要)

for i in 1:N-1 loop
  // 质量守恒:准稳态形式 — 各节点质量流量相等(无质量积累)
  0 = Q[i] - Q[i+1];

  // 能量守恒:流体储能变化 = 入口焓流 - 出口焓流 + 壁面传热功率
  A * rho1[i] * der(h[i+1]) * dx1 = hb[i] * Q[i] - hb[i+1] * Q[i+1] + dW1[i];

  // 壁面→油的对流换热:牛顿冷却公式
  dW1[i] = hc[i] * dSi * (Tp[i] - T1[i]);
end for;

逐项解读

含义 量纲分析
A * rho1[i] * dx1 热节点内流体质量 m² × kg/m³ × m = kg
der(h[i+1]) 比焓变化率 J/(kg·s)
左端整体 热节点流体储能变化功率 kg × J/(kg·s) = W
hb[i] * Q[i] 流入焓功率 J/kg × kg/s = W
hb[i+1] * Q[i+1] 流出焓功率 J/kg × kg/s = W
dW1[i] 壁面传热功率 W

(e) 物性查表 — 温度、密度、比热、黏度、导热系数

T1[i]  = OilMedium.Temperature_h(h = h[i+1]);        // 焓→温度
rho1[i]= OilMedium.Density_T(temp = T1[i]);           // 温度→密度
cp[i]  = OilMedium.SpecificHeatCp_T(temp = T1[i]);    // 温度→比热
mu1[i] = OilMedium.DynamicViscosity_T(temp = T1[i]);  // 温度→黏度
k[i]   = OilMedium.ThermalConductivity_T(temp = T1[i]);//温度→导热系数

(f) 管内对流换热系数

if noEvent(Re1[i] > 2000) then
  // 湍流:Dittus-Boelter 关联式,适用于管内充分发展湍流(加热)
  hc[i] = hcCorr * 0.023 * k[i] / D * Re1[i]^0.8 * Pr[i]^0.4;
else
  // 层流:充分发展层流 Nu = 3.66(等壁温边界理论解)
  hc[i] = hcCorr * 3.66 * k[i] / D;
end if;

noEvent() 的作用:告知编译器此条件不产生事件,允许平滑过渡,避免仿真卡在 Re≈2000 处反复触发事件。

(g) 水力节点 — 动量平衡

P[i] - P[i+1] - dpf[i] - dpg[i] - dpa[i] = 0;

三项压降:

含义 公式
dpf 摩擦压降 `dpfCorr * λ * dx2/D * Q
dpg 重力压降 ρ * g * (z2-z1) * dx2/L
dpa 对流加速压降 `Q

摩擦系数 λ 使用 Shacham 显式公式(Colebrook 方程的显式近似,无需迭代):

lambda[i] = 0.25 / (log10(13/Re2[i] + rugosrel/3.7/D))^2;

(h) 流向反转处理

if continuous_flow_reversal then
  0 = if (Q[i] > Qeps) then hb[i] - h[i]
      else if (Q[i] < -Qeps) then hb[i] - h[i+1]
      else hb[i] - 0.5*((h[i]-h[i+1])*sin(π*Q[i]/2/Qeps) + h[i+1] + h[i]);
end if;

当流量接近零时,使用 sin() 函数在上下游焓之间做平滑插值,避免数值突变。流量远大于 Qeps (默认 0.001) 时,直接用上游焓值。

5.7 输出变量

W1t  = sum(dW1);     // 总换热功率(所有热节点之和),W
Stot = dSi * Ns;     // 管道总内表面换热面积,m²

6. 测试案例:Test1

6.1 模型结构

OilMassFlowSource_h                  FixedTemperature[10]
  (m_flow=1, T=560K)                 (each T=650K)
        │                                  │
        ▼                                  ▼ (×10)
    port_a ─────────── pipe ────────── port_b
                 DynamicOnePhaseFlowPipe_Oil
                 (Ns=10, steady_state=false,
                  T0=fill(560,10))           │
                                             ▼
                                     OilPressureSink_h
                                     (p=1e5, T_reverse=560K)

6.2 组件参数

组件 关键参数 含义
oilMassFlowSource_h 默认 m_flow0=1, T_in=560K 560K (287°C) 的导热油以 1 kg/s 流入
pipe Ns=10, steady_state=false, T0=fill(560,10) 10 段离散,从均匀 560K 瞬态启动
wallTemperature[10] each T=650K 每段管壁固定 650K (377°C) — 模拟集热器加热
oilPressureSink_h p0=1e5, T_reverse=560K 出口 1 bar 背压

6.3 监控变量

Real pipeHeatingPower  = pipe.W1t;                    // 总吸热功率
Real pipeInletTemp     = pipe.T1[1];                   // 第一段油温
Real pipeOutletTemp    = pipe.T1[pipe.Ns];             // 最后一段油温
Real pipeTempRise      = pipe.T1[Ns] - pipe.T1[1];    // 温升
Real pipeFirstHeatFlow = pipe.dW1[1];                  // 第一段换热功率
Real pipeLastHeatFlow  = pipe.dW1[pipe.Ns];            // 最后一段换热功率
Real pipeInletMassFlow = pipe.Q[1];                    // 入口质量流量
Real pipeOutletMassFlow= pipe.Q[pipe.Ns + 1];          // 出口质量流量

6.4 连接关系

connect(oilMassFlowSource_h.port, pipe.port_a);
connect(pipe.port_b, oilPressureSink_h.port);
for i in 1:pipe.Ns loop
  connect(wallTemperature[i].port, pipe.heatPorts[i]);
end for;

6.5 仿真设置

参数 说明
StopTime 200 s 观察瞬态到稳态的全过程
Interval 0.5 s 输出步长,适合教学观察
Tolerance 1e-6 标准容差

6.6 预期物理行为

  1. t = 0:管道内油温均匀 560K,壁温 650K
  2. 0 ~ ~50s:650K 壁面向 560K 油传热,管道出口温度从 560K 快速上升
  3. ~50 ~ 200s:系统趋于新稳态,出口温度接近 650K,但受流量和换热系数限制略低

教学观察:

  • 出口温度应始终 ≤ 壁温 650K(热力学第二定律)
  • 前几段温升大(温差大),后几段温升小(温差渐小)
  • 总功率 W1t 随时间递减,趋近稳态值

7. 可扩展方向

7.1 介质替换

只需创建新的介质包(如 Oil_DowthermA),实现 PartialOilMedium 的 6 个函数,然后在管道/边界中:

redeclare package OilMedium = SolorControl.Media.Oil_DowthermA;

7.2 耦合集热器

pipe.heatPorts[i] 设计为直接连接 SolarCollector.ITemperature[i]

for i in 1:Ns loop
  connect(solarCollector.ITemperature[i], pipe.heatPorts[i]);
end for;

此时壁温不再是固定值,而是由集热器根据辐照度和入射角动态计算,构成完整的光-热-流耦合系统

7.3 增加管道壁热容

当前 Tp[i] = heatPorts[i].T 直接使用端口温度(壁温由外界给定)。增加壁热容需要:

parameter HeatCapacity C_wall;  // 管壁热容,J/K
equation
C_wall * der(Tp[i]) = heatPorts[i].Q_flow - dW1[i];  // 壁热容动态方程

7.4 启用动态动量和质量方程

模型中已预留被注释掉的代码块:

// parameter Boolean dynamic_mass_balance=true;
//   A*(ddph*der(P) + ddhp*der(h))*dx = Q[i] - Q[i+1];
// parameter Boolean inertia=true;
//   1/A*der(Q[i])*dx = P[i] - P[i+1] - dpf - dpg - dpa;

取消注释并设为 true 后,模型在全动态模式下运行,可模拟水锤、压力波传播等快速瞬态。

7.5 多路并联

修改参数 ntubes > 1,模型按并联管道等效处理(面积、直径自动乘以 ntubes),适合模拟实际集热器阵列中的多管并联。

7.6 自定义换热关联式

当前换热系数写死在模型内(Dittus-Boelter / Nu=3.66)。可通过 replaceable model 将换热模型参数化:

replaceable model HeatTransfer =
  SolorControl.Pipe.Basic.HT_DittusBoelter
  constrainedby SolorControl.Pipe.Basic.Interfaces.PartialHT;

学生可内置 Gnielinski(过渡区更准)、Sieder-Tate(含黏度修正)等关联式。


8. 教学建议

课时安排(建议 2 学时)

环节 时间 内容
第一学时
导入 10 min 槽式太阳能集热器原理、为何需要管道模型
介质讲解 20 min PartialOilMedium 接口设计、多项式拟合、replaceable package
边界讲解 15 min OilMassFlowSource_hOilPressureSink_h 的 Modelica Fluid 符号约定
第二学时
管道核心 30 min 能量守恒、动量守恒、交错网格、换热系数、流向反转
测试案例 15 min Test1 搭建、仿真、变量观察
扩展讨论 10 min 介质替换、耦合集热器、动态动量、换热关联式

课堂提问示例

  1. 为什么 port.m_flow = -m_flow0 要加负号?
  2. dW1[i] = hc[i] * dSi * (Tp[i] - T1[i]) 中,温差的正负号各代表什么物理含义?
  3. 如果 wallHeatTransfer 设错了会观察到什么?为什么 Test1 不需要设这个参数?
  4. steady_state=truefalse 的仿真结果有什么不同?何时该用哪个?

9. 与教学文档.md 的关系

教学文档.md 本文档
覆盖 Plants(集热器光学 + 机械) 覆盖 Pipe(管内流动 + 换热)
覆盖 Control(PID 跟踪) 覆盖 Boundary(流体边界)
覆盖 DemoTest/Test.mo(全系统) 覆盖 DemoTest/Test1.mo(管道单测)
重点是集热器的光学效率 + 热损失 重点是管道的对流换热 + 压降 + 瞬态焓

两者配合使用,构成完整的 "太阳辐照 → 集热器壁温 → 管道换热 → 导热油升温" 教学链条。

版本说明

V0.0.1,2026-05-15 01:43

  • 初始版本

使用许可

本模型库版权由MoHub版权所有,未经许可,不得用于商业用途。