栏目分类
热点资讯
你的位置:软件软件开发要多少钱 > 软件开发资讯 > 软件软件开发要多少钱 OpenFOAM编程案例|03 看望网格信息

软件开发资讯

软件软件开发要多少钱 OpenFOAM编程案例|03 看望网格信息

发布日期:2024-08-09 07:55    点击次数:70

软件软件开发要多少钱

本文描摹应用fvMesh类获取网格信息的一些基本用法。

OpenFOAM应用经过中需要经常地与网格进行交互,比如获取网格面信息,获取网格中心坐标等。应用fvMesh类中的相应成员函数很容易达成这类需求。

fvMesh类是一个极为复杂的类,其继承自polyMesh、lduMesh、fvSchemes、surfaceInterpolation、fvSolution及data类,因此不仅不错看望网格,还不错看望与网格相干的各式算法神情。其中对网格信息的看望功能(如看望网格面、得到网格规模信息等)主要继承自polyMesh类。

图片

上期开出奇偶比3:2,近10期奇偶比为26:24,本期前区推荐奇偶比1:4。

上期龙头开出奇数球05,近10期龙头开出07 04 06 04 05 02 08 01 01 05,奇偶比5:5,本期参考奇数球05。

1 准备文献

与前边的案例同样,本案例只需一个源文献及Make文献夹,应用底下的大呼创建文献结构。

cd $FOAM_RUNmkdir demo3cd demo3touch demo3.Cmkdir Makecd Maketouch filestouch optionscd ..

文献结构如下图所示。

图片

修改files文献的履行
demo3.CEXE = demo3
修改options文献的履行
EXE_INC = \        -I$(FOAM_SRC)/finiteVolume/lnInclude \        -I$(FOAM_SRC)/meshTools/lnInclude EXE_LIBS = \        -lfiniteVolume \        -lmeshTools
2 测试文献

本案例触及到网格操作,因此需要准备网格文献。简易起见,使用一个OpenFOAM案例库中的文献进行测试,如使用cavity。

cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity .cd cavityblockMesh

实践blockMesh生成网格后不错搜检网格信息,如下图所示。

图片

看到网格数目为400,网格面数为1640。

3 源代码3.1 读取网格数目

应用fvMesh类的C()及Cf()函数不错获取网格体中心坐标列表及里面面中心列表。

剪辑源文献demo3.C,输入底下的代码:

#include "fvCFD.H" int main(int argc, char *argv[]){#include "setRootCase.H"#include "createTime.H"// 在头文献createMesh.H中创建了一个名为mesh的fvMesh对象#include "createMesh.H"     // 输出现时网格信息    // 应用mesh.C()得到网格单位体心坐标列表,mesh.Cf()得到网格里面面中心坐标列表    Info << "现时时分文献:" << runTime.timeName() << nl         << "网格数目:" << mesh.C().size() << nl         << "网格面数目:" << mesh.Cf().size() << nl << nl;     // 不错用轮回输出一些网格坐标信息    for (int cellI = 0; cellI < mesh.C().size(); cellI++)    {        // 由于网格数目太多,这里作念一些不详,拒绝20输出一个        if (cellI % 20 == 0)        {            Info << "Cell[" << cellI << "]的中心坐标为:" << mesh.C()[cellI] << endl;        }    }    Info << endl;    return 0;}

编译上头的设施并启动。

图片

注目需要到测试旅途(本案例为cavity文献夹)下实践此设施。启动成果如下图所示。

图片

不错看到,设施正确地获取了网格数目与网格面的数目,并输出了网格中心坐标。

3.2 得到owner及neighbour的信息

若念念要得到网格面的owner及neighbour网格索引,不错使用mesh.owner()及mesh.neighbour()函数。

在前边的代码中添加底下履行:

    // 不错使用mesh.owner()及mesh.neighbour()得到owner及neightbour的网格编号    for (label faceI = 0; faceI < mesh.owner().size(); faceI++)    {        if (faceI % 100 == 0)        {            Info << "里面面[" << faceI << "]的中心坐标为:" << mesh.C()[faceI] << nl                 << "owner[" << faceI << "]为:" << mesh.owner()[faceI] << nl                 << "neighbour[" << faceI << "]为:" << mesh.neighbour()[faceI] << nl;        }    }    Info << endl;

编译实践,如下图所示。

图片

3.3 获取规模面信息

应用mesh.boundaryMesh()函数不错获取规模面上的信息。

添加以下代码。

