FEATURE: Immersed boundary solver. Authors: Zeljko Tukovic, Hrvoje Jasak. Merge: Dominik Christ.

This commit is contained in:
Dominik Christ 2015-05-12 16:18:51 +01:00
commit d08127d5a9
405 changed files with 253902 additions and 0 deletions

View file

@ -0,0 +1,49 @@
Make/options: add
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I../immersedBoundary/lnInclude
-ltriSurface \
-lmeshTools \
-L$(FOAM_USER_LIBBIN) -limmersedBoundary \
createFields.H: add
# include "createIbMasks.H"
solver:
1) add immersed boundary headers
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryAdjustPhi.H"
2) on calculation of face fluxes (or their components), mask with faceIbMask
3) before to adjustPhi, add:
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phi, U);
4) on explicit updates, add correctBoundaryConditions();
eg.
U = fvc::reconstruct(phi);
U.correctBoundaryConditions();
5) On reports of continuity error, add masking:
Info<< "IB-masked continuity error = "
<< mag(cellIbMask*fvc::div(phi))().weightedAverage(mesh.V()).value()
<< endl;
or use immersedBoundaryContinuityErrs.H
5) Chenge Courant number check to be IB-sensitive, using
immersedBoundaryCourantNo.H

View file

@ -0,0 +1,3 @@
icoIbFoam.C
EXE = $(FOAM_APPBIN)/icoIbFoam

View file

@ -0,0 +1,15 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary \
-llduSolvers

View file

