Skip to content

Commit 3eea7c0

Browse files
committed
feat(domino): support domino for training and test
1 parent a313b5d commit 3eea7c0

File tree

7 files changed

+274
-8
lines changed

7 files changed

+274
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ PaddleScience 是一个基于深度学习框架 PaddlePaddle 开发的科学计
9898
| 热仿真 | [1D 换热器热仿真](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/heat_exchanger) | 机理驱动 | PI-DeepONet | 无监督学习 | - | - |
9999
| 热仿真 | [2D 热仿真](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/heat_pinn) | 机理驱动 | PINN | 无监督学习 | - | [Paper](https://arxiv.org/abs/1711.10561)|
100100
| 热仿真 | [2D 芯片热仿真](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/chip_heat) | 机理驱动 | PI-DeepONet | 无监督学习 | - | [Paper](https://doi.org/10.1063/5.0194245)|
101+
| 外流空气动力学 | [DoMINO](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/domino) | 数据驱动 | FNO | 监督学习 | [Data](https://caemldatasets.org/drivaerml/) | [Paper](https://arxiv.org/abs/2501.13350)|
101102

102103
<br>
103104
<p align="center"><b>材料科学(AI for Material)</b></p>

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
| 热仿真 | [1D 换热器热仿真](./zh/examples/heat_exchanger.md) | 机理驱动 | PI-DeepONet | 无监督学习 | - | - |
134134
| 热仿真 | [2D 热仿真](./zh/examples/heat_pinn.md) | 机理驱动 | PINN | 无监督学习 | - | [Paper](https://arxiv.org/abs/1711.10561)|
135135
| 热仿真 | [2D 芯片热仿真](./zh/examples/chip_heat.md) | 机理驱动 | PI-DeepONet | 无监督学习 | - | [Paper](https://doi.org/10.1063/5.0194245)|
136+
| 外流空气动力学 | [DoMINO](./zh/examples/domino.md) | 数据驱动 | FNO | 监督学习 | [Data](https://caemldatasets.org/drivaerml/) | [Paper](https://arxiv.org/abs/2501.13350)|
136137

137138
<br>
138139
<p align="center"><b>材料科学(AI for Material)</b></p>

docs/zh/examples/domino.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# DoMINO
2+
3+
=== "模型训练命令"
4+
5+
``` sh
6+
cd examples/domino
7+
8+
# 1. Download the DrivAer ML dataset using the provided download_aws_dataset.sh script or using the Hugging Face repo(https://huggingface.co/datasets/neashton/drivaerml).
9+
sh download_aws_dataset.sh
10+
11+
# 2. Specify the configuration settings in `examples/domino/conf/config.yaml`.
12+
13+
# 3. Run process_data.py. This will process VTP/VTU files and save them as npy for faster processing in DoMINO datapipe. Modify data_processor key in config file. Additionally, run cache_data.py to save outputs of DoMINO datapipe in the .npy files. The DoMINO datapipe is set up to calculate Signed Distance Field and Nearest Neighbor interpolations on-the-fly during training. Caching will save these as a preprocessing step and should be used in cases where the STL surface meshes are upwards of 30 million cells. The final processed dataset should be divided and saved into 2 directories, for training and validation. Specify these directories in conf/config.yaml.
14+
python3 process_data.py
15+
16+
# 4. run train
17+
python3 train.py
18+
```
19+
20+
=== "模型评估命令"
21+
22+
暂无
23+
24+
=== "模型导出命令"
25+
26+
暂无
27+
28+
=== "模型推理命令"
29+
30+
``` sh
31+
cd examples/domino
32+
python3 test.py
33+
```
34+
35+
## 1. 背景简介
36+
37+
外部空气动力学涉及高雷诺数Navier-Stokes方程求解,传统CFD方法计算成本高昂。神经算子通过端到端映射提升了效率,但面临多尺度耦合建模与长期预测稳定性不足的挑战。Decomposable Multi-scale Iterative Neural Operator(Domino)提出可分解多尺度架构,通过分层特征解耦、迭代残差校正及参数独立编码,显著提升跨尺度流动建模精度与泛化能力。实验显示,其计算速度较CFD快2-3个量级,分离流预测精度较FNO等模型提升约40%,为飞行器设计等工程问题提供高效解决方案。
38+
39+
## 2. 模型原理
40+
41+
DOMINO (Decomposable Multi-scale Iterative Neural Operator)是一种新颖的机器学习模型架构,旨在解决大规模工程仿真代理建模中的挑战。它是一个基于点云的机器学习模型,利用局部几何信息来预测离散点上的流场 。
42+
43+
以下是DOMINO模型的主要原理:
44+
45+
- 全局几何表示学习(Global Geometry Representation):
46+
- 模型首先以几何体的三维表面网格作为输入。
47+
- 在几何体周围构建一个紧密贴合的表面包围盒和一个表示计算域的包围盒。
48+
- 几何点云的特征(如空间坐标)通过可学习的点卷积核投影到表面包围盒上的N维结构化网格上(分辨率为$m×m×m×f$)。
49+
- 点卷积核的实现使用了NVIDIA Warp加速的自定义球查询层 。
50+
- 通过两种方法将几何特征传播到计算域包围盒中:1)学习一组单独的多尺度点卷积核,将几何信息投影到计算域网格上;2)使用包含卷积、池化和反池化层的CNN块,将表面包围盒网格上的特征$G_s$​传播到计算域包围盒网格$G_c$。CNN块会迭代评估。
51+
- 计算域网格上计算出的$m×m×m×f$特征代表了几何点云的全局编码。此外,还会计算符号距离场(SDF)及其梯度分量,并附加到学习到的特征中,以提供关于几何拓扑的额外信息。
52+
53+
- 局部几何表示(Local Geometry Representation):
54+
- 局部几何表示取决于计算域中评估解场的物理位置。
55+
- 在计算局部几何表示之前,会在计算域中采样一批离散点。
56+
- 对于批次中每个采样点,在其周围定义一个大小为$l×l×l$的子区域,并计算局部几何编码。
57+
- 局部编码本质上是全局编码的一个子集,取决于其在计算域中的位置,并通过点卷积计算。
58+
- 提取的局部特征通过全连接神经网络进一步转换。
59+
- 这种局部几何表示用于使用聚合网络评估采样点上的解场。
60+
61+
- 聚合网络(Aggregation Network):
62+
- 局部几何表示代表了采样点及其邻居的计算模板附近几何和解的学习特征。
63+
- 计算模板中的每个点都由其在计算域中的物理坐标、这些坐标处的SDF、来自域质心的法向量以及表面法向量(如果点在表面上)表示。
64+
- 这些输入特征通过一个全连接神经网络(称为基函数神经网络),计算出一个潜在向量,代表计算模板中每个点的这些特征。
65+
- 每个潜在向量与局部几何编码连接,并通过另一组全连接层,以预测计算模板中每个点上的解向量。
66+
- 解向量通过逆距离加权方案进行平均,以预测采样点处的最终解向量。
67+
- 对于每个解变量,都使用聚合网络的一个独立实例,但全局几何编码网络在它们之间是共享的。
68+
69+
DOMINO模型通过这种分解式、多尺度和迭代的方法,能够有效地处理大规模仿真数据,捕捉长距离和短距离的相互作用,并在不牺牲准确性的情况下提供可扩展、准确和可推广的代理模型 。
70+
71+
## 3. 完整代码
72+
73+
``` py linenums="1" title="examples/domino/train.py"
74+
--8<--
75+
examples/domino/train.py
76+
--8<--
77+
```
78+
79+
``` py linenums="1" title="examples/domino/test.py"
80+
--8<--
81+
examples/domino/test.py
82+
--8<--
83+
```
84+
85+
## 4. 结果展示
86+
87+
## 5. 参考资料
88+
89+
- [DoMINO: A Decomposable Multi-scale Iterative Neural Operator for Modeling Large Scale Engineering Simulations](https://arxiv.org/abs/2501.13350)

examples/domino/conf/config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ hydra: # Hydra config
2828
output_subdir: hydra # Default is .hydra which causes files not being uploaded in W&B.
2929

3030
data: # Input directory for training and validation data
31-
input_dir: /home/aistudio/modulus/examples/cfd/external_aerodynamics/domino/outputs/volume_data/
32-
input_dir_val: /home/aistudio/modulus/examples/cfd/external_aerodynamics/domino/outputs/volume_data/
31+
input_dir: outputs/volume_data/
32+
input_dir_val: outputs/volume_data/
3333
bounding_box: # Bounding box dimensions for computational domain
3434
min: [-3.5, -2.25 , -0.32]
3535
max: [8.5 , 2.25 , 3.00]
@@ -103,7 +103,7 @@ train: # Training configurable parameters
103103
sampler:
104104
shuffle: true
105105
drop_last: false
106-
checkpoint_dir: /lustre/rranade/modulus_dev/modulus_forked/modulus/examples/cfd/external_aerodynamics/domino/outputs/AWS_Dataset/3/models/
106+
checkpoint_dir: outputs/AWS_Dataset/3/models/
107107

108108
val: # Validation configurable parameters
109109
dataloader:
@@ -113,12 +113,12 @@ val: # Validation configurable parameters
113113
drop_last: false
114114

115115
eval: # Testing configurable parameters
116-
test_path: /home/aistudio/modulus/examples/cfd/external_aerodynamics/domino/drivaer_data_full_new
117-
save_path: /home/aistudio/modulus/examples/cfd/external_aerodynamics/domino/outputs/mesh_predictions_surf_final1/
118-
checkpoint_name: /home/aistudio/xiaoyewww/PaddleScience/examples/domino/outputs/AWS_Dataset/1/models/DoMINO.0.30.pdparams
116+
test_path: drivaer_data_full
117+
save_path: outputs/mesh_predictions_surf_final1/
118+
checkpoint_name: outputs/AWS_Dataset/1/models/DoMINO.0.30.pdparams
119119

120120
data_processor: # Data processor configurable parameters
121121
kind: drivaer_aws # must be either drivesim or drivaer_aws
122-
output_dir: /lustre/rranade/modulus_dev/data/volume_data/
123-
input_dir: /lustre/datasets/drivaer_aws/drivaer_data_full/
122+
output_dir: data/volume_data/
123+
input_dir: drivaer_aws/drivaer_data_full/
124124
num_processors: 12
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/bash
2+
3+
# This Bash script downloads the AWS DrivAer files from the Amazon S3 bucket to a local directory.
4+
# Only the volume files (.vtu), STL files (.stl), and VTP files (.vtp) are downloaded.
5+
# It uses a function, download_run_files, to check for the existence of three specific files (".vtu", ".stl", ".vtp") in a run directory.
6+
# If a file doesn't exist, it's downloaded from the S3 bucket. If it does exist, the download is skipped.
7+
# The script runs multiple downloads in parallel, both within a single run and across multiple runs.
8+
# It also includes checks to prevent overloading the system by limiting the number of parallel downloads.
9+
10+
# Set the local directory to download the files
11+
LOCAL_DIR="./drivaer_data_full" # <--- This is the directory where the files will be downloaded.
12+
13+
# Set the S3 bucket and prefix
14+
S3_BUCKET="caemldatasets"
15+
S3_PREFIX="drivaer/dataset"
16+
17+
# Create the local directory if it doesn't exist
18+
mkdir -p "$LOCAL_DIR"
19+
20+
# Function to download files for a specific run
21+
download_run_files() {
22+
local i=$1
23+
RUN_DIR="run_$i"
24+
RUN_LOCAL_DIR="$LOCAL_DIR/$RUN_DIR"
25+
26+
# Create the run directory if it doesn't exist
27+
mkdir -p "$RUN_LOCAL_DIR"
28+
29+
# Check if the .vtu file exists before downloading
30+
if [ ! -f "$RUN_LOCAL_DIR/volume_$i.vtu" ]; then
31+
aws s3 cp --no-sign-request "s3://$S3_BUCKET/$S3_PREFIX/$RUN_DIR/volume_$i.vtu" "$RUN_LOCAL_DIR/" &
32+
else
33+
echo "File volume_$i.vtu already exists, skipping download."
34+
fi
35+
36+
# Check if the .stl file exists before downloading
37+
if [ ! -f "$RUN_LOCAL_DIR/drivaer_$i.stl" ]; then
38+
aws s3 cp --no-sign-request "s3://$S3_BUCKET/$S3_PREFIX/$RUN_DIR/drivaer_$i.stl" "$RUN_LOCAL_DIR/" &
39+
else
40+
echo "File drivaer_$i.stl already exists, skipping download."
41+
fi
42+
43+
# Check if the .vtp file exists before downloading
44+
if [ ! -f "$RUN_LOCAL_DIR/boundary_$i.vtp" ]; then
45+
aws s3 cp --no-sign-request "s3://$S3_BUCKET/$S3_PREFIX/$RUN_DIR/boundary_$i.vtp" "$RUN_LOCAL_DIR/" &
46+
else
47+
echo "File boundary_$i.vtp already exists, skipping download."
48+
fi
49+
50+
wait # Ensure that both files for this run are downloaded before moving to the next run
51+
}
52+
53+
# Loop through the run folders and download the files
54+
for i in $(seq 1 500); do
55+
download_run_files "$i" &
56+
57+
# Limit the number of parallel jobs to avoid overloading the system
58+
if (( $(jobs -r | wc -l) >= 8 )); then
59+
wait -n # Wait for the next background job to finish before starting a new one
60+
fi
61+
done
62+
63+
# Wait for all remaining background jobs to finish
64+
wait

examples/domino/process_data.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2023 - 2024 NVIDIA CORPORATION & AFFILIATES.
2+
# SPDX-FileCopyrightText: All rights reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""
18+
This code runs the data processing in parallel to load OpenFoam files, process them
19+
and save in the npy format for faster processing in the DoMINO datapipes. Several
20+
parameters such as number of processors, input and output paths, etc. can be
21+
configured in config.yaml in the data_processing tab.
22+
"""
23+
24+
import multiprocessing
25+
import os
26+
import time
27+
28+
import hydra
29+
import numpy as np
30+
from omegaconf import DictConfig
31+
from omegaconf import OmegaConf
32+
from openfoam_datapipe import OpenFoamDataset
33+
from physicsnemo.utils.domino.utils import * # noqa: F403
34+
35+
36+
def process_files(*args_list):
37+
ids = args_list[0]
38+
processor_id = args_list[1]
39+
fm_data = args_list[2]
40+
output_dir = args_list[3]
41+
for j in ids:
42+
fname = fm_data.filenames[j]
43+
if len(os.listdir(os.path.join(fm_data.data_path, fname))) == 0:
44+
print(f"Skipping {fname} - empty.")
45+
continue
46+
outname = os.path.join(output_dir, fname)
47+
print("Filename:%s on processor: %d" % (outname, processor_id))
48+
filename = f"{outname}.npy"
49+
if os.path.exists(filename):
50+
print(f"Skipping {filename} - already exists.")
51+
continue
52+
start_time = time.time()
53+
data_dict = fm_data[j]
54+
np.save(filename, data_dict)
55+
print("Time taken for %d = %f" % (j, time.time() - start_time))
56+
57+
58+
@hydra.main(version_base="1.3", config_path="conf", config_name="config")
59+
def main(cfg: DictConfig):
60+
print(f"Config summary:\n{OmegaConf.to_yaml(cfg, sort_keys=True)}")
61+
volume_variable_names = list(cfg.variables.volume.solution.keys())
62+
num_vol_vars = 0
63+
for j in volume_variable_names:
64+
if cfg.variables.volume.solution[j] == "vector":
65+
num_vol_vars += 3
66+
else:
67+
num_vol_vars += 1
68+
69+
surface_variable_names = list(cfg.variables.surface.solution.keys())
70+
num_surf_vars = 0
71+
for j in surface_variable_names:
72+
if cfg.variables.surface.solution[j] == "vector":
73+
num_surf_vars += 3
74+
else:
75+
num_surf_vars += 1
76+
77+
fm_data = OpenFoamDataset(
78+
cfg.data_processor.input_dir,
79+
kind=cfg.data_processor.kind,
80+
volume_variables=volume_variable_names,
81+
surface_variables=surface_variable_names,
82+
model_type=cfg.model.model_type,
83+
)
84+
output_dir = cfg.data_processor.output_dir
85+
create_directory(output_dir) # noqa: F405
86+
n_processors = cfg.data_processor.num_processors
87+
88+
num_files = len(fm_data)
89+
ids = np.arange(num_files)
90+
num_elements = int(num_files / n_processors) + 1
91+
process_list = []
92+
ctx = multiprocessing.get_context("spawn")
93+
for i in range(n_processors):
94+
if i != n_processors - 1:
95+
sf = ids[i * num_elements : i * num_elements + num_elements]
96+
else:
97+
sf = ids[i * num_elements :]
98+
# print(sf)
99+
process = ctx.Process(target=process_files, args=(sf, i, fm_data, output_dir))
100+
101+
process.start()
102+
process_list.append(process)
103+
104+
for process in process_list:
105+
process.join()
106+
107+
108+
if __name__ == "__main__":
109+
main()

examples/domino/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
hydra-core
22
importlib_metadata
33
pyvista==0.34.2
4+
termcolor
5+
treelib
46
warp-lang

0 commit comments

Comments
 (0)