OpenFOAM 中使用 functionObject

使用 functionObject 进行后处理或者 run-time 处理。新旧两个版本的 OpenFOAM,使用方法略微不同。

In OpenFOAM, functionObjects are code snippets that can be loaded into any solver during run-time. This enables each solver to be coupled with some additional functionality, that is independent from the flow model. All functionObjects have to be included in system/controlDict like the following:

functions
{
<name>
{
type <type>;
functionObjectLibs ("<lib>");
writeControl timeStep;
outputInterval 1;
// Specific parameters for the functionObject
}
}

使用方法

大概是 OF-4.0 以前的版本

  • 运行时:
    先在 controlDict 中添加 functions,然后直接运行算例即可。支持并行算例。
  • 运行后:
    先在 controlDict 中添加 functions,然后执行这个命令 execFlowFunctionObjects -noFlow
    支持并行,使用命令 mpirun -np 2 execFlowFunctionObjects -noFlow -parallel

OF-dev

  • controlDict 中添加 functions 之后,直接运行求解器即可。支持并行算例。

  • 运行后,在 controlDict 文件中添加 functions之后,运行 postProcess -fields '(T p U)'
    -fields 一定要加,因为这相当于输入的场信息,和 functionsfields 的不一样,那个是操作的场。输入的场要包含操作的场才行。

  • 高级用法:运行后,可以只对某个(些)时间文件夹进行处理,如:postProcess -fields '(T p)' -time '1.75e-05'。或者:postProcess -fields '(T p)' -time ':1.75e-05' 冒号表示从最开始到 1.75e-05 所有的时间。另外还可以处理不连续的时间,如 postProcess -fields '(T p)' -time '1.25e-05,1.75e-05' 用逗号隔开即可。运行 solver 时好像不支持只对某些时间段进行操作。
    支持并行,使用命令 mpirun -np 2 postProcess -fields '(T p U)' -parallel

functionObjects 分为两大类 libfieldFunctionObjectslibutilityFunctionObjects

所有可选的 type 可以通过这个命令获取: postProcess -list。另一个命令可以和它互相补充:foamList -functionObjects

libfieldFunctionObjects

常用操作举例:

vol 场操作

functions
{
volFieldValue1
{
type volFieldValue;
libs ("libfieldFunctionObjects.so");

log true;
writeControl writeTime;
writeFields true;

regionType cellZone;
name c0;
operation volAverage;

weightField alpha1;

fields
(
p
U
);
}
}

operation 有:

operation说明代码
CoVCoefficient of variation: standard deviation/mean
averageEnsemble averagegSum(values)/nCells()
maxMaximumgMax(values)
minMinimumgMin(values)
noneNo operation
sumSumgSum(values)
sumMagSum of component magnitudesgSum(cmptMag(values))
volAverageVolume weighted averagegSum(V*values)/this->V()
volIntegrateVolume integralgSum(V*values)
weightedAverageWeighted averagegSum(weightField*values)/gSum(weightField)
weightedSumWeighted sumgSum(weightField*values)
weightedVolAverageWeighted volume averagegSum(weightField*V*values)/gSum(weightField*V)
weightedVolIntegrateWeighted volume integralgSum(weightField*V*values)

Surface 场操作

operation:

operation说明代码
CoVCoefficient of variation: standard deviation/mean
averageensemble averagesum(values)/values.size()
maxmaximummax(values)
minminimummin(values)
noneno operation
sumsumsum(values)
sumMagsum of component magnitudessum(cmptMag(values))
areaAveragearea weighted averagesum(magSf*values)/sum(magSf)
areaIntegratearea integralsum(magSf*values)
areaNormalAveragearea weighted average in face normal directionvector( sum(values & Sf)/sum(mag(Sf)), 0.0, 0.0 )
areaNormalIntegratearea weighted integral in face normal directonvector( sum(values & Sf), 0.0, 0.0 )
weightedAreaAverageweighted area averagesum(weightField*magSf*values)/sum(magSf*weightField)
weightedAreaIntegrateweighted area integralsum(weightField*magSf*values)
weightedAverageweighted averagesum(weightField*values)/sum(weightField)
weightedSumweighted sumsum(weightField*values)
sumDirectionsum values which are positive in given direction
sumDirectionBalancesum of balance of values in given direction

Surface 场操作举例1

面平均,计算 f0 这个 faceZonezeta 的平均值

functions
{
poolHeight
{
type surfaceFieldValue;
libs ("libfieldFunctionObjects.so");
writeControl timeStep;
writeInterval 1;
log yes;
writeTotalArea no;
writeFields no;
regionType faceZone;
name f0;
operation areaAverage;
fields
(
zeta
);
}
};

Surface 场操作举例2

面求和,计算 inlet 这个 patchrhoPhi 的和

functions
{
inletFlux
{
type surfaceFieldValue;
libs ("libfieldFunctionObjects.so");
writeControl timeStep;
log true;
// Output field values as well
writeFields false;
regionType patch;
name inlet;
operation sum;
fields
(
rhoPhi
);
}
outletFlux
{
$inletFlux;
name outlet;
}
atmosphereFlux
{
$inletFlux;
name atmosphere;
}
}

