CFD中文网

    CFD中文网

    • 登录
    • 搜索
    • 最新

    你要的OpenFOAM编程杂七杂八

    OpenFOAM
    19
    25
    29373
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 李东岳
      李东岳 管理员 最后由 李东岳 编辑

      因为最近又开始重写求解器代码,代码又搞得有点多。本篇文章谈一谈OpenFOAM代码方面的杂七杂八,不谈CFD算法,只是编程,算是这些年写代码,重写代码,再重写代码,再再重写代码的总结。

      OpenFOAM的入门请参考:OpenFOAM入门建议


      第一句:可能有些刚入门CFD的朋友不知道我说的是什么,但你总会明白的。

      开源和闭源

      现在CFD软件非常多,相对于ANSYS Fluent,OpenFOAM最大的特点是开源,也就是代码是公开的。因此我们可以从代码这方面把所有的CFD软件分为:

      • 闭源CFD求解器,例如
        • ANSYS Fluent
        • Star-CD
      • 开源CFD求解器,例如
        • OpenFOAM
        • PyFR

      比较直观的就是闭源Windows以及开源Linux,开源和闭源虽然只是代码是否公开的问题,但是导致截然不同的运营体系。

      我们以ANSYS Fluent来举例,据我所知是世界上用户群最大的CFD软件,用户群远大于OpenFOAM。作为一个闭源软件,ANSYS Fluent起码要承担以下的任务:

      • 所有发布版本的bug修复
      • 新版本的开发
      • 友好的用户接口

      上面只是简单几项,当然ANSYS Fluent做的事情要比这几个多出几百倍。需要注意的是,这些都是ANSYS公司内部人员需要处理的,因此就需要雇佣大量的人员去处理,那么ANSYS就需要通过闭源Fluent去盈利来循环整个系统。

      为什么OpenFOAM开源了?开源有什么好处?

      Weller没有告诉我当时为什么把OpenFOAM开源化。但我猜想有以下可能:

      • Weller是一个狂热的开源软件抵制者(我从他话语中判断出来的,不清楚是他后来变成这个样子还是刚出生就是开源战士 :big_mouth: )

      开源CFD软件由于不从用户那收费,因此发布者并没有义务去做bug修复,因此开源软件强调的是

      • 软件是大家的,bug是大家的,bug一起改,发布一起用

      例如Linux,世界上大量的公司在用linux,大量的公司甚至个人发现bug之后,可以修复,经发行商采用就可以发布。目前OpenFOAM也是用的这种策略。各大公司也会赞助OpenFOAM基金会,个人也可以写求解器并且提供给OpenFOAM基金会。bug大家一起改,然后OpenFOAM基金会统一发布。

      开源有什么坏处?

      一旦开源,就会存在很多的衍生版本,比如你看到了各种各样的Linux发行版,例如Ubuntu,OpenSUSE,Arch等。很遗憾的是在中国,国外的开源软件有些情况下会变成自主创新。比如国外的Android被小米摇身一变打造成自主创新内核的MIUI。国外的版权意识比较良好,并且也是百花齐放,比如各种基于OpenFOAM的CFD代码,比如做的比较大的:

      • ESI-OpenFOAM
      • foam-extend
      • SimScale

      等。类似这种基于OpenFOAM的CFD代码我见过不下几十个。

      想当然大家会发现OpenFOAM版本号最近更新的比较快,比如从OpenFOAM-4.1直接步进到OpenFOAM-5.0。这都是有原因的,存在商业的原因。

      面向对象和面向过程

      由于OpenFOAM和ANSYS Fluent最大的区别在于开源和闭源。因此大多数用户使用OpenFOAM需要调用起开源的特性,也就是需要对OpenFOAM的代码进行改动。否则用户会选择更加友好的闭源CFD软件。

      下面是一个简单的C++代码:

      void foo(int y)
      {
          using namespace std;
          cout << "y = " << y << endl;
      }
       
      int main()
      {
          foo(5); 
       
          int x = 6;
          foo(x); 
          foo(x+1); 
       
          return 0;
      }
      

      下面是OpenFOAM中一个非常简单的CFD求解器代码:

          scalar packedAlpha
          (
              readScalar
              (
                  kinematicCloud.particleProperties().subDict("constantProperties")
                 .lookup("packedAlpha")
              )
          );
          scalar packedAlphac(1.0 - packedAlpha);
      
          // Update alphac from the particle locations
          alphac = max(1.0 - kinematicCloud.theta(), packedAlphac);
          alphac.correctBoundaryConditions();
      
          surfaceScalarField alphacf("alphacf", fvc::interpolate(alphac));
          surfaceScalarField alphaPhic("alphaPhic", alphacf*phic);
      
          autoPtr<incompressible::turbulenceModel> continuousPhaseTurbulence
          (
              incompressible::turbulenceModel::New(Uc, phic, continuousPhaseTransport)
          );
      

      很明显,OpenFOAM虽然是使用C++编写的,但是OpenFOAM的代码对于不会OpenFOAM的C++(即使熟练工),也完全不明白OpenFOAM的C++代码是什么。

      主要原因是OpenFOAM完全的面向对象。你看到的OpenFOAM的代码每一个都是对象,比如surfaceScalarField是一个对象,incompressible::turbulenceModel是一个对象,kinematicCloud是一个对象。

      用一个最简单的例子表示面向对象和面向过程的区别:如果我们要求解矩阵A,面向过程是这样的代码:

      solve(A);//矩阵A是一个参数
      

      面向对象是这样的代码:

      A.solve();//矩阵A是一个对象
      

      再用一个小李子强调一下区别,如果你在求解矩阵A的时候,同时需要aaaa,bbbb,cccc,dddd,eeee等5个参数,面向过程是这个样子:

      solve(A,aaaa,bbbb,cccc,dddd,eeee);//矩阵A是一个参数
      

      面向对象是这样的代码:

      A.solve();//矩阵A是一个对象
      

      另一个面向过程和面向对象的例子:

      dog(eat, shit);//面向过程,2个参数
      dog.eat(shit);//面向对象,1个参数
      

      你的参数越多,你的传入参数越多。有可能你50行代码全是参数!!上面只是一个最容易理解的面向对象的举例,当然不仅仅是参数的区别。

      继承,封装,多态

      如果面向对象、面向过程把你搞晕了,这个主题可能会更晕。继承,封装,多态三个老哥可以最大化的减少代码复用。

      继承

      我们在面向对象的基础上,再举个小李子。如果我们需求定义OpenFOAM中fvScalarMatrix和fvVectorMatrix对象的求解(实际上OpenFOAM已经帮你写好了,因此你不需要去关注到底怎么写,这也是后面要提及的封装),或许可以这样做:

      //- fvScalarMatrix的函数定义
      fvScalarMatrix::solve()
      {
          int a = 1;
          int b = 1;
          int c = 1;
          int d = 1;
          int e = a + b + c + d;
      
          //...
      }
      
      //- fvVectorMatrix的函数定义
      fvVectorMatrix::solve()
      {
          int a = 1;
          int b = 1;
          int c = 1;
          int d = 1;
          int e = a + b + c + d;
      
          //...
      }
      

      我们暂且不去管e = a + b + c + d有什么用(其实我就是瞎写的),但是很明显,对于不同的fvScalarMatrix和fvVectorMatrix,每个函数体内都需要写这些函数。

      对于OpenFOAM这种大型CFD求解代码,代码复用是难以接受的。面向对象中的继承可以一定程度上解决这个问题。我们这样考虑:既然fvScalarMatrix和fvVectorMatrix都需要计算e = a + b + c + d,为什么不定义一个总管来计算,然后在fvScalarMatrix和fvVectorMatrix调用就可以了?这种思想形成了面向对象中的继承。

      因此上面的代码可以这样写:

      //- 大总管
      fvMatrix::calculateE()
      {
          int a = 1;
          int b = 1;
          int c = 1;
          int d = 1;
          int e = a + b + c + d;
      }
      
      //- fvScalarMatrix是fvMatrix类型的继承类
      fvScalarMatrix::solve()
      {
          calculateE()
      
          //...
      }
      
      //- fvVectorMatrix是fvMatrix类型的继承类
      fvVectorMatrix::solve()
      {
          calculateE()
      
          //...
      }
      

      在OpenFOAM代码中,这种通过继承减少代码复用的情况在每一个类中都可以见到,比如在viscosity粘度模型中,具体的幂率粘度模型以及BC粘度模型都可以调用viscosity(大总管)中定义的strainRate()函数:

      0_1511430572870_草图.png

      多态

      面向对象中的多态主要可以实现函数的多重定义,也可以减少代码复用并且使得代码架构更加简洁。在说起多态的时候,我更倾向于从OpenFOAM中的运行时选择 RunTimeSelection谈起。

      运行时选择在CFD中非常重要,举个小李子,如果你在算法中需要使用RANS湍流模型,你在传统的代码上需要这样定义

      RASN.solve();
      

      如果你不知道选择RANS还是LES还是DNS等,你可能要通过关键词来实现如:

      if (turbulenceType == "RANS")
          RANS.solve();
      if (turbulenceType == "LES")
          LES.solve();
      if (turbulenceType == "PANS")
          PANS.solve();
      if (turbulenceType == "DES")
          DES.solve();
      else
          DNS.solve();
      

      你大可以通过这种if来实现选择具体的湍流模型,但是这种每个时间步进行的选择是耗费时间的!

      运行时选择是结合智能指针的一种机制。如果你不了解指针或者你觉得指针头晕,我用下面这个代码表示通过运行时选择对上述代码进行的简化:

      autoPtr<turbulenceModel> turPtr(turPtr::New(turbulenceType));
      
      turPtr->solve();
      

      是的,下面两行实现了上面N行的效果。最重要的是,你省略了大量的判断语句。

      下面是OpenFOAM中真实的通过多态实现的自动选择功能。在计算升力LiftForce的时候,需要调用升力系数Cl,OpenFOAM把具体的StaffMay升力系数计算方法和Tomiyama省力系数计算方法作为继承类,实现了Cl()函数的多态。

      0_1511432057281_草图.png

      封装

      面向对象最后一个特性就是封装了。封装主要是可以把你的实现(函数)隐藏起来,并且不让用户知道。由于OpenFOAM是开源的代码,因此OpenFOAM并没有此意。

      这种隐藏实现的细节的另一个特点是用户不需要关心到底是怎么样去实现,比如OpenFOAM里面的fvScalarMatrix类型,在求解的时候,用户只需要TEqn.solve()就可以。完全不需要关心里面具体怎样solve()的。

      Your Code Your Way

      所以说,由于OpenFOAM这种逆天神级的C++操作,用户在学习OpenFOAM代码的时候,基本上找不到C++基本的各种类型,完全是OpenFOAM自己定义的类型。因此这个学习OpenFOAM的过程,更倾向是在学习OpenFOAM的自定义类型而不是学习C++,当然这个要建立在学习C++基础之上。

      如果各种类继承感觉很晕的话,用户一定就要用么?No。连Elsevier在投稿的时候都提供Your Paper Your Way,你自己写的代码当然也是Your Code Your Way。完全可以面向过程,不用管传递引用还是指针,直接传递拷贝复制就可以。大家更关心的是你的代码能不能出结果,写文章,慢一点还是相对可以忍受。

      底层和架构

      很遗憾上面谈的也只是OpenFOAM代码中的冰山一角,并且和CFD的具体算法模型关系很大。OpenFOAM更加底层的实现偏离CFD很远,比如数据输入和输出、MPI的实现、网格分解算法等,这些我也没有研究过。其他的ID可能会有更丰富的讨论。

      谈完了美妙绝伦的继承、封装和多态,剩下的就是架构。不管是在CFD代码中,还是互联网大厂中,架构师一般都是最高薪的。当然互联网那面的架构师由于行业特性,基本上属于管理层了。还有好多不同的架构师定义。

      但是CFD代码架构师和互联网那面还有所区别,在这里我们讨论纯粹的CFD代码架构师而不是那种设计到管理层面的架构师。一个好的CFD架构师需要能在统揽算法全局的基础上,在顶端设计好代码结构。举个例子,比如OpenFOAM中的thermo类型,这是一个巨大的类。架构师的作用就是要搭建好这个类型的基本类型以及衍生类型,哪些需要提供接口,哪些可以封闭,哪些可以嵌套。

      否则的话你可能加一个算法,要么硬植入,要么重新架构。这也就是为什么我最近重新写代码了,因为要重新设计代码的结构。很遗憾目前我还不能做到对算法有一个全局的概念,远不能达到架构师的地步。

      最后,可能有的刚入门CFD的朋友不知道我说的是什么,但你总会明白的。

      在这里声明下:这篇文章是李东岳写的。

      :huahua:

      CFD高性能服务器 http://dyfluid.com/servers.html

      M 1 条回复 最后回复 回复 引用
      • sibo
        sibo 最后由 编辑

        感谢东岳前辈的总结!非常生动~
        一开始总觉得OF把code封装成这样会不会是故意的,不过后来发现如果直接用C++代码,可能入门的时间更久。
        现在还完全处于“my code my way”的阶段哈哈,做好validation再着手学习结构设计~

        1 条回复 最后回复 回复 引用
        • .J.
          .J. 最后由 编辑

          Weller是一个狂热的开源软件抵制者

          这句话是不是有笔误

          Blog: http://www.cnblogs.com/Jay-CFD/
          Research Gate: https://www.researchgate.net/profile/Weijie_Yin2

          1 条回复 最后回复 回复 引用
          • P
            peperpanDUT 最后由 编辑

            此坑甚深,marryed first then to be a CFDer

            1 条回复 最后回复 回复 引用
            • W
              wwzhao 教授 最后由 编辑

              OpenFOAM不但用了大量面向对象的特性,而且还用了很多泛型编程/元编程的思想,这两部分都是C++的难点。

              1 条回复 最后回复 回复 引用
              • M
                mohui @李东岳 最后由 编辑

                @李东岳 每次看thermo的类就是头疼,看了一段时间放弃了,想想不甘心又去看,如此反复真心折磨人啊。

                1 条回复 最后回复 回复 引用
                • 李东岳
                  李东岳 管理员 最后由 李东岳 编辑

                  @sibo Your code your way挺好,我支持你小伙子,
                  @J 是的,写反了。
                  @peperpanDUT 哈哈,做CFD先结婚
                  @wwzhao 是的,OpenFOAM模板用出了花
                  @mohui 你用的什么编辑器看代码?gedit?

                  CFD高性能服务器 http://dyfluid.com/servers.html

                  M 1 条回复 最后回复 回复 引用
                  • M
                    mohui @李东岳 最后由 编辑

                    @李东岳 由于thermo是个大类很多东西所以看起来就很繁琐,虽然也知道个中的继承关系,但是看起来就是累:crying: 。我用的是sublime看代码。

                    1 条回复 最后回复 回复 引用
                    • 黄
                      黄岛主HEU 最后由 编辑

                      @李东岳 我辈楷模 👍

                      1 条回复 最后回复 回复 引用
                      • L
                        LiuSW 最后由 编辑

                        期待@东岳 老师可以写一篇介绍OpenFoam整体程序架构的文章,供大家学习,也可以将其架构设计实现在自己的非OpenFoam代码中、。

                        1 条回复 最后回复 回复 引用
                        • 同学博
                          同学博 最后由 编辑

                          学习了🐶

                          李东岳 1 条回复 最后回复 回复 引用
                          • 李东岳
                            李东岳 管理员 @同学博 最后由 编辑

                            @同学博
                            才学习啊 :wocao: 你都混论坛好久了 哈哈

                            CFD高性能服务器 http://dyfluid.com/servers.html

                            1 条回复 最后回复 回复 引用
                            • 气
                              气固两相流 最后由 编辑

                              受教了东岳老师

                              气固两相流模拟

                              1 条回复 最后回复 回复 引用
                              • R
                                random_ran 副教授 最后由 编辑

                                @东岳 谢谢东岳老师的分享。

                                我想补充一点:

                                开源软件虽然是大多数人都听过的,但实际上更准确的说法是自由软件(FOSS )。这是 OF 官网的自我介绍:

                                OpenFOAM is the leading free, open source software for computational fluid dynamics (CFD), owned by the OpenFOAM Foundation and distributed exclusively under the General Public Licence (GPL).

                                两个术语:"开源"和"自由"的区别:wiki 上有这样的解释。

                                Yours in CFD,

                                Ran

                                bestucan 1 条回复 最后回复 回复 引用
                                • bestucan
                                  bestucan 版主 副教授 @random_ran 最后由 编辑

                                  @random_ran 刚开始是英语用词的争议,用的是free。本来想表达自由,但是free很容易被理解成免费,所以free这个词受到了抵制(程序员也要吃饭)。才有了open source这个词。FOSS组织成立早,那时候还没free和open source争议。但是你看 开源中国,没有叫自由中国。新的开源软件多以 libre- 前缀冠名,都是为了避免用free。free中的免费含义有对程序员工作成果的不尊重。

                                  事实上没有任何代码是自由的,开源的代码都有许可证,代码的使用都要受许可证限制。

                                  至于更细致的划分,一群满口哲学的程序员,天天争、分辨、一大堆许可证。

                                  滚来滚去……~(~o ̄▽ ̄)~o 滚来滚去都不能让大家看出来我不是老师么 O_o

                                  异步沟通方式(《posting style》from wiki)(下载后打开):
                                  https://www.jianguoyun.com/p/Dc52X2sQsLv2BRiqnKYD
                                  提问的智慧(github在gitee的镜像):
                                  https://gitee.com/bestucan/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md

                                  1 条回复 最后回复 回复 引用
                                  • 尼古拉斯
                                    尼古拉斯 最后由 李东岳 编辑

                                    刚从LB的坑出来,就是那种your code your way那种感觉,被 @mohui 带到OF来了,多看下架构顶层什么的,希望有一天能学 @东岳 在LB开源上做点自己的贡献,仅此而已。哈哈

                                    1 条回复 最后回复 回复 引用
                                    • 爱
                                      爱学习的LDH 最后由 编辑

                                      注册CFD中文网一段时间了,之前一直用商软做CFD,最近感觉不学习一点编程,不研究一下CFD理论,难以适应未来的发展,因此开始学习OpenFOAM,就只不知道写文章大概需要多久?

                                      哎 1 条回复 最后回复 回复 引用
                                      • Z
                                        Zhoujq 最后由 编辑

                                        @东岳 老师写的太好了,这是个艰辛的道路

                                        1 条回复 最后回复 回复 引用
                                        • 哎
                                          哎呦不错哦 @爱学习的LDH 最后由 编辑

                                          @爱学习的LDH 俺也一样哈哈哈握爪

                                          1 条回复 最后回复 回复 引用
                                          • 李东岳
                                            李东岳 管理员 最后由 编辑

                                            因此开始学习OpenFOAM,就只不知道写文章大概需要多久?

                                            看是否有人带你。我这面今年带了一个老师,算是互相学习,3月份开始合作,现在已经开始写文章了。这个老师自身也是很给力的。

                                            自己弄的话很慢,我当时纯自悟,11年入学之后,到13年,纯学openfoam,啥文章没有,出国之后,那面导师带我,第一篇文章用了1年时间。这个是比较典型的出文章速度。几个月出文章,肯定需要一个老手带。

                                            CFD高性能服务器 http://dyfluid.com/servers.html

                                            1 条回复 最后回复 回复 引用
                                            • J
                                              Jacob Z 最后由 编辑

                                              名称空间中有名称空间,类中有类,函数中有函数。初学者感觉OF的代码首先是把“::”的前前后后是什么东西搞明白。我这个说法对吗老师?:135:

                                              bestucan 1 条回复 最后回复 回复 引用
                                              • bestucan
                                                bestucan 版主 副教授 @Jacob Z 最后由 编辑

                                                @Jacob-Z 搞不明白,或者说不能分开搞明白,这是个知识网,交错分布,不能一小块一小块的搞明白,否则老得回头看回头搜,时间成本更大。

                                                滚来滚去……~(~o ̄▽ ̄)~o 滚来滚去都不能让大家看出来我不是老师么 O_o

                                                异步沟通方式(《posting style》from wiki)(下载后打开):
                                                https://www.jianguoyun.com/p/Dc52X2sQsLv2BRiqnKYD
                                                提问的智慧(github在gitee的镜像):
                                                https://gitee.com/bestucan/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md

                                                J 1 条回复 最后回复 回复 引用
                                                • J
                                                  Jacob Z @bestucan 最后由 编辑

                                                  @bestucan 感谢感谢,先看再说吧:146:

                                                  1 条回复 最后回复 回复 引用
                                                  • 五好青年
                                                    五好青年 最后由 编辑

                                                    点赞收藏,学习

                                                    I am a CFD machine with no emotions. Welcome to browse my Bilibili, search: seeeeeeeeeeer

                                                    1 条回复 最后回复 回复 引用
                                                    • J
                                                      Joann 最后由 编辑

                                                      学OF时间长了就越明白OF编程的这种独特,刚开始入门知道用的是C++我还找了以前学C++的书出来重刷,但是后来发现OF虽然也是基于C++但是自己很有自己的特点,所以如果C++不好的入门者也不用担心,耐心点慢慢看OF的码有不懂的就网上搜一搜别人的解析还是能理解的。

                                                      Hello, CFD. Hello, OpenFOAM.

                                                      1 条回复 最后回复 回复 引用
                                                      • First post
                                                        Last post