PRECICE 工具介绍与使用示例
PRECICE 简介
PRECICE (Precise Code Interaction Coupling Environment) 是一个开源的耦合库,用于实现多物理场仿真中不同求解器之间的协同仿真。它允许不同的仿真软件(如计算流体力学(CFD)和结构力学(CSM)工具)在运行时交换数据并进行耦合计算。
主要特点:
- 支持并行计算
- 提供灵活的耦合配置
- 可处理非匹配网格
- 支持显式和隐式耦合方案
- 提供多种数据映射方法
安装 PRECICE
Linux 系统安装
# 使用预编译包 (Ubuntu/Debian)
sudo apt-get install precice
# 或者从源码编译
git clone https://github.com/precice/precice.git
cd precice
mkdir build && cd build
cmake -DBUILD_SHARED_LIBS=ON ..
make -j 4
sudo make install
使用示例:流体-结构相互作用 (FSI)
下面展示一个简单的流体-结构相互作用(FSI)示例,使用 PRECICE 耦合一个简化的流体求解器和一个结构求解器。
1. 创建 PRECICE 配置文件 (precice-config.xml
)
<?xml version="1.0"?>
<precice-configuration>
<solver-interface dimensions="2">
<data:vector name="Forces" />
<data:vector name="Displacements" />
<mesh name="FluidMesh">
<use-data name="Forces" />
<use-data name="Displacements" />
</mesh>
<mesh name="StructureMesh">
<use-data name="Forces" />
<use-data name="Displacements" />
</mesh>
<participant name="FluidSolver">
<provide-mesh name="FluidMesh" />
<receive-data name="Displacements" mesh="FluidMesh" />
<write-data name="Forces" mesh="FluidMesh" />
</participant>
<participant name="StructureSolver">
<provide-mesh name="StructureMesh" />
<receive-data name="Forces" mesh="StructureMesh" />
<write-data name="Displacements" mesh="StructureMesh" />
</participant>
<m2n:sockets from="FluidSolver" to="StructureSolver" />
<coupling-scheme:serial-implicit>
<participants first="FluidSolver" second="StructureSolver" />
<max-time-windows value="10" />
<time-window-size value="0.1" />
<relative-convergence-measure limit="1e-3" data="Displacements" mesh="StructureMesh" />
<exchange data="Forces" mesh="FluidMesh" from="FluidSolver" to="StructureSolver" />
<exchange data="Displacements" mesh="StructureMesh" from="StructureSolver" to="FluidSolver" />
</coupling-scheme:serial-implicit>
</solver-interface>
</precice-configuration>
2. 简化的流体求解器示例 (Python)
import numpy as np
import precice
# 设置PRECICE接口
participant_name = "FluidSolver"
config_file_name = "precice-config.xml"
solver_process_index = 0
solver_process_size = 1
interface = precice.Interface(participant_name, config_file_name,
solver_process_index, solver_process_size)
mesh_name = "FluidMesh"
mesh_id = interface.get_mesh_id(mesh_name)
# 定义网格和顶点
vertices = np.array([[0, 0], [1, 0], [1, 1], [0, 1]]) # 简单正方形网格
vertex_ids = interface.set_mesh_vertices(mesh_id, vertices)
# 定义数据
displacements_id = interface.get_data_id("Displacements", mesh_id)
forces_id = interface.get_data_id("Forces", mesh_id)
# 初始化PRECICE
precice_dt = interface.initialize()
# 模拟时间步进
while interface.is_coupling_ongoing():
# 接收来自结构求解器的位移
displacements = interface.read_block_vector_data(displacements_id, vertex_ids)
# 在这里进行流体计算...
# 这是一个简化示例,实际应用中会有完整的流体求解器
# 计算作用在结构上的力 (简化示例)
forces = np.random.rand(len(vertices), 2) # 随机力,实际应用中应计算真实力
# 发送力给结构求解器
interface.write_block_vector_data(forces_id, vertex_ids, forces)
# 推进耦合
precice_dt = interface.advance(precice_dt)
# 结束耦合
interface.finalize()
3. 简化的结构求解器示例 (Python)
import numpy as np
import precice
# 设置PRECICE接口
participant_name = "StructureSolver"
config_file_name = "precice-config.xml"
solver_process_index = 0
solver_process_size = 1
interface = precice.Interface(participant_name, config_file_name,
solver_process_index, solver_process_size)
mesh_name = "StructureMesh"
mesh_id = interface.get_mesh_id(mesh_name)
# 定义网格和顶点 (应与流体网格对应)
vertices = np.array([[0, 0], [1, 0], [1, 1], [0, 1]]) # 简单正方形网格
vertex_ids = interface.set_mesh_vertices(mesh_id, vertices)
# 定义数据
displacements_id = interface.get_data_id("Displacements", mesh_id)
forces_id = interface.get_data_id("Forces", mesh_id)
# 初始化PRECICE
precice_dt = interface.initialize()
# 初始位移
displacements = np.zeros((len(vertices), 2))
# 模拟时间步进
while interface.is_coupling_ongoing():
# 接收来自流体求解器的力
forces = interface.read_block_vector_data(forces_id, vertex_ids)
# 在这里进行结构计算...
# 这是一个简化示例,实际应用中会有完整的结构求解器
# 计算位移 (简化示例)
stiffness = 0.1
displacements = forces * stiffness
# 发送位移给流体求解器
interface.write_block_vector_data(displacements_id, vertex_ids, displacements)
# 推进耦合
precice_dt = interface.advance(precice_dt)
# 结束耦合
interface.finalize()
运行耦合仿真
要运行这个耦合仿真,你需要:
-
将上述代码保存为三个文件:
precice-config.xml
(配置文件)fluid_solver.py
(流体求解器)structure_solver.py
(结构求解器)
-
在两个不同的终端中分别运行:
python fluid_solver.py
和
python structure_solver.py
实际应用中的注意事项
-
网格匹配:在实际应用中,流体和结构网格通常不完全匹配,PRECICE 提供了多种数据映射方法。
-
收敛标准:隐式耦合需要设置适当的收敛标准。
-
并行计算:PRECICE 支持并行计算,可以显著提高大规模仿真的效率。
-
时间步长:耦合时间步长需要仔细选择以确保数值稳定性。
-
真实求解器:实际应用中,你会用真实的 CFD 和 CSM 求解器(如 OpenFOAM、CalculiX 等)替代上述简化示例。
PRECICE 提供了与多种流行仿真工具的适配器,可以方便地集成到现有仿真工作流程中。
使用preCICE在OpenFOAM求解器之间进行耦合计算
preCICE是一个用于分区多物理场耦合的库,可以方便地在不同求解器之间建立耦合关系。下面我将介绍如何在两个OpenFOAM求解器之间使用preCICE进行耦合计算,并提供示例代码。
基本配置步骤
- 安装preCICE和OpenFOAM的preCICE适配器
- 准备两个OpenFOAM案例
- 为每个案例创建preCICE配置文件
- 配置OpenFOAM案例以使用preCICE适配器
示例场景
假设我们有两个OpenFOAM求解器:
- 求解器A:计算流体流动(如pimpleFoam)
- 求解器B:计算热传递(如buoyantPimpleFoam)
我们希望在这两个求解器之间耦合传热(温度)和壁面热通量。
示例代码结构
1. preCICE配置文件 (precice-config.xml)
<?xml version="1.0"?>
<precice-configuration>
<solver-interface dimensions="3">
<data:vector name="Velocity" />
<data:scalar name="Temperature" />
<data:scalar name="Heat-Flux" />
<participant name="FluidSolver">
<use-mesh name="FluidMesh" provide="yes" />
<write-data name="Temperature" mesh="FluidMesh" />
<read-data name="Heat-Flux" mesh="FluidMesh" />
</participant>
<participant name="ThermalSolver">
<use-mesh name="ThermalMesh" provide="yes" />
<read-data name="Temperature" mesh="ThermalMesh" />
<write-data name="Heat-Flux" mesh="ThermalMesh" />
</participant>
<m2n:sockets from="FluidSolver" to="ThermalSolver" />
<coupling-scheme:serial-implicit>
<participants first="FluidSolver" second="ThermalSolver" />
<max-time-windows value="100" />
<time-window-size value="0.1" />
<relative-convergence-measure limit="1e-3" data="Heat-Flux" />
<exchange data="Temperature" mesh="FluidMesh" from="FluidSolver" to="ThermalSolver" />
<exchange data="Heat-Flux" mesh="ThermalMesh" from="ThermalSolver" to="FluidSolver" />
</coupling-scheme:serial-implicit>
</solver-interface>
</precice-configuration>
2. OpenFOAM案例配置
对于每个OpenFOAM案例,你需要在system/
目录下添加preCICE配置:
system/preciceDict (流体求解器)
preciceConfig "precice-config.xml";
participantName "FluidSolver";
modules (FF);
interfaces
{
interface
{
mesh "FluidMesh";
patches (wall);
writeData
(
Temperature
);
readData
(
Heat-Flux
);
}
};
system/preciceDict (热求解器)
preciceConfig "precice-config.xml";
participantName "ThermalSolver";
modules (CHT);
interfaces
{
interface
{
mesh "ThermalMesh";
patches (wall);
writeData
(
Heat-Flux
);
readData
(
Temperature
);
}
};
3. 修改边界条件
在流体求解器的0/T
文件中:
wall
{
type preciceTemperature;
preciceConfig "precice-config.xml";
participantName "FluidSolver";
meshName "FluidMesh";
dataName "Temperature";
value $internalField;
}
在热求解器的0/q
文件中:
wall
{
type preciceHeatFlux;
preciceConfig "precice-config.xml";
participantName "ThermalSolver";
meshName "ThermalMesh";
dataName "Heat-Flux";
value $internalField;
}
4. 运行脚本
创建一个运行两个求解器的脚本runCoupled.sh
:
#!/bin/bash
# 在一个终端中运行流体求解器
gnome-terminal -- bash -c "cd fluidCase && pimpleFoam -precice-participant FluidSolver; exec bash"
# 在另一个终端中运行热求解器
gnome-terminal -- bash -c "cd thermalCase && buoyantPimpleFoam -precice-participant ThermalSolver; exec bash"
关键点说明
-
preCICE配置:
- 定义了参与耦合的两个求解器
- 指定了交换的数据类型(标量/矢量)
- 设置了耦合方案(这里使用串行隐式)
-
OpenFOAM适配器配置:
- 每个求解器通过
preciceDict
指定其在preCICE配置中的名称 - 定义接口面和交换的数据
- 每个求解器通过
-
边界条件:
- 使用特殊的preCICE边界条件类型替换常规边界条件
- 确保数据名称与preCICE配置中一致
注意事项
- 确保两个案例的耦合面网格在几何上是兼容的(不一定需要节点匹配)
- 时间步长设置应该协调,通常使用固定时间步长
- 初始条件应该合理设置以避免数值不稳定
- 耦合收敛标准需要根据具体问题调整
扩展
对于更复杂的耦合场景,你还可以:
- 添加更多耦合数据(如压力、位移等)
- 使用并行耦合方案
- 结合其他求解器(如结构力学求解器)
- 实现动态网格变形耦合
希望这个示例能帮助你开始使用preCICE进行OpenFOAM求解器之间的耦合计算。实际应用中可能需要根据具体问题调整配置和参数。