同步操作将从 poplee/openFoamUserManual 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
在OpenFOAM中,有两种主要的后处理方法。首先,有一些工具在模拟完成后执行。这些工具处理模拟结果的写入数据。sample和paraView是这类的两个工具。
除此之外,还有实时后处理。实时后处理是在生成模拟结果数据时执行某种操作。因此,实时后处理允许更精细的时间问题。函数对象,例如用于计算力或阻力系数,是一个实时后处理的示例。这种方法的最大缺点是,用户开始模拟之前,必须知道预期的后处理的步骤。有关实时后处理详细信息请看http://www.openfoam.com/features/runtime-postprocessing.php。
一般来说,函数对象是以与函数类似的方式使用的对象。函数对象的这一主要优点是它们可以有一个永久的状态。此状态可用于存储数据(在“调用”函数对象之间)。一个非常有说服力的例子是OpenFOAM的函数对象 fieldAverage,它用于计算场的时均值。此函数对象需要在每次计算时间步长时更新自身,并且当前的时均场需要在fieldAverage的“调用”之间保留。
函数对象通常用于一个特定的目的,例如计算场量的时均值。因此,在OpenFOAM中可用的函数对象数量很多,而且在持续增加。下面列出一些,让人了解OpenFOAM函数对象涵盖任务之广泛:
fieldAverage 计算场量的时均值
fieldValue系列 计算场量(或其他操作)的空间平均值
forces 计算物体(表面)上的力
forceCoeffs 计算力的系数,例如阻力、升力和扭矩
sampledSet 保存某个区域的场量的值,例如沿一条直线
probes 在某些点保存场量值
streamLine 计算流线
scalarTransport 求解被动标量输运方程
codedFunctionObject 在一个不是从零头开始的框架中实现自己的函数对象
上面的列表只是可用功能的一小部分。所有的可用函数对象资料,查看OpenFOAM的源码[141]。
使用函数对象进行实时后处理是OpenFOAM的一个特性,它在应用程序和日常使用非常多,这与mesh类的内部工作方式不同。因此,函数对象更受开发者关注的是添加新的函数对象,扩展已有的函数对象,或重新组织和重命名现有函数对象。
前两点(添加和扩展)显然是对用户有利,而后一点(重组)在减少代码重复或便于维护方面,最可能对开发人员有利。函数对象的重组可能和重命名同步进行[142]。在这种情况下,你可能需要修改函数对象定义,当将你的算例迁移到新的[143]版本时。
除了使用最新版本的OpenFOAM的所有其他好处外,尤其是在函数对象,如果OpenFOAM的版本已经包含了一个实现你所需功能的函数对象,您就可以不必自己开发一个函数对象。
函数对象在文件controlDict中定义。在那里创建一个包含所有必要的信息的函数字典。列表320显示了这样一个定义的基本结构。
每个函数都有一个名称。在列表320中,这个名称在NAME占位符处被声明。这个名称也是OpenFOAM在算例目录中创建的文件夹的名称。在那里,存储所有由函数对象产生的数据。
每个函数对象也有一个类型。需要在TYPE占位符的位置指定此类型。类型必须来自可用函数的列表。要了解哪些函数可用,则可以使用banana-trick[144]。列表321显示了由banana-trick引起的错误消息。
占位符LIBRARY标记需要输入库名称的位置。函数对象不是一个单独可执行的程序。它只是一个供其他程序使用的库。在在我们的例子中,函数对象由解算器调用。因此,函数对象不会编译成可执行的。编译器在编译函数对象时创建库。此库包含机器可读形式的函数。
关键字**enabled**是可选的。使用此关键字函数,对象可以从执行中排除。
functions
{
NAME
{
type TYPE ;
functionObjectLibs (" LIBRARY ");
enabled true;
/*
Definition
*/
}
}
列表320:文件controlDict中函数对象的定义
--> FOAM FATAL ERROR :
Unknown function type banana
Valid functions are :
13
(
cellSource
faceSource
fieldAverage
fieldCoordinateSystemTransform
fieldMinMax
nearWallFields
patchProbes
probes
readFields
sets
streamLine
surfaceInterpolateFields
surfaces
)
列表321 :banana-trick的输出;应用于关键字type
所有函数对象或多或少都与基类functionObject直接相关,后者在文件**$FOAM_SRC/OpenFOAM/db/functionObjects/functionObject/functionObject.H**中定义,这个类定义
所有函数对象的最小公共行为。因此,学习这个类,正如它应用于所有函数对象一样,我们也许会有回报。
函数对象的阶段
一些OpenFOAM函数对象可能有一些需要更新的内部状态,而另一些对象有一些内部状态需要更新时,可能不需要内部状态。简单的函数对象,后一类情况,例如,函数对象fieldValue族中的函数对象surfaceRegion,只需将指定patches程序中的数据写入磁盘情况,将选定的数据写入磁盘可能会失败。这只是在写入时才执行。
另一方面,函数对象可能需要从结果数据中计算数据,因此需要一个内部状态,例如,fieldAverage函数对象需要为连续更新时均值,即使它不太频繁地将它们写入磁盘。
因此,函数对象的操作阶段分为执行(用于更新其内部状态)和写入(用于写入数据,并计算要写入的数据,这不是内部状态)
执行和写控制
何时写入的函数对象的属性是writeControl和writeInterval,在OpenFOAM旧版本中,这些属性是outputControl和outpunterval。它们控制从函数对象写入磁盘数据的时间和频率。
存在一对相似的控件(executeControl和executeInterval)来控制函数对象的执行,即内部状态更新。
请注意,当能够使用writeInterval adjustableRunTime设置时;对于函数对象的写入间隔,一般来说,我们需要确保对模拟进行相同的设置。如果模拟使用设置writeInterval runTime,则函数对象的设置被否决。
启用
启用标志控制是否启用函数对象。这需要一个布尔值和控制是否执行函数对象。这对测试或调试模拟算例可能很有用。此标志允许您在不从controlDict 中删除的情况下,定义和停止使用函数对象。从算例文件编辑的角度来看,这个标志的一个粗暴的替代方法是注释函数对象定义。但是,将标志从“开”改为“关”,或者相反,所需更少字符,相比更改为注释和取消注释[145]。
timeStart和timeEnd控制何时开始和何时停止使用函数对象。这些控件是可选的,在大多数情况下被省略。当省略时,默认行为是执行函数对象,从模拟开始直到模拟完成。事实上,默认值是一个负数,对于timeStart和timeEnd来说是个大得离谱的数字[146]。因此,在timeStart的默认值之前,不会启动任何可能的模拟,或者任何大于timeEnd的默认值。这样,一个简单的与当前时间进行比较就足够了,就不需要条件语句了。
region关键字控制函数对象应用于哪个网格区域。只有一个网格区域时都可以省略,这种情况下说明网格区域是多余的。然而,在OpenFOAM中也有具有多个网格区域的,如共轭传热模拟。在这种情况下,当求解传热时有一个网格(区域)为流体区域,一个网格(区域)为的固体部分。在这种情况下,我们可以使用一个函数对象来记录流体和固体区域的平均温度。因此,我们指定两个函数对象来计算体积平均温度,但是,我们需要指定要为其执行函数对象的区域。
负责选择要操作的网格区域的(抽象类[147])基类是regionFunctionObject。许多函数对象或多或少是直接从regionFunctionObject派生的。其中包括fieldValues系列的函数对象以及fieldMinMax和fieldAverage。
函数探针在空间中的指定点保存特定场量的值。列表322显示了一个探针函数对象定义的示例。
此函数对象的类型为probes。函数对象的名称是probes1。此函数生成的数据存储在probes1目录中。此目录包含一个子目录。此子目录名称对应于模拟开始的时间。这样可以防止文件在某个时间点继续模拟时被覆盖。
图112显示了模拟结束后的目录树。在那里,probes1文件夹包含一个名为0的子目录。这是模拟开始的时间。0文件夹包含文件p和U。
关键字outputControl和outputInterval是可选的。正如他们的名字所示,他们控制着数据写入硬盘的方式。
字段包含感兴趣场的名称。probeLocations 包含一系列点。计算这些点位置指定场的数据,并将其写入文件。文件名就是场名。列表322将生成两个文件。文件p包含所有位置的压力值,文件U将包含所有位置的速度值。
probes函数包含在文件中libsampling.so文件。 这些信息可以从教程获得。有关如何在教程中搜索特定信息的更多信息,请参见第66.3节。
functions
{
probes1
{
type probes ;
functionObjectLibs (" libsampling .so ");
enabled true ;
outputControl timeStep ;
outputInterval 1;
fields
(
p
U
);
probeLocations
(
( 0.0254 0.0253 0 )
( 0.0508 0.0253 0 )
);
}
}
列表322:controlDict文件中probes的定义
图112: 模拟结束后目录树的一部分
区域外的探测位置
如果探针位置在域之外,OpenFOAM将发出警告消息并继续模拟。
--> FOAM Warning :
From function findElements :: findElements ( const fvMesh &)
in file probes / probes .C at line 102
Did not find location (0.075 0 0.48) in any cell. Skipping location.
列表323:探针位于区域外
未知和不存在的场
如果探测字典包含不存在要探测的字段,则不会警告或发布错误消息。OpenFOAM只是继续计算。如果字典中没有要探测的有效字段,则不会执行探测功能。因此,不会创建存储数据的文件夹。
在动网格中使用探针
当我们使用探针时,OpenFOAM会在网格中搜索包含指定探针位置的单元。更具体地说,它确定包含探针位置的单元的单元索引。因此,OpenFOAM可以很容易得到探测场的单元值。实际上,OpenFOAM中的一个场是一个值列表,而单元索引用于导航列表。
然而,当我们使用移动网格时,与空间中某一点相关的单元索引,在时间上可能会发生变化,例如旋转网格区域内探测一个点时。因此,每次网格更新时,需要确保被探测的单元索引也被更新。
在OpenFOAM中,探针有一个布尔标志(fixedLocations)来控制单元索引的更新,默认情况下,此标志设置为true,表示不需要更新。在下面列表324中,我们看到头文件probes.C中此标志的说明。
// - Fixed locations , default = yes
// Note : set to false for moving mesh calations where locations
// should move with the mesh
bool fixedLocations_ ;
列表324:在probes.H中fixedLocations布尔标志的描述
使用移动网格时,将fixedLocations标志添加到probesDict中,如清单325所示下面。
fields
(
...
)
probeLocations
(
...
)
// add this for cases using moving meshes
fixedLocations false ;
列表325:使用带有动网格的探针时,向probesDict添加fixedLocations标志
fieldAverage计算时均场。列表326显示一个函数已设置例子。
functions
{
fieldAverage1
{
type fieldAverage ;
functionObjectLibs ( " libfieldFunctionObjects .so" );
enabled true ;
outputControl outputTime ;
fields
(
Ua
{
mean on;
prime2Mean off ;
base time ;
}
);
}
}
列表326:文件controlDict中fieldAverage函数对象的定义
fieldAverage函数对象可以提供一个平均窗口尺寸和名称来计算滑动平均。在这种情况下,生成的平均值场除了以场命名和加后缀Mean,还将窗口名作为文件名后缀。使用此功能,可以计算一个场的多个平均值。列表327显示了场U.water的两个平均值。
如果没有指定窗口,fieldAverage从函数对象的开始时间计算平均值。这个结果场包含要平均的场的名称和后缀Mean。如果指定了一个窗口尺寸和窗口名称,则结果场的名称将窗口名称作为扩展名。
U. water U. waterMean U. waterMean_w1
列表 327: U. water的多个平均值
面源从曲面(面)中提取数据。列表328显示了在一个切割平面上,场量的平均值如何设置。
functions
{
fieldAverage1
{
type fieldAverage ;
functionObjectLibs ("libfieldFunctionObjects.so" );
enabled true ;
outputControl outputTime ;
// Output to log & file (true) or to file only
log true ;
// Output field values as well
valueOutput false ;
// Type of source : patch/faceZone/sampledSurface
source sampledSurface ;
sampledSurfaceDict
{
// Sampling on triSurface
type cuttingPlane ;
planeType pointAndNormal ;
pointAndNormalDict
{
basePoint ( 0 0 0.3 );
normalVector ( 0 0 1 );
}
interpolate true ;
}
// Operation : areaAverage/sum/weightedAverage ...
operation areaAverage ;
fields
(
alpha
);
}
}
列表328:在controlDict文件中定义一个faceSource对象
列表329显示了一个函数对象的定义,该对象用于计算边界面上的体积流率。其中的关键点是定义权重场和使用求和运算。这个权重场是自动应用于后处理场的,不需要指定一个操作,如weightedSum。如果未定义权重场,则不使用权重场。
functions
{
faceIn
{
type faceSource ;
functionObjectLibs ("libfieldFunctionObjects.so");
enabled true ;
outputControl timeStep ;
log true ;
valueOutput false ;
source patch ;
sourceName spargerInlet ;
surfaceFormat raw;
operation sum;
weightField alpha1;
fields
(
phi1
);
}
}
列表239:在文件controlDict中定义一个faceSource对象
选项valueOutput将采样曲面上的场量值写入磁盘。当outputControl设置为timeStep时,会使用巨大的磁盘空间。在这种情况下,每个时间步都会写入场量值。除非确实需要,否则应禁用选项valueOutput。
图113显示了两个时间步写入磁盘后处理文件夹的内容。对于每个采样场,采样片上的场量值将写入磁盘的surface文件夹中的文件中。
图113:postPrecessing 文件夹中内容
cellSource函数对象作用于网格的所有单元或cellZone的单元。
列表330显示了cellSource函数对象的定义。在本例中,在左边的单元里,包含了区域的一部分。函数对象计算空气体积组分的体积平均值。这个关键字valueOutput设置为false,并被注释标记为邪恶,原因如第49.6.3条所述。
functions
{
airContent_left
{
type cellSource ;
functionObjectLibs ("libfieldFunctionObjects.so");
enabled true ;
outputControl timeStep ;
log true ;
valueOutput false ; // evil
source cellZone ;
sourceName left ;
operation volAverage ;
fields
(
alpha.air
);
}
}
列表330:cellSource函数对象使用例子
如果我们想后处理一个算例,我们使用创建自定义场的自定义求解器计算,并且后处理涉及这些自定义场,在运行后处理函数对象时,OpenFOAM很可能会抱怨这些场没有在数据库中。就在那时,读入场就可以上台了。
头文件中的说明如下:
从时间目录中读取场,并将其添加到万个数据库中,为进一步的后处理。
这个函数对象服务于读取指定场,并将这些场添加到数据库中。因此,添加后处理函数对象的这个函数对象,允许我们使用OpenFOAM的标准函数对象后处理任何自定义场。
如果我们想对默认情况下不写入的场进行后期处理,那么我们可以告诉OpenFOAM写入指定的场到磁盘中。此对象的文件头函数说明:
允许指定注册到数据库的对象的不同写入频率。
OpenFOAM让执行C++代码作为一个函数对象[148]成为可能。默认情况下此功能禁用。要激活它,必须更改一个标志。单个用户在**~/.OpenFOAM/$WM_PROJECT_VERSION/controlDict中设置,系统范围内的在$WM_PROJECT_DIR/etc/controlDict**中。在其中一个文件,列表331所示的标志必须设置为1。第一个文件可能不存在,即没有用户指定设置。作者没有探讨优先权问题(用户设置优先于系统范围设置)。
列表332显示这个特性的一个示例。读取场量U1、U2和p,并且一些计算值将打印到终端。
// Allow case - supplied C++ code (# codeStream , codedFixedValue )
allowSystemOperations 1;
列表331:运行 算例提供的 C++代码
extraInfo
{
type coded ;
functionObjectLibs ("libutilityFunctionObjects.so");
redirectType average ;
code
#{
const volVectorField& U1 = mesh().lookupObject<volVectorField>("U1");
const volVectorField& U2 = mesh().lookupObject<volVectorField>("U2");
Info<<" max U1 = "<<max(mag(U1)).value()<< ", U2 = "<<max(mag(U2)).value()<< endl ;
const volScalarField& p = mesh().lookupObject<volScalarField>("p");
Info<<"p min/max = "<<min(p).value()<< ", " << max(p).value()<<endl ;
#};
}
列表332:用C++定义一个函数对象
当求解器被调用时,所谓的编码函数对象会被即时编译。列表333显示了求解器输出的一部分。在进入时间循环和第一次计算之间,从controlDict读取代码并粘贴到一个编码functionObject的模板中。
Starting time loop
Using dynamicCode for functionObject extraInfo at line 69 in "/home/user/OpenFOAM /user-2.1.x/
run/twoPhaseEulerFoam/bubbleColumn/system/controlDict::functions::extraInfo"
Creating new library in " dynamicCode/average/platforms/linux64GccDPOpt/lib/
libaverage_731fed868edc5a1d75988808649ac874cf00e044.so"
Invoking "wmake -s libso/home/user/OpenFOAM/user-2.1.x/run/twoPhaseEulerFoam/bubbleColumn/
dynamicCode/average "
wmakeLnInclude : linking include files to ./lnInclude
Making dependency list for source file functionObjectTemplate.C
Making dependency list for source file FilterFunctionObjectTemplate.C
’/home/user/OpenFOAM/user-2.1.x/run/twoPhaseEulerFoam/bubbleColumn/dynamicCode/average/../
platforms/linux64GccDPOpt/lib/libaverage_731fed868edc5a1d75988808649ac874cf00e044.so’ is
up to date .
Courant Number mean : 1.68517e-05 max: 0.00363
Max Ur Courant Number = 0.00363
Time = 0.001
MULES: Solving for alpha1
列表333:C++编码函数对象的即时编译
OpenFOAM在算例目录中创建一个名为dynamicCode的目录。在那里,与编码函数对象有关的所有文件、源文件和二进制文件都可以找到。图114显示了OpenFOAM编译编码的functionObject后的目录树。
图114:编码函数对象编译后的目录
wallHeatFlux函数对象可用于确定壁面热流密度。默认情况下,wallHeatFlux计算所有patches中类型为wall的壁面热流密度。或者,patches列表可以传递给使用patches关键字的函数对象。
确定物理单位
在列表334的第7行中,我们看到壁面热流密度场用物理单位千克每立方秒初始化。在第17行中,我们看到壁热通量是由焓的热扩散率和焓内能场[149]的梯度的乘积计算得出的。
$$ \rm[wallHeatFlux] =[alpah] \cdot [he.snGrad()] \tag{161} $$
$$ \rm [wallHeatFlux] =\frac{kg}{m s} \cdot \frac{J}{kg} \frac{1}{m} =\frac{1}{m s} \cdot \frac{W s}{m} = \frac{W}{m^2} \tag{162} $$
上面的方程说明,如何通过这个函数对象,推导壁面热流密度的物理单位。实际上,结果是每平方米瓦特。注意,α场是热场焓的扩散系数[150]。
tmp<volScalarField> twallHeatFlux
(
volScalarField::New
(
type () ,
mesh_ ,
dimensionedScalar(dimMass/pow3( dimTime), 0)
)
);
/* some code removed for brevity */
forAll(wallHeatFluxBf, patchi )
{
if(!wallHeatFluxBf[patchi].coupled())
{
wallHeatFluxBf[patchi] = alphaBf[patchi]*heBf[patchi].snGrad();
}
}
列表334:wallHeatFlux.C中壁面热流密度的计算
wallHeatFlux函数对象,不仅将壁面热流作为一个场来计算,而且还可以打印每个patch的积分和极值到终端,并将这些值写入数据文件。积分值当然是每个patch传递的能量,是以瓦特为单位。
execFlowFunctionObjects是OpenFOAM的后处理工具。此工具允许用户执行功模拟完成后的函数对象。通常,函数对象是在模拟过程中执行的。然而,在某些情况下,将一个函数应用于已经完成的模拟的数据集是有用的,例如用于测试函数。
在单独的文件中定义函数对象
列表335显示了一个只包含函数对象定义的文件。为了清楚起见,这个文件名为functionDict。在单独的文件中定义函数在某种程度上反映了分工。文件controlDict控制求解器,而文件functionDict定义函数对象。文件
functionDict可以通过**#include语句包含在文件controlDict**中。参见第11.3.5节例子。
FoamFile
{
version 2.0;
format ascii ;
class dictionary ;
location " system ";
object functionDict ;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
functions
{
probes1
{
type probes ;
functionObjectLibs ("libsampling.so");
dictionary probesDict ;
}
}
列表335:在单独的字典中定义函数。文件functionDict
运行execFlowFunctionObejcts
必须告诉execFlowFunctionObjects,这些函数是在单独的文件中定义的。默认情况下,工具
读取文件controlDict。通过使用参数-dict,用户可以指定一个包含函数字典的替代文件。
execFlowFunctionObjects -noFlow -dict functionDict
列表336:调用execFlowFunctionObjects
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。