OpenFOAM libtorch tutorial step by step
-
一个libtorch下自编码器范例
可以自己添加skip connection变成Unet
class NN : public torch::nn::Module { torch::nn::Sequential net_; public: NN() { net_ = register_module ( "net", torch::nn::Sequential ( // encoder torch::nn::Conv2d(2, 5, 3),// 2 5 138 torch::nn::BatchNorm2d(5), torch::nn::Tanh(), torch::nn::MaxPool2d(2),// 2 5 69 torch::nn::Conv2d(5, 10, 3), //5 10 67 torch::nn::BatchNorm2d(10), torch::nn::Tanh(), torch::nn::MaxPool2d(2), // 5 10 33 torch::nn::Conv2d(10, 10, 3), // 10 10 31 torch::nn::BatchNorm2d(10), torch::nn::Tanh(), torch::nn::MaxPool2d(2), // 10 10 15 torch::nn::Conv2d(10, 10, 3), // 10 10 13 torch::nn::BatchNorm2d(10), torch::nn::Tanh(), torch::nn::MaxPool2d(2), // 10 10 6 // decoder torch::nn::Upsample ( torch::nn::UpsampleOptions().scale_factor ( std::vector<double>{2.0, 2.0} ).mode(torch::kBilinear).align_corners(true) ), // 10 10 12 torch::nn::Conv2d(10, 10, 2), // 10 10 11 torch::nn::Tanh(), torch::nn::Upsample ( torch::nn::UpsampleOptions().scale_factor ( std::vector<double>{2.0, 2.0} ).mode(torch::kBilinear).align_corners(true) ),// 10 10 22 torch::nn::Conv2d(10, 10, 3),// 10 10 20 torch::nn::Tanh(), torch::nn::Upsample ( torch::nn::UpsampleOptions().scale_factor ( std::vector<double>{2.0, 2.0} ).mode(torch::kBilinear).align_corners(true) ),// 10 10 40 torch::nn::Conv2d(10, 10, 3),// 10 10 38 torch::nn::Tanh(), torch::nn::Upsample ( torch::nn::UpsampleOptions().scale_factor ( std::vector<double>{2.0, 2.0} ).mode(torch::kBilinear).align_corners(true) ),// 10 10 76 torch::nn::Conv2d(10, 10, 3),// 10 10 74 torch::nn::Tanh(), torch::nn::Upsample ( torch::nn::UpsampleOptions().scale_factor ( std::vector<double>{2.0, 2.0} ).mode(torch::kBilinear).align_corners(true) ),// 10 10 148 torch::nn::Conv2d(10, 10, 3),// 10 10 146 torch::nn::Tanh(), torch::nn::Conv2d(10, 5, 3),// 10 10 144 torch::nn::Tanh(), torch::nn::Conv2d(5, 2, 3),// 10 10 142 torch::nn::Tanh(), torch::nn::Conv2d(2, 2, 3)// 10 10 140 ) ); } auto forward(torch::Tensor x) { return net_->forward(x); } };
-
@李东岳 李老师,问题解决了,是我把option文件改错了个地方。。新的问题又来了,我在OF11中(仍是该虚拟机)对bed案例进行foamRun或foamRun -solver multiphaseEuler时,为何报错:```
--> FOAM FATAL ERROR:
solvers table is emptyFrom function static Foam::autoPtr<Foam::solver> Foam::solver::New(const Foam::word&, Foam::fvMesh&) in file solver/solverNew.C at line 48.
-
添加几点注意
- 第一步libtorch需要下载到OpenFOAM的目录里面并解压。
- 第二步WSL2 里面可能没装 uzip,用
sudo apt-install zip uzip
安装 - 解压torchFoam.tar.xz 后进入torchFoam
wmake
的时候,需要把torchFoam/Make
里面的options里面所有的dyfluid
换成自己的这个WSL的用户名,pwd
一下看/home/后面是啥就知道了
-
@李东岳 在 OpenFOAM libtorch tutorial step by step 中说:
更新gcc之后你openfoam就编译不了了。那你尝试安装老版本的libtorch吧
李老师,我用的是ubuntu18.04,Of2.4.0,您有推荐的libtorch版本么
-
@chengan-wang 太老了,gcc版本啥的都太低了,我没有折腾过,你得亲自自己都尝试一下看看哪个能用
-
@李东岳 李老师,http://dyfluid.com/pinn.html ,#include "output.H"这个文件能补充上传么,想研究一下您的完整代码,谢谢
-
@chengan-wang 那个我已经删了,你可以参考这个写个类似的,纯粹是C++的输出数据:
if (iter % 500 == 0) { cout<< iter << " loss = " << loss.item<double>() << endl; auto meshxy = torch::cat({mesh,x,y}, 1); std::ofstream filex("results"); filex << meshxy << "\n"; filex.close(); }
-
You can use the following code to initialize libtorch tensors from OpenFOAM mesh. It is much easier to generate any kinds of geometries. Please see the following clipped cavity geometry. I am using English since I hope it can be helpful for all the people.
// openfoam initialization vectorField ofMesh = mesh.C(); auto meshTorch = torch::full({ofMesh.size(),1,2}, 0.0); forAll(ofMesh, i) { double x = ofMesh[i].x(); double y = ofMesh[i].y(); auto posi = torch::tensor({x,y}).reshape({1,2}); meshTorch[i] = posi; } const surfaceVectorField& Cf = mesh.Cf(); label topID = mesh.boundaryMesh().findPatchID("top"); label leftID = mesh.boundaryMesh().findPatchID("left"); label rightID = mesh.boundaryMesh().findPatchID("right"); label bottomID = mesh.boundaryMesh().findPatchID("bottom"); vectorField cfTop = Cf.boundaryField()[topID]; vectorField cfLeft = Cf.boundaryField()[leftID]; vectorField cfRight = Cf.boundaryField()[rightID]; vectorField cfBottom = Cf.boundaryField()[bottomID]; auto top = torch::full({cfTop.size(),1,2}, 0.0); auto left = torch::full({cfLeft.size(),1,2}, 0.0); auto right = torch::full({cfRight.size(),1,2}, 0.0); auto bottom = torch::full({cfBottom.size(),1,2}, 0.0); forAll(cfTop, i) { double x = cfTop[i].x(); double y = cfTop[i].y(); auto posi = torch::tensor({x,y}).reshape({1,2}); top[i] = posi; } forAll(cfRight, i) { double x = cfRight[i].x(); double y = cfRight[i].y(); auto posi = torch::tensor({x,y}).reshape({1,2}); right[i] = posi; } forAll(cfLeft, i) { double x = cfLeft[i].x(); double y = cfLeft[i].y(); auto posi = torch::tensor({x,y}).reshape({1,2}); left[i] = posi; } forAll(cfBottom, i) { double x = cfBottom[i].x(); double y = cfBottom[i].y(); auto posi = torch::tensor({x,y}).reshape({1,2}); bottom[i] = posi; } meshTorch = meshTorch.reshape({-1,2}); top = top.reshape({-1,2}); left = left.reshape({-1,2}); right = right.reshape({-1,2}); bottom = bottom.reshape({-1,2}); auto u_top = torch::full({cfTop.size()}, vel); auto v_top = torch::full({cfTop.size()}, 0.0); std::cout<< "top: " << top << std::endl; std::cout<< "left: " << left << std::endl; std::cout<< "right: " << right << std::endl; std::cout<< "bottom: " << bottom << std::endl;