时间平均

functions
{
field_average
{
type fieldAverage; // fieldAverage 是时间平均
functionObjectLibs ("libfieldFunctionObjects.so");
enabled true;
writeControl outputTime;
fields
(
U
{
mean on;
prime2Mean on;
base time;
}
k
{
mean on;
prime2Mean off;
base time;
}
);
}
}

更多关于时间平均的细节请看这里

极值

这个好像前边的场操作 volFieldValue 也能实现。

functions
{
minMax
{
// Type of functionObject
type fieldMinMax;
// Where to load it from (if not already in solver)
functionObjectLibs ("libfieldFunctionObjects.so");
// Function object enabled flag
enabled true;
// Log to output (default: false)
log false;
// Write information to file (default: true)
write true;
location no;
// Fields to be monitored - runTime modifiable
fields (U p T);
//fields (T);
writeControl timeStep;
writeInterval 2;
}
}

streamLine

functions
{
streamLines
{
type streamLine;
// Where to load it from (if not already in solver)
libs ("libfieldFunctionObjects.so");
// Output every
writeControl writeTime;
// writeInterval 10;
setFormat vtk; //gnuplot;//xmgr;//raw;//jplot;//csv;//ensight;
// Tracked forwards (+U) or backwards (-U)
trackForward true;
// Names of fields to sample. Should contain above velocity field!
fields (p k U);
// Steps particles can travel before being removed
lifeTime 10000;
// Number of steps per cell (estimate). Set to 1 to disable subcycling.
nSubCycle 5;
// Cloud name to use
cloudName particleTracks;
// Seeding method.
seedSampleSet
{
type uniform;
axis x; //distance;
start (-0.0205 0.001 0.00001);
end (-0.0205 0.0251 0.00001);
nPoints 10;
}
}
}

MachNo

functions
{
libs ("libfieldFunctionObjects.so");
Ma
{
type MachNo;
executeControl writeTime;
writeControl writeTime;
}
}

probes

functions
{
my_name
{
type probes;
probeLocations
(
(0.0 0.05 0.0)
);
functionObjectLibs ("libfieldFunctionObjects.so");
fields (T);
}
}

libutilityFunctionObjects:

所有可选 type:

abort
coded//使用代码
patchProbes
probes//检测某些点的某些物理量,需要指定 probeLocations fields,和上边重复了。。。
psiReactionThermoMoleFractions
removeRegisteredObject
residuals
rhoReactionThermoMoleFractions
setTimeStep//设置时间步长,如:从表格中读取,sine函数等。
sets
surfaces
systemCall
time
timeActivatedFileUpdate//可以设置多套controlDict,运行到某一时刻自动切换
writeDictionary
writeObjects//write一些计算过程中的对象,可以多输出一些信息

writeObjects

functions
{
writeFields // name of the function object
{
type writeObjects;
libs ( "libutilityFunctionObjects.so" );

objects
(
T U rho // list of fields/variables to be written
);

// E.g. write every 1e-5 seconds of simulation time only the specified fields
writeControl runTime;
writeInterval 1e-5; // write every 1e-5 seconds
}
}

You can also define multiple function objects in order to write different subsets of fields at different times. You can also use wildcards in the list of fields- for example, in order to write out all fields starting with “RR_” you can add

"RR_.*"

可以输出每个组分的反应速率?放热率呢?如何输出?Qdot[1 -1 -3 0 0 0 0] 是dQ[1 2 -3 0 0 0 0]除以体积,dQ的单位是J/s。那么我们需要对Qdot进行volumeIntegrate 操作。

定义:fvc::volumeIntegrate(df)=df.mesh().V()*df.field()//df是被操作的场
使用:volScalarField dQ = fvc::volumeIntegrate(Qdot);//dQ的量纲是多少?

setTimeStep

functions
{
timeStepping
{
type setTimeStep;
functionObjectLibs ("libutilityFunctionObjects.so");
enabled yes;
deltaT tableFile;
file "system/deltaTvalues";
}
}

timeActivatedFileUpdate

运行时更改某些文件

Performs a file copy/replacement once a specified time has been reached.

Example usage to update the fvSolution dictionary at various times throughout the calculation:

\verbatim
fileUpdate1
{
type timeActivatedFileUpdate;
libs ("libutilityFunctionObjects.so");
writeControl timeStep;
writeInterval 1;
fileToUpdate "$FOAM_CASE/system/fvSolution";
timeVsFile
(
(-1 "$FOAM_CASE/system/fvSolution.0")
(0.10 "$FOAM_CASE/system/fvSolution.10")
(0.20 "$FOAM_CASE/system/fvSolution.20")
(0.35 "$FOAM_CASE/system/fvSolution.35")
);
}
\endverbatim

coded