// 应用mesh.boundaryMesh()函数获取规模面信息// forAll是OpenFOAM界说的轮回宏forAll(mesh.boundaryMesh(), patchI){    Info << "Patch[" << patchI << "]:" << mesh.boundary()[patchI].name() << "包括"        << mesh.boundary()[patchI].Cf().size() << "个网格面" << nl        << "肇端面为:" << mesh.boundary()[patchI].start() << endl;}Info << endl;

编译并启动,成果如下图所示。

图片

除了frontAndBack的网格面数外,其他规模的信息皆是莫得问题的。至于为什么会有问题,因为该规模类型为empty导致,惩处要领在文末。

3.4 规模网格面面积

若念念要获取规模面上某个网格的面积,不错使用函数sf(),如底下的代码:

// 应用函数faceCells()得到网格面相邻的网格// 应用函数sf()不错得到网格面的面积向量,该向量的模即为面积//界说一个索引,仅为测试使用,若是要得到几何面积,则需要将该规模上的扫数网格面积乞降label patchFaceI(0);forAll(mesh.boundaryMesh(), patchI){    Info << "Patch[" << patchI << "]的网格面" << patchFaceI << "与网格["        << mesh.boundary()[patchI].patch().faceCells()[patchFaceI] <<"]相邻,"        << "其面积向量:" << mesh.boundary()[patchI].Sf()[patchFaceI] << ",其面积为:"        << mag(mesh.boundary()[patchI].Sf()[patchFaceI])        << endl;     }Info << endl;

设施启动成果如下图所示。

图片

关于里面面,软件软件开发要多少钱不错平直在mesh实例上调用Sf()要领。若要获取网格面的面积,不错使用函数magSf(),其等同于mag(Sf()),复返一个标量面积值。

关于里面面,法向量从owner指向neightbour,况兼owner的索引小于neighbour。关于规模面,法向量老是指向诡计域外部。

3.5 网格面的节点信息

不错更详备地搜检组成每个网格面的点。领先,咱们通过获取对网格中各个对象的援用来界说一些变量。这些变量被界说为const,因为咱们不磋磨以任何时势调动网格。注目:这些列表指的是网格的物理界说,因此包括规模面。不错使用mesh.edge()[patchi].Cf().size()和mesh.edge()[patchi].start()要领检验网格面是位于里面如故位于规模上。

如底下的代码:

软件开发
// 搜检网格细节// 将变量界说为const,则此变量只可读取,而不成修改const faceList &fcs = mesh.faces();            // 得到扫数的网格面列表const List<point> &pts = mesh.points();        //得到扫数的网格节点列表const List<point> &cents = mesh.faceCentres(); //得到网格面心点列表 // 遍历索引能被80整除的网格面forAll(fcs, faceI) if (faceI % 80 == 0){    if (faceI < mesh.Cf().size())    {        Info << "里面面";    }    else    {        forAll(mesh.boundary(), patchI) if ((mesh.boundary()[patchI].start() <= faceI) &&                                            (faceI < mesh.boundary()[patchI].start() + mesh.boundary()[patchI].Cf().size()))        {            Info << "网格面在规模[" << patchI << "]上,网格面[";            break;        }    }     Info << faceI << "]的中心为:" << cents[faceI] << ",领有" << fcs[faceI].size() << "个节点:";     forAll(fcs[faceI], vertexI)    {        Info << " " << pts[fcs[faceI][vertexI]];    }    Info << endl;}Info << endl; return 0;}

启动 成果如下图所示。

图片

3.6 一些特等的问题

在本测试案例中,FrontAndBack规模被界说为empty类型。这是一种特别的规模,在使用上头的函数时会出现一些出东说念观念象的问题,如调用Cf函数时会复返空列表,导致size()函数的值为零。为了幸免出现此类问题,在进行Cf()函数调用时,不错先检验规模类型。

如底下的代码:

// 判断规模类型是否为empty类型forAll(mesh.boundaryMesh(), patchID){    const polyPatch &pp = mesh.boundaryMesh()[patchID];    if (isA<emptyPolyPatch>(pp))    {        Info << "patch[" << patchID <<"]:" << mesh.boundary()[patchID].name()            << "的规模类型为empty" << endl;    }    else    {        Info << "patch[" << patchID << "]:"<< mesh.boundary()[patchID].name()            <<"的规模类型不是empty" << endl;    }}

启动成果如下图所示。

图片

也不错通过patch的称呼应用函数findPatchID获取其ID,如底下的代码:

// 应用规模称呼得到其IDword patchName("movingWall");label patchID = mesh.boundaryMesh().findPatchID(patchName);Info << "patch name:" << patchName << nl << "patchID:" << patchID << endl;

启动成果如下图所示。

图片

4 完满代码

本案例的十足设施代码如下所示。

