CFD_Benchmark / model /PointNet.py
OneScience's picture
Upload folder using huggingface_hub
ff0fadf verified
Raw
History Blame Contribute Delete
3.11 kB
import torch
import torch.nn as nn
import torch_geometric.nn as nng
from onescience.modules.embedding import timestep_embedding, unified_pos_embedding
from onescience.modules.mlp.MLP import StandardMLP
class Model(nn.Module):
"""
PointNet 模型。
用于处理点云数据,通过 MLP 提取局部特征,并使用全局最大池化提取全局特征。
"""
def __init__(self, args, device):
super(Model, self).__init__()
self.__name__ = "PointNet"
# 1. Input Block
self.in_block = StandardMLP(
input_dim=args.n_hidden,
output_dim=args.n_hidden * 2,
hidden_dims=[args.n_hidden * 2],
activation=args.act,
use_bias=True
)
# 2. Max Pooling Block
self.max_block = StandardMLP(
input_dim=args.n_hidden * 2,
output_dim=args.n_hidden * 32,
hidden_dims=[args.n_hidden * 8],
activation=args.act,
use_bias=True
)
# 3. Output Block
self.out_block = StandardMLP(
input_dim=args.n_hidden * (2 + 32), # 34 * hidden
output_dim=args.n_hidden * 4,
hidden_dims=[args.n_hidden * 16],
activation=args.act,
use_bias=True
)
# 4. Encoder
self.encoder = StandardMLP(
input_dim=args.fun_dim + args.space_dim,
output_dim=args.n_hidden,
hidden_dims=[args.n_hidden * 2],
activation=args.act,
use_bias=True
)
# 5. Decoder
self.decoder = StandardMLP(
input_dim=args.n_hidden,
output_dim=args.out_dim,
hidden_dims=[args.n_hidden * 2],
activation=args.act,
use_bias=True
)
self.fcfinal = nn.Linear(args.n_hidden * 4, args.n_hidden)
def forward(self, x, fx, T=None, geo=None):
if geo is None:
raise ValueError("Please provide edge index for Graph Neural Networks")
# 兼容 batch_size = 1 输入
if x.dim() == 3:
x = x.squeeze(0) # [1, N, C] → [N, C]
if fx is not None and fx.dim() == 3:
fx = fx.squeeze(0)
assert (
x.size(0) > 0 # Simple check
), "Input cannot be empty"
# 构造 batch 索引
batch = torch.zeros(x.shape[0], dtype=torch.long, device=x.device)
# 编码 + 局部特征提取
z = torch.cat((x, fx), dim=-1).float()
z = self.encoder(z)
z = self.in_block(z)
# 全局特征(max pooling)
global_coef = self.max_block(z)
global_coef = nng.global_max_pool(global_coef, batch=batch)
# 重复 global coef 到每个点
nb_points = torch.tensor([batch.shape[0]], device=z.device)
global_coef = global_coef.repeat_interleave(nb_points, dim=0)
# 拼接全局 + 局部特征
z = torch.cat([z, global_coef], dim=1)
z = self.out_block(z)
z = self.fcfinal(z)
z = self.decoder(z)
return z.unsqueeze(0)