@李东岳
东岳老师你好,我训练的时候GPU占比%38左右。 我还想顺便请教一下
loss_ini = 1000*crit(meanU, init)
这个损失的意义。 因为我发现1D槽道流openfoam基准数据的平均值差不多就是1左右,而这里相当于是要对训练添加一个整体约束之类的东西吗。
@李东岳
东岳老师你好,我训练的时候GPU占比%38左右。 我还想顺便请教一下
loss_ini = 1000*crit(meanU, init)
这个损失的意义。 因为我发现1D槽道流openfoam基准数据的平均值差不多就是1左右,而这里相当于是要对训练添加一个整体约束之类的东西吗。
老哥,我把东岳老师那个1D槽道流的代码用AI改成了CUDA版本。然后在https://download.pytorch.org/libtorch/cu117 (我的cuda版本是11.7)下载的gpu版本的libtorch。现在发现已经可以用gpu训练了,但是训练速度还不如cpu,慢不少。 准备后续再捣鼓一下。 我机器配置 GPU: nvidia T400 4G, CPU:I7-12700,供参考
#include <torch/torch.h>
#include <torch/cuda.h> // 添加CUDA支持
using namespace std;
class NN : public torch::nn::Module {
torch::nn::Sequential net_;
public:
NN() {
net_ = register_module("net", torch::nn::Sequential(
torch::nn::Linear(1,8),
torch::nn::Tanh(),
torch::nn::Linear(8,1)
));
}
torch::Tensor forward(torch::Tensor x) {
return net_->forward(x);
}
};
int main() {
// 设备检测与设置
torch::Device device = torch::kCPU;
if (torch::cuda::is_available()) {
std::cout << "CUDA可用,使用GPU加速训练" << std::endl;
device = torch::kCUDA;
}
int iter = 1;
int IterationNum = 1000000;
double learning_rate = 0.001;
double dy = 0.00125;
int cellN = static_cast<int>(0.05/dy);
// 模型迁移至GPU
auto model = std::make_shared<NN>();
model->to(device);
// 优化器
auto opti = std::make_shared<torch::optim::AdamW>(
model->parameters(),
torch::optim::AdamWOptions(learning_rate)
);
// 数据迁移至GPU (关键步骤!)
auto init = torch::full({}, 1.0).to(device);
auto mesh = torch::arange(-0.05, 0, dy, torch::requires_grad())
.unsqueeze(1).to(device);
auto dpdxByNu = torch::ones({cellN, 1}, torch::kFloat).to(device);
auto nut = torch::zeros({cellN}).to(device);
for (int i = 0; i < IterationNum; i++) {
opti->zero_grad();
auto upred = model->forward(mesh);
// 梯度计算(确保权重张量在GPU)
auto dudy = torch::autograd::grad(
{upred}, {mesh},
{torch::ones_like(upred).to(device)}, true, true
)[0];
auto dudyy = torch::autograd::grad(
{dudy}, {mesh},
{torch::ones_like(upred).to(device)}, true, true
)[0];
auto dudyTop = dudy[cellN - 1][0];
auto meanU = torch::mean(upred);
auto ubottom = torch::full_like(upred[0], 0.0375).to(device); // 边界条件迁移
auto dpdxByNu = torch::full({cellN}, 1.2e-05/1e-08).to(device);
// 损失计算
auto loss_bottom = torch::mse_loss(upred[0], ubottom);
auto loss_top = torch::mse_loss(dudyTop, torch::zeros_like(dudyTop));
auto loss_bd = loss_bottom + 1000*loss_top;
auto loss_ini = 1000*torch::mse_loss(meanU, init);
auto loss_pde = torch::mse_loss(-dudyy.reshape({cellN}), dpdxByNu);
auto loss = loss_pde + loss_bd + loss_ini;
// 反向传播
loss.backward();
opti->step();
// 输出需同步到CPU
if (iter % 500 == 0) {
double loss_value = loss.item<double>();
cout << iter << " loss = " << loss_value << endl;
}
iter++;
}
torch::save(model, "model.pth");
std::cout << "训练完成!" << std::endl;
return 0;
}
我也想问一下,不知道理解对不对。对于湍流粘度(Eddy Viscosity)模型,壁面切应力应该是这个
$$ \tau_{w}=\tau_{d} \cdot {n}_f =-\mu_{eff} \cdot {dev}(2S) \cdot {n}_f $$
$ S $是应变率张量, $\mu_{eff}$ 是流体的有效动力粘度(考虑湍流影响), $dev$ 是二阶应力张量的deviatoric操作,用以获取该项的剪切应力部分
$$ dev(\tau)=\tau - \frac{1}{3}tr(\tau)\bf{I} $$
$$ S = \frac{1}{2}(L + L^T) = \begin{bmatrix} \frac{\partial u}{\partial x} & \frac{1}{2}(\frac{\partial v}{\partial x} + \frac{\partial u}{\partial y}) & \frac{1}{2}(\frac{\partial v}{\partial x} + \frac{\partial u}{\partial y}) \\ \frac{1}{2}(\frac{\partial u}{\partial y} + \frac{\partial v}{\partial x}) & \frac{\partial v}{\partial y} & \frac{1}{2}(\frac{\partial w}{\partial y} + \frac{\partial v}{\partial z}) \\ \frac{1}{2}(\frac{\partial u}{\partial z} + \frac{\partial w}{\partial x}) & \frac{1}{2}(\frac{\partial v}{\partial z} + \frac{\partial w}{\partial y}) & \frac{\partial w}{\partial z}\end{bmatrix}$$
这样看的话,假设 $\tau_d$ 可以写成
$$\tau_d = \begin{bmatrix} \sigma_{xx} & \sigma_{xy} & \sigma_{xz} \\ \sigma_{yx} & \sigma_{yy} & \sigma_{yz} \\ \sigma_{zx} & \sigma_{zy} & \sigma_{zz}\end{bmatrix}$$
有$ {n}_f$为沿 z轴垂直于xy的平面A的法向矢量,写成
$$\bf{n}_f =\begin{bmatrix} 0 \\ 0 \\ 1 \end{bmatrix}$$
那么得到的 $\tau_w $为,其中 $\sigma_{xz}$ 和 $\sigma_{yz}$为 A平面平行于 x 和 y 轴的分量, $\sigma_{zz}$ 为沿 z 轴 垂直于 A 平面的法向分量
$$\tau_w =\begin{bmatrix} \sigma_{xz} \\ \sigma_{yz} \\ \sigma_{zz} \end{bmatrix}$$
所以壁面切应力矢量$\tau_w $和面法向$\bf{n}_f$矢量方向不一致
终于注册上了!