#include "fvCFD.H" int main(int argc, char *argv[]){#include "setRootCase.H"#include "createTime.H"// 在头文献createMesh.H中创建了一个名为mesh的fvMesh对象#include "createMesh.H"     // 输出现时网格信息    // 应用mesh.C()得到网格单位体心坐标列表,mesh.Cf()得到网格里面面中心坐标列表    Info << "现时时分文献:" << runTime.timeName() << nl         << "网格数目:" << mesh.C().size() << nl         << "网格面数目:" << mesh.Cf().size() << nl << nl;     // 不错用轮回输出一些网格坐标信息    for (int cellI = 0; cellI < mesh.C().size(); cellI++)    {        // 由于网格数目太多,这里作念一些不详,拒绝20输出一个        if (cellI % 20 == 0)        {            Info << "Cell[" << cellI << "]的中心坐标为:" << mesh.C()[cellI] << endl;        }    }    Info << endl;     // 不错使用mesh.owner()及mesh.neighbour()得到owner及neightbour的网格中心坐标列表    for (label faceI = 0; faceI < mesh.owner().size(); faceI++)    {        if (faceI % 100 == 0)        {            Info << "里面面[" << faceI << "]的中心坐标为:" << mesh.C()[faceI] << nl                 << "owner[" << faceI << "]为:" << mesh.owner()[faceI] << nl                 << "neighbour[" << faceI << "]为:" << mesh.neighbour()[faceI] << nl;        }    }    Info << endl;     // 应用mesh.boundaryMesh()函数获取规模面信息    // forAll是OpenFOAM界说的轮回宏    forAll(mesh.boundaryMesh(), patchI)    {        Info << "Patch[" << patchI << "]:" << mesh.boundary()[patchI].name() << "包括"             << mesh.boundary()[patchI].Cf().size() << "个网格面" << nl             << "肇端面为:" << mesh.boundary()[patchI].start() << endl;    }    Info << endl;     // 应用函数faceCells()得到网格面相邻的网格    // 应用函数sf()不错得到网格面的面积向量,该向量的模即为面积    //界说一个索引,仅为测试使用,若是要得到几何面积,则需要将该规模上的扫数网格面积乞降    label patchFaceI(0);    forAll(mesh.boundaryMesh(), patchI)    {        Info << "Patch[" << patchI << "]的网格面" << patchFaceI << "与网格["             << mesh.boundary()[patchI].patch().faceCells()[patchFaceI] << "]相邻,"             << "其面积向量:" << mesh.boundary()[patchI].Sf()[patchFaceI] << ",其面积为:"             << mag(mesh.boundary()[patchI].Sf()[patchFaceI])             << endl;    }    Info << endl;     // 搜检网格细节    // 将变量界说为const,则此变量只可读取,而不成修改    const faceList &fcs = mesh.faces();            // 得到扫数的网格面列表    const List<point> &pts = mesh.points();        //得到扫数的网格节点列表    const List<point> &cents = mesh.faceCentres(); //得到网格面心点列表     // 遍历索引能被80整除的网格面    forAll(fcs, faceI) if (faceI % 80 == 0)    {        if (faceI < mesh.Cf().size())        {            Info << "里面面";        }        else        {            forAll(mesh.boundary(), patchI) if ((mesh.boundary()[patchI].start() <= faceI) &&                                                (faceI < mesh.boundary()[patchI].start() + mesh.boundary()[patchI].Cf().size()))            {                Info << "网格面在规模[" << patchI << "]上,网格面[";                break;            }        }         Info << faceI << "]的中心为:" << cents[faceI] << ",领有" << fcs[faceI].size() << "个节点:";         forAll(fcs[faceI], vertexI)        {            Info << " " << pts[fcs[faceI][vertexI]];        }        Info << endl;    }    Info << endl;     // 判断规模类型是否为empty类型    forAll(mesh.boundaryMesh(), patchID)    {        const polyPatch &pp = mesh.boundaryMesh()[patchID];        if (isA<emptyPolyPatch>(pp))        {            Info << "patch[" << patchID << "]:" << mesh.boundary()[patchID].name()                 << "的规模类型为empty" << endl;        }        else        {            Info << "patch[" << patchID << "]:" << mesh.boundary()[patchID].name()                 << "的规模类型不是empty" << endl;        }    }    Info << endl;     // 应用规模称呼得到其ID    word patchName("movingWall");    label patchID = mesh.boundaryMesh().findPatchID(patchName);    Info << "patch name:" << patchName << nl << "patchID:" << patchID << endl;     Info << endl;     return 0;} 

(本文罢了)

本站仅提供存储干事,扫数履行均由用户发布,如发现存害或侵权履行,请点击举报。