potentialFoam
potentialFoam.C
这个比我想象的要复杂一点,感觉是因为方程中没有时间项,但是一般方程中都是同过构造时间步进行推进求解,有点不知道它是怎么做的
#include "fvCFD.H"
#include "pisoControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addOption
(
"pName",
"pName",
"Name of the pressure field"
);
argList::addBoolOption
(
"initialiseUBCs",
"Initialise U boundary conditions"
);
argList::addBoolOption
(
"writePhi",
"Write the velocity potential field"
);
argList::addBoolOption
(
"writep",
"Calculate and write the pressure field"
);
argList::addBoolOption
(
"withFunctionObjects",
"execute functionObjects"
);
//***************************************************************************
//*********************************前面这一长串不知道在干嘛
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
pisoControl potentialFlow(mesh, "potentialFlow");
//这里与之前icoFoam中的 { pisoControl piso(mesh);} 多了一个关键字,暂时不清楚干嘛的
#include "createFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< nl << "Calculating potential flow" << endl;
// Since solver contains no time loop it would never execute
// function objects so do it ourselves
runTime.functionObjects().start();//****************************************************
MRF.makeRelative(phi);//旋转坐标系的相关内容
adjustPhi(phi, U, p);//应该是边界的调整
// Non-orthogonal velocity potential corrector loop
while (potentialFlow.correctNonOrthogonal())
{
fvScalarMatrix PhiEqn
(
fvm::laplacian(dimensionedScalar("1", dimless, 1), Phi)
==
fvc::div(phi)
);
PhiEqn.setReference(PhiRefCell, PhiRefValue);
PhiEqn.solve();
if (potentialFlow.finalNonOrthogonalIter())
{
phi -= PhiEqn.flux();
}
}
MRF.makeAbsolute(phi);//前面是相对,这里是绝对
Info<< "Continuity error = "
<< mag(fvc::div(phi))().weightedAverage(mesh.V()).value()
<< endl;
U = fvc::reconstruct(phi);
U.correctBoundaryConditions();
Info<< "Interpolated velocity error = "
<< (sqrt(sum(sqr(fvc::flux(U) - phi)))/sum(mesh.magSf())).value()
<< endl;
// Write U and phi
U.write();
phi.write();
// Optionally write Phi
if (args.optionFound("writePhi"))
{
Phi.write();
}
// Calculate the pressure field
if (args.optionFound("writep"))
{
Info<< nl << "Calculating approximate pressure field" << endl;
label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell
(
p,
potentialFlow.dict(),
pRefCell,
pRefValue
);
// Calculate the flow-direction filter tensor
volScalarField magSqrU(magSqr(U));
volSymmTensorField F(sqr(U)/(magSqrU + SMALL*average(magSqrU)));
// Calculate the divergence of the flow-direction filtered div(U*U)
// Filtering with the flow-direction generates a more reasonable
// pressure distribution in regions of high velocity gradient in the
// direction of the flow
volScalarField divDivUU
(
fvc::div
(
F & fvc::div(phi, U),
"div(div(phi,U))"
)
);
// Solve a Poisson equation for the approximate pressure
while (potentialFlow.correctNonOrthogonal())
{
fvScalarMatrix pEqn
(
fvm::laplacian(p) + divDivUU
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
}
p.write();
}
runTime.functionObjects().end();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
Info<< "End\n" << endl;
return 0;
}
createFields.H
Info<< "Reading velocity field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
U = dimensionedVector("0", U.dimensions(), Zero);
surfaceScalarField phi
(
IOobject
(
"phi",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
fvc::flux(U)
);
if (args.optionFound("initialiseUBCs"))
{
U.correctBoundaryConditions();
phi = fvc::flux(U);
}
// Default name for the pressure field
word pName("p");
// Update name of the pressure field from the command-line option
args.optionReadIfPresent("pName", pName);
// Infer the pressure BCs from the velocity
wordList pBCTypes
(
U.boundaryField().size(),
fixedValueFvPatchScalarField::typeName
);
forAll(U.boundaryField(), patchi)
{
if (U.boundaryField()[patchi].fixesValue())
{
pBCTypes[patchi] = zeroGradientFvPatchScalarField::typeName;
}
}
Info<< "Constructing pressure field " << pName << nl << endl;
volScalarField p
(
IOobject
(
pName,
runTime.timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
mesh,
dimensionedScalar(pName, sqr(dimVelocity), 0),
pBCTypes
);
// Infer the velocity potential BCs from the pressure
wordList PhiBCTypes
(
p.boundaryField().size(),
zeroGradientFvPatchScalarField::typeName
);
forAll(p.boundaryField(), patchi)
{
if (p.boundaryField()[patchi].fixesValue())
{
PhiBCTypes[patchi] = fixedValueFvPatchScalarField::typeName;
}
}
Info<< "Constructing velocity potential field Phi\n" << endl;
volScalarField Phi
(
IOobject
(
"Phi",
runTime.timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
mesh,
dimensionedScalar("Phi", dimLength*dimVelocity, 0),
PhiBCTypes
);
label PhiRefCell = 0;
scalar PhiRefValue = 0;
setRefCell
(
Phi,
potentialFlow.dict(),
PhiRefCell,
PhiRefValue
);
mesh.setFluxRequired(Phi.name());
#include "createMRF.H"//处理旋转坐标系下的修正
createControls.H
const dictionary& potentialFlow
(
mesh.solutionDict().subDict("potentialFlow")
);
const int nNonOrthCorr
(
potentialFlow.lookupOrDefault<int>("nNonOrthogonalCorrectors", 0)
);
求解设置
主要看fvSolution中
solvers
{
Phi
{
solver GAMG;
smoother DIC;
tolerance 1e-06;
relTol 0.01;
}
p
{
$Phi;
}
}
potentialFlow //这里定义了这个字典,在createControls.H中读取
{
nNonOrthogonalCorrectors 2;
}
这边具体的细节不是太懂