diff --git a/58..General_remarks_on_OpenFOAM_programming.md b/58..General_remarks_on_OpenFOAM_programming.md new file mode 100644 index 0000000000000000000000000000000000000000..40c8b6239e9acd259f1b07504d1b2fe81cb821a2 --- /dev/null +++ b/58..General_remarks_on_OpenFOAM_programming.md @@ -0,0 +1,142 @@ +### 58 关于OpenFOAM编程的一般评论 +本章为用户提供了关于植入自己的模型、求解器或者对现有代码进行二次开发的一般建议。 + +#### 58.1 准备任务 +##### 58.1.1 创建自定义目录 +为了将标准求解器和模型与用户自定义的求解器和求解模块区分开来,建议创建一些新的目录。不仅是为了与OpenFOAM安装的标准模型和应用程序区分开,而且可以使自定义的模型、应用程序与其他用户创建的模型、应用程序区分开。因此,每一个用户都拥有自己的目录。该用户目录的名字也要遵循OpenFOAM的命名规范,即将用户名与OpenFOAM的版本号结合,比如user-4.0。这样,也可以保持OpenFOAM-X版本的内容与OpenFOAM-Y的区分开来。 + +在此,我们遵循OpenFOAM标准求解器和模块的组织方式,其中源代码存放在目录$WM_PROJECT_DIR/applications/solvers 和$WM_PROJECT_DIR/OpenFOAM-2.1.x/ src中。因此,需要创建放置自定义源代码的文件夹:$WM_PROJECT_USER_DIR/applications/ solvers and $WM_PROJECT_USER_DIR/src。列表473展示了一些必要命令,打开终端并输入列表的命令即可完成该任务。 + +``` +cd $WM_PROJECT_USER_DIR +mkdir -p applications/solvers +mkdir src +``` +列表473:为用户的求解器和模块创建格式的目录 + +注意变量$WM_PROJECT_USER_DIR的使用,该变量解析为OpenFOAM安装的用户目录,还包含运行目录($ FOAM_RUN)。 + +#### 58.2 从现有代码开始 +##### 58.2.1 复制源代码 +如果想要创建一个新的模块或者求解器,一般推荐基于OpenFOAM标准安装的模块或求解器进行开发,并选取最接近您预期实现功能的标准模型或求解器。 + +##### 58.2.2 更改编译设置 +在继续进入任何其他编译工作之前,必须先从OpenFOAM的标准代码中更改编译设置。 + +###### 更改可执行文件或库的名称 +可执行文件或库的名称取决于相应求解器模块的源代码中Make/files文件的设置。对于求解程序,可执行文件的名称由EXE设置确定。列表475展示了如何定义求解器pimpleFoam的可执行文件名称。 + +``` +EXE = $(FOAM_APPBIN)/pimpleFoam +``` +列表474:pimpleFoam源代码中Make/files文件关于pimpleFoam可执行文件的名称设置 + +类似地,共享库名称的定义是通过库源代码中Make/files的LIB设置完成的。 + +``` +LIB = $(FOAM_LIBBIN)/liblagrangian +``` +列表475:在文件Lagrangian库的源代码中,通过Make / files设置LagrangianParticles库的共享库名称 + +EXE和LIB的设置采用完整的文件路径。因此,在分配设置(=符号)附近,可以找到目录、路径名分隔符(/符号)以及可执行文件或共享库的实际名称。 + +###### 更改可执行文件或库的位置 +为了避免混淆用户自定义求解器、模块与OpenFOAM标准安装的求解器、模块,除了更改可执行文件或共享对象的文件名之外,还可以更改可执行文件或共享对象的存放路径。 + +对于用户创建的求解器和模型,建议分别将路径说明符更改为FOAM_USER_APPBIN或FOAM_USER_LIBBIN。因此,用户生成的求解器和库也与标准求解器和库在存储空间上分离。 + +如果您使用的是全系统的OpenFOAM安装,则您很可能仅具有对FOAM_APPBIN和FOAM_LIBBIN目录的读取权限。因此,即使没有错误,尝试编译您的求解器或模型也将失败。在这种情况下,产生的错误消息可能包含一些有关缺少权限的提示。 + +###### 检查Make/files +调整好编译设置后,请仔细检查Make/files文件。列表476展示了突出标记的关键条目。在列表中,源文件与可执行文件同名。同时可执行文件将放置在用户创建的应用程序目录中。 +``` +myApplication.C +EXE = $(FOAM_USER_APPBIN)/myApplication +``` +列表476:Make/files的内容 + +Make/files文件控制编译的内容以及所生成可执行文件的存储位置。因此,正确设置Make/files文件将使您免于遭受其他破坏,例如,新模型或应用程序所基于的模型或应用程序。另一方面,文件Make/options控制成功编译模型或应用程序所依赖的内容。最初错误设置了Make/options也不会造成任何损害。 + +###### 检查Make/options + +Make/options文件告诉编译器在哪里可以找到其他源文件,并告诉链接器在哪里可以找到其他库。如果使用现有模型或其他目录中的源文件,则仅需要编辑Make/options文件。 +然而,通常都是前一种情况。 + +文件Make/options的内容分为两部分。第一部分,是一些编译器需要寻找所包含源文件的路径。第二部分,是链接器用来链接当前模型或应用程序所需要的库列表。 + +``` +EXE_INC = \ +-I$(LIB_SRC)/meshTools/lnInclude \ +-I$(LIB_SRC)/finiteVolume/lnInclude + +LIB_LIBS = \ +-lmeshTools +``` +列表477:Make/options的内容 + +###### 初始编译 +一旦对现有源代码完成复制,最重要的是更改编译设置,之后就可以运行初始编译。尽管此时源代码中的任何内容都没有改变,但是建议运行初始编译来检查我们是否正确设置了编译设置。 +对于应用程序,只需执行wmake即可;对于共享库,运行编译可加上一个附加参数:wmake libso。编译后,已编译的二进制文件应分别显示在FOAM_USER_APPBIN或FOAM_USER_LIBBIN中。 + +#### 58.3 从头开始创建源代码 +某些用户可能不需要以上所讨论的步骤。OpenFOAM提供了一些宏,为创建新的应用程序、边界条件或函数对象时提供基本的源代码框架。在从头开始创建新应用程序的情况下,用户只需调用宏foamNewApp并提供所需的应用程序名称即可,可执行文件的路径将自动设置为FOAM_USER_APPBIN,新功能对象或边界条件将自动编译为FOAM_USER_LIBBIN。 + +#### 58.4 使用用户创建的库 +在求解器和库之间进行区分是一件好事,这样我们可以创建和重用某些模型。如果希望自定义的应用程序调用之前自己创建的模型,则需要告诉编译器和链接器在哪里可以找到自定义的(已编译)模型。 +在列表478中,可以看到应用程序的文件Make/options中的必要条目,该应用程序将使用用户创建的库,其名称为myLibrary。列表第4行代码中的绿线告诉编译器在哪里可以找到库myLibrary的源代码。 +在成功完成编译阶阶段后,需要将已编译的应用程序链接到已编译的库,即共享对象。这一过程在列表的第8行和第9行中展示。红线定义了在一个用来查找共享库的附加目录。 +处于良好编程风格的要求,需要将自己的库编译为FOAM_USER_LIBBIN,因此链接程序的附加目录为FOAM_USER_LIBBIN。 + +蓝线,即列表的第9行,告诉链接器myLibrary共享对象的名称。 + +``` +EXE_INC = \ +-I$(LIB_SRC)/meshTools/lnInclude \ +-I$(LIB_SRC)/finiteVolume/lnInclude \ +-I$(MY_LIB_SRC_PATH)/myLibary/lnInclude +LIB_LIBS = \ +-lmeshTools \ +-L$(FOAM_USER_LIBBIN) \ +-lmyLibary +``` +列表478:使用用户创建库的应用程序,相应make /option文件的内容 + +#### 58.5 陷阱 +修改现有模型或创建新模型可能会导致许多bug和错误。本节试图讨论其中的一些情况,这些情况经常发生,或者可能难以追踪。这样的清单永远不可能是完整的,并且显然偏向于作者所犯和遇到的错误。这些错误不一定仅限于OpenFOAM,此外,修改OpenFOAM涉及编程,而编程必然涉及bug和错误。享受这些内容吧。 + +##### 58.5.1 由于修改库导致的内存区段错误并且无法更新求解器 +库是代码的可重用部分,它们与使用它们的求解器无关。但是,如果修改了库并且无法重新编译正在使用所述库的求解器,这种独立性也会带来问题,即使所述求解器并没有涉及更改。可能会出现的问题是在构造修改对象时出现分段错误(简称为段错误)。不幸的是,segfault不会产生非常明显的错误消息,请参见列表479。请注意,我们假设该库的编译已成功完成。 + +``` +#0 Foam::error :: printStack(Foam:: Ostream &) at ??:? +#1 Foam:: sigSegv :: sigHandler(int) at ??:? +#2 ? in "/lib/x86_64 -linux -gnu/libc.so.6" +#3 ? in "/lib/x86_64 -linux -gnu/libc.so.6" Segmentation fault (Core dumped) +``` +列表479: 内存段错误 + +这种现象的原因是,求解器在启动时由于分段错误而严重失败,由于我们对库的修改改变了其内存布局。但我们没有重新编译求解器,造成求解器无法了解已更改的内存布局。因此,在求解器启动时,求解器为库的对象保留了不正确的内存量。在构造这些对象时,这种不匹配会导致分段错误。 +重新编译尚未解决的求解器,这个操作似乎违反直觉。但是,当库的内存布局已更改,求解器将根据旧的内存布局保留内存。重新编译求解器将仅更新内存分配。 + +该错误的棘手之处在于,它并不总是发生。如果我们改变库并且没有改变更改内存布局,一切都很好,不会发生错误。修改库并使用该库运行求解器,这样就可能导致有时起作用,有时导致失败。 +进一步阅读: +https://stackoverflow.com/questions/2346806/what-is-a-segmentation-fault +https://en.wikipedia.org/wiki/Segmentation_fault + +##### 58.5.2告诉求解器使用库的失败 +修改现有库或从头开始创建自己的库,将FOAM_USER_LIBBIN directory目录生成一个新的共享对象文件。但是,如果您希望求解器使用此库,则需要告诉求解器。默认情况下,应用程序不会加载FOAM_USER_LIBBIN中的模型! +可以通过controlDict中的libs列表条目实现,请参见第11.3.3节。不这样做会导致非常奇怪的情况。模型编译时没有报错,并且使用自己库的求解器在进行编译时也不会出错,案例设置似乎也没有错误。但是当尝试调用自己创建的模型时,案例就不会运行。在这种情况下,看似正确的案例设置会产生与banana测试相同的结果(请参见第11.2.1节),因为OpenFOAM无法找到与我们在案例文件中提供的名称相关的正确模型。 + +#### 58.6 小技巧 +###### 仔细检查是否编译到用户目录 + +始终确保将应用程序编译为FOAM_USER_APPBIN,将库编译为FOAM_USER_LIBBIN。58.2.2中讨论了这样做的原因以及如何确保这一点。 + +修改库时,同时对使用库的求解器进行重新编译 +这是看似无关紧要的步骤,但是可能会防止出现怪异的行为。上面58.5.1节讨论了重新编译使用最近修改库的求解器的原因。 +此外,尤其是在涉及模板时,例如当修改模板化的类时,对提供模板化模型的库和使用模板化模型的求解器进行重新编译是至关重要的。模板需要特别注意,关心和爱护,不要忽略它们。 + +###### 自由地使用Allwclean或者wclean +通过运行wclean来清理临时构建文件来取得良好效果。特别是当涉及模板类时,清除构建文件可能是必不可少的。 +另外,如果您更新OpenFOAM的基础版本,在重新编译自定义库和求解器时必需要清理构建文件。如果是安装OpenFOAM基础版本,则依赖项列表(即代码Make目录中存在的* .dep文件)可能包含可能已经不存在的文件的文件名。 +