@ -0,0 +1,55 @@
Info<< "Reading transportProperties\n" << endl;
IOdictionary transportProperties
(
IOobject
(
"transportProperties",
runTime.constant(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
dimensionedScalar nu
(
transportProperties.lookup("nu")
);
Info<< "Reading field p\n" << endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
# include "createPhi.H"
label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell(p, mesh.solutionDict().subDict("PIMPLE"), pRefCell, pRefValue);

View file

@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
icoIbFoam
Description
Transient solver for incompressible, laminar flow of Newtonian fluids
with immersed boundary support.
Author
Hrvoje Jasak, Wikki Ltd. All rights reserved
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryAdjustPhi.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
# include "createIbMasks.H"
# include "createFields.H"
# include "initContinuityErrs.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl;
while (runTime.loop())
{
Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readPIMPLEControls.H"
# include "CourantNo.H"
// Pressure-velocity corrector
int oCorr = 0;
do
{
fvVectorMatrix UEqn
(
fvm::ddt(U)
+ fvm::div(phi, U)
- fvm::laplacian(nu, U)
);
solve(UEqn == -fvc::grad(p));
// --- PISO loop
for (int corr = 0; corr < nCorr; corr++)
{
volScalarField rUA = 1.0/UEqn.A();
U = rUA*UEqn.H();
// Immersed boundary update
U.correctBoundaryConditions();
phi = faceIbMask*(fvc::interpolate(U) & mesh.Sf());
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phi, U);
adjustPhi(phi, U, p);
for (int nonOrth = 0; nonOrth <= nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pEqn
(
fvm::laplacian(rUA, p) == fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
if (nonOrth == nNonOrthCorr)
{
phi -= pEqn.flux();
}
}
# include "immersedBoundaryContinuityErrs.H"
U -= rUA*fvc::grad(p);
U.correctBoundaryConditions();
}
} while (++oCorr < nOuterCorr);
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
interIbFoam.C
EXE = $(FOAM_APPBIN)/interIbFoam

View file

@ -0,0 +1,24 @@
EXE_INC = \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/lnInclude \
-I$(LIB_SRC)/transportModels/interfaceProperties/lnInclude \
-I$(LIB_SRC)/turbulenceModels/incompressible/turbulenceModel \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude
EXE_LIBS = \
-linterfaceProperties \
-lincompressibleTransportModels \
-lincompressibleTurbulenceModel \
-lincompressibleRASModels \
-lincompressibleLESModels \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary \
-llduSolvers

View file

@ -0,0 +1,34 @@
surfaceScalarField muEff
(
"muEff",
twoPhaseProperties.muf()
+ fvc::interpolate(rho*turbulence->nut())
);
fvVectorMatrix UEqn
(
fvm::ddt(rho, U)
+ fvm::div(rhoPhi, U)
- fvm::laplacian(muEff, U)
- (fvc::grad(U) & fvc::grad(muEff))
//- fvc::div(muEff*(fvc::interpolate(dev(fvc::grad(U))) & mesh.Sf()))
);
UEqn.relax();
if (momentumPredictor)
{
solve
(
UEqn
==
fvc::reconstruct
(
(
fvc::interpolate(interface.sigmaK())*fvc::snGrad(alpha1)
- ghf*fvc::snGrad(rho)
- fvc::snGrad(pd)
) * mesh.magSf()
)
);
}

View file

@ -0,0 +1,37 @@
{
word alphaScheme("div(phi,alpha)");
word alpharScheme("div(phirb,alpha)");
surfaceScalarField phic = mag(phi/mesh.magSf());
phic = min(interface.cAlpha()*phic, max(phic));
surfaceScalarField phir = faceIbMask*phic*interface.nHatf();
fvScalarMatrix alpha1Eqn
(
fvm::ddt(alpha1)
+ fvm::div(phi, alpha1, alphaScheme)
+ fvm::div
(
-fvc::flux(-phir, scalar(1) - alpha1, alpharScheme),
alpha1,
alpharScheme
)
);
alpha1Eqn.solve();
Info<< "Liquid phase volume fraction = "
<< alpha1.weightedAverage(mesh.V()).value()
<< " Min(alpha1) = " << min(cellIbMask*alpha1).value()
<< " Max(alpha1) = " << max(cellIbMask*alpha1).value()
<< endl;
// Limit alpha to handle IB cells
alpha1.max(0);
alpha1.min(1);
// Update of interface and density
interface.correct();
rho == alpha1*rho1 + (scalar(1) - alpha1)*rho2;
}

View file

@ -0,0 +1,56 @@
{
# include "continuityErrs.H"
wordList pcorrTypes
(
pd.boundaryField().size(),
zeroGradientFvPatchScalarField::typeName
);
for (label i=0; i<pd.boundaryField().size(); i++)
{
if (pd.boundaryField()[i].fixesValue())
{
pcorrTypes[i] = fixedValueFvPatchScalarField::typeName;
}
}
volScalarField pcorr
(
IOobject
(
"pcorr",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensionedScalar("pcorr", pd.dimensions(), 0.0),
pcorrTypes
);
dimensionedScalar rUAf("(1|A(U))", dimTime/rho.dimensions(), 1.0);
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phi, U);
adjustPhi(phi, U, pcorr);
for(int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pcorrEqn
(
fvm::laplacian(rUAf, pcorr) == fvc::div(phi)
);
pcorrEqn.setReference(pdRefCell, pdRefValue);
pcorrEqn.solve();
if (nonOrth == nNonOrthCorr)
{
phi -= pcorrEqn.flux();
}
}
# include "immersedBoundaryContinuityErrs.H"
}

View file

@ -0,0 +1,138 @@
Info<< "Reading field pd\n" << endl;
volScalarField pd
(
IOobject
(
"pd",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading field alpha1\n" << endl;
volScalarField alpha1
(
IOobject
(
"alpha1",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
# include "createPhi.H"
Info<< "Reading transportProperties\n" << endl;
twoPhaseMixture twoPhaseProperties(U, phi, "alpha1");
const dimensionedScalar& rho1 = twoPhaseProperties.rho1();
const dimensionedScalar& rho2 = twoPhaseProperties.rho2();
// Need to store rho for ddt(rho, U)
volScalarField rho
(
IOobject
(
"rho",
runTime.timeName(),
mesh,
IOobject::READ_IF_PRESENT
),
alpha1*rho1 + (scalar(1) - alpha1)*rho2,
alpha1.boundaryField().types()
);
rho.oldTime();
// Mass flux
// Initialisation does not matter because rhoPhi is reset after the
// alpha1 solution before it is used in the U equation.
surfaceScalarField rhoPhi
(
IOobject
(
"rho*phi",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
rho1*phi
);
Info<< "Calculating field g.h\n" << endl;
volScalarField gh("gh", g & mesh.C());
surfaceScalarField ghf("gh", g & mesh.Cf());
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
pd + rho*gh
);
label pdRefCell = 0;
scalar pdRefValue = 0.0;
setRefCell
(
pd,
mesh.solutionDict().subDict("PIMPLE"),
pdRefCell,
pdRefValue
);
scalar pRefValue = 0.0;
if (pd.needReference())
{
pRefValue = readScalar
(
mesh.solutionDict().subDict("PIMPLE").lookup("pRefValue")
);
p += dimensionedScalar
(
"p",
p.dimensions(),
pRefValue - getRefCellValue(p, pdRefCell)
);
}
// Construct interface from alpha1 distribution
interfaceProperties interface(alpha1, U, twoPhaseProperties);
// Construct incompressible turbulence model
autoPtr<incompressible::turbulenceModel> turbulence
(
incompressible::turbulenceModel::New(U, phi, twoPhaseProperties)
);

View file

@ -0,0 +1,136 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
interIbFoam
Description
Solver for 2 incompressible, isothermal immiscible fluids using a VOF
(volume of fluid) phase-fraction based interface capturing approach,
with immersed boundary support
The momentum and other fluid properties are of the "mixture" and a single
momentum equation is solved.
Turbulence modelling is generic, i.e. laminar, RAS or LES may be selected.
For a two-fluid approach see twoPhaseEulerFoam.
Author
Hrvoje Jasak, Wikki Ltd. All rights reserved
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "interfaceProperties.H"
#include "twoPhaseMixture.H"
#include "turbulenceModel.H"
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryAdjustPhi.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
# include "readGravitationalAcceleration.H"
# include "readPIMPLEControls.H"
# include "initContinuityErrs.H"
# include "createFields.H"
# include "createIbMasks.H"
# include "readTimeControls.H"
# include "correctPhi.H"
# include "CourantNo.H"
# include "setInitialDeltaT.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl;
while (runTime.run())
{
# include "readPIMPLEControls.H"
# include "readTimeControls.H"
# include "immersedBoundaryCourantNo.H"
# include "setDeltaT.H"
runTime++;
Info<< "Time = " << runTime.timeName() << nl << endl;
// Pressure-velocity corrector
int oCorr = 0;
do
{
twoPhaseProperties.correct();
# include "alphaEqn.H"
# include "UEqn.H"
// --- PISO loop
for (int corr = 0; corr < nCorr; corr++)
{
# include "pEqn.H"
}
# include "immersedBoundaryContinuityErrs.H"
# include "limitU.H"
// Recalculate the mass fluxes
rhoPhi = phi*fvc::interpolate(rho);
p = pd + cellIbMask*rho*gh;
if (pd.needReference())
{
p += dimensionedScalar
(
"p",
p.dimensions(),
pRefValue - getRefCellValue(p, pdRefCell)
);
}
turbulence->correct();
} while (++oCorr < nOuterCorr);
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,24 @@
{
scalar limitMagU = readScalar(pimple.lookup("limitMagU"));
volScalarField magU(mag(U));
scalar maxMagU = max(magU).value();
Info<< "mag(U): max: " << maxMagU
<< " avg: " << magU.weightedAverage(mesh.V()).value();
if (maxMagU > limitMagU)
{
U.internalField() *=
neg(magU.internalField() - limitMagU)
+ pos(magU.internalField() - limitMagU)*
limitMagU/(magU.internalField() + SMALL);
U.correctBoundaryConditions();
Info << " ...limiting" << endl;
}
else
{
Info << endl;
}
}

View file

@ -0,0 +1,64 @@
{
if (nOuterCorr != 1)
{
pd.storePrevIter();
}
volScalarField rUA = 1.0/UEqn.A();
surfaceScalarField rUAf = fvc::interpolate(rUA);
U = rUA*UEqn.H();
// Immersed boundary update
U.correctBoundaryConditions();
surfaceScalarField phiU
(
"phiU",
faceIbMask*(fvc::interpolate(U) & mesh.Sf())
);
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phiU, U);
adjustPhi(phiU, U, pd);
phi = phiU
+ faceIbMask*
(
fvc::interpolate(interface.sigmaK())*fvc::snGrad(alpha1)
- ghf*fvc::snGrad(rho)
)*rUAf*mesh.magSf();
for(int nonOrth = 0; nonOrth <= nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pdEqn
(
fvm::laplacian(rUAf, pd) == fvc::div(phi)
);
pdEqn.setReference(pdRefCell, pdRefValue);
if (corr == nCorr - 1 && nonOrth == nNonOrthCorr)
{
pdEqn.solve(mesh.solutionDict().solver(pd.name() + "Final"));
}
else
{
pdEqn.solve(mesh.solutionDict().solver(pd.name()));
}
if (nonOrth == nNonOrthCorr)
{
phi -= pdEqn.flux();
}
}
// Explicitly relax pressure except for last corrector
if (oCorr != nOuterCorr - 1)
{
pd.relax();
}
U += rUA*fvc::reconstruct((phi - phiU)/rUAf);
U.correctBoundaryConditions();
}

View file

@ -0,0 +1,3 @@
porousSimpleIbFoam.C
EXE = $(FOAM_APPBIN)/porousSimpleIbFoam

View file

@ -0,0 +1,22 @@
EXE_INC = \
-I$(LIB_SRC)/turbulenceModels \
-I$(LIB_SRC)/turbulenceModels/incompressible/RAS/RASModel \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude
EXE_LIBS = \
-lincompressibleRASModels \
-lincompressibleTransportModels \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary \
-limmersedBoundaryTurbulence \
-llduSolvers

View file

@ -0,0 +1,17 @@
// Solve the Momentum equation
tmp<fvVectorMatrix> UEqn
(
fvm::div(phi, U)
+ turbulence->divDevReff(U)
);
UEqn().relax();
pZones.addResistance(UEqn());
eqnResidual = solve
(
UEqn() == -fvc::grad(p)
).initialResidual();
maxResidual = max(eqnResidual, maxResidual);

View file

@ -0,0 +1,9 @@
// check convergence
if (maxResidual < convergenceCriterion)
{
Info<< "reached convergence criterion: " << convergenceCriterion << endl;
runTime.writeAndEnd();
Info<< "latestTime = " << runTime.timeName() << endl;
}

View file

@ -0,0 +1,44 @@
Info << "Reading field p\n" << endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info << "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
# include "createPhi.H"
label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell(p, mesh.solutionDict().subDict("SIMPLE"), pRefCell, pRefValue);
singlePhaseTransportModel laminarTransport(U, phi);
autoPtr<incompressible::RASModel> turbulence
(
incompressible::RASModel::New(U, phi, laminarTransport)
);
porousZones pZones(mesh);

View file

@ -0,0 +1,7 @@
// initialize values for convergence checks
scalar eqnResidual = 1, maxResidual = 0;
scalar convergenceCriterion = 0;
simple.readIfPresent("convergence", convergenceCriterion);

View file

@ -0,0 +1,51 @@
p.boundaryField().updateCoeffs();
volScalarField AU = UEqn().A();
U = UEqn().H()/AU;
// Immersed boundary update
U.correctBoundaryConditions();
UEqn.clear();
phi = faceIbMask*(fvc::interpolate(U) & mesh.Sf());
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phi, U);
adjustPhi(phi, U, p);
// Non-orthogonal pressure corrector loop
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pEqn
(
fvm::laplacian(1.0/AU, p) == fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
// Retain the residual from the first iteration
if (nonOrth == 0)
{
eqnResidual = pEqn.solve().initialResidual();
maxResidual = max(eqnResidual, maxResidual);
}
else
{
pEqn.solve();
}
if (nonOrth == nNonOrthCorr)
{
phi -= pEqn.flux();
}
}
# include "immersedBoundaryContinuityErrs.H"
// Explicitly relax pressure for momentum corrector
p.relax();
// Momentum corrector
U -= fvc::grad(p)/AU;
U.correctBoundaryConditions();

View file

@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
simpleIbFoam
Description
Steady-state solver for incompressible, turbulent flow
with porous zones and immersed boundary support.
Author
Hrvoje Jasak, Wikki Ltd. All rights reserved
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "singlePhaseTransportModel.H"
#include "RASModel.H"
#include "porousZones.H"
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryAdjustPhi.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
# include "createIbMasks.H"
# include "createFields.H"
# include "initContinuityErrs.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl;
while (runTime.loop())
{
Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSIMPLEControls.H"
# include "initConvergenceCheck.H"
p.storePrevIter();
// Pressure-velocity SIMPLE corrector
{
# include "UEqn.H"
# include "pEqn.H"
}
turbulence->correct();
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
# include "convergenceCheck.H"
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
potentialIbFoam.C
EXE = $(FOAM_APPBIN)/potentialIbFoam

View file

@ -0,0 +1,15 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary \
-llduSolvers

View file

@ -0,0 +1,49 @@
Info<< "Reading field p\n" << endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
mesh
);
// Do not reset p
Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
// Do not reset U
surfaceScalarField phi
(
IOobject
(
"phi",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
fvc::interpolate(U) & mesh.Sf()
);
label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell(p, mesh.solutionDict().subDict("SIMPLE"), pRefCell, pRefValue);

View file

@ -0,0 +1,229 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
potentialIbFoam
Description
Potential flow solver with immersed boundary support.
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryAdjustPhi.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::validOptions.insert("writep", "");
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
# include "createIbMasks.H"
# include "createFields.H"
# include "readSIMPLEControls.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< nl << "Calculating potential flow" << endl;
// Do correctors over the complete set
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
phi = faceIbMask*(linearInterpolate(U) & mesh.Sf());
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phi, U);
// Adjust fluxes
adjustPhi(phi, U, p);
p.storePrevIter();
fvScalarMatrix pEqn
(
fvm::laplacian
(
dimensionedScalar
(
"1",
dimTime/p.dimensions()*dimensionSet(0, 2, -2, 0, 0),
1
),
p
)
==
fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
// Correct the flux
phi -= pEqn.flux();
if (nonOrth != nNonOrthCorr)
{
p.relax();
}
Info<< "p min " << gMin(p.internalField())
<< " max " << gMax(p.internalField())
<< " masked min "
<< gMin(cellIbMask.internalField()*p.internalField())
<< " max "
<< gMax(cellIbMask.internalField()*p.internalField())
<< endl;
Info<< "continuity error = "
<< mag
(
fvc::div(faceIbMask*phi)
)().weightedAverage(mesh.V()).value()
<< endl;
Info<< "Contour continuity error = "
<< mag(sum(phi.boundaryField()))
<< endl;
U = fvc::reconstruct(phi);
U.correctBoundaryConditions();
Info<< "Interpolated U error = "
<< (
sqrt
(
sum
(
sqr
(
faceIbMask*
(
fvc::interpolate(U) & mesh.Sf()
)
- phi
)
)
)/sum(mesh.magSf())
).value()
<< endl;
}
// Calculate velocity magnitude
{
volScalarField magU = cellIbMask*mag(U);
Info << "IB-masked mag(U): max: " << gMax(magU.internalField())
<< " min: " << gMin(magU.internalField()) << endl;
}
// Force the write
U.write();
phi.write();
cellIbMask.write();
cellIbMaskExt.write();
if (args.optionFound("writep"))
{
// Find reference patch
label refPatch = -1;
scalar maxMagU = 0;
// Go through all velocity patches and find the one that fixes
// velocity to the largest value
forAll (U.boundaryField(), patchI)
{
const fvPatchVectorField& Upatch = U.boundaryField()[patchI];
if (Upatch.fixesValue())
{
// Calculate mean velocity
scalar u = sum(mag(Upatch));
label patchSize = Upatch.size();
reduce(u, sumOp<scalar>());
reduce(patchSize, sumOp<label>());
if (patchSize > 0)
{
scalar curMag = u/patchSize;
if (curMag > maxMagU)
{
refPatch = patchI;
maxMagU = curMag;
}
}
}
}
if (refPatch > -1)
{
// Calculate reference pressure
const fvPatchVectorField& Upatch = U.boundaryField()[refPatch];
const fvPatchScalarField& pPatch = p.boundaryField()[refPatch];
scalar patchE = sum(mag(pPatch + 0.5*magSqr(Upatch)));
label patchSize = Upatch.size();
reduce(patchE, sumOp<scalar>());
reduce(patchSize, sumOp<label>());
scalar e = patchE/patchSize;
Info<< "Using reference patch " << refPatch
<< " with mag(U) = " << maxMagU
<< " p + 0.5*U^2 = " << e << endl;
p.internalField() = e - 0.5*magSqr(U.internalField());
p.correctBoundaryConditions();
}
else
{
Info<< "No reference patch found. Writing potential function"
<< endl;
}
p.write();
}
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
simpleIbFoam.C
EXE = $(FOAM_APPBIN)/simpleIbFoam

View file

@ -0,0 +1,22 @@
EXE_INC = \
-I$(LIB_SRC)/turbulenceModels \
-I$(LIB_SRC)/turbulenceModels/incompressible/RAS/RASModel \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude
EXE_LIBS = \
-lincompressibleRASModels \
-lincompressibleTransportModels \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary \
-limmersedBoundaryTurbulence \
-llduSolvers

View file

@ -0,0 +1,15 @@
// Solve the Momentum equation
tmp<fvVectorMatrix> UEqn
(
fvm::div(phi, U)
+ turbulence->divDevReff(U)
);
UEqn().relax();
eqnResidual = solve
(
UEqn() == -fvc::grad(p)
).initialResidual();
maxResidual = max(eqnResidual, maxResidual);

View file

@ -0,0 +1,9 @@
// check convergence
if (maxResidual < convergenceCriterion)
{
Info<< "reached convergence criterion: " << convergenceCriterion << endl;
runTime.writeAndEnd();
Info<< "latestTime = " << runTime.timeName() << endl;
}

View file

@ -0,0 +1,42 @@
Info<< "Reading field p\n" << endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
# include "createPhi.H"
label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell(p, mesh.solutionDict().subDict("SIMPLE"), pRefCell, pRefValue);
singlePhaseTransportModel laminarTransport(U, phi);
autoPtr<incompressible::RASModel> turbulence
(
incompressible::RASModel::New(U, phi, laminarTransport)
);

View file

@ -0,0 +1,7 @@
// initialize values for convergence checks
scalar eqnResidual = 1, maxResidual = 0;
scalar convergenceCriterion = 0;
simple.readIfPresent("convergence", convergenceCriterion);

View file

@ -0,0 +1,51 @@
p.boundaryField().updateCoeffs();
volScalarField AU = UEqn().A();
U = UEqn().H()/AU;
// Immersed boundary update
U.correctBoundaryConditions();
UEqn.clear();
phi = faceIbMask*(fvc::interpolate(U) & mesh.Sf());
// Adjust immersed boundary fluxes
immersedBoundaryAdjustPhi(phi, U);
adjustPhi(phi, U, p);
// Non-orthogonal pressure corrector loop
for (int nonOrth = 0; nonOrth <= nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pEqn
(
fvm::laplacian(1.0/AU, p) == fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
// Retain the residual from the first iteration
if (nonOrth == 0)
{
eqnResidual = pEqn.solve().initialResidual();
maxResidual = max(eqnResidual, maxResidual);
}
else
{
pEqn.solve();
}
if (nonOrth == nNonOrthCorr)
{
phi -= pEqn.flux();
}
}
# include "immersedBoundaryContinuityErrs.H"
// Explicitly relax pressure for momentum corrector
p.relax();
// Momentum corrector
U -= fvc::grad(p)/AU;
U.correctBoundaryConditions();

View file

@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
simpleIbFoam
Description
Steady-state solver for incompressible, turbulent flow
with immersed boundary support.
Author
Hrvoje Jasak, Wikki Ltd. All rights reserved
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "singlePhaseTransportModel.H"
#include "RASModel.H"
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryAdjustPhi.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
# include "createIbMasks.H"
# include "createFields.H"
# include "initContinuityErrs.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl;
while (runTime.loop())
{
Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSIMPLEControls.H"
# include "initConvergenceCheck.H"
p.storePrevIter();
// Pressure-velocity SIMPLE corrector
{
# include "UEqn.H"
# include "pEqn.H"
}
turbulence->correct();
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
# include "convergenceCheck.H"
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
ibContinuityError.C
EXE = $(FOAM_APPBIN)/ibContinuityError

View file

@ -0,0 +1,14 @@
EXE_INC = \
-I$(LIB_SRC)/postProcessing/postCalc \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/immersedBoundary/lnInclude
EXE_LIBS = \
$(FOAM_LIBBIN)/postCalc.o \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary

View file

@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
shapeDerivative
Description
Calculate continuity error on immersed boundary mesh
\*---------------------------------------------------------------------------*/
#include "calc.H"
#include "fvc.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::calc(const argList& args, const Time& runTime, const fvMesh& mesh)
{
IOobject phiHeader
(
"phi",
runTime.timeName(),
mesh,
IOobject::MUST_READ
);
IOobject faceIbMaskHeader
(
"faceIbMask",
runTime.timeName(),
mesh,
IOobject::MUST_READ
);
if (phiHeader.headerOk() && faceIbMaskHeader.headerOk())
{
Info<< " Reading phi" << endl;
surfaceScalarField phi(phiHeader, mesh);
Info<< " Reading faceIbMask" << endl;
surfaceScalarField faceIbMask(faceIbMaskHeader, mesh);
volScalarField contErr = fvc::div(faceIbMask*phi);
scalar sumLocalContErr = runTime.deltaT().value()*
mag(contErr)().weightedAverage(mesh.V()).value();
scalar globalContErr = runTime.deltaT().value()*
contErr.weightedAverage(mesh.V()).value();
Info<< "IB time step continuity errors : sum local = "
<< sumLocalContErr
<< ", global = " << globalContErr
<< endl;
volScalarField magContErr
(
"magContErr",
mag(contErr)
);
magContErr.write();
}
else
{
Info<< " No phi or faceIbMask" << endl;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
makeTriSurfaceMesh.C
EXE = $(FOAM_APPBIN)/makeTriSurfaceMesh

View file

@ -0,0 +1,10 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/cfdTools/general/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ltriSurface \
-lmeshTools

View file

@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
makeTriSurfaceMesh
Description
Generate a triSurface mesh from fvMesh patches
Author
Zeljko Tukovic
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "triSurface.H"
#include "triSurfaceTools.H"
// #include "labelHashSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
labelHashSet includedPatches;
forAll (mesh.boundaryMesh(), patchI)
{
includedPatches.insert(patchI);
}
triSurface triSurf =
triSurfaceTools::triangulate
(
mesh.boundaryMesh(),
includedPatches
);
// Writing triSurface mesh
Info << "Write triSurface mesh ... ";
triSurf.write(runTime.caseName() + ".stl");
triSurf.write(runTime.caseName() + ".ftr");
Info << "done" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
refineImmersedBoundaryMesh.C
EXE = $(FOAM_APPBIN)/refineImmersedBoundaryMesh

View file

@ -0,0 +1,15 @@
EXE_INC = \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude \
-I$(LIB_SRC)/dynamicMesh/dynamicMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary

View file

@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
refineImmersedBoundaryMesh
Description
Refine the background mesh around the immersed surface
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "refineImmersedBoundaryMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::validOptions.insert("ibCells", "");
argList::validOptions.insert("ibCellCells", "");
argList::validOptions.insert("ibCellCellFaces", "");
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
refineImmersedBoundaryMesh rib(mesh);
labelList rc;
if (args.optionFound("ibCells"))
{
rc = rib.refinementCells
(
refineImmersedBoundaryMesh::IB_CELLS
);
}
else if (args.optionFound("ibCellCells"))
{
rc = rib.refinementCells
(
refineImmersedBoundaryMesh::IB_CELL_CELLS
);
}
else if (args.optionFound("ibCellCellFaces"))
{
rc = rib.refinementCells
(
refineImmersedBoundaryMesh::IB_CELL_CELL_FACES
);
}
else
{
FatalErrorIn(args.executable())
<< "Specify one of the available options for cell selection: "
<< "[-ibCells] [-ibCellCells] [-ibCellCellFaces]" << nl
<< exit(FatalError);
}
Info<< "Number of refinement cells = " << rc.size() << endl;
rib.refineMesh(rc);
mesh.write();
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
surfaceInvertNormal.C
EXE = $(FOAM_APPBIN)/surfaceInvertNormal

View file

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-ltriSurface \
-lmeshTools

View file

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
Write surface and normal vector
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "triSurface.H"
#include "IFstream.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.clear();
argList::validArgs.append("surface file");
argList::validArgs.append("output surface file");
argList args(argc, argv);
fileName surfFileName(args.additionalArgs()[0]);
Info<< "Reading surf from " << surfFileName << " ..." << endl;
fileName outFileName(args.additionalArgs()[1]);
Info<< "Writing surf to " << outFileName << " ..." << endl;
triSurface ts(surfFileName);
triFaceList invertedFaces(ts.size());
forAll (ts, tsI)
{
invertedFaces[tsI] = ts[tsI].reverseFace();
}
triSurface invertedTs
(
invertedFaces,
ts.points()
);
invertedTs.write(outFileName);
Info << "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
surfaceNormal.C
EXE = $(FOAM_APPBIN)/surfaceNormal

View file

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-ltriSurface \
-lmeshTools

View file

@ -0,0 +1,69 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
Write surface and normal vector
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "triSurface.H"
#include "IFstream.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.clear();
argList::validArgs.append("surface file");
argList args(argc, argv);
fileName surfFileName(args.additionalArgs()[0]);
Info<< "Reading surf from " << surfFileName << " ..." << endl;
triSurface ts(surfFileName);
fileName normalFileName(surfFileName.lessExt() + "Normals");
Info<< "Writing normals to file " << normalFileName << endl;
triSurface::writeVTKNormals
(
normalFileName,
ts,
ts.points()
);
Info << "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,3 @@
writeIbMasks.C
EXE = $(FOAM_APPBIN)/writeIbMasks

View file

@ -0,0 +1,15 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/immersedBoundary/immersedBoundary/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-limmersedBoundary \
-llduSolvers

View file

@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
writeIbMasks
Description
Calculate and write immersed boundary masks
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "immersedBoundaryFvPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createMesh.H"
# include "createIbMasks.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "Time = " << runTime.timeName() << nl << endl;
cellIbMask.write();
cellIbMaskExt.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View file

@ -71,6 +71,10 @@ wmake libso multiSolver
wmake libso solidModels
wmake libso dbns
wmake libso immersedBoundary
wmake libso immersedBoundaryForce
wmake libso immersedBoundaryTurbulence
( cd cudaSolvers ; ./Allwmake )
# ----------------------------------------------------------------- end-of-file

View file

@ -0,0 +1,17 @@
immersedBoundaryPolyPatch/immersedBoundaryPolyPatch.C
immersedBoundaryPointPatch/immersedBoundaryPointPatch.C
immersedBoundaryFvPatch/immersedBoundaryFvPatch.C
immersedBoundaryFvPatch/immersedBoundaryFvPatchLeastSquaresFit.C
immersedBoundaryFvPatch/immersedBoundaryFvPatchSamplingWeights.C
immersedBoundaryFvPatch/immersedBoundaryFvPatchTriAddressing.C
immersedBoundaryFvPatchField/immersedBoundaryFvPatchFields.C
immersedBoundaryFvsPatchField/immersedBoundaryFvsPatchFields.C
immersedBoundaryAdjustPhi/immersedBoundaryAdjustPhi.C
refineImmersedBoundaryMesh/refineImmersedBoundaryMesh.C
ibSwirlFlowRateInletVelocity/ibSwirlFlowRateInletVelocityFvPatchVectorField.C
LIB = $(FOAM_LIBBIN)/libimmersedBoundary

View file

@ -0,0 +1,15 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/dynamicMesh/dynamicMesh/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh

View file

@ -0,0 +1,225 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "ibSwirlFlowRateInletVelocityFvPatchVectorField.H"
#include "volFields.H"
#include "addToRunTimeSelectionTable.H"
#include "fvPatchFieldMapper.H"
#include "surfaceFields.H"
#include "mathematicalConstants.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::
ibSwirlFlowRateInletVelocityFvPatchVectorField::
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF
)
:
fixedValueFvPatchField<vector>(p, iF),
flowRate_(0),
phiName_("phi"),
rhoName_("rho"),
rpm_(0)
{
calcGeom();
}
Foam::
ibSwirlFlowRateInletVelocityFvPatchVectorField::
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const ibSwirlFlowRateInletVelocityFvPatchVectorField& ptf,
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
fixedValueFvPatchField<vector>(ptf, p, iF, mapper),
flowRate_(ptf.flowRate_),
phiName_(ptf.phiName_),
rhoName_(ptf.rhoName_),
rpm_(ptf.rpm_)
{
calcGeom();
}
Foam::
ibSwirlFlowRateInletVelocityFvPatchVectorField::
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF,
const dictionary& dict
)
:
fixedValueFvPatchField<vector>(p, iF, dict),
flowRate_(readScalar(dict.lookup("flowRate"))),
phiName_(dict.lookupOrDefault<word>("phi", "phi")),
rhoName_(dict.lookupOrDefault<word>("rho", "rho")),
rpm_(readScalar(dict.lookup("rpm")))
{
calcGeom();
}
Foam::
ibSwirlFlowRateInletVelocityFvPatchVectorField::
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const ibSwirlFlowRateInletVelocityFvPatchVectorField& ptf
)
:
fixedValueFvPatchField<vector>(ptf),
flowRate_(ptf.flowRate_),
phiName_(ptf.phiName_),
rhoName_(ptf.rhoName_),
rpm_(ptf.rpm_)
{
calcGeom();
}
Foam::
ibSwirlFlowRateInletVelocityFvPatchVectorField::
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const ibSwirlFlowRateInletVelocityFvPatchVectorField& ptf,
const DimensionedField<vector, volMesh>& iF
)
:
fixedValueFvPatchField<vector>(ptf, iF),
flowRate_(ptf.flowRate_),
phiName_(ptf.phiName_),
rhoName_(ptf.rhoName_),
rpm_(ptf.rpm_)
{
calcGeom();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ibSwirlFlowRateInletVelocityFvPatchVectorField::calcGeom()
{
// Lookup cellIbMask
const fvPatchScalarField& patchCellIbMask =
lookupPatchField<volScalarField, scalar>("cellIbMask");
scalarField faceMask = patchCellIbMask.patchInternalField();
totArea_ = gSum(faceMask*patch().magSf());
avgCenter_ = gSum(faceMask*patch().Cf()*patch().magSf())/totArea_;
avgNormal_ = gSum(faceMask*patch().Sf())/totArea_;
}
void Foam::ibSwirlFlowRateInletVelocityFvPatchVectorField::updateCoeffs()
{
if (updated())
{
return;
}
const scalar avgU = -flowRate_/totArea_;
// Update angular velocity - convert [rpm] to [rad/s]
vectorField tangentialVelocity =
(rpm_*mathematicalConstant::pi/30.0)
* ((patch().Cf() - avgCenter_) ^ avgNormal_);
vectorField n = patch().nf();
vectorField& U = *this;
const surfaceScalarField& phi =
db().lookupObject<surfaceScalarField>(phiName_);
// Lookup cellIbMask
const fvPatchScalarField& patchCellIbMask =
lookupPatchField<volScalarField, scalar>("cellIbMask");
scalarField faceMask = patchCellIbMask.patchInternalField();
if (phi.dimensions() == dimVelocity*dimArea)
{
// Volumetric flow-rate
U = faceMask*(tangentialVelocity + n*avgU);
}
else if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
{
const fvPatchField<scalar>& rhop =
patch().lookupPatchField<volScalarField, scalar>(rhoName_);
// Mass flow-rate
U = faceMask*(tangentialVelocity + n*avgU/rhop);
}
else
{
FatalErrorIn
(
"ibSwirlFlowRateInletVelocityFvPatchVectorField::updateCoeffs()"
) << "dimensions of " << phiName_ << " are incorrect" << nl
<< " on patch " << this->patch().name()
<< " of field " << this->dimensionedInternalField().name()
<< " in file " << this->dimensionedInternalField().objectPath()
<< nl << exit(FatalError);
}
fixedValueFvPatchField<vector>::updateCoeffs();
}
void Foam::ibSwirlFlowRateInletVelocityFvPatchVectorField::write
(
Ostream& os
) const
{
fvPatchField<vector>::write(os);
os.writeKeyword("flowRate") << flowRate_ << token::END_STATEMENT << nl;
writeEntryIfDifferent<word>(os, "phi", "phi", phiName_);
writeEntryIfDifferent<word>(os, "rho", "rho", rhoName_);
os.writeKeyword("rpm") << rpm_ << token::END_STATEMENT << nl;
writeEntry("value", os);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
makePatchTypeField
(
fvPatchVectorField,
ibSwirlFlowRateInletVelocityFvPatchVectorField
);
}
// ************************************************************************* //

View file

@ -0,0 +1,202 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::ibSwirlFlowRateInletVelocityFvPatchVectorField
Description
Describes a volumetric/mass flow normal vector boundary condition by its
magnitude as an integral over its area with a swirl component determined
by the RPM
The basis of the patch (volumetric or mass) is determined by the
dimensions of the flux, phi.
The current density is used to correct the velocity when applying the
mass basis.
The boundary condition is sensitised to work only on live IB cells
Example of the boundary condition specification:
\verbatim
inlet
{
type ibSwirlFlowRateInletVelocity;
flowRate 0.2; // Volumetric/mass flow rate [m3/s or kg/s]
rpm 100;
}
\endverbatim
Note
- The value is positive inwards
SourceFiles
ibSwirlFlowRateInletVelocityFvPatchVectorField.C
\*---------------------------------------------------------------------------*/
#ifndef ibSwirlFlowRateInletVelocityFvPatchVectorField_H
#define ibSwirlFlowRateInletVelocityFvPatchVectorField_H
#include "fixedValueFvPatchFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class ibSwirlFlowRateInletVelocityFvPatchVectorField Declaration
\*---------------------------------------------------------------------------*/
class ibSwirlFlowRateInletVelocityFvPatchVectorField
:
public fixedValueFvPatchVectorField
{
// Private data
//- Inlet integral flow rate
const scalar flowRate_;
//- Name of the flux transporting the field
const word phiName_;
//- Name of the density field used to normalize the mass flux
const word rhoName_;
//- RPM
const scalar rpm_;
// Derived parameters
//- Total area of inlet patch
scalar totArea_;
//- Average centre
vector avgCenter_;
//- Average normal
vector avgNormal_;
// Private member functions
//- Calculate geometrical characteristics of the patch
void calcGeom();
public:
//- Runtime type information
TypeName("ibSwirlFlowRateInletVelocity");
// Constructors
//- Construct from patch and internal field
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const fvPatch&,
const DimensionedField<vector, volMesh>&
);
//- Construct from patch, internal field and dictionary
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const fvPatch&,
const DimensionedField<vector, volMesh>&,
const dictionary&
);
//- Construct by mapping given
// flowRateInletVelocityFvPatchVectorField
// onto a new patch
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const ibSwirlFlowRateInletVelocityFvPatchVectorField&,
const fvPatch&,
const DimensionedField<vector, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const ibSwirlFlowRateInletVelocityFvPatchVectorField&
);
//- Construct and return a clone
virtual tmp<fvPatchVectorField> clone() const
{
return tmp<fvPatchVectorField>
(
new ibSwirlFlowRateInletVelocityFvPatchVectorField(*this)
);
}
//- Construct as copy setting internal field reference
ibSwirlFlowRateInletVelocityFvPatchVectorField
(
const ibSwirlFlowRateInletVelocityFvPatchVectorField&,
const DimensionedField<vector, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchVectorField> clone
(
const DimensionedField<vector, volMesh>& iF
) const
{
return tmp<fvPatchVectorField>
(
new ibSwirlFlowRateInletVelocityFvPatchVectorField(*this, iF)
);
}
// Member functions
// Access
//- Return the flux
scalar flowRate() const
{
return flowRate_;
}
//- Update the coefficients associated with the patch field
virtual void updateCoeffs();
//- Write
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,281 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryAdjustPhi.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "immersedBoundaryFvPatchFields.H"
#include "immersedBoundaryFvsPatchFields.H"
#include "inletOutletFvPatchFields.H"
#include "fvc.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
void Foam::immersedBoundaryAdjustPhi
(
surfaceScalarField& phi,
volVectorField& U
)
{
const fvMesh& mesh = phi.mesh();
// If the mesh is moving, adjustment needs to be calculated on
// relative fluxes. HJ, 13/Feb/2009
if (mesh.moving())
{
fvc::makeRelative(phi, U);
}
forAll (phi.boundaryField(), patchI)
{
const fvPatchVectorField& Up = U.boundaryField()[patchI];
if (isA<immersedBoundaryFvPatchVectorField>(Up))
{
if (Up.fixesValue())
{
// Found immersed boundary path which fixes value.
// Correction is necessary
// Cast into immersedBoundary types
const immersedBoundaryFvPatchVectorField& ibU =
refCast<const immersedBoundaryFvPatchVectorField>(Up);
const immersedBoundaryFvPatch& ibPatch = ibU.ibPatch();
// Complete immersed boundary triangular surface is present
// on all processors: no need for parallel reduction
// Sum the flux through the immersed boundary
const scalar triFlux = sum(ibU.refValue() & ibPatch.triSf());
scalarField& phiInternal = phi.internalField();
scalar fluxIn = 0;
scalar fluxOut = 0;
scalar fixedFlux = 0;
// Get all IB faces
const labelList& ibFaces = ibPatch.ibFaces();
const boolList& ibFaceFlips = ibPatch.ibFaceFlips();
forAll (ibFaces, faceI)
{
const label curFace = ibFaces[faceI];
const bool curFlip = ibFaceFlips[faceI];
if (mesh.isInternalFace(curFace))
{
const scalar curFlux = phiInternal[curFace];
if (!curFlip)
{
// Face points out of the live cell
if (curFlux >= 0)
{
// Flux out of the live cell
fluxOut += curFlux;
}
else
{
// Flux into the live cell
fluxIn -= curFlux;
}
}
else
{
// Face points into the live cell: flip it
if (curFlux >= 0)
{
// Flux into of the live cell
fluxIn += curFlux;
}
else
{
// Flux out the live cell
fluxOut -= curFlux;
}
}
}
else
{
const label patchID =
mesh.boundaryMesh().whichPatch(curFace);
const label faceID =
mesh.boundaryMesh()[patchID].whichFace(curFace);
const scalar curFlux =
phi.boundaryField()[patchID][faceID];
// Note: only coupled patches may carry flux
// In order to avoid double summation and
// inconsistencies in the correction,
// coupled face fluxes will NOT be corrected,
// but only accounted for in the summation.
if (mesh.boundaryMesh()[patchID].coupled())
{
// Only do the master side; slave will
// be handled on the other side of the couple
if (!curFlip)
{
fixedFlux += curFlux;
}
}
}
}
reduce(fluxIn, sumOp<scalar>());
reduce(fluxOut, sumOp<scalar>());
reduce(fixedFlux, sumOp<scalar>());
scalar imbalance = (fluxIn - fluxOut + fixedFlux) - triFlux;
if (fvMesh::debug)
{
Info<< "triFlux = " << triFlux
<< " fluxIn = " << fluxIn << " fluxOut = " << fluxOut
<< " fixedFlux = " << fixedFlux
<< " imbalance = " << imbalance
<< endl;
}
scalar massCorr = 1.0;
if (mag(imbalance) > SMALL)
{
// Scaling required: scale to match the smaller of two
// fluxes
if (fluxIn > fluxOut)
{
// Scale down incoming flux
// Note change of sign: imbalance is negative
massCorr = 1 - imbalance/(fluxIn + SMALL);
if (fvMesh::debug)
{
Info<< "Scaling down incoming flux with factor = "
<< massCorr << endl;
}
scalar newFluxIn = 0;
// Visit all incoming flux faces and re-scale the flux
forAll (ibFaces, faceI)
{
const label curFace = ibFaces[faceI];
const bool curFlip = ibFaceFlips[faceI];
if (mesh.isInternalFace(curFace))
{
// Take reference to current flux
scalar& curFlux = phiInternal[curFace];
if (!curFlip)
{
// Face points out of the live cell
if (curFlux < 0)
{
// Flux out of the live cell
curFlux *= massCorr;
newFluxIn -= curFlux;
}
}
else
{
// Face points into the live cell: flip it
if (curFlux >= 0)
{
// Flux out the live cell
curFlux *= massCorr;
newFluxIn += curFlux;
}
}
}
}
}
else
{
// Scale down outgoing flux
massCorr = 1 + imbalance/(fluxOut + SMALL);
if (fvMesh::debug)
{
Info<< "Scaling down outgoing flux with factor = "
<< massCorr << endl;
}
scalar newFluxOut = 0;
// Visit all outgoing flux faces and re-scale the flux
forAll (ibFaces, faceI)
{
const label curFace = ibFaces[faceI];
const bool curFlip = ibFaceFlips[faceI];
if (mesh.isInternalFace(curFace))
{
// Take reference to current flux
scalar& curFlux = phiInternal[curFace];
if (!curFlip)
{
// Face points out of the live cell
if (curFlux >= 0)
{
// Flux out of the live cell
curFlux *= massCorr;
newFluxOut += curFlux;
}
}
else
{
// Face points into the live cell: flip it
if (curFlux < 0)
{
// Flux out the live cell
curFlux *= massCorr;
newFluxOut -= curFlux;
}
}
}
}
}
}
}
}
}
// If the mesh is moving, adjustment needs to be calculated on
// relative fluxes. Now reverting to absolute fluxes. HJ, 13/Feb/2009
if (mesh.moving())
{
fvc::makeAbsolute(phi, U);
}
}
// ************************************************************************* //

View file

@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
InNamespace
Foam
Description
Adjust immersed boundary fluxes to obey continuity
SourceFiles
immersedBoundaryAdjustPhi.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryAdjustPhi_H
#define immersedBoundaryAdjustPhi_H
#include "volFieldsFwd.H"
#include "surfaceFieldsFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
//- Adjust the fluxes on immersed boundary to obey continuity.
void immersedBoundaryAdjustPhi
(
surfaceScalarField& phi,
volVectorField& U
);
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,572 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::immersedBoundaryFvPatch
Description
Immersed boundary FV patch
Author
Zeljko Tukovic
Reorganisation by Hrvoje Jasak
SourceFiles
immersedBoundaryFvPatch.C
immersedBoundaryFvPatchLeastSquaresFit.C
immersedBoundaryFvPatchTriAddressing.C
immersedBoundaryFvPatchSamplingWeights.C
immersedBoundaryFvPatchTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvPatch_H
#define immersedBoundaryFvPatch_H
#include "fvPatch.H"
#include "immersedBoundaryPolyPatch.H"
#include "volFieldsFwd.H"
#include "surfaceFieldsFwd.H"
#include "labelPair.H"
#include "FieldFields.H"
#include "scalarMatrices.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class fvMesh;
/*---------------------------------------------------------------------------*\
Class immersedBoundaryFvPatch Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryFvPatch
:
public fvPatch
{
// Private data
//- Reference to processor patch
const immersedBoundaryPolyPatch& ibPolyPatch_;
//- Finite volume mesh reference
const fvMesh& mesh_;
// Static data
//- Fitting angle rejection factor (deg)
// Cells within the the radius will be used for the fitting function
static scalar angleFactor_;
//- Fitting radius factor
// Cells within the the radius will be used for the fitting function
static scalar radiusFactor_;
//- Maximum number of rows in cell-cell search
static label maxCellCellRows_;
//- Sampling point distance factor
// Sampling point is located distFactor further away from the wall
// from the immersed boundary cell centre
static scalar distFactor_;
// Demand-driven data
// Immersed boundary data
//- Fluid cells indicator, marking only live fluid cells
mutable volScalarField* gammaPtr_;
//- Fluid cells indicator, marking live and IB cells
mutable volScalarField* gammaExtPtr_;
//- Fluid faces indicator, marking faces between live cells
mutable surfaceScalarField* sGammaPtr_;
//- List of fluid cells next to immersed boundary (IB cells)
mutable labelList* ibCellsPtr_;
//- List of faces for which one neighbour is an IB cell
// and another neighbour is a live fluid cell (IB faces)
mutable labelList* ibFacesPtr_;
//- List of IB cell index for each ibFace
mutable labelList* ibFaceCellsPtr_;
//- List of IB face flip:
// false if IB face points into IB cell (out of the live cell)
// true if IB face points into a live cell
mutable boolList* ibFaceFlipsPtr_;
//- List of fluid faces for which one neighbour is an IB cell
// and another neighbour is a dead cell (inside IB faces)
mutable labelList* ibInsideFacesPtr_;
//- List of internal faces in the region bounded by IB faces
mutable labelList* ibInternalFacesPtr_;
//- Points at the immersed boundary (IB points)
// nearest to the IB cell centres
mutable vectorField* ibPointsPtr_;
//- Normals at IB points
mutable vectorField* ibNormalsPtr_;
//- List of faces (triangles) which are part of IB mesh
// nearest to the IB cell centres
mutable labelList* hitFacesPtr_;
//- Sampling points for IB cells
mutable vectorField* ibSamplingPointsPtr_;
//- Interpolation weights for sampling weights
mutable scalarListList* ibSamplingWeightsPtr_;
//- Interpolation weights for sampling processor weights
mutable scalarListList* ibSamplingProcWeightsPtr_;
//- Interpolation addressing from IB points to tri faces
mutable labelListList* cellsToTriAddrPtr_;
//- Interpolation weights from IB points to tri faces
mutable scalarListList* cellsToTriWeightsPtr_;
//- Neighbour cells for immersed boundary cells
// (extended stencil)
mutable labelListList* ibCellCellsPtr_;
//- List of cells needed by neighbour processors
mutable labelListList* ibProcCellsPtr_;
//- Centres of cells from neighbour processors
mutable FieldField<Field, vector>* ibProcCentresPtr_;
//- Gamma of cells from neighbour processors
mutable FieldField<Field, scalar>* ibProcGammaPtr_;
//- Cell-proc-cell addressing
mutable List<List<labelPair> >* ibCellProcCellsPtr_;
//- Dead cells list
mutable labelList* deadCellsPtr_;
//- Extended dead cells list (dead cells + IB cells)
mutable labelList* deadCellsExtPtr_;
//- Dead faces list
mutable labelList* deadFacesPtr_;
//- List of live cells
mutable labelList* liveCellsPtr_;
//- Average IB cell sizes
mutable scalarField* ibCellSizesPtr_;
//- Inverse interpolation matrices for Dirichlet BC at the IB
mutable PtrList<scalarRectangularMatrix>* invDirichletMatricesPtr_;
//- Inverse interpolation matrices for Neumann BC at the IB
mutable PtrList<scalarRectangularMatrix>* invNeumannMatricesPtr_;
//- IB face area vectors
mutable vectorField* ibSfPtr_;
//- IB face area vector magnitudess
mutable scalarField* ibMagSfPtr_;
//- IB cell centre distances to IB
mutable scalarField* ibDeltaPtr_;
//- IB cell centre distances to IB
mutable scalarField* ibSamplingPointDeltaPtr_;
// Tri surface data
//- Tri surface face area vectors
mutable vectorField* triSfPtr_;
// Private Member Functions
// Storage management
//- Clear all demand-driven data
void clearOut();
// Make demand-driven data
//- Make fluid cells indicator, marking only live fluid cells
void makeGamma() const;
//- Make extended fluid cells indicator, marking live and IB cells
void makeGammaExt() const;
//- Make fluid faces indicator
void makeSGamma() const;
//- Make list of cells next to immersed boundary
void makeIbCells() const;
//- Add corner points to IB cells list
void addIbCornerCells() const;
//- Make IB faces
void makeIbFaces() const;
//- Make tri addressing
void makeTriAddressing() const;
//- Make inside IB faces
void makeIbInsideFaces() const;
//- Make internal IB faces
void makeIbInternalFaces() const;
//- Make immersed boundary points and normals
void makeIbPointsAndNormals() const;
//- Make sampling point weights
void makeIbSamplingWeights() const;
//- Make extended IB cells stencils
void makeIbCellCells() const;
//- Make list of dead cells
void makeDeadCells() const;
//- Make extended list of dead cells
void makeDeadCellsExt() const;
//- Make list of dead faces
void makeDeadFaces() const;
//- Make list of live cells
void makeLiveCells() const;
//- Make immersed boundary cell sizes
void makeIbCellSizes() const;
//- Make face area vectors and magnitudes
void makeIbSf() const;
//- Make distance between IB cell centres
// and corresponding IB points
void makeIbDelta() const;
//- Make distance between IB cell centres
// and corresponding sample IB points
void makeIbSamplingPointDelta() const;
//- Make triangular surface face area vectors
void makeTriSf() const;
//- Find nearest cell
label findNearestCell(const point& location) const;
//- Return extended cell-cell addressing
void findCellCells
(
const vector& pt,
const label cellID,
labelList& cellCells
) const;
//- Calc cell size
scalar cellSize(label cellID) const;
//- Calc cell projection area
scalar cellProjection(label cellID, const vector& dir) const;
// Boundary evaluation matrices
//- Make inverse Dirichlet interpolation matrices
void makeInvDirichletMatrices() const;
//- Make inverse Neumann interpolation matrices
void makeInvNeumannMatrices() const;
protected:
// Protected Member Functions
//- Initialise the patches for moving points
virtual void initMovePoints();
//- Correct patches after moving points
virtual void movePoints();
public:
//- Runtime type information
TypeName(immersedBoundaryPolyPatch::typeName_());
// Constructors
//- Construct from polyPatch
immersedBoundaryFvPatch
(
const polyPatch& patch,
const fvBoundaryMesh& bm
);
//- Destructor
virtual ~immersedBoundaryFvPatch()
{}
// Member Functions
// Access to immersed boundary components
//- Return reference to immersed boundary polyPatch
const immersedBoundaryPolyPatch& ibPolyPatch() const
{
return ibPolyPatch_;
}
//- Return immersed boundary surface mesh
const triSurfaceMesh& ibMesh() const
{
return ibPolyPatch_.ibMesh();
}
bool internalFlow() const
{
return ibPolyPatch_.internalFlow();
}
//- Is the immersed boundary patch moving?
bool movingIb() const
{
return ibPolyPatch_.movingIb();
}
// Immersed boundary data access
//- Get fluid cells indicator, marking only live fluid cells
const volScalarField& gamma() const;
//- Get extended flud cells indicator, including live and IB cells
const volScalarField& gammaExt() const;
//- Get fluid faces indicator, marking faces between live cells
const surfaceScalarField& sGamma() const;
//- Return list of fluid cells next to immersed boundary (IB cells)
const labelList& ibCells() const;
//- Return list of faces for which one neighbour is an IB cell
// and another neighbour is a live fluid cell (IB faces)
const labelList& ibFaces() const;
//- Return list of IB cell index for each ibFace
const labelList& ibFaceCells() const;
//- Return list of IB face flip:
// false if IB face points into IB cell (out of the live cell)
// true if IB face points into a live cell
const boolList& ibFaceFlips() const;
//- Return list of fluid faces for which one neighbour is an
// IB cell and another neighbour is a dead cell (inside IB faces)
const labelList& ibInsideFaces() const;
//- Return list of internal faces in the region bounded by IB faces
const labelList& ibInternalFaces() const;
//- Return IB points
const vectorField& ibPoints() const;
//- Return IB normals
const vectorField& ibNormals() const;
//- Return list of triangles in IB mesh nearest
// nearest to IB cell centres
const labelList& hitFaces() const;
//- Return IB sampling points
const vectorField& ibSamplingPoints() const;
//- Interpolation weights for sampling points
const scalarListList& ibSamplingWeights() const;
//- Processor interpolation weights for sampling points
const scalarListList& ibSamplingProcWeights() const;
//- Interpolation addressing from IB points to tri faces
const labelListList& cellsToTriAddr() const;
//- Interpolation weights from IB points to tri faces
const scalarListList& cellsToTriWeights() const;
//- Return IB cell extended stencil
const labelListList& ibCellCells() const;
//- Return neighbour proc centres
// These are centres from neighbouring processors the
// local processor needs to receive
const FieldField<Field, vector>& ibProcCentres() const;
//- Return neighbour proc gamma
// These are gamma values from neighbouring processors the
// local processor needs to receive
const FieldField<Field, scalar>& ibProcGamma() const;
//- Return neighbour cell addressing
const List<List<labelPair> >& ibCellProcCells() const;
//- Return neighbour proc cells
// These are cell data that other processors need from
// local processor
const labelListList& ibProcCells() const;
//- Return dead cells
const labelList& deadCells() const;
//- Return extended dead cells
const labelList& deadCellsExt() const;
//- Return dead faces
const labelList& deadFaces() const;
//- Return live cells
const labelList& liveCells() const;
//- Return immersed boundary cell sizes
const scalarField& ibCellSizes() const;
//- Get inverse Dirichlet interpolation matrix
const PtrList<scalarRectangularMatrix>&
invDirichletMatrices() const;
//- Get inverse Neumann interpolation matrix
const PtrList<scalarRectangularMatrix>&
invNeumannMatrices() const;
//- Return IB face area vectors
const vectorField& ibSf() const;
//- Return IB face area vector magnitudes
const scalarField& ibMagSf() const;
//- Return distance to IB
const scalarField& ibDelta() const;
//- Return distance to IB
const scalarField& ibSamplingPointDelta() const;
//- Return triangular surface face area vectors
const vectorField& triSf() const;
//- Return triangular surface face centres
const vectorField& triCf() const;
// Parallel communication
//- Send and receive
template<class Type>
tmp<FieldField<Field, Type> > sendAndReceive
(
const Field<Type>& psi
) const;
// Interpolation functions to and from triangular surface
//- Collect ibPoint values: from tri face fields onto intersection
// points on the IB surface
template<class Type>
tmp<Field<Type> > toIbPoints
(
const Field<Type>& triValues
) const;
//- Collect ibPoint values: from tri face fields onto intersection
// points on the IB surface with tmp
template<class Type>
tmp<Field<Type> > toIbPoints
(
const tmp<Field<Type> >& ttriValues
) const;
//- triFace values: collect data from IB fields onto intersection
// points on the IB surface
template<class Type>
tmp<Field<Type> > toTriFaces
(
const Field<Type>& ibValues
) const;
//- triFace values: collect data from IB fields onto intersection
// points on the IB surface with tmp
template<class Type>
tmp<Field<Type> > toTriFaces
(
const tmp<Field<Type> >& tibValues
) const;
//- Interpolation functions to sampling points from mesh cell centres
template<class Type>
tmp<Field<Type> > toSamplingPoints
(
const Field<Type>& cellValues
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "immersedBoundaryFvPatchTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,594 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryFvPatch.H"
#include "fvMesh.H"
#include "volFields.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::immersedBoundaryFvPatch::makeInvDirichletMatrices() const
{
if (debug)
{
Info<< "immersedBoundaryFvPatch::makeInvDirichletMatrices() : "
<< "making immersed boundary inverse matrices"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (invDirichletMatricesPtr_)
{
FatalErrorIn
(
"void immersedBoundaryFvPatch::makeInvDirichletMatrices()"
) << "immersed boundary inverse least squares matrices already exist"
<< abort(FatalError);
}
// Get addressing
const labelList& ibc = ibCells();
const labelListList& ibcc = ibCellCells();
const List<List<labelPair> >& ibcProcC = ibCellProcCells();
const vectorField& ibp = ibPoints();
invDirichletMatricesPtr_ =
new PtrList<scalarRectangularMatrix>(ibc.size());
PtrList<scalarRectangularMatrix>& idm = *invDirichletMatricesPtr_;
const vectorField& C = mesh_.C().internalField();
scalarField conditionNumber(ibc.size(), 0.0);
// Initialize maxRowSum for debug
scalar maxRowSum = 0.0;
const FieldField<Field, vector>& procC = ibProcCentres();
label nCoeffs = 5;
if (mesh_.nGeometricD() == 3)
{
nCoeffs += 4;
}
forAll (idm, cellI)
{
const labelList& interpCells = ibcc[cellI];
const List<labelPair>& interpProcCells = ibcProcC[cellI];
vectorField allPoints
(
interpCells.size()
+ interpProcCells.size(),
vector::zero
);
if (allPoints.size() < nCoeffs)
{
FatalErrorIn
(
"void immersedBoundaryFvPatch::makeInvDirichletMatrices()"
) << "allPoints.size() < " << nCoeffs << " : "
<< allPoints.size() << abort(FatalError);
}
label pointID = 0;
// Cells
for (label i = 0; i < interpCells.size(); i++)
{
allPoints[pointID++] = C[interpCells[i]];
}
// Processor cells
for (label i = 0; i < interpProcCells.size(); i++)
{
allPoints[pointID++] =
procC
[
interpProcCells[i].first()
]
[
interpProcCells[i].second()
];
}
// Weights calculation
vector origin = C[ibc[cellI]];
scalarField curDist = mag(allPoints - origin);
// Calculate weights
scalarField W =
0.5*
(
1
+ cos(mathematicalConstant::pi*curDist/(1.1*max(curDist)))
);
idm.set
(
cellI,
new scalarRectangularMatrix
(
nCoeffs,
allPoints.size(),
0.0
)
);
scalarRectangularMatrix& curMatrix = idm[cellI];
scalarRectangularMatrix M
(
allPoints.size(),
nCoeffs,
0.0
);
origin = ibp[cellI];
for(label i = 0; i < allPoints.size(); i++)
{
scalar X = allPoints[i].x() - origin.x();
scalar Y = allPoints[i].y() - origin.y();
label coeff = 0;
M[i][coeff++] = X;
M[i][coeff++] = Y;
M[i][coeff++] = X*Y;
M[i][coeff++] = sqr(X);
M[i][coeff++] = sqr(Y);
if (mesh_.nGeometricD() == 3)
{
scalar Z = allPoints[i].z() - origin.z();
M[i][coeff++] = Z;
M[i][coeff++] = X*Z;
M[i][coeff++] = Y*Z;
M[i][coeff++] = sqr(Z);
}
}
for (label i = 0; i < M.n(); i++)
{
for (label j = 0; j < M.m(); j++)
{
M[i][j] *= W[i];
}
}
scalarSquareMatrix lsM(nCoeffs, 0.0);
for (label i = 0; i < lsM.n(); i++)
{
for (label j = 0; j < lsM.m(); j++)
{
for (label k=0; k<M.n(); k++)
{
lsM[i][j] += M[k][i]*M[k][j];
}
}
}
if (debug)
{
// Calculate matrix norm
maxRowSum = 0.0;
for (label i = 0; i < lsM.n(); i++)
{
scalar curRowSum = 0.0;
for (label j = 0; j < lsM.m(); j++)
{
curRowSum += lsM[i][j];
}
if (curRowSum > maxRowSum)
{
maxRowSum = curRowSum;
}
}
conditionNumber[cellI] = maxRowSum;
}
// Calculate inverse
scalarSquareMatrix invLsM = lsM.LUinvert();
for (label i = 0; i < lsM.n(); i++)
{
for (label j = 0; j < M.n(); j++)
{
for (label k = 0; k < lsM.n(); k++)
{
curMatrix[i][j] += invLsM[i][k]*M[j][k]*W[j];
}
}
}
if (debug)
{
// Calculate condition number
maxRowSum = 0.0;
for (label i = 0; i < lsM.n(); i++)
{
scalar curRowSum = 0.0;
for (label j = 0; j < lsM.m(); j++)
{
curRowSum += invLsM[i][j];
}
if (curRowSum > maxRowSum)
{
maxRowSum = curRowSum;
}
}
conditionNumber[cellI] *= maxRowSum;
InfoIn
(
"void immersedBoundaryFvPatch::"
"makeInvDirichletMatrices() const"
) << "Max Dirichlet matrix condition number: "
<< gMax(conditionNumber) << endl;
}
}
}
void Foam::immersedBoundaryFvPatch::makeInvNeumannMatrices() const
{
if (debug)
{
Info<< "immersedBoundaryFvPatch::makeInvNeumannMatrices() : "
<< "making immersed boundary inverse least sqares matrices"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (invNeumannMatricesPtr_)
{
FatalErrorIn("immersedBoundaryFvPatch::makeInvNeumannMatrices()")
<< "immersed boundary inverse least squares matrices already exist"
<< abort(FatalError);
}
// Get addressing
const labelList& ibc = ibCells();
const labelListList& ibcc = ibCellCells();
const List<List<labelPair> >& ibcProcC = ibCellProcCells();
const vectorField& ibp = ibPoints();
// Note: the algorithm is originally written with inward-facing normals
// and subsequently changed: IB surface normals point outwards
// HJ, 21/May/2012
const vectorField& ibn = ibNormals();
invNeumannMatricesPtr_ =
new PtrList<scalarRectangularMatrix>(ibc.size());
PtrList<scalarRectangularMatrix>& inm = *invNeumannMatricesPtr_;
const vectorField& C = mesh_.C().internalField();
scalarField conditionNumber(ibc.size(), 0);
// Initialize maxRowSum for debug
scalar maxRowSum = 0.0;
const FieldField<Field, vector>& procC = ibProcCentres();
label nCoeffs = 6;
if (mesh_.nGeometricD() == 3)
{
nCoeffs += 4;
}
forAll (inm, cellI)
{
const labelList& interpCells = ibcc[cellI];
const List<labelPair>& interpProcCells = ibcProcC[cellI];
vectorField allPoints
(
interpCells.size() + 1
+ interpProcCells.size(),
vector::zero
);
label pointID = 0;
// Cells
for (label i = 0; i < interpCells.size(); i++)
{
allPoints[pointID++] = C[interpCells[i]];
}
// IB point
allPoints[pointID++] = ibp[cellI];
// Processor cells
for (label i = 0; i < interpProcCells.size(); i++)
{
allPoints[pointID++] =
procC
[
interpProcCells[i].first()
]
[
interpProcCells[i].second()
];
}
// Weights calculation
vector origin = C[ibc[cellI]];
scalarField curR = mag(allPoints - origin);
// Calculate weights
scalarField W = 1 - curR/(1.1*max(curR));
inm.set
(
cellI,
new scalarRectangularMatrix
(
nCoeffs,
allPoints.size(),
0.0
)
);
scalarRectangularMatrix& curMatrix = inm[cellI];
scalarRectangularMatrix M
(
allPoints.size(),
nCoeffs,
0.0
);
pointID = 0;
origin = ibp[cellI];
for (label i = 0; i < interpCells.size(); i++)
{
scalar X = allPoints[pointID].x() - origin.x();
scalar Y = allPoints[pointID].y() - origin.y();
M[pointID][0] = 1.0;
M[pointID][1] = X;
M[pointID][2] = Y;
M[pointID][3] = X*Y;
M[pointID][4] = sqr(X);
M[pointID][5] = sqr(Y);
if (mesh_.nGeometricD() == 3)
{
scalar Z = allPoints[pointID].z() - origin.z();
M[pointID][6] = Z;
M[pointID][7] = X*Z;
M[pointID][8] = Y*Z;
M[pointID][9] = sqr(Z);
}
pointID++;
}
scalar X = allPoints[pointID].x() - origin.x();
scalar Y = allPoints[pointID].y() - origin.y();
M[pointID][0] = 0;
M[pointID][1] = -ibn[cellI].x();
M[pointID][2] = -ibn[cellI].y();
M[pointID][3] =
(
-ibn[cellI].x()*Y
- ibn[cellI].y()*X
);
M[pointID][4] = -2*ibn[cellI].x()*X;
M[pointID][5] = -2*ibn[cellI].y()*Y;
if (mesh_.nGeometricD() == 3)
{
scalar Z = allPoints[pointID].z() - origin.z();
M[pointID][6] = -ibn[cellI].z();
M[pointID][7] =
(
-ibn[cellI].x()*Z
- ibn[cellI].z()*X
);
M[pointID][8] =
(
-ibn[cellI].y()*Z
- ibn[cellI].z()*Y
);
M[pointID][9] = -2*ibn[cellI].z()*Z;
}
pointID++;
for(label i = 0; i < interpProcCells.size(); i++)
{
scalar X = allPoints[pointID].x() - origin.x();
scalar Y = allPoints[pointID].y() - origin.y();
M[pointID][0] = 1.0;
M[pointID][1] = X;
M[pointID][2] = Y;
M[pointID][3] = X*Y;
M[pointID][4] = sqr(X);
M[pointID][5] = sqr(Y);
if (mesh_.nGeometricD() == 3)
{
scalar Z = allPoints[pointID].z() - origin.z();
M[pointID][6] = Z;
M[pointID][7] = X*Z;
M[pointID][8] = Y*Z;
M[pointID][9] = sqr(Z);
}
pointID++;
}
for (label i = 0; i < M.n(); i++)
{
for (label j = 0; j < M.m(); j++)
{
M[i][j] *= W[i];
}
}
scalarSquareMatrix lsM(nCoeffs, 0.0);
for (label i = 0; i < lsM.n(); i++)
{
for (label j = 0; j < lsM.m(); j++)
{
for (label k = 0; k < M.n(); k++)
{
lsM[i][j] += M[k][i]*M[k][j];
}
}
}
// Calculate matrix norm
if (debug)
{
maxRowSum = 0.0;
for (label i = 0; i < lsM.n(); i++)
{
scalar curRowSum = 0.0;
for (label j = 0; j < lsM.m(); j++)
{
curRowSum += lsM[i][j];
}
if (curRowSum > maxRowSum)
{
maxRowSum = curRowSum;
}
}
conditionNumber[cellI] = maxRowSum;
}
// Calculate inverse
scalarSquareMatrix invLsM = lsM.LUinvert();
for (label i = 0; i < lsM.n(); i++)
{
for (label j = 0; j < M.n(); j++)
{
for (label k = 0; k < lsM.n(); k++)
{
curMatrix[i][j] += invLsM[i][k]*M[j][k]*W[j];
}
}
}
// Calculate condition number
if (debug)
{
maxRowSum = 0.0;
for (label i = 0; i < lsM.n(); i++)
{
scalar curRowSum = 0.0;
for (label j = 0; j < lsM.m(); j++)
{
curRowSum += invLsM[i][j];
}
if (curRowSum > maxRowSum)
{
maxRowSum = curRowSum;
}
}
conditionNumber[cellI] *= maxRowSum;
if (conditionNumber[cellI] > 1e6)
{
labelList CC = interpCells;
sort(CC);
Info<< "Condition = " << conditionNumber[cellI] << nl
<< "cell cells: " << CC
<< "M = " << lsM
<< endl;
}
InfoIn
(
"void immersedBoundaryFvPatch::makeInvNeumannMatrices() const"
) << "Max Neumann matrix condition number: "
<< gMax(conditionNumber) << endl;
}
}
}
const Foam::PtrList<Foam::scalarRectangularMatrix>&
Foam::immersedBoundaryFvPatch::invDirichletMatrices() const
{
if (!invDirichletMatricesPtr_)
{
makeInvDirichletMatrices();
}
return *invDirichletMatricesPtr_;
}
const Foam::PtrList<Foam::scalarRectangularMatrix>&
Foam::immersedBoundaryFvPatch::invNeumannMatrices() const
{
if (!invNeumannMatricesPtr_)
{
makeInvNeumannMatrices();
}
return *invNeumannMatricesPtr_;
}
// ************************************************************************* //

View file

@ -0,0 +1,208 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryFvPatch.H"
#include "fvMesh.H"
#include "volFields.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::immersedBoundaryFvPatch::makeIbSamplingWeights() const
{
if (debug)
{
Info<< "immersedBoundaryFvPatch::makeIbSamplingWeights() : "
<< "making sampling point weights"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (ibSamplingWeightsPtr_ || ibSamplingProcWeightsPtr_)
{
FatalErrorIn("void immersedBoundaryFvPatch::makeIbSamplingWeights()")
<< "sampling point weights already exist"
<< abort(FatalError);
}
// Get addressing
const labelList& ibc = ibCells();
const labelListList& ibcc = ibCellCells();
const List<List<labelPair> >& ibcProcC = ibCellProcCells();
// Initialise the weights
ibSamplingWeightsPtr_ = new scalarListList(ibc.size());
scalarListList& cellWeights = *ibSamplingWeightsPtr_;
forAll (cellWeights, cellI)
{
cellWeights[cellI].setSize(ibcc[cellI].size(), 0);
}
ibSamplingProcWeightsPtr_ = new scalarListList(ibc.size());
scalarListList& cellProcWeights = *ibSamplingProcWeightsPtr_;
forAll (cellProcWeights, cellI)
{
cellProcWeights[cellI].setSize(ibcProcC[cellI].size(), 0);
}
// Get sampling point locations
const vectorField& samplingPoints = ibSamplingPoints();
const scalarField& gammaIn = gamma().internalField();
const vectorField& CIn = mesh_.C().internalField();
const FieldField<Field, scalar>& gammaProc = ibProcGamma();
const FieldField<Field, vector>& CProc = ibProcCentres();
// Go through all cellCells and calculate inverse distance for
// all live points
forAll (samplingPoints, cellI)
{
const vector& curP = samplingPoints[cellI];
scalar sumW = 0;
// Local weights
scalarList& curCW = cellWeights[cellI];
const labelList& curCells = ibcc[cellI];
forAll (curCells, ccI)
{
// Only pick live cells
if (gammaIn[curCells[ccI]] > SMALL)
{
curCW[ccI] = 1/mag(CIn[curCells[ccI]] - curP);
sumW += curCW[ccI];
}
else
{
curCW[ccI] = 0;
}
}
// Processor weights
const List<labelPair>& interpProcCells = ibcProcC[cellI];
scalarList& curProcCW = cellProcWeights[cellI];
forAll (interpProcCells, cProcI)
{
if
(
gammaProc
[
interpProcCells[cProcI].first()
]
[
interpProcCells[cProcI].second()
] > SMALL
)
{
curProcCW[cProcI] =
1/mag
(
CProc
[
interpProcCells[cProcI].first()
]
[
interpProcCells[cProcI].second()
] - curP
);
sumW += curProcCW[cProcI];
}
else
{
curProcCW[cProcI] = 0;
}
}
// Divide through by the sum
if (sumW < SMALL)
{
InfoIn
(
"void immersedBoundaryFvPatch::makeIbSamplingWeights()"
) << "Insufficient live neighbourhood for IB cell "
<< ibc[cellI] << "." << nl
<< "Please adjust radiusFactor, angleFactor or "
<< "immersedBoundaryMaxCellCellRows "
<< "in immersedBoundaryFvPatch."
<< endl;
// Reset sum and weights and use all points
sumW = 0;
curCW = 0;
forAll (curCells, ccI)
{
// Use all cells
curCW[ccI] = 1/mag(CIn[curCells[ccI]] - curP);
sumW += curCW[ccI];
}
}
forAll (curCells, ccI)
{
curCW[ccI] /= sumW;
}
forAll (curProcCW, cProcI)
{
curProcCW[cProcI] /= sumW;
}
}
}
const Foam::scalarListList&
Foam::immersedBoundaryFvPatch::ibSamplingWeights() const
{
if (!ibSamplingWeightsPtr_)
{
makeIbSamplingWeights();
}
return *ibSamplingWeightsPtr_;
}
const Foam::scalarListList&
Foam::immersedBoundaryFvPatch::ibSamplingProcWeights() const
{
if (!ibSamplingProcWeightsPtr_)
{
makeIbSamplingWeights();
}
return *ibSamplingProcWeightsPtr_;
}
// ************************************************************************* //

View file

@ -0,0 +1,324 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryFvPatch.H"
#include "fvMesh.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::FieldField<Foam::Field, Type> >
Foam::immersedBoundaryFvPatch::sendAndReceive
(
const Field<Type>& psi
) const
{
tmp<FieldField<Field, Type> > tprocPsi
(
new FieldField<Field, Type>(Pstream::nProcs())
);
FieldField<Field, Type>& procPsi = tprocPsi();
forAll (procPsi, procI)
{
procPsi.set
(
procI,
new Field<Type>
(
ibProcCentres()[procI].size(),
pTraits<Type>::zero
)
);
}
if (Pstream::parRun())
{
// Send
for (label procI = 0; procI < Pstream::nProcs(); procI++)
{
if (procI != Pstream::myProcNo())
{
// Do not send empty lists
if (!ibProcCells()[procI].empty())
{
Field<Type> curPsi(psi, ibProcCells()[procI]);
// Parallel data exchange
OPstream toProc
(
Pstream::blocking,
procI,
curPsi.size()*sizeof(Type)
);
toProc << curPsi;
}
}
}
// Receive
for (label procI = 0; procI < Pstream::nProcs(); procI++)
{
if (procI != Pstream::myProcNo())
{
// Do not receive empty lists
if (!procPsi[procI].empty())
{
// Parallel data exchange
IPstream fromProc
(
Pstream::blocking,
procI,
procPsi[procI].size()*sizeof(Type)
);
fromProc >> procPsi[procI];
}
}
}
}
return tprocPsi;
}
template<class Type>
Foam::tmp<Foam::Field<Type> >
Foam::immersedBoundaryFvPatch::toIbPoints
(
const Field<Type>& triValues
) const
{
if (triValues.size() != ibMesh().size())
{
FatalErrorIn
(
"template<class Type>\n"
"Foam::tmp<Foam::Field<Type> >\n"
"immersedBoundaryFvPatch::toIbPoints\n"
"(\n"
" const Field<Type>& triValues\n"
") const"
) << "Field size does not correspond to size of immersed boundary "
<< "triangulated surface for patch " << name() << nl
<< "Field size = " << triValues.size()
<< " surface size = " << ibMesh().size()
<< abort(FatalError);
}
const labelList& ibc = ibCells();
tmp<Field<Type> > tIbPsi
(
new Field<Type>(ibc.size(), pTraits<Type>::zero)
);
Field<Type>& ibPsi = tIbPsi();
const labelList& hf = hitFaces();
// Assuming triSurface data is on triangles
forAll (ibPsi, cellI)
{
ibPsi[cellI] = triValues[hf[cellI]];
}
// const vectorField& p = ibPoints();
// const List<labelledTri>& faces = ibMesh();
// const vectorField& triPoints = ibMesh().points();
// // Assuming triSurface data is on vertices
// forAll (ibPsi, cellI)
// {
// const labelledTri& tri = faces[hf[cellI]];
// triPointRef triPt = faces[hf[cellI]].tri(triPoints);
// ibPsi[cellI] =
// triValues[tri[0]]*triPt.Ni(0, p[cellI])
// + triValues[tri[1]]*triPt.Ni(1, p[cellI])
// + triValues[tri[2]]*triPt.Ni(2, p[cellI]);
// }
return tIbPsi;
}
template<class Type>
Foam::tmp<Foam::Field<Type> >
Foam::immersedBoundaryFvPatch::toIbPoints
(
const tmp<Field<Type> >& ttriValues
) const
{
tmp<Field<Type> > tint = toIbPoints(ttriValues());
ttriValues.clear();
return tint;
}
template<class Type>
Foam::tmp<Foam::Field<Type> >
Foam::immersedBoundaryFvPatch::toTriFaces
(
const Field<Type>& ibValues
) const
{
if (ibValues.size() != ibCells().size())
{
FatalErrorIn
(
"template<class Type>\n"
"Foam::tmp<Foam::Field<Type> >\n"
"immersedBoundaryFvPatch::toTriFaces\n"
"(\n"
" const Field<Type>& ibValues\n"
") const"
) << "Field size does not correspond to size of IB points "
<< "triangulated surface for patch " << name() << nl
<< "Field size = " << ibValues.size()
<< " IB points size = " << ibCells().size()
<< abort(FatalError);
}
const labelListList& ctfAddr = cellsToTriAddr();
const scalarListList& ctfWeights = cellsToTriWeights();
tmp<Field<Type> > tIbPsi
(
new Field<Type>(ctfAddr.size(), pTraits<Type>::zero)
);
Field<Type>& ibPsi = tIbPsi();
// Do interpolation
forAll (ctfAddr, triI)
{
const labelList& curAddr = ctfAddr[triI];
const scalarList& curWeights = ctfWeights[triI];
forAll (curAddr, cellI)
{
ibPsi[triI] += curWeights[cellI]*ibValues[curAddr[cellI]];
}
}
return tIbPsi;
}
template<class Type>
Foam::tmp<Foam::Field<Type> >
Foam::immersedBoundaryFvPatch::toTriFaces
(
const tmp<Field<Type> >& tibValues
) const
{
tmp<Field<Type> > tint = toTriFaces(tibValues());
tibValues.clear();
return tint;
}
template<class Type>
Foam::tmp<Foam::Field<Type> >
Foam::immersedBoundaryFvPatch::toSamplingPoints
(
const Field<Type>& cellValues
) const
{
if (cellValues.size() != mesh_.nCells())
{
FatalErrorIn
(
"template<class Type>\n"
"Foam::tmp<Foam::Field<Type> >\n"
"immersedBoundaryFvPatch::toSamplingPoints\n"
"(\n"
" const Field<Type>& cellValues\n"
") const"
) << "Field size does not correspond to cell centres "
<< "for patch " << name() << nl
<< "Field size = " << cellValues.size()
<< " nCells = " << mesh_.nCells()
<< abort(FatalError);
}
// Get addressing
const labelList& ibc = ibCells();
const labelListList& ibcc = ibCellCells();
const List<List<labelPair> >& ibcProcC = ibCellProcCells();
// Get weights
const scalarListList& cellWeights = ibSamplingWeights();
const scalarListList& cellProcWeights = ibSamplingProcWeights();
tmp<Field<Type> > tIbPsi
(
new Field<Type>(ibc.size(), pTraits<Type>::zero)
);
Field<Type>& ibPsi = tIbPsi();
// Do interpolation, local cell data
forAll (ibc, cellI)
{
const labelList& curAddr = ibcc[cellI];
const scalarList& curWeights = cellWeights[cellI];
forAll (curAddr, ccI)
{
ibPsi[cellI] += curWeights[ccI]*cellValues[curAddr[ccI]];
}
}
// Parallel communication for psi
FieldField<Field, Type> procCellValues = sendAndReceive(cellValues);
// Do interpolation, cell data from other processors
forAll (ibc, cellI)
{
const List<labelPair>& curProcCells = ibcProcC[cellI];
const scalarList& curProcWeights = cellProcWeights[cellI];
forAll (curProcCells, cpcI)
{
ibPsi[cellI] +=
curProcWeights[cpcI]*
procCellValues
[
curProcCells[cpcI].first()
]
[
curProcCells[cpcI].second()
];
}
}
return tIbPsi;
}
// ************************************************************************ //

View file

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryFvPatch.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::immersedBoundaryFvPatch::makeTriAddressing() const
{
if (debug)
{
InfoIn("void immersedBoundaryFvPatch::makeTriAddressing() const")
<< "creating tri addressing for immersed boundary " << name()
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already set
if (cellsToTriAddrPtr_ || cellsToTriWeightsPtr_)
{
FatalErrorIn("immersedBoundaryFvPatch::makeTriAddressing() const")
<< "tri addressing already exist"
<< "for immersed boundary" << name()
<< abort(FatalError);
}
// Get reference to tri patch and hit faces
const triSurface& triPatch = ibPolyPatch_.ibMesh();
const vectorField& triCentres = triPatch.faceCentres();
const labelList& hf = hitFaces();
const vectorField& ibp = ibPoints();
// Create a markup field and mark all tris containing an ib point with its
// index
labelList hitTris(triPatch.size(), -1);
forAll (hf, hfI)
{
hitTris[hf[hfI]] = hfI;
}
// Allocate storage
cellsToTriAddrPtr_ = new labelListList(triPatch.size());
labelListList& addr = *cellsToTriAddrPtr_;
cellsToTriWeightsPtr_ = new scalarListList(triPatch.size());
scalarListList& w = *cellsToTriWeightsPtr_;
// Algorithm:
// For each tri face, check if it contains an IB point
// - if so, set the addressing to the index of IB point and weight to 1
// - if not, search the neighbouring faces of the visited faces until
// at least 3 IB points are found, or the neighbourhood is exhausted.
// When a sufficient number of points is found, calculate the weights
// using inverse distance weighting
// Get addressing from the triangular patch
const labelListList& pf = triPatch.pointFaces();
forAll (triPatch, triI)
{
if (hitTris[triI] > -1)
{
// Triangle contains IB point
addr[triI].setSize(1);
w[triI].setSize(1);
addr[triI] = hitTris[triI];
w[triI] = 1;
}
else
{
// No direct hit. Start a neighbourhood search
// Record already visited faces
labelHashSet visited;
// Collect new faces to visit
SLList<label> nextToVisit;
// Collect IB points for interpolation
labelHashSet ibPointsToUse;
// Initialise with the original tri
nextToVisit.insert(triI);
do
{
const label curTri = nextToVisit.removeHead();
// Discard tri if already visited
if (visited[curTri]) continue;
visited.insert(curTri);
const triFace& curTriPoints = triPatch[curTri];
// For all current points of face, pick up neighbouring faces
forAll (curTriPoints, tpI)
{
const labelList curNbrs = pf[curTriPoints[tpI]];
forAll (curNbrs, nbrI)
{
if (!visited.found(curNbrs[nbrI]))
{
// Found a face which is not visited. Add it to
// the list of faces to visit
nextToVisit.append(curNbrs[nbrI]);
if (hitTris[curNbrs[nbrI]] > -1)
{
// Found a neighbour with a hit: use this
// IB point
ibPointsToUse.insert(hitTris[curNbrs[nbrI]]);
}
}
}
}
} while
(
ibPointsToUse.size() < 3
&& !nextToVisit.empty()
);
// Found neighbourhood: collect addressing and weights
addr[triI] = ibPointsToUse.toc();
w[triI].setSize(addr[triI].size());
labelList& curAddr = addr[triI];
scalarList& curW = w[triI];
vector curTriCentre = triCentres[triI];
scalar sumW = 0;
forAll (curAddr, ibI)
{
curW[ibI] = 1/mag(curTriCentre - ibp[curAddr[ibI]]);
sumW += curW[ibI];
}
// Divide weights by sum distance
forAll (curW, ibI)
{
curW[ibI] /= sumW;
}
}
}
}
const Foam::labelListList&
Foam::immersedBoundaryFvPatch::cellsToTriAddr() const
{
if (!cellsToTriAddrPtr_)
{
makeTriAddressing();
}
return *cellsToTriAddrPtr_;
}
const Foam::scalarListList&
Foam::immersedBoundaryFvPatch::cellsToTriWeights() const
{
if (!cellsToTriWeightsPtr_)
{
makeTriAddressing();
}
return *cellsToTriWeightsPtr_;
}
// ************************************************************************* //

View file

@ -0,0 +1,402 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::immersedBoundaryFvPatchField
Description
Foam::immersedBoundaryFvPatchField
Author
Hrvoje Jasak
SourceFiles
immersedBoundaryFvPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvPatchField_H
#define immersedBoundaryFvPatchField_H
#include "fvPatchField.H"
#include "immersedBoundaryFvPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryFvPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class immersedBoundaryFvPatchField
:
public fvPatchField<Type>
{
// Private data
//- Local reference cast into the processor patch
const immersedBoundaryFvPatch& ibPatch_;
//- Local reference to fvMesh
const fvMesh& mesh_;
// Defining fields
// Note: defining fields carry values on faces of the IB patch
// represented as a triangulated surface
//- Defining value field
Field<Type> refValue_;
//- Defining normal gradient field
Field<Type> refGrad_;
//- Does the boundary condition fix the value
Switch fixesValue_;
// Dead cell controls
//- Set dead cell value
Switch setDeadCellValue_;
//- Dead cell value
Type deadCellValue_;
// Fields on the IB intersection points
// Field size equals the number of cells intesected with the IB
//- Time index for last update of mesh or moving boundary
mutable label ibUpdateTimeIndex_;
//- Value field
mutable Field<Type> ibValue_;
//- Normal gradient field
mutable Field<Type> ibGrad_;
// Private Member Functions
//- Update IB value and gradient
void updateIbValues() const;
//- Impose Dirichlet BC at IB cells and return corrected cells values
// Calculate value and gradient on IB intersection points
tmp<Field<Type> > imposeDirichletCondition() const;
//- Impose Neumann BC at IB cells and return corrected cells values
// Calculate value and gradient on IB intersection points
tmp<Field<Type> > imposeNeumannCondition() const;
//- Impose condition in dead cells
void imposeDeadCondition();
// Manipulate matrix
//- Check and correct zero diagonal in dead cells
void correctDiag
(
fvMatrix<Type>& eqn
) const;
//- Impose fixed gradient condition by manipulating matrix
// Note: reconsider pre-factor for diffusivity
// HJ, 16/Apr/2012
void correctOffDiag
(
fvMatrix<Type>& eqn
) const;
protected:
// Protected Member Functions
//- Does immersed boundary patch field need motion update?
bool motionUpdateRequired() const;
//- Execute immersed boundary patch field motion update
virtual void motionUpdate() const;
//- Set IB cell values
virtual void setIbCellValues(const Field<Type>&) const;
public:
//- Runtime type information
TypeName(immersedBoundaryFvPatch::typeName_());
// Static algorithm control data
//- Number of boundary condition update iterations
static label nBcIter_;
//- Boundary condition update tolerance
static scalar bcTolerance_;
// Constructors
//- Construct from patch and internal field
immersedBoundaryFvPatchField
(
const fvPatch&,
const DimensionedField<Type, volMesh>&
);
//- Construct from patch, internal field and dictionary
immersedBoundaryFvPatchField
(
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const dictionary&
);
//- Construct by mapping given immersedBoundaryFvPatchField
// onto a new patch
immersedBoundaryFvPatchField
(
const immersedBoundaryFvPatchField<Type>&,
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
immersedBoundaryFvPatchField
(
const immersedBoundaryFvPatchField<Type>&
);
//- Construct and return a clone
virtual tmp<fvPatchField<Type> > clone() const
{
return tmp<fvPatchField<Type> >
(
new immersedBoundaryFvPatchField<Type>(*this)
);
}
//- Construct as copy setting internal field reference
immersedBoundaryFvPatchField
(
const immersedBoundaryFvPatchField<Type>&,
const DimensionedField<Type, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchField<Type> > clone
(
const DimensionedField<Type, volMesh>& iF
) const
{
return tmp<fvPatchField<Type> >
(
new immersedBoundaryFvPatchField<Type>(*this, iF)
);
}
//- Destructor
virtual ~immersedBoundaryFvPatchField()
{}
// Member functions
//- Return reference to immersed boundary patch
const immersedBoundaryFvPatch& ibPatch() const
{
return ibPatch_;
}
// Return defining fields
// Note: defining fields carry values on faces of the IB patch
// represented as a triangulated surface
//- Return access to reference value
virtual Field<Type>& refValue()
{
return refValue_;
}
//- Return reference value
virtual const Field<Type>& refValue() const
{
return refValue_;
}
//- Return access to reference gradient
virtual Field<Type>& refGrad()
{
return refGrad_;
}
//- Return reference gradient
virtual const Field<Type>& refGrad() const
{
return refGrad_;
}
//- Return true if this patch field fixes a value
virtual bool fixesValue() const
{
return fixesValue_;
}
//- Return access to fixes value switch
Switch& fixesValue()
{
return fixesValue_;
}
//- Return fields on intersection points interacting with the IB
//- Return IB field
const Field<Type>& ibValue() const;
//- Return IB surface-normal gradient
const Field<Type>& ibGrad() const;
//- Return IB cell field
tmp<Field<Type> > ibCellValue() const;
//- Return IB sample point field
tmp<Field<Type> > ibSamplingPointValue() const;
//- Return fields on triangular faces
//- Return IB field
tmp<Field<Type> > triValue() const;
//- Return IB surface-normal gradient
tmp<Field<Type> > triGrad() const;
// Mapping functions
//- Map (and resize as needed) from self given a mapping object
virtual void autoMap
(
const fvPatchFieldMapper&
)
{}
//- Reverse map the given fvPatchField onto this fvPatchField
virtual void rmap
(
const fvPatchField<Type>&,
const labelList&
)
{}
// Evaluation functions
//- Update the coefficients associated with the patch field
void updateCoeffs();
//- Initialise the evaluation of the patch field
virtual void initEvaluate
(
const Pstream::commsTypes commsType = Pstream::blocking
);
//- Evaluate the patch field
virtual void evaluate
(
const Pstream::commsTypes commsType = Pstream::blocking
);
//- Return the matrix diagonal coefficients corresponding to the
// evaluation of the value of this patchField with given weights
virtual tmp<Field<Type> > valueInternalCoeffs
(
const tmp<scalarField>&
) const
{
return tmp<Field<Type> >(new Field<Type>(0));
}
//- Return the matrix source coefficients corresponding to the
// evaluation of the value of this patchField with given weights
virtual tmp<Field<Type> > valueBoundaryCoeffs
(
const tmp<scalarField>&
) const
{
return tmp<Field<Type> >(new Field<Type>(0));
}
//- Return the matrix diagonal coefficients corresponding to the
// evaluation of the gradient of this patchField
tmp<Field<Type> > gradientInternalCoeffs() const
{
return tmp<Field<Type> >(new Field<Type>(0));
}
//- Return the matrix source coefficients corresponding to the
// evaluation of the gradient of this patchField
tmp<Field<Type> > gradientBoundaryCoeffs() const
{
return tmp<Field<Type> >(new Field<Type>(0));
}
//- Manipulate matrix
virtual void manipulateMatrix(fvMatrix<Type>& matrix);
// I-O
//- Write
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "immersedBoundaryFvPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "volFields.H"
#include "surfaceFields.H"
#include "immersedBoundaryFvPatchFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makePatchFields(immersedBoundary);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvPatchFields_H
#define immersedBoundaryFvPatchFields_H
#include "immersedBoundaryFvPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeFieldTypedefs(immersedBoundary)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvPatchFieldsFwd_H
#define immersedBoundaryFvPatchFieldsFwd_H
#include "fvPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class immersedBoundaryFvPatchField;
makePatchTypeFieldTypedefs(immersedBoundary)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryFvsPatchField.H"
#include "fvPatchFieldMapper.H"
#include "surfaceMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
immersedBoundaryFvsPatchField<Type>::immersedBoundaryFvsPatchField
(
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF
)
:
fvsPatchField<Type>(p, iF),
ibPatch_(refCast<const immersedBoundaryFvPatch>(p))
{}
template<class Type>
immersedBoundaryFvsPatchField<Type>::immersedBoundaryFvsPatchField
(
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF,
const dictionary& dict
)
:
fvsPatchField<Type>(p, iF, dict),
ibPatch_(refCast<const immersedBoundaryFvPatch>(p))
{}
template<class Type>
immersedBoundaryFvsPatchField<Type>::immersedBoundaryFvsPatchField
(
const immersedBoundaryFvsPatchField<Type>& ptf,
const fvPatch& p,
const DimensionedField<Type, surfaceMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
fvsPatchField<Type>(ptf, p, iF, mapper),
ibPatch_(refCast<const immersedBoundaryFvPatch>(p))
{}
template<class Type>
immersedBoundaryFvsPatchField<Type>::immersedBoundaryFvsPatchField
(
const immersedBoundaryFvsPatchField<Type>& ptf
)
:
fvsPatchField<Type>(ptf),
ibPatch_(ptf.ibPatch())
{}
template<class Type>
immersedBoundaryFvsPatchField<Type>::immersedBoundaryFvsPatchField
(
const immersedBoundaryFvsPatchField<Type>& ptf,
const DimensionedField<Type, surfaceMesh>& iF
)
:
fvsPatchField<Type>(ptf, iF),
ibPatch_(ptf.ibPatch())
{}
// template<class Type>
// void immersedBoundaryFvsPatchField<Type>::operator=
// (
// const fvPatchField<Type>& ptf
// )
// {
// const immersedBoundaryFvPatchField<Type>& ibf =
// refCast<const immersedBoundaryFvPatchField<Type> > (ptf);
// this->check(ptf);
// fvsPatchField<Type>::operator=(ptf);
// }
template<class Type>
void immersedBoundaryFvsPatchField<Type>::write(Ostream& os) const
{
fvsPatchField<Type>::write(os);
this->writeEntry("value", os);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,195 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::immersedBoundaryFvsPatchField
Description
Foam::immersedBoundaryFvsPatchField
Author
Hrvoje Jasak
SourceFiles
immersedBoundaryFvsPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvsPatchField_H
#define immersedBoundaryFvsPatchField_H
#include "fvsPatchField.H"
#include "immersedBoundaryFvPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
template<class Type>
class immersedBoundaryFvPatchField;
/*---------------------------------------------------------------------------*\
Class immersedBoundaryFvsPatch Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class immersedBoundaryFvsPatchField
:
public fvsPatchField<Type>
{
// Private data
//- Local reference cast into the processor patch
const immersedBoundaryFvPatch& ibPatch_;
public:
//- Runtime type information
TypeName(immersedBoundaryFvPatch::typeName_());
// Constructors
//- Construct from patch and internal field
immersedBoundaryFvsPatchField
(
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&
);
//- Construct from patch, internal field and dictionary
immersedBoundaryFvsPatchField
(
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&,
const dictionary&
);
//- Construct by mapping given immersedBoundaryFvsPatchField
// onto a new patch
immersedBoundaryFvsPatchField
(
const immersedBoundaryFvsPatchField<Type>&,
const fvPatch&,
const DimensionedField<Type, surfaceMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
immersedBoundaryFvsPatchField
(
const immersedBoundaryFvsPatchField<Type>&
);
//- Construct and return a clone
virtual tmp<fvsPatchField<Type> > clone() const
{
return tmp<fvsPatchField<Type> >
(
new immersedBoundaryFvsPatchField<Type>(*this)
);
}
//- Construct as copy setting internal field reference
immersedBoundaryFvsPatchField
(
const immersedBoundaryFvsPatchField<Type>&,
const DimensionedField<Type, surfaceMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvsPatchField<Type> > clone
(
const DimensionedField<Type, surfaceMesh>& iF
) const
{
return tmp<fvsPatchField<Type> >
(
new immersedBoundaryFvsPatchField<Type>(*this, iF)
);
}
//- Destructor
virtual ~immersedBoundaryFvsPatchField()
{}
// Member functions
// Mapping functions
//- Map (and resize as needed) from self given a mapping object
virtual void autoMap
(
const fvPatchFieldMapper&
)
{}
//- Reverse map the given fvsPatchField onto this fvsPatchField
virtual void rmap
(
const fvPatchField<Type>&,
const labelList&
)
{}
// Member functions
//- Return reference to immersed boundary patch
const immersedBoundaryFvPatch& ibPatch() const
{
return ibPatch_;
}
//- Write
virtual void write(Ostream&) const;
// Member operators
// virtual void operator=(const fvPatchField<Type>&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "immersedBoundaryFvsPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryFvsPatchFields.H"
#include "fvsPatchFields.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "immersedBoundaryFvPatchFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makeFvsPatchFields(immersedBoundary);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvsPatchFields_H
#define immersedBoundaryFvsPatchFields_H
#include "immersedBoundaryFvsPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makeFvsPatchTypeFieldTypedefs(immersedBoundary)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryFvsPatchFieldsFwd_H
#define immersedBoundaryFvsPatchFieldsFwd_H
#include "fvsPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class immersedBoundaryFvsPatchField;
makeFvsPatchTypeFieldTypedefs(immersedBoundary)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryPointPatch.H"
#include "pointConstraint.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(immersedBoundaryPointPatch, 0);
addToRunTimeSelectionTable
(
facePointPatch,
immersedBoundaryPointPatch,
polyPatch
);
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::immersedBoundaryPointPatch
Description
Immersed boundary point patch.
Author
Hrvoje Jasak
SourceFiles
immersedBoundaryPointPatch.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryPointPatch_H
#define immersedBoundaryPointPatch_H
#include "facePointPatch.H"
#include "immersedBoundaryPolyPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryPointPatch Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryPointPatch
:
public facePointPatch
{
public:
//- Runtime type information
TypeName(immersedBoundaryPolyPatch::typeName_());
// Constructors
//- Construct from polyPatch
immersedBoundaryPointPatch
(
const polyPatch& patch,
const pointBoundaryMesh& bm
)
:
facePointPatch(patch, bm)
{}
// Destructor
virtual ~immersedBoundaryPointPatch()
{}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,296 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryPolyPatch.H"
#include "polyBoundaryMesh.H"
#include "polyMesh.H"
#include "Time.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(immersedBoundaryPolyPatch, 0);
addToRunTimeSelectionTable(polyPatch, immersedBoundaryPolyPatch, word);
addToRunTimeSelectionTable
(
polyPatch,
immersedBoundaryPolyPatch,
dictionary
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::immersedBoundaryPolyPatch::makeTriSurfSearch() const
{
if (debug)
{
Info<< "void immersedBoundaryPolyPatch::makeTriSurfSearch() const : "
<< "creating triSurface search algorithm"
<< endl;
}
// It is an error to attempt to recalculate
// if the pointer is already
if (triSurfSearchPtr_)
{
FatalErrorIn("immersedBoundaryPolyPatch::makeTriSurfSearch() const")
<< "triSurface search algorithm already exist"
<< abort(FatalError);
}
triSurfSearchPtr_ = new triSurfaceSearch(ibMesh_);
}
void Foam::immersedBoundaryPolyPatch::clearOut()
{
deleteDemandDrivenData(triSurfSearchPtr_);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::immersedBoundaryPolyPatch::movePoints(const pointField& p)
{
// Handle motion of immersed boundary
clearOut();
primitivePatch::movePoints(p);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::immersedBoundaryPolyPatch::immersedBoundaryPolyPatch
(
const word& name,
const label size,
const label start,
const label index,
const polyBoundaryMesh& bm
)
:
polyPatch(name, size, start, index, bm),
ibMesh_
(
IOobject
(
name + ".ftr",
bm.mesh().time().constant(), // instance
"triSurface", // local
bm.mesh(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE
)
),
internalFlow_(false),
triSurfSearchPtr_(NULL),
movingIb_(false)
{}
Foam::immersedBoundaryPolyPatch::immersedBoundaryPolyPatch
(
const word& name,
const dictionary& dict,
const label index,
const polyBoundaryMesh& bm
)
:
polyPatch(name, dict, index, bm),
ibMesh_
(
IOobject
(
name + ".ftr",
bm.mesh().time().constant(), // instance
"triSurface", // local
bm.mesh(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE
)
),
internalFlow_(dict.lookup("internalFlow")),
triSurfSearchPtr_(NULL),
movingIb_(false)
{
if (size() > 0)
{
FatalIOErrorIn
(
"immersedBoundaryPolyPatch::immersedBoundaryPolyPatch\n"
"(\n"
" const word& name,\n"
" const dictionary& dict,\n"
" const label index,\n"
" const polyBoundaryMesh& bm\n"
")",
dict
) << "Faces detected in the immersedBoundaryPolyPatch. "
<< "This is not allowed: please make sure that the patch size "
<< "equals zero."
<< abort(FatalIOError);
}
}
Foam::immersedBoundaryPolyPatch::immersedBoundaryPolyPatch
(
const immersedBoundaryPolyPatch& pp,
const polyBoundaryMesh& bm
)
:
polyPatch(pp, bm),
ibMesh_
(
IOobject
(
pp.name() + ".ftr",
bm.mesh().time().constant(), // instance
"triSurface", // local
bm.mesh(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE
)
),
internalFlow_(pp.internalFlow_),
triSurfSearchPtr_(NULL),
movingIb_(false)
{}
Foam::immersedBoundaryPolyPatch::immersedBoundaryPolyPatch
(
const immersedBoundaryPolyPatch& pp,
const polyBoundaryMesh& bm,
const label index,
const label newSize,
const label newStart
)
:
polyPatch(pp, bm, index, newSize, newStart),
ibMesh_
(
IOobject
(
pp.name() + ".ftr",
bm.mesh().time().constant(), // instance
"triSurface", // local
bm.mesh(), // registry
IOobject::MUST_READ,
IOobject::NO_WRITE
)
),
internalFlow_(pp.internalFlow_),
triSurfSearchPtr_(NULL),
movingIb_(false)
{}
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
Foam::immersedBoundaryPolyPatch::~immersedBoundaryPolyPatch()
{
clearOut();
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
const Foam::triSurfaceSearch&
Foam::immersedBoundaryPolyPatch::triSurfSearch() const
{
if (!triSurfSearchPtr_)
{
makeTriSurfSearch();
}
return *triSurfSearchPtr_;
}
void Foam::immersedBoundaryPolyPatch::moveTriSurfacePoints
(
const pointField& p
)
{
// Record the motion of the patch
movingIb_ = true;
// Move points of the triSurface
const pointField& oldPoints = ibMesh_.points();
if (oldPoints.size() != p.size())
{
FatalErrorIn
(
"void immersedBoundaryPolyPatch::moveTriSurfacePoints\n"
"(\n"
" const pointField& p\n"
")"
) << "Incorrect size of motion points for patch " << name()
<< ". oldPoints = "
<< oldPoints.size() << " p = " << p.size()
<< abort(FatalError);
}
Info<< "Moving immersed boundary points for patch " << name()
<< endl;
ibMesh_.movePoints(p);
fileName path(boundaryMesh().mesh().time().path()/"VTK");
mkDir(path);
ibMesh_.triSurface::write
(
path/
word
(
name() + "_"
+ Foam::name(boundaryMesh().mesh().time().timeIndex())
+ ".stl"
)
);
clearOut();
}
void Foam::immersedBoundaryPolyPatch::write(Ostream& os) const
{
polyPatch::write(os);
os.writeKeyword("internalFlow") << internalFlow_
<< token::END_STATEMENT << nl;
}
// ************************************************************************* //

View file

@ -0,0 +1,235 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::immersedBoundaryPolyPatch
Description
Immersed boundary patch
Author
Zeljko Tukovic
Reorganisation by Hrvoje Jasak
SourceFiles
immersedBoundaryPolyPatch.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryPolyPatch_H
#define immersedBoundaryPolyPatch_H
#include "polyPatch.H"
#include "triSurfaceMesh.H"
#include "triSurfaceTools.H"
#include "triSurfaceSearch.H"
#include "Switch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryPolyPatch Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryPolyPatch
:
public polyPatch
{
// Private data
//- Triangular surface representing immersed boundary.
// Name of tri surface will be identical to the name of the patch
triSurfaceMesh ibMesh_;
//- Internal or external flow calculation
Switch internalFlow_;
// Demand-driven data
//- Triangular surface search algorithm
mutable triSurfaceSearch* triSurfSearchPtr_;
//- Moving immersed boundary
bool movingIb_;
// Private Member Functions
// Storage management
//- Clear all demand-driven data
void clearOut();
// Make demand-driven data
//- Make triSurface search algorithm
void makeTriSurfSearch() const;
protected:
// Protected Member Functions
//- Initialise the patches for moving points
virtual void initMovePoints(const pointField&)
{}
//- Correct patches after moving points
virtual void movePoints(const pointField& p);
public:
//- Runtime type information
TypeName("immersedBoundary");
// Constructors
//- Construct from components
immersedBoundaryPolyPatch
(
const word& name,
const label size,
const label start,
const label index,
const polyBoundaryMesh& bm
);
//- Construct from dictionary
immersedBoundaryPolyPatch
(
const word& name,
const dictionary& dict,
const label index,
const polyBoundaryMesh& bm
);
//- Construct as copy, resetting the boundary mesh
immersedBoundaryPolyPatch
(
const immersedBoundaryPolyPatch&,
const polyBoundaryMesh&
);
//- Construct given the original patch and resetting the
// face list and boundary mesh information
immersedBoundaryPolyPatch
(
const immersedBoundaryPolyPatch& pp,
const polyBoundaryMesh& bm,
const label index,
const label newSize,
const label newStart
);
//- Construct and return a clone, resetting the boundary mesh
virtual autoPtr<polyPatch> clone(const polyBoundaryMesh& bm) const
{
return autoPtr<polyPatch>
(
new immersedBoundaryPolyPatch(*this, bm)
);
}
//- Construct and return a clone, resetting the face list
// and boundary mesh
virtual autoPtr<polyPatch> clone
(
const polyBoundaryMesh& bm,
const label index,
const label newSize,
const label newStart
) const
{
return autoPtr<polyPatch>
(
new immersedBoundaryPolyPatch
(
*this,
bm,
index,
newSize,
newStart
)
);
}
//- Destructor
virtual ~immersedBoundaryPolyPatch();
// Member Functions
// Access
//- Return immersed boundary surface mesh
const triSurfaceMesh& ibMesh() const
{
return ibMesh_;
}
//- Return true if solving for flow inside the immersed boundary
bool internalFlow() const
{
return internalFlow_;
}
//- Return triSurface search object
const triSurfaceSearch& triSurfSearch() const;
//- Return true if immersed boundary is moving
bool movingIb() const
{
return movingIb_;
}
// Edit
//- Correct patches after moving points
void moveTriSurfacePoints(const pointField& p);
//- Write
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,72 @@
//
// createIbMask.H
// ~~~~~~~~~~~~
Info<< "Create immersed boundary cell mask" << endl;
volScalarField cellIbMask
(
IOobject
(
"cellIbMask",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("one", dimless, 1)
);
volScalarField cellIbMaskExt
(
IOobject
(
"cellIbMaskExt",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("one", dimless, 1)
);
Info<< "Create immersed boundary face mask" << endl;
surfaceScalarField faceIbMask
(
IOobject
(
"faceIbMask",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("one", dimless, 1)
);
forAll (mesh.boundary(), patchI)
{
if (isA<immersedBoundaryFvPatch>(mesh.boundary()[patchI]))
{
Info<< "Found immersed boundary patch " << patchI
<< " named " << mesh.boundary()[patchI].name()
<< endl;
const immersedBoundaryFvPatch& ibPatch =
refCast<const immersedBoundaryFvPatch>
(
mesh.boundary()[patchI]
);
cellIbMask *= ibPatch.gamma();
cellIbMaskExt *= ibPatch.gammaExt();
faceIbMask *= ibPatch.sGamma();
}
}
// Evaluate boundary conditions for IB masks
cellIbMask.boundaryField().evaluateCoupled();
cellIbMaskExt.boundaryField().evaluateCoupled();

View file

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Global
immersedBoundaryContinuityErrs
Description
Calculates and prints the continuity errors with
immersed boundary correction.
\*---------------------------------------------------------------------------*/
{
volScalarField contErr = fvc::div(faceIbMask*phi);
// volScalarField contErr = cellIbMask*fvc::div(phi);
sumLocalContErr = runTime.deltaT().value()*
mag(contErr)().weightedAverage(mesh.V()).value();
globalContErr = runTime.deltaT().value()*
contErr.weightedAverage(mesh.V()).value();
cumulativeContErr += globalContErr;
Info<< "IB time step continuity errors : sum local = " << sumLocalContErr
<< ", global = " << globalContErr
<< ", cumulative = " << cumulativeContErr
<< endl;
}
// ************************************************************************* //

View file

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Global
CourantNo
Description
Calculates and outputs the mean and maximum Courant Numbers with
immersed boundary correction.
\*---------------------------------------------------------------------------*/
scalar CoNum = 0.0;
scalar meanCoNum = 0.0;
scalar velMag = 0.0;
if (mesh.nInternalFaces())
{
surfaceScalarField magPhi = mag(faceIbMask*phi);
surfaceScalarField SfUfbyDelta =
mesh.surfaceInterpolation::deltaCoeffs()*magPhi;
CoNum = max(SfUfbyDelta/mesh.magSf())
.value()*runTime.deltaT().value();
meanCoNum = (sum(SfUfbyDelta)/sum(mesh.magSf()))
.value()*runTime.deltaT().value();
velMag = max(magPhi/mesh.magSf()).value();
}
Info<< "Courant Number mean: " << meanCoNum
<< " max: " << CoNum
<< " velocity magnitude: " << velMag
<< endl;
// ************************************************************************* //

View file

@ -0,0 +1,475 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "refineImmersedBoundaryMesh.H"
#include "immersedBoundaryFvPatch.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "plane.H"
#include "wedgePolyPatch.H"
#include "multiDirRefinement.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
template<>
const char*
Foam::NamedEnum<Foam::refineImmersedBoundaryMesh::ibCellCollection, 4>
::names[] =
{
"undefined",
"ibCells",
"ibCellCells",
"ibCellCellFaces"
};
const Foam::NamedEnum<Foam::refineImmersedBoundaryMesh::ibCellCollection, 4>
Foam::refineImmersedBoundaryMesh::ibCellCollectionNames_;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::refineImmersedBoundaryMesh::addIbCells
(
labelHashSet& refCellSet
) const
{
Info<< "Adding ibCells for refinement" << endl;
// Insert immersed boundary cells from all immersed boundary patches
forAll (mesh_.boundary(), patchI)
{
if (isA<immersedBoundaryFvPatch>(mesh_.boundary()[patchI]))
{
Info<< "Found immersed boundary patch " << patchI
<< " named " << mesh_.boundary()[patchI].name()
<< endl;
const immersedBoundaryFvPatch& ibPatch =
refCast<const immersedBoundaryFvPatch>
(
mesh_.boundary()[patchI]
);
const labelList& c = ibPatch.ibCells();
forAll (c, cI)
{
if (!refCellSet.found(c[cI]))
{
refCellSet.insert(c[cI]);
}
}
}
}
}
void Foam::refineImmersedBoundaryMesh::addIbCellCells
(
labelHashSet& refCellSet
) const
{
Info<< "Adding ibCellCells for refinement" << endl;
// Insert immersed boundary cells from all immersed boundary patches
forAll (mesh_.boundary(), patchI)
{
if (isA<immersedBoundaryFvPatch>(mesh_.boundary()[patchI]))
{
const immersedBoundaryFvPatch& ibPatch =
refCast<const immersedBoundaryFvPatch>
(
mesh_.boundary()[patchI]
);
const labelListList& cc = ibPatch.ibCellCells();
forAll (cc, cellI)
{
const labelList& curCells = cc[cellI];
forAll (curCells, cI)
{
if (!refCellSet.found(curCells[cI]))
{
refCellSet.insert(curCells[cI]);
}
}
}
}
}
}
void Foam::refineImmersedBoundaryMesh::addIbCellCellFaces
(
labelHashSet& refCellSet
) const
{
Info<< "Adding ibCellCellFaces for refinement" << endl;
const unallocLabelList& owner = mesh_.owner();
const unallocLabelList& neighbour = mesh_.neighbour();
// Insert immersed boundary cells from all immersed boundary patches
forAll (mesh_.boundary(), patchI)
{
if (isA<immersedBoundaryFvPatch>(mesh_.boundary()[patchI]))
{
const immersedBoundaryFvPatch& ibPatch =
refCast<const immersedBoundaryFvPatch>
(
mesh_.boundary()[patchI]
);
const scalarField& gammaExtI = ibPatch.gammaExt().internalField();
const labelList& ibInsideFaces = ibPatch.ibInsideFaces();
forAll (ibInsideFaces, faceI)
{
const label ownCell = owner[ibInsideFaces[faceI]];
const label ngbCell = neighbour[ibInsideFaces[faceI]];
if (gammaExtI[ownCell] < SMALL)
{
if (!refCellSet.found(ownCell))
{
refCellSet.insert(ownCell);
}
}
else
{
if (!refCellSet.found(ngbCell))
{
refCellSet.insert(ngbCell);
}
}
}
}
}
}
// Return index of coordinate axis.
Foam::label Foam::refineImmersedBoundaryMesh::axis(const vector& normal) const
{
const scalar edgeTol = 1e-3;
label axisIndex = -1;
if (mag(normal & vector(1, 0, 0)) > (1 - edgeTol))
{
axisIndex = 0;
}
else if (mag(normal & vector(0, 1, 0)) > (1 - edgeTol))
{
axisIndex = 1;
}
else if (mag(normal & vector(0, 0, 1)) > (1 - edgeTol))
{
axisIndex = 2;
}
return axisIndex;
}
//- Returns -1 or cartesian coordinate component (0=x, 1=y, 2=z) of normal
// in case of 2D mesh
Foam::label Foam::refineImmersedBoundaryMesh::twoDNess() const
{
const pointField& ctrs = mesh_.cellCentres();
if (ctrs.size() < 2)
{
return -1;
}
//
// 1. All cell centres on single plane aligned with x, y or z
//
// Determine 3 points to base plane on.
vector vec10 = ctrs[1] - ctrs[0];
vec10 /= mag(vec10);
label otherCellI = -1;
for (label cellI = 2; cellI < ctrs.size(); cellI++)
{
vector vec(ctrs[cellI] - ctrs[0]);
vec /= mag(vec);
if (mag(vec & vec10) < 0.9)
{
// ctrs[cellI] not in line with n
otherCellI = cellI;
break;
}
}
if (otherCellI == -1)
{
// Cannot find cell to make decent angle with cell0-cell1 vector.
// Note: what to do here? All cells (almost) in one line.
// Maybe 1D case?
return -1;
}
plane cellPlane(ctrs[0], ctrs[1], ctrs[otherCellI]);
forAll (ctrs, cellI)
{
const labelList& cEdges = mesh_.cellEdges()[cellI];
scalar minLen = GREAT;
forAll (cEdges, i)
{
minLen = min(minLen, mesh_.edges()[cEdges[i]].mag(mesh_.points()));
}
if (cellPlane.distance(ctrs[cellI]) > 1e-6*minLen)
{
// Centres not in plane
return -1;
}
}
label axisIndex = axis(cellPlane.normal());
if (axisIndex == -1)
{
return axisIndex;
}
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
//
// 2. No edges without points on boundary
//
// Mark boundary points
boolList boundaryPoint(mesh_.allPoints().size(), false);
forAll (patches, patchI)
{
const polyPatch& patch = patches[patchI];
forAll (patch, patchFaceI)
{
const face& f = patch[patchFaceI];
forAll (f, fp)
{
boundaryPoint[f[fp]] = true;
}
}
}
const edgeList& edges = mesh_.edges();
forAll (edges, edgeI)
{
const edge& e = edges[edgeI];
if (!boundaryPoint[e.start()] && !boundaryPoint[e.end()])
{
// Edge has no point on boundary.
return -1;
}
}
// 3. For all non-wedge patches: all faces either perp or aligned with
// cell-plane normal. (wedge patches already checked upon construction)
forAll (patches, patchI)
{
const polyPatch& patch = patches[patchI];
if (!isA<wedgePolyPatch>(patch))
{
const vectorField& n = patch.faceAreas();
scalarField cosAngle = mag(n/mag(n) & cellPlane.normal());
if (mag(min(cosAngle) - max(cosAngle)) > 1e-6)
{
// cosAngle should be either ~1 over all faces (2D front and
// back) or ~0 (all other patches perp to 2D)
return -1;
}
}
}
return axisIndex;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::refineImmersedBoundaryMesh::refineImmersedBoundaryMesh
(
fvMesh& mesh
)
:
mesh_(mesh)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::refineImmersedBoundaryMesh::~refineImmersedBoundaryMesh()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::labelList
Foam::refineImmersedBoundaryMesh::refinementCells
(
const ibCellCollection& collectionType
) const
{
labelHashSet refCellSet;
switch (collectionType)
{
// Note: fall-through is intentional. HJ, 25/Oct/2012
case IB_CELL_CELL_FACES:
{
addIbCellCellFaces(refCellSet);
}
case IB_CELL_CELLS:
{
addIbCellCells(refCellSet);
}
case IB_CELLS:
{
addIbCells(refCellSet);
}
break;
default:
{
FatalErrorIn
(
"labelList refineImmersedBoundaryMesh::refinementCells\n"
"(\n"
" const ibCellCollection& collectionType\n"
") const"
) << "Collection type undefined: "
<< ibCellCollectionNames_[collectionType]
<< abort(FatalError);
}
}
return refCellSet.toc();
}
void Foam::refineImmersedBoundaryMesh::refineMesh
(
const labelList& refCells
) const
{
Info << "nRefCells = " << refCells.size() << "\n" << endl;
// Dictionary to control refinement
dictionary refineDict;
// Set refinement directions based on 2D/3D
label axisIndex = twoDNess();
if (axisIndex == -1)
{
Info<< "3D case; refining all directions" << nl << endl;
wordList directions(3);
directions[0] = "tan1";
directions[1] = "tan2";
directions[2] = "normal";
refineDict.add("directions", directions);
// Use hex cutter
refineDict.add("useHexTopology", "true");
}
else
{
wordList directions(2);
if (axisIndex == 0)
{
Info<< "2D case; refining in directions y,z\n" << endl;
directions[0] = "tan2";
directions[1] = "normal";
}
else if (axisIndex == 1)
{
Info<< "2D case; refining in directions x,z\n" << endl;
directions[0] = "tan1";
directions[1] = "normal";
}
else
{
Info<< "2D case; refining in directions x,y\n" << endl;
directions[0] = "tan1";
directions[1] = "tan2";
}
refineDict.add("directions", directions);
// Use standard cutter
refineDict.add("useHexTopology", "false");
}
refineDict.add("coordinateSystem", "global");
dictionary coeffsDict;
coeffsDict.add("tan1", vector(1, 0, 0));
coeffsDict.add("tan2", vector(0, 1, 0));
refineDict.add("globalCoeffs", coeffsDict);
refineDict.add("geometricCut", "false");
refineDict.add("writeMesh", "false");
// Multi-directional refinement (does multiple iterations)
multiDirRefinement multiRef(mesh_, refCells, refineDict);
}
// ************************************************************************* //

View file

@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::refineImmersedBoundaryMesh
Description
Refine a mesh with immersed boundary
SourceFiles
refineImmersedBoundaryMesh.C
\*---------------------------------------------------------------------------*/
#ifndef refineImmersedBoundaryMesh_H
#define refineImmersedBoundaryMesh_H
#include "fvMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class refineImmersedBoundaryMesh Declaration
\*---------------------------------------------------------------------------*/
class refineImmersedBoundaryMesh
{
public:
// Public enumerations
//- Cell collection method
enum ibCellCollection
{
UNDEFINED_COLLECTION = 0,
IB_CELLS,
IB_CELL_CELLS,
IB_CELL_CELL_FACES
};
//- Projection method names
static const NamedEnum<ibCellCollection, 4> ibCellCollectionNames_;
private:
// Private data
//- Reference to mesh
fvMesh& mesh_;
// Private Member Functions
//- Disallow default bitwise copy construct
refineImmersedBoundaryMesh(const refineImmersedBoundaryMesh&);
//- Disallow default bitwise assignment
void operator=(const refineImmersedBoundaryMesh&);
// Mesh refinement
//- Add ibCells for refinement
void addIbCells(labelHashSet& refCellSet) const;
//- Add ibCellCells for refinement
void addIbCellCells(labelHashSet& refCellSet) const;
//- Add ibCellCellFaces for refinement
void addIbCellCellFaces(labelHashSet& refCellSet) const;
//- From refineMesh application
label axis(const vector& normal) const;
//- From refineMesh application
label twoDNess() const;
public:
// Constructors
//- Construct from mesh
refineImmersedBoundaryMesh(fvMesh& mesh);
//- Destructor
~refineImmersedBoundaryMesh();
// Member Functions
//- Return list of cells for refinement based on specifie collection
// type (see enumeration)
labelList refinementCells
(
const ibCellCollection& collectionType
) const;
// Refine mesh given a list of cells for refinement
void refineMesh(const labelList& refCells) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Typedef
Foam::IOimmersedBoundaryForces
Description
Instance of the generic IOOutputFilter for immersedBoundaryForces.
\*---------------------------------------------------------------------------*/
#ifndef IOimmersedBoundaryForces_H
#define IOimmersedBoundaryForces_H
#include "immersedBoundaryForces.H"
#include "IOOutputFilter.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef IOOutputFilter<immersedBoundaryForces> IOimmersedBoundaryForces;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,4 @@
immersedBoundaryForces.C
immersedBoundaryForcesFunctionObject.C
LIB = $(FOAM_LIBBIN)/libimmersedBoundaryForceFunctionObject

View file

@ -0,0 +1,28 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/postProcessing/functionObjects/forces/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \
-I../immersedBoundary/lnInclude \
-I../immersedBoundaryTurbulence/lnInclude
LIB_LIBS = \
-lforces \
-lincompressibleTransportModels \
-lincompressibleRASModels \
-lincompressibleLESModels \
-lbasicThermophysicalModels \
-lspecie \
-lcompressibleRASModels \
-lcompressibleLESModels \
-lfiniteVolume \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh \
-L$(FOAM_USER_LIBBIN) \
-limmersedBoundary \
-limmersedBoundaryTurbulence

View file

@ -0,0 +1,249 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryForces.H"
#include "immersedBoundaryFvPatch.H"
#include "immersedBoundaryFvPatchFields.H"
#include "immersedBoundaryVelocityWallFunctionFvPatchVectorField.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "dictionary.H"
#include "Time.H"
using namespace Foam::incompressible::RASModels;
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(immersedBoundaryForces, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::immersedBoundaryForces::immersedBoundaryForces
(
const word& name,
const objectRegistry& obr,
const dictionary& dict,
const bool loadFromFiles
)
:
forces
(
name,
obr,
dict,
loadFromFiles
)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::immersedBoundaryForces::~immersedBoundaryForces()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::immersedBoundaryForces::forcesMoments
Foam::immersedBoundaryForces::calcForcesMoment() const
{
forcesMoments fm
(
pressureViscous(vector::zero, vector::zero),
pressureViscous(vector::zero, vector::zero)
);
if (directForceDensity_)
{
const volVectorField& fD = obr_.lookupObject<volVectorField>(fDName_);
const fvMesh& mesh = fD.mesh();
forAllConstIter(labelHashSet, patchSet_, iter)
{
label patchI = iter.key();
// Check and cast into immersed boundary type
if
(
isA<immersedBoundaryFvPatchVectorField>
(
fD.boundaryField()[patchI]
)
)
{
// Found immersed boundary patch and field.
// Cast into immersed boundary type
const immersedBoundaryFvPatch& ibPatch =
refCast<const immersedBoundaryFvPatch>
(
mesh.boundary()[patchI]
);
const immersedBoundaryFvPatchVectorField& fDpatch =
refCast<const immersedBoundaryFvPatchVectorField>
(
fD.boundaryField()[patchI]
);
// Get face area vectors for triangles
const vectorField& Sfb = ibPatch.triSf();
scalarField sA = mag(Sfb);
// Calculate distance for triangles
vectorField Md = ibPatch.triCf() - CofR_;
// Old treatment:
// Normal force =
// surfaceNormal*(surfaceUnitNormal & forceDensity)
// The first operation will be done on ibPoints, the data will
// then be distributed onto the ib surface
// for surface integration
// vectorField fN =
// Sfb*
// ibPatch.toTriFaces
// (
// ibPatch.ibNormals() & fDpatch.ibValue()
// );
// New treatment: normal force calculated on triangles
// Damir Rigler, 30/Apr/2014
vectorField fN = Sfb/sA*(Sfb & fDpatch.triValue());
fm.first().first() += sum(fN);
fm.second().first() += sum(Md ^ fN);
// Tangential force (total force minus normal fN)
vectorField fT = sA*fDpatch.triValue() - fN;
fm.first().second() += sum(fT);
fm.second().second() += sum(Md ^ fT);
}
}
}
else
{
const volVectorField& U = obr_.lookupObject<volVectorField>(UName_);
const volScalarField& p = obr_.lookupObject<volScalarField>(pName_);
const fvMesh& mesh = U.mesh();
// Stress from turbulence model. Note: this does not account
// for wall functions on the Immersed Boundary: use wallShearStress
// from Immersed Boundary U wall patch instead.
// HJ, 11/Aug/2014
// volSymmTensorField stress = devRhoReff();
// Scale pRef by density for incompressible simulations
scalar pRef = pRef_/rho(p);
forAllConstIter(labelHashSet, patchSet_, iter)
{
label patchI = iter.key();
// Check and cast into immersed boundary type
if
(
isA<immersedBoundaryFvPatchVectorField>
(
U.boundaryField()[patchI]
)
)
{
// Found immersed boundary patch and field.
// Cast into immersed boundary type
const immersedBoundaryFvPatch& ibPatch =
refCast<const immersedBoundaryFvPatch>
(
mesh.boundary()[patchI]
);
// Get immersed boundary velocity. Used to access wall
// shear stress
const immersedBoundaryVelocityWallFunctionFvPatchVectorField&
UPatch =
refCast
<
const
immersedBoundaryVelocityWallFunctionFvPatchVectorField
>
(
U.boundaryField()[patchI]
);
// const immersedBoundaryFvPatchSymmTensorField stressPatch =
// refCast<const immersedBoundaryFvPatchSymmTensorField>
// (
// stress.boundaryField()[patchI]
// );
const immersedBoundaryFvPatchScalarField pPatch =
refCast<const immersedBoundaryFvPatchScalarField>
(
p.boundaryField()[patchI]
);
// Get face area vectors for triangles
const vectorField& Sfb = ibPatch.triSf();
scalarField sA = mag(Sfb);
// Calculate distance for triangles
vectorField Md = ibPatch.triCf() - CofR_;
// Pressure force is an integral of interpolated pressure
// on triangular faces
vectorField pf = Sfb*(pPatch.triValue() - pRef);
fm.first().first() += rho(p)*sum(pf);
fm.second().first() += rho(p)*sum(Md ^ pf);
// Old treatment:
// Shear force is obtained from velocity wall functions
// and integrated on triangular faces
vectorField vf =
sA*ibPatch.toTriFaces(UPatch.wallShearStress());
// New treatment: normal force calculated on triangles
// Damir Rigler, 30/Apr/2014
// vectorField vfOld = (Sfb & stressPatch.triValue());
// Info<< "Force difference " << sumMag(vf - vfOld) << endl;
fm.first().second() += sum(vf);
fm.second().second() += sum(Md ^ vf);
}
}
}
reduce(fm, sumOp());
return fm;
}
// ************************************************************************* //

View file

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::immersedBoundaryForces
Description
Calculates the forces and moments by integrating the pressure and
skin-friction forces over a given list of immersed boundary patches.
Member function calcForcesMoment() calculates and returns the forces and
moments on immersed boundary patches.
Author
Hrvoje Jasak. All rights reserved.
SourceFiles
immersedBoundaryForces.C
IOimmersedBoundaryForces.H
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryForces_H
#define immersedBoundaryForces_H
#include "forces.H"
#include "fvPatchFields.H"
#include "volFieldsFwd.H"
#include "HashSet.H"
#include "Tuple2.H"
#include "OFstream.H"
#include "Switch.H"
#include "pointFieldFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryForces Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryForces
:
public forces
{
public:
//- Runtime type information
TypeName("immersedBoundaryForces");
// Constructors
//- Construct for given objectRegistry and dictionary.
// Allow the possibility to load fields from files
immersedBoundaryForces
(
const word& name,
const objectRegistry&,
const dictionary&,
const bool loadFromFiles = false
);
//- Destructor
virtual ~immersedBoundaryForces();
// Member Functions
//- Calculate and return forces and moment
virtual forcesMoments calcForcesMoment() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryForcesFunctionObject.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineNamedTemplateTypeNameAndDebug
(
immersedBoundaryForcesFunctionObject,
0
);
addToRunTimeSelectionTable
(
functionObject,
immersedBoundaryForcesFunctionObject,
dictionary
);
}
// ************************************************************************* //

View file

@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Typedef
Foam::immersedBoundaryForcesFunctionObject
Description
FunctionObject wrapper around immersedBoundaryForces to allow them to be
created via the functions entry within controlDict.
SourceFiles
immersedBoundaryForcesFunctionObject.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryForcesFunctionObject_H
#define immersedBoundaryForcesFunctionObject_H
#include "immersedBoundaryForces.H"
#include "OutputFilterFunctionObject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef OutputFilterFunctionObject<immersedBoundaryForces>
immersedBoundaryForcesFunctionObject;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,6 @@
wallFunctions/immersedBoundaryWallFunctions/immersedBoundaryWallFunctionFvPatchFields.C
wallFunctions/immersedBoundaryEpsilonWallFunctions/immersedBoundaryEpsilonWallFunctionFvPatchScalarField.C
wallFunctions/immersedBoundaryOmegaWallFunctions/immersedBoundaryOmegaWallFunctionFvPatchScalarField.C
wallFunctions/immersedBoundaryVelocityWallFunctions/immersedBoundaryVelocityWallFunctionFvPatchVectorField.C
LIB = $(FOAM_LIBBIN)/libimmersedBoundaryTurbulence

View file

@ -0,0 +1,26 @@
EXE_INC = \
-IlnInclude \
-I../immersedBoundary/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/turbulenceModels \
-I$(LIB_SRC)/turbulenceModels/incompressible/RAS/RASModel \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/dynamicMesh/dynamicMesh/lnInclude
EXE_LIBS = \
-limmersedBoundary \
-lfiniteVolume \
-lincompressibleTurbulenceModel \
-lincompressibleRASModels \
-lincompressibleLESModels \
-lincompressibleTransportModels \
-ltriSurface \
-lmeshTools \
-lsurfMesh \
-lsampling \
-ldynamicMesh

View file

@ -0,0 +1,394 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryEpsilonWallFunctionFvPatchScalarField.H"
#include "immersedBoundaryVelocityWallFunctionFvPatchVectorField.H"
#include "RASModel.H"
#include "fvPatchFieldMapper.H"
#include "volFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
immersedBoundaryEpsilonWallFunctionFvPatchScalarField::
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF
)
:
immersedBoundaryWallFunctionFvPatchScalarField(p, iF),
UName_("U"),
kName_("k"),
GName_("RASModel::G"),
nuName_("nu"),
nutName_("nut"),
Cmu_(0.09),
kappa_(0.41),
E_(9.8)
{}
immersedBoundaryEpsilonWallFunctionFvPatchScalarField::
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const dictionary& dict
)
:
immersedBoundaryWallFunctionFvPatchScalarField(p, iF, dict),
UName_(dict.lookupOrDefault<word>("U", "U")),
kName_(dict.lookupOrDefault<word>("k", "k")),
GName_(dict.lookupOrDefault<word>("G", "RASModel::G")),
nuName_(dict.lookupOrDefault<word>("nu", "nu")),
nutName_(dict.lookupOrDefault<word>("nut", "nut")),
Cmu_(dict.lookupOrDefault<scalar>("Cmu", 0.09)),
kappa_(dict.lookupOrDefault<scalar>("kappa", 0.41)),
E_(dict.lookupOrDefault<scalar>("E", 9.8))
{}
immersedBoundaryEpsilonWallFunctionFvPatchScalarField::
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const immersedBoundaryEpsilonWallFunctionFvPatchScalarField& ptf,
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
immersedBoundaryWallFunctionFvPatchScalarField(ptf, p, iF, mapper),
UName_(ptf.UName_),
kName_(ptf.kName_),
GName_(ptf.GName_),
nuName_(ptf.nuName_),
nutName_(ptf.nutName_),
Cmu_(ptf.Cmu_),
kappa_(ptf.kappa_),
E_(ptf.E_)
{}
immersedBoundaryEpsilonWallFunctionFvPatchScalarField::
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const immersedBoundaryEpsilonWallFunctionFvPatchScalarField& ewfpsf
)
:
immersedBoundaryWallFunctionFvPatchScalarField(ewfpsf),
UName_(ewfpsf.UName_),
kName_(ewfpsf.kName_),
GName_(ewfpsf.GName_),
nuName_(ewfpsf.nuName_),
nutName_(ewfpsf.nutName_),
Cmu_(ewfpsf.Cmu_),
kappa_(ewfpsf.kappa_),
E_(ewfpsf.E_)
{}
immersedBoundaryEpsilonWallFunctionFvPatchScalarField::
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const immersedBoundaryEpsilonWallFunctionFvPatchScalarField& ewfpsf,
const DimensionedField<scalar, volMesh>& iF
)
:
immersedBoundaryWallFunctionFvPatchScalarField(ewfpsf, iF),
UName_(ewfpsf.UName_),
kName_(ewfpsf.kName_),
GName_(ewfpsf.GName_),
nuName_(ewfpsf.nuName_),
nutName_(ewfpsf.nutName_),
Cmu_(ewfpsf.Cmu_),
kappa_(ewfpsf.kappa_),
E_(ewfpsf.E_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void immersedBoundaryEpsilonWallFunctionFvPatchScalarField::updateCoeffs()
{
if (updated())
{
return;
}
// If G field is not present, execute zero gradient evaluation
// HJ, 20/Mar/2011
if (!db().foundObject<volScalarField>(GName_))
{
InfoIn
(
"void immersedBoundaryEpsilonWallFunctionFvPatchScalarField::"
"updateCoeffs()"
) << "Cannot access " << GName_ << " field. for patch "
<< patch().name() << ". Evaluating as regular immersed boundary"
<< endl;
immersedBoundaryWallFunctionFvPatchScalarField::evaluate();
return;
}
const vectorField& n = ibPatch().ibNormals();
const RASModel& rasModel = db().lookupObject<RASModel>("RASProperties");
const scalar yPlusLam = rasModel.yPlusLam(kappa_, E_);
const scalar Cmu25 = pow(Cmu_, 0.25);
const scalar Cmu50 = sqrt(Cmu_);
const scalar Cmu75 = pow(Cmu_, 0.75);
volScalarField& G = const_cast<volScalarField&>
(db().lookupObject<volScalarField>(GName_));
// Grab values of other fields required for wall functions
// Velocity
const fvPatchVectorField& Uwg =
patch().lookupPatchField<volVectorField, vector>(UName_);
const immersedBoundaryVelocityWallFunctionFvPatchVectorField& Uw =
refCast<const immersedBoundaryVelocityWallFunctionFvPatchVectorField>
(
Uwg
);
// Calculate tangential component, taking into account wall velocity
const vectorField UtanOld =
(I - sqr(n)) & (Uw.ibSamplingPointValue() - Uw.ibValue());
const scalarField magUtanOld = mag(UtanOld);
// Tangential velocity component
scalarField& UTangentialNew = Uw.wallTangentialValue();
// Wall shear stress
vectorField& tauWall = Uw.tauWall();
// Turbulence kinetic energy
const fvPatchScalarField& kg =
patch().lookupPatchField<volScalarField, scalar>(kName_);
const immersedBoundaryWallFunctionFvPatchScalarField& kw =
refCast<const immersedBoundaryWallFunctionFvPatchScalarField>(kg);
// Current and new values of k at sampling point
scalarField k = kw.ibSamplingPointValue();
scalarField& kNew = kw.wallValue();
// Laminar viscosity
const fvPatchScalarField& nuwg =
patch().lookupPatchField<volScalarField, scalar>(nuName_);
const immersedBoundaryFvPatchScalarField& nuw =
refCast<const immersedBoundaryFvPatchScalarField>(nuwg);
scalarField nu = nuw.ibCellValue();
// Turbulent viscosity
const fvPatchScalarField& nutwg =
patch().lookupPatchField<volScalarField, scalar>(nutName_);
const immersedBoundaryWallFunctionFvPatchScalarField& nutw =
refCast<const immersedBoundaryWallFunctionFvPatchScalarField>(nutwg);
// New values of nut
scalarField nutOld = nutw.ibCellValue();
scalarField& nutNew = nutw.wallValue();
const scalarField magGradUw = mag(Uw.ibGrad());
// Get the IB addressing and distance
const labelList& ibc = ibPatch().ibCells();
// Distance to sampling point
const scalarField& ySample = ibPatch().ibSamplingPointDelta();
// Distance from wall to IB point
const scalarField& y = ibPatch().ibDelta();
// Epsilon: store IB cell values for direct insertion
scalarField epsilonSample = this->ibSamplingPointValue();
scalarField& epsilonNew = this->wallValue();
// Mark values to be fixed
boolList wf(ibc.size(), false);
// Calculate yPlus for sample points
scalarField ypd = Cmu25*ySample*sqrt(k)/nu;
// Calculate wall function conditions
forAll (ibc, ibCellI)
{
const scalar nuLam = nu[ibCellI];
// Calculate yPlus from k and laminar viscosity for the IB point
const scalar yPlusSample = ypd[ibCellI];
scalar uTau;
if (yPlusSample > yPlusLam)
{
// Calculate uTau from log-law, knowing sampled k and U
uTau = magUtanOld[ibCellI]*kappa_/log(E_*yPlusSample);
}
else
{
// Sampling point is in laminar sublayer
// Bug fix: HJ, 11/Aug/2014
uTau = yPlusSample;
}
// Set wall shear stress
tauWall[ibCellI] = sqr(uTau)*UtanOld[ibCellI]/(magUtanOld[ibCellI] + SMALL);
// Calculate yPlus for IB point
// scalar yPlusIB = uTau*y[ibCellI]/nuLam;
scalar yPlusIB = yPlusSample*y[ibCellI]/ySample[ibCellI];
// Calculate wall function data in the immersed boundary point
if (yPlusIB > yPlusLam)
{
// Logarithmic region
wf[ibCellI] = true;
scalar nutw = nuLam*(yPlusIB*kappa_/log(E_*yPlusIB) - 1);
// Fix generation even though it if is not used
G[ibc[ibCellI]] =
sqr((nutw + nuLam)*magGradUw[ibCellI])/
(Cmu25*sqrt(k[ibCellI])*kappa_*y[ibCellI]);
// Log-Law for tangential velocity
UTangentialNew[ibCellI] =
min
(
magUtanOld[ibCellI],
uTau/kappa_*log(E_*yPlusIB)
);
// Calculate turbulent viscosity
nutNew[ibCellI] = nutw;
// Calculate k in the IB cell from G = epsilon
kNew[ibCellI] = (nutw + nuLam)*magGradUw[ibCellI]/Cmu50;
// Calculate epsilon from yPlus and set it
epsilonNew[ibCellI] =
Cmu75*pow(kNew[ibCellI], 1.5)/(kappa_*y[ibCellI]);
}
else
{
// Laminar sub-layer
wf[ibCellI] = false;
// G is zero
G[ibc[ibCellI]] = 0;
// Laminar sub-layer for tangential velocity: uPlus = yPlus
UTangentialNew[ibCellI] = min(magUtanOld[ibCellI], uTau*yPlusIB);
// Turbulent viscosity is zero
nutNew[ibCellI] = SMALL;
// k is zero gradient: use the sampled value
kNew[ibCellI] = k[ibCellI];
// Calculate epsilon from yPlus and set it.
// Note: calculating equilibrium epsilon in the sub-layer creates
// an unrealistic oscillation: use sampled value
// HJ, 27/Jul/2012
epsilonNew[ibCellI] = epsilonSample[ibCellI];
}
}
// Info<< "UTangentialNew " << min(UTangentialNew) << " " << max(UTangentialNew) << endl;
// Info<< "nutNew " << min(nutNew) << " " << max(nutNew) << endl;
// Info<< "kNew " << min(kNew) << " " << max(kNew) << endl;
// Info<< "epsilonNew " << min(epsilonNew) << " " << max(epsilonNew) << endl;
// Set the fields to calculated wall function values
Uw.wallMask() = true;
kw.wallMask() = wf;
nutw.wallMask() = true;
this->wallMask() = true;
// Insert epsilon values into the internal field
immersedBoundaryWallFunctionFvPatchScalarField::updateCoeffs();
}
void immersedBoundaryEpsilonWallFunctionFvPatchScalarField::evaluate
(
const Pstream::commsTypes commsType
)
{
// Insert epsilon values into the internal field
this->setIbCellValues(this->wallValue());
fvPatchScalarField::evaluate(commsType);
}
void immersedBoundaryEpsilonWallFunctionFvPatchScalarField::
write(Ostream& os) const
{
immersedBoundaryWallFunctionFvPatchScalarField::write(os);
writeEntryIfDifferent<word>(os, "U", "U", UName_);
writeEntryIfDifferent<word>(os, "k", "k", kName_);
writeEntryIfDifferent<word>(os, "G", "RASModel::G", GName_);
writeEntryIfDifferent<word>(os, "nu", "nu", nuName_);
writeEntryIfDifferent<word>(os, "nut", "nut", nutName_);
os.writeKeyword("Cmu") << Cmu_ << token::END_STATEMENT << nl;
os.writeKeyword("kappa") << kappa_ << token::END_STATEMENT << nl;
os.writeKeyword("E") << E_ << token::END_STATEMENT << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeField
(
fvPatchScalarField,
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,202 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::incompressible::RASModels::
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
Description
Boundary condition for epsilon when using wall functions
- calculates y+, G, tangential velocity, nut and k
- each of calculated values is handled separately by the appropriate
boundary condition
- epsilon values added directly into the field to act as a constraint
SourceFiles
immersedBoundaryEpsilonWallFunctionFvPatchScalarField.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryEpsilonWallFunctionFvPatchScalarField_H
#define immersedBoundaryEpsilonWallFunctionFvPatchScalarField_H
#include "immersedBoundaryWallFunctionFvPatchFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryEpsilonWallFunctionFvPatchScalarField Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryEpsilonWallFunctionFvPatchScalarField
:
public immersedBoundaryWallFunctionFvPatchScalarField
{
// Private data
//- Name of velocity field
word UName_;
//- Name of turbulence kinetic energy field
word kName_;
//- Name of turbulence generation field
word GName_;
//- Name of laminar viscosity field
word nuName_;
//- Name of turbulent viscosity field
word nutName_;
//- Cmu coefficient
scalar Cmu_;
//- Von Karman constant
scalar kappa_;
//- E coefficient
scalar E_;
public:
//- Runtime type information
TypeName("immersedBoundaryEpsilonWallFunction");
// Constructors
//- Construct from patch and internal field
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&
);
//- Construct from patch, internal field and dictionary
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const dictionary&
);
//- Construct by mapping given
// immersedBoundaryEpsilonWallFunctionFvPatchScalarField
// onto a new patch
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const immersedBoundaryEpsilonWallFunctionFvPatchScalarField&,
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const immersedBoundaryEpsilonWallFunctionFvPatchScalarField&
);
//- Construct and return a clone
virtual tmp<fvPatchScalarField> clone() const
{
return tmp<fvPatchScalarField>
(
new immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
*this
)
);
}
//- Construct as copy setting internal field reference
immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
const immersedBoundaryEpsilonWallFunctionFvPatchScalarField&,
const DimensionedField<scalar, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchScalarField> clone
(
const DimensionedField<scalar, volMesh>& iF
) const
{
return tmp<fvPatchScalarField>
(
new immersedBoundaryEpsilonWallFunctionFvPatchScalarField
(
*this,
iF
)
);
}
//- Destructor
virtual ~immersedBoundaryEpsilonWallFunctionFvPatchScalarField()
{}
// Member functions
// Evaluation functions
//- Update the coefficients associated with the patch field
virtual void updateCoeffs();
//- Evaluate the patchField
virtual void evaluate
(
const Pstream::commsTypes = Pstream::blocking
);
// I-O
//- Write
void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,386 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryOmegaWallFunctionFvPatchScalarField.H"
#include "immersedBoundaryVelocityWallFunctionFvPatchVectorField.H"
#include "RASModel.H"
#include "fvPatchFieldMapper.H"
#include "volFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
immersedBoundaryOmegaWallFunctionFvPatchScalarField::
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF
)
:
immersedBoundaryWallFunctionFvPatchScalarField(p, iF),
UName_("U"),
kName_("k"),
GName_("RASModel::G"),
nuName_("nu"),
nutName_("nut"),
Cmu_(0.09),
kappa_(0.41),
E_(9.8),
beta1_(0.075)
{}
immersedBoundaryOmegaWallFunctionFvPatchScalarField::
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const dictionary& dict
)
:
immersedBoundaryWallFunctionFvPatchScalarField(p, iF, dict),
UName_(dict.lookupOrDefault<word>("U", "U")),
kName_(dict.lookupOrDefault<word>("k", "k")),
GName_(dict.lookupOrDefault<word>("G", "RASModel::G")),
nuName_(dict.lookupOrDefault<word>("nu", "nu")),
nutName_(dict.lookupOrDefault<word>("nut", "nut")),
Cmu_(dict.lookupOrDefault<scalar>("Cmu", 0.09)),
kappa_(dict.lookupOrDefault<scalar>("kappa", 0.41)),
E_(dict.lookupOrDefault<scalar>("E", 9.8)),
beta1_(dict.lookupOrDefault<scalar>("beta1", 0.075))
{}
immersedBoundaryOmegaWallFunctionFvPatchScalarField::
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const immersedBoundaryOmegaWallFunctionFvPatchScalarField& ptf,
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
immersedBoundaryWallFunctionFvPatchScalarField(ptf, p, iF, mapper),
UName_(ptf.UName_),
kName_(ptf.kName_),
GName_(ptf.GName_),
nuName_(ptf.nuName_),
nutName_(ptf.nutName_),
Cmu_(ptf.Cmu_),
kappa_(ptf.kappa_),
E_(ptf.E_),
beta1_(ptf.beta1_)
{}
immersedBoundaryOmegaWallFunctionFvPatchScalarField::
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const immersedBoundaryOmegaWallFunctionFvPatchScalarField& owfpsf
)
:
immersedBoundaryWallFunctionFvPatchScalarField(owfpsf),
UName_(owfpsf.UName_),
kName_(owfpsf.kName_),
GName_(owfpsf.GName_),
nuName_(owfpsf.nuName_),
nutName_(owfpsf.nutName_),
Cmu_(owfpsf.Cmu_),
kappa_(owfpsf.kappa_),
E_(owfpsf.E_)
{}
immersedBoundaryOmegaWallFunctionFvPatchScalarField::
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const immersedBoundaryOmegaWallFunctionFvPatchScalarField& owfpsf,
const DimensionedField<scalar, volMesh>& iF
)
:
immersedBoundaryWallFunctionFvPatchScalarField(owfpsf, iF),
UName_(owfpsf.UName_),
kName_(owfpsf.kName_),
GName_(owfpsf.GName_),
nuName_(owfpsf.nuName_),
nutName_(owfpsf.nutName_),
Cmu_(owfpsf.Cmu_),
kappa_(owfpsf.kappa_),
E_(owfpsf.E_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void immersedBoundaryOmegaWallFunctionFvPatchScalarField::updateCoeffs()
{
if (updated())
{
return;
}
// If G field is not present, execute zero gradient evaluation
// HJ, 20/Mar/2011
if (!db().foundObject<volScalarField>(GName_))
{
InfoIn
(
"void immersedBoundaryOmegaWallFunctionFvPatchScalarField::"
"updateCoeffs()"
) << "Cannot access " << GName_ << " field. for patch "
<< patch().name() << ". Evaluating as regular immersed boundary"
<< endl;
immersedBoundaryWallFunctionFvPatchScalarField::evaluate();
return;
}
const vectorField& n = ibPatch().ibNormals();
const RASModel& rasModel = db().lookupObject<RASModel>("RASProperties");
const scalar yPlusLam = rasModel.yPlusLam(kappa_, E_);
const scalar Cmu25 = pow(Cmu_, 0.25);
const scalar Cmu50 = sqrt(Cmu_);
volScalarField& G = const_cast<volScalarField&>
(db().lookupObject<volScalarField>(GName_));
// Grab values of other fields required for wall functions
// Velocity
const fvPatchVectorField& Uwg =
patch().lookupPatchField<volVectorField, vector>(UName_);
const immersedBoundaryVelocityWallFunctionFvPatchVectorField& Uw =
refCast<const immersedBoundaryVelocityWallFunctionFvPatchVectorField>
(
Uwg
);
// Calculate tangential component, taking into account wall velocity
const scalarField UtanOld =
mag((I - sqr(n)) & (Uw.ibSamplingPointValue() - Uw.ibValue()));
scalarField& UTangentialNew = Uw.wallTangentialValue();
// Turbulence kinetic energy
const fvPatchScalarField& kg =
patch().lookupPatchField<volScalarField, scalar>(kName_);
const immersedBoundaryWallFunctionFvPatchScalarField& kw =
refCast<const immersedBoundaryWallFunctionFvPatchScalarField>(kg);
// Current and new values of k at sampling point
scalarField k = kw.ibSamplingPointValue();
scalarField& kNew = kw.wallValue();
// Laminar viscosity
const fvPatchScalarField& nuwg =
patch().lookupPatchField<volScalarField, scalar>(nuName_);
const immersedBoundaryFvPatchScalarField& nuw =
refCast<const immersedBoundaryFvPatchScalarField>(nuwg);
scalarField nu = nuw.ibCellValue();
// Turbulent viscosity
const fvPatchScalarField& nutwg =
patch().lookupPatchField<volScalarField, scalar>(nutName_);
const immersedBoundaryWallFunctionFvPatchScalarField& nutw =
refCast<const immersedBoundaryWallFunctionFvPatchScalarField>(nutwg);
// New values of nut
scalarField nutOld = nutw.ibCellValue();
scalarField& nutNew = nutw.wallValue();
const scalarField magGradUw = mag(Uw.ibGrad());
// Get the IB addressing and distance
const labelList& ibc = ibPatch().ibCells();
// Distance to sampling point
const scalarField& ySample = ibPatch().ibSamplingPointDelta();
// Distance from wall to IB point
const scalarField& y = ibPatch().ibDelta();
// Omega: store IB cell values for direct insertion
scalarField omegaSample = this->ibSamplingPointValue();
scalarField& omegaNew = this->wallValue();
// Mark values to be fixed
boolList wf(ibc.size(), false);
// Calculate yPlus for sample points
scalarField ypd = Cmu25*ySample*sqrt(k)/nu;
// Calculate wall function conditions
forAll (ibc, ibCellI)
{
const scalar nuLam = nu[ibCellI];
// Calculate yPlus from k and laminar viscosity for the IB point
const scalar yPlusSample = ypd[ibCellI];
scalar tauW, uTau; // wall-shear and friction velocity from LOW
if (yPlusSample > yPlusLam)
{
// Calculate tauW from log-law using k and U at sampling point
tauW = UtanOld[ibCellI]*Cmu25*sqrt(k[ibCellI])*kappa_
/log(E_*yPlusSample);
}
else
{
// Sampling point is in laminar sublayer
tauW = UtanOld[ibCellI]*Cmu25*sqrt(k[ibCellI])/yPlusSample;
}
// friction velocity computed from k and U at sampling point
uTau = sqrt(tauW);
// Calculate yPlus for IB point
scalar yPlusIB = yPlusSample*y[ibCellI]/ySample[ibCellI];
// Calculate wall function data in the immersed boundary point
if (yPlusIB > yPlusLam)
{
// Logarithmic region
wf[ibCellI] = true;
// turbulent viscosity at IB cell and at wall
scalar nutw = nuLam*(yPlusIB*kappa_/log(E_*yPlusIB) - 1);
// Fix generation even though it if is not used
G[ibc[ibCellI]] =
sqr((nutw + nuLam)*magGradUw[ibCellI])/
(Cmu25*sqrt(k[ibCellI])*kappa_*y[ibCellI]);
// Compute k at the IB cell
kNew[ibCellI] = tauW/Cmu50; // equilibrium boundary layer
// kNew[ibCellI] = k[ibCellI]; // zero-Gradient (less stable)
// Compute omega at the IB cell
omegaNew[ibCellI] = sqrt(kNew[ibCellI])/(Cmu25*kappa_*y[ibCellI]);
// Log-Law for tangential velocity - uTau = Cmu25*sqrt(kNew)
UTangentialNew[ibCellI] = uTau/kappa_*log(E_*yPlusIB);
// Calculate turbulent viscosity
nutNew[ibCellI] = nutw;
}
else
{
// Laminar sub-layer
wf[ibCellI] = false;
// G is zero - immaterial!
// G[ibc[ibCellI]] = 0;
// quadratic fit
kNew[ibCellI] = k[ibCellI]*sqr(yPlusIB/yPlusLam);
// Compute omega at the IB cell
omegaNew[ibCellI] = 6.0*nu[ibCellI]/(beta1_*sqr(y[ibCellI]));
// Laminar sub-layer for tangential velocity: uPlus = yPlus
UTangentialNew[ibCellI] = uTau*yPlusIB;
// Turbulent viscosity is zero
nutNew[ibCellI] = SMALL;
}
}
// Info<< "UTangentialNew " << min(UTangentialNew) << " " << max(UTangentialNew) << endl;
// Info<< "nutNew " << min(nutNew) << " " << max(nutNew) << endl;
// Info<< "kNew " << min(kNew) << " " << max(kNew) << endl;
// Info<< "epsilonNew " << min(epsilonNew) << " " << max(epsilonNew) << endl;
// Set the fields to calculated wall function values
Uw.wallMask() = true;
kw.wallMask() = wf;
nutw.wallMask() = true;
this->wallMask() = true;
// Insert epsilon values into the internal field
immersedBoundaryWallFunctionFvPatchScalarField::updateCoeffs();
}
void immersedBoundaryOmegaWallFunctionFvPatchScalarField::evaluate
(
const Pstream::commsTypes commsType
)
{
// Insert epsilon values into the internal field
this->setIbCellValues(this->wallValue());
fvPatchScalarField::evaluate(commsType);
}
void immersedBoundaryOmegaWallFunctionFvPatchScalarField::
write(Ostream& os) const
{
immersedBoundaryWallFunctionFvPatchScalarField::write(os);
writeEntryIfDifferent<word>(os, "U", "U", UName_);
writeEntryIfDifferent<word>(os, "k", "k", kName_);
writeEntryIfDifferent<word>(os, "G", "RASModel::G", GName_);
writeEntryIfDifferent<word>(os, "nu", "nu", nuName_);
writeEntryIfDifferent<word>(os, "nut", "nut", nutName_);
os.writeKeyword("Cmu") << Cmu_ << token::END_STATEMENT << nl;
os.writeKeyword("kappa") << kappa_ << token::END_STATEMENT << nl;
os.writeKeyword("E") << E_ << token::END_STATEMENT << nl;
os.writeKeyword("beta1") << beta1_ << token::END_STATEMENT << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeField
(
fvPatchScalarField,
immersedBoundaryOmegaWallFunctionFvPatchScalarField
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,217 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::incompressible::RASModels::
immersedBoundaryOmegaWallFunctionFvPatchScalarField
Description
Provides a wall function boundary condition/constraint on omega
Computed value is:
omega = sqrt(omega_vis^2 + omega_log^2)
where
omega_vis = omega in viscous region
omega_log = omega in logarithmic region
Model described by Eq.(15) of:
@verbatim
Menter, F., Esch, T.
"Elements of Industrial Heat Transfer Prediction"
16th Brazilian Congress of Mechanical Engineering (COBEM),
Nov. 2001
@endverbatim
SourceFiles
immersedBoundaryOmegaWallFunctionFvPatchScalarField.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryOmegaWallFunctionFvPatchScalarField_H
#define immersedBoundaryOmegaWallFunctionFvPatchScalarField_H
#include "immersedBoundaryWallFunctionFvPatchFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryOmegaWallFunctionFvPatchScalarField Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryOmegaWallFunctionFvPatchScalarField
:
public immersedBoundaryWallFunctionFvPatchScalarField
{
// Private data
//- Name of velocity field
word UName_;
//- Name of turbulence kinetic energy field
word kName_;
//- Name of turbulence generation field
word GName_;
//- Name of laminar viscosity field
word nuName_;
//- Name of turbulent viscosity field
word nutName_;
//- Cmu coefficient
scalar Cmu_;
//- Von Karman constant
scalar kappa_;
//- E coefficient
scalar E_;
//- beta1 coefficient
scalar beta1_;
public:
//- Runtime type information
TypeName("immersedBoundaryOmegaWallFunction");
// Constructors
//- Construct from patch and internal field
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&
);
//- Construct from patch, internal field and dictionary
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const dictionary&
);
//- Construct by mapping given
// immersedBoundaryOmegaWallFunctionFvPatchScalarField
// onto a new patch
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const immersedBoundaryOmegaWallFunctionFvPatchScalarField&,
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const immersedBoundaryOmegaWallFunctionFvPatchScalarField&
);
//- Construct and return a clone
virtual tmp<fvPatchScalarField> clone() const
{
return tmp<fvPatchScalarField>
(
new immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
*this
)
);
}
//- Construct as copy setting internal field reference
immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
const immersedBoundaryOmegaWallFunctionFvPatchScalarField&,
const DimensionedField<scalar, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchScalarField> clone
(
const DimensionedField<scalar, volMesh>& iF
) const
{
return tmp<fvPatchScalarField>
(
new immersedBoundaryOmegaWallFunctionFvPatchScalarField
(
*this,
iF
)
);
}
//- Destructor
virtual ~immersedBoundaryOmegaWallFunctionFvPatchScalarField()
{}
// Member functions
// Evaluation functions
//- Update the coefficients associated with the patch field
virtual void updateCoeffs();
//- Evaluate the patchField
virtual void evaluate
(
const Pstream::commsTypes = Pstream::blocking
);
// I-O
//- Write
void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,224 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryVelocityWallFunctionFvPatchVectorField.H"
#include "immersedBoundaryWallFunctionFvPatchFields.H"
#include "RASModel.H"
#include "fvPatchFieldMapper.H"
#include "volFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
void immersedBoundaryVelocityWallFunctionFvPatchVectorField::setIbCellValues
(
const vectorField& ibcValues
) const
{
const labelList& ibc = ibPatch().ibCells();
if (ibcValues.size() != ibc.size())
{
FatalErrorIn
(
"void immersedBoundaryVelocityWallFunctionFvPatchVectorField::"
"setIbCellValues\n"
"(\n"
" const vectorField& ibcValues\n"
") const"
) << "Size of ibcValues field not equal to the number of IB cells."
<< nl << "ibcValues: " << ibcValues.size()
<< " ibc: " << ibc.size()
<< abort(FatalError);
}
// Get non-const access to internal field
vectorField& psiI = const_cast<vectorField&>(this->internalField());
immersedBoundaryFvPatchVectorField::setIbCellValues(ibcValues);
if (wallTangentialValue_.empty() || wallMask_.empty())
{
immersedBoundaryFvPatchVectorField::setIbCellValues(ibcValues);
}
else
{
const vectorField& n = ibPatch().ibNormals();
// Calculate tangential component taking into account wall velocity
scalarField UtanOld = mag((I - sqr(n)) & this->ibCellValue());
vectorField Uwall = this->ibValue();
forAll (ibcValues, cellI)
{
// If mask is set, correct the velocity for the
// tangential wall value, otherwise use the fitted value
if (wallMask_[cellI])
{
// Decompose fitted velocity into the normal and
// tangential components
const vector& curN = n[cellI];
const vector curU = psiI[ibc[cellI]];
scalar ibcNormal = curN & ibcValues[cellI];
// Get tangential velocity and direction
vector ibcTangential = (I - sqr(curN)) & curU;
ibcTangential /= mag(ibcTangential) + SMALL;
// Reconstruct the velocity, imposing the magnitude of
// tangential value and add wall velocity
psiI[ibc[cellI]] = curN*ibcNormal
+ ibcTangential*wallTangentialValue_[cellI]
+ Uwall[cellI];
}
else
{
psiI[ibc[cellI]] = ibcValues[cellI];
}
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
immersedBoundaryVelocityWallFunctionFvPatchVectorField::
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF
)
:
immersedBoundaryFvPatchVectorField(p, iF),
wallTangentialValue_(),
tauWall_(),
wallMask_()
{}
immersedBoundaryVelocityWallFunctionFvPatchVectorField::
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF,
const dictionary& dict
)
:
immersedBoundaryFvPatchVectorField(p, iF, dict),
wallTangentialValue_(),
tauWall_(),
wallMask_()
{}
immersedBoundaryVelocityWallFunctionFvPatchVectorField::
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const immersedBoundaryVelocityWallFunctionFvPatchVectorField& ptf,
const fvPatch& p,
const DimensionedField<vector, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
immersedBoundaryFvPatchVectorField(ptf, p, iF, mapper),
wallTangentialValue_(),
tauWall_(),
wallMask_()
{}
immersedBoundaryVelocityWallFunctionFvPatchVectorField::
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const immersedBoundaryVelocityWallFunctionFvPatchVectorField& ewfpsf
)
:
immersedBoundaryFvPatchVectorField(ewfpsf),
wallTangentialValue_(),
tauWall_(),
wallMask_()
{}
immersedBoundaryVelocityWallFunctionFvPatchVectorField::
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const immersedBoundaryVelocityWallFunctionFvPatchVectorField& ewfpsf,
const DimensionedField<vector, volMesh>& iF
)
:
immersedBoundaryFvPatchVectorField(ewfpsf, iF),
wallTangentialValue_(),
tauWall_(),
wallMask_()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const vectorField&
immersedBoundaryVelocityWallFunctionFvPatchVectorField::wallShearStress() const
{
if (tauWall_.empty())
{
FatalErrorIn
(
"const vectorField& "
"immersedBoundaryVelocityWallFunctionFvPatchVectorField::"
"wallShearStress() const"
) << "tauWall not set for IB patch " << patch().name()
<< " for field " << dimensionedInternalField().name()
<< abort(FatalError);
}
return tauWall_;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeField
(
fvPatchVectorField,
immersedBoundaryVelocityWallFunctionFvPatchVectorField
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View file

@ -0,0 +1,229 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::incompressible::RASModels::
immersedBoundaryVelocityWallFunctionFvPatchVectorField
Description
Boundary condition for velocity when using wall functions
- uses tangential velocity as prescribed by the epsilon boundary condition
to enforce into the fit
SourceFiles
immersedBoundaryVelocityWallFunctionFvPatchVectorField.C
\*---------------------------------------------------------------------------*/
#ifndef immersedBoundaryVelocityWallFunctionFvPatchVectorField_H
#define immersedBoundaryVelocityWallFunctionFvPatchVectorField_H
#include "fvPatchFields.H"
#include "immersedBoundaryFvPatchFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
/*---------------------------------------------------------------------------*\
Class immersedBoundaryVelocityWallFunctionFvPatchVectorField Declaration
\*---------------------------------------------------------------------------*/
class immersedBoundaryVelocityWallFunctionFvPatchVectorField
:
public immersedBoundaryFvPatchVectorField
{
// Private data
//- Tangential velocity value to fix in IB cell
mutable scalarField wallTangentialValue_;
//- Wall shear stress
mutable vectorField tauWall_;
//- Indicator on values to fix
mutable boolList wallMask_;
protected:
// Protected Member Functions
//- Set IB cell values: contains data manipulation
virtual void setIbCellValues(const vectorField&) const;
public:
//- Runtime type information
TypeName("immersedBoundaryVelocityWallFunction");
// Constructors
//- Construct from patch and internal field
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const fvPatch&,
const DimensionedField<vector, volMesh>&
);
//- Construct from patch, internal field and dictionary
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const fvPatch&,
const DimensionedField<vector, volMesh>&,
const dictionary&
);
//- Construct by mapping given
// immersedBoundaryVelocityWallFunctionFvPatchVectorField
// onto a new patch
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const immersedBoundaryVelocityWallFunctionFvPatchVectorField&,
const fvPatch&,
const DimensionedField<vector, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const immersedBoundaryVelocityWallFunctionFvPatchVectorField&
);
//- Construct and return a clone
virtual tmp<fvPatchVectorField> clone() const
{
return tmp<fvPatchVectorField>
(
new immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
*this
)
);
}
//- Construct as copy setting internal field reference
immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
const immersedBoundaryVelocityWallFunctionFvPatchVectorField&,
const DimensionedField<vector, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchVectorField> clone
(
const DimensionedField<vector, volMesh>& iF
) const
{
return tmp<fvPatchVectorField>
(
new immersedBoundaryVelocityWallFunctionFvPatchVectorField
(
*this,
iF
)
);
}
//- Destructor
virtual ~immersedBoundaryVelocityWallFunctionFvPatchVectorField()
{}
// Member functions
// Access
//- Access to tangential velocity value to fix in IB cell
// Note non-const access
scalarField& wallTangentialValue() const
{
if (wallTangentialValue_.empty())
{
wallTangentialValue_.setSize
(
this->ibPatch().ibCells().size(),
0
);
}
return wallTangentialValue_;
}
//- Return wall shear stress
const vectorField& wallShearStress() const;
//- Access to wall shear stress in IB cell
// Note non-const access
vectorField& tauWall() const
{
if (tauWall_.empty())
{
tauWall_.setSize
(
this->ibPatch().ibCells().size(),
vector::zero
);
}
return tauWall_;
}
//- Access to indicator on fixed values. Note non-const access
boolList& wallMask() const
{
if (wallMask_.empty())
{
wallMask_.setSize
(
this->ibPatch().ibCells().size(),
false
);
}
return wallMask_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,183 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "immersedBoundaryWallFunctionFvPatchField.H"
#include "fvPatchFieldMapper.H"
#include "addToRunTimeSelectionTable.H"
#include "wallFvPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
namespace RASModels
{
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
template<class Type>
void immersedBoundaryWallFunctionFvPatchField<Type>::motionUpdate() const
{
wallValue_.clear();
wallMask_.clear();
immersedBoundaryFvPatchField<Type>::motionUpdate();
}
template<class Type>
void immersedBoundaryWallFunctionFvPatchField<Type>::setIbCellValues
(
const Field<Type>& ibcValues
) const
{
const labelList& ibc = this->ibPatch().ibCells();
if (ibcValues.size() != ibc.size())
{
FatalErrorIn
(
"template<class Type>\n"
"void immersedBoundaryWallFunctionFvPatchField<Type>::"
"setIbCellValues\n"
"(\n"
" const Field<Type>& ibcValues\n"
") const"
) << "Size of ibcValues field not equal to the number of IB cells."
<< nl << "ibcValues: " << ibcValues.size()
<< " ibc: " << ibc.size()
<< abort(FatalError);
}
// Get non-const access to internal field
Field<Type>& psiI = const_cast<Field<Type>&>(this->internalField());
if (wallValue_.empty() || wallMask_.empty())
{
immersedBoundaryFvPatchField<Type>::setIbCellValues(ibcValues);
}
else
{
forAll (ibcValues, cellI)
{
// If mask is set use the wall value, otherwise use the
// fitted value
if (wallMask_[cellI])
{
psiI[ibc[cellI]] = wallValue_[cellI];
}
else
{
psiI[ibc[cellI]] = ibcValues[cellI];
}
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
immersedBoundaryWallFunctionFvPatchField<Type>::
immersedBoundaryWallFunctionFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF
)
:
immersedBoundaryFvPatchField<Type>(p, iF),
wallValue_(),
wallMask_()
{}
template<class Type>
immersedBoundaryWallFunctionFvPatchField<Type>::
immersedBoundaryWallFunctionFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const dictionary& dict
)
:
immersedBoundaryFvPatchField<Type>(p, iF, dict),
wallValue_(),
wallMask_()
{}
template<class Type>
immersedBoundaryWallFunctionFvPatchField<Type>::
immersedBoundaryWallFunctionFvPatchField
(
const immersedBoundaryWallFunctionFvPatchField& ptf,
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
immersedBoundaryFvPatchField<Type>(ptf, p, iF, mapper),
wallValue_(),
wallMask_()
{}
template<class Type>
immersedBoundaryWallFunctionFvPatchField<Type>::
immersedBoundaryWallFunctionFvPatchField
(
const immersedBoundaryWallFunctionFvPatchField& tkqrwfpf
)
:
immersedBoundaryFvPatchField<Type>(tkqrwfpf),
wallValue_(),
wallMask_()
{}
template<class Type>
immersedBoundaryWallFunctionFvPatchField<Type>::
immersedBoundaryWallFunctionFvPatchField
(
const immersedBoundaryWallFunctionFvPatchField& tkqrwfpf,
const DimensionedField<Type, volMesh>& iF
)
:
immersedBoundaryFvPatchField<Type>(tkqrwfpf, iF),
wallValue_(),
wallMask_()
{}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace RASModels
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show more