functions
{
timeStep
{
type coded;
libs ("libutilityFunctionObjects.so");
name setDeltaT;
code
#{
#};
codeExecute
#{
const Time& runTime = mesh().time();
if (runTime.timeToUserTime(runTime.value()) >= -15.0)
{
const_cast<Time&>(runTime).setDeltaT
(
runTime.userTimeToTime(0.025)
);
}
#};
}
}
functions
{
error
{
// Load the library containing the 'coded' functionObject
libs ("libutilityFunctionObjects.so");
type coded;
// Name of on-the-fly generated functionObject
name error;
codeEnd
#{
// Lookup U
Info<< "Looking up field U\n" << endl;
const volVectorField& U = mesh().lookupObject<volVectorField>("U");
Info<< "Reading inlet velocity uInfX\n" << endl;
scalar ULeft = 0.0;
label leftI = mesh().boundaryMesh().findPatchID("left");
const fvPatchVectorField& fvp = U.boundaryField()[leftI];
if (fvp.size())
{
ULeft = fvp[0].x();
}
reduce(ULeft, maxOp<scalar>());
dimensionedScalar uInfX
(
"uInfx",
dimensionSet(0, 1, -1, 0, 0),
ULeft
);
Info << "U at inlet = " << uInfX.value() << " m/s" << endl;
scalar magCylinder = 0.0;
label cylI = mesh().boundaryMesh().findPatchID("cylinder");
const fvPatchVectorField& cylFvp = mesh().C().boundaryField()[cylI];
if (cylFvp.size())
{
magCylinder = mag(cylFvp[0]);
}
reduce(magCylinder, maxOp<scalar>());
dimensionedScalar radius
(
"radius",
dimensionSet(0, 1, 0, 0, 0),
magCylinder
);
Info << "Cylinder radius = " << radius.value() << " m" << endl;
volVectorField UA
(
IOobject
(
"UA",
mesh().time().timeName(),
U.mesh(),
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
U
);
Info<< "\nEvaluating analytical solution" << endl;
const volVectorField& centres = UA.mesh().C();
volScalarField magCentres(mag(centres));
volScalarField theta(acos((centres & vector(1,0,0))/magCentres));
volVectorField cs2theta
(
cos(2*theta)*vector(1,0,0)
+ sin(2*theta)*vector(0,1,0)
);
UA = uInfX*(dimensionedVector(vector(1,0,0))
- pow((radius/magCentres),2)*cs2theta);
// Force writing of UA (since time has not changed)
UA.write();
volScalarField error("error", mag(U-UA)/mag(UA));
Info<<"Writing relative error in U to " << error.objectPath()
<< endl;
error.write();
#};
}
}

Misc

probes 前面有另一种实现方法

functions
{
probes
{
type probes;
libs ("libsampling.so");
writeControl timeStep;
writeInterval 1;
probeLocations
(
(0 9.95 19.77)
(0 -9.95 19.77)
);
fixedLocations false;
fields
(
p
);
}
}

##等值面

functions
{
surfaces
{
type surfaces;
libs ("libsampling.so");
writeControl adjustableRunTime;
writeInterval 0.01;
timeStart 10;
surfaceFormat vtk;
fields (p_rgh U);
interpolationScheme cellPoint;
surfaces
(
interface
{
type isoSurface;
isoField alpha.water;
isoValue 0.5;
interpolate true;
}
);
}
}

forces

functions
{
forces
{
type forces;
libs ("libforces.so");
writeControl writeTime;
patches (floatingObject);
rho rhoInf;
log yes;
rhoInf 1000;
CofR (0 0 0);
}
};

输出控制

这里分两种情况,分别是 solver 运行时和运行后。

  • 运行后,一定需要记住的是必须使用参数 -fields 指定此次后处理过程中涉及的所有场(作为输入信息)。可以使用前面提到的 -time 参数来控制需要处理的时间段。
  • 运行时
    在 solver 运行时可以手动控制输出时间间隔,通过这两个选项: writeControl writeInterval。
    writeControl 常用的可选项:
outputTime//同主程序输出间隔相同。
writeTime//每 writeInterval个输出步长写一次。这里的输出步长指主程序的write步长。即,如果主程序每秒write一次,这里的function就是每3秒写一次。
adjustableRunTime//每 writeInterval 秒物理时间写一次,但是对于可调节步长的话,会自动调节最后一次的时间步长,以便准确时间输出。

writeControl 所有的可选项:

outputTime//同主程序输出间隔相同。
runTime//每 writeInterval 秒物理时间写一次。
adjustableRunTime//每 writeInterval 秒物理时间写一次,但是对于可调节步长的话,会自动调节最后一次的时间步长,以便准确时间输出。
clockTime//每 writeInterval 秒实际时间写一次。
cpuTime//每 writeInteral 秒 cpu 时间写一次。
none//不输出。
writeTime//每 writeInterval个输出步长写一次。这里的输出步长指主程序的write步长。即,如果主程序每秒write一次,这里的function就是每3秒写一次。
timeStep//每 writeInterval 个时间步长写一次。
文章作者: Yan Zhang
文章链接: https://openfoam.top/functionObject/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 OpenFOAM 成长之路
微信打赏给博主更多动力吧~