Field settings can now be specified within
createNonConformalCouplesDict. This allows for patchType overrides; for
example to create a jump condition over the coupling.
An alternate syntax has been added to facilitate this. If patch fields
do not need overriding then the old syntax can be used where patches
that are to be coupled are specified as a pair of names; e.g.:
fields yes;
nonConformalCouples
{
fan
{
patches (fan0 fan1);
transform none;
}
}
If patch fields do need overriding, then instead of the "patches" entry,
separate "owner" and "neighbour" sub-dictionaries should be used. These
can both contain a "patchFields" section detailing the boundary
conditions that apply to the newly created patches:
fields yes;
nonConformalCouples
{
fan
{
owner
{
patch fan0;
patchFields
{
p
{
type fanPressureJump;
patchType nonConformalCyclic;
jump uniform 0;
value uniform 0;
jumpTable polynomial 1((100 0));
}
}
}
neighbour
{
patch fan1;
patchFields
{
$../../owner/patchFields;
}
}
transform none;
}
}
In this example, only the pressure boundary condition is overridden on
the newly created non-conformal cyclic. All other fields will have the
basic constraint type (i.e., nonConformalCyclic) applied.
Settings for the individual non-conformal couples can now be put in a
"nonConformalCouples" sub-dictionary of the
system/createNonConformalCouplesDict. For example:
fields no;
nonConformalCouples // <-- new sub-dictionary
{
nonConformalCouple_none
{
patches (nonCouple1 nonCouple2);
transform none;
}
nonConformalCouple_30deg
{
patches (nonCoupleBehind nonCoupleAhead);
transform rotational;
rotationAxis (-1 0 0);
rotationCentre (0 0 0);
rotationAngle 30;
}
}
This permits settings to be #include-d from files that themselves
contain sub-dictionaries without the utility treating those
sub-dictionaries as if they specify a non-conformal coupling. It also
makes the syntax more comparable to that of createBafflesDict.
The new "nonConformalCouples" sub-dictionary is optional, so this change
is backwards compatible. The new syntax is recommended, however, and all
examples have been changed accordingly.
executed with foamRun for single region simulations of foamMultiRun for
multi-region simulations. Replaces pimpleFoam, pisoFoam and simpleFoam and all
the corresponding tutorials have been updated and moved to
tutorials/modules/incompressibleFluid.
Class
Foam::solvers::incompressibleFluid
Description
Solver module for steady or transient turbulent flow of incompressible
isothermal fluids with optional mesh motion and change.
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Optional fvModels and fvConstraints are provided to enhance the simulation
in many ways including adding various sources, constraining or limiting
the solution.
Reference:
\verbatim
Greenshields, C. J., & Weller, H. G. (2022).
Notes on Computational Fluid Dynamics: General Principles.
CFD Direct Ltd.: Reading, UK.
\endverbatim
SourceFiles
incompressibleFluid.C
See also
Foam::solvers::fluidSolver
Foam::solvers::isothermalFluid
in which different solver modules can be selected in each region to for complex
conjugate heat-transfer and other combined physics problems such as FSI
(fluid-structure interaction).
For single-region simulations the solver module is selected, instantiated and
executed in the PIMPLE loop in the new foamRun application.
For multi-region simulations the set of solver modules, one for each region, are
selected, instantiated and executed in the multi-region PIMPLE loop of new the
foamMultiRun application.
This provides a very general, flexible and extensible framework for complex
coupled problems by creating more solver modules, either by converting existing
solver applications or creating new ones.
The current set of solver modules provided are:
isothermalFluid
Solver module for steady or transient turbulent flow of compressible
isothermal fluids with optional mesh motion and mesh topology changes.
Created from the rhoSimpleFoam, rhoPimpleFoam and buoyantFoam solvers but
without the energy equation, hence isothermal. The buoyant pressure
formulation corresponding to the buoyantFoam solver is selected
automatically by the presence of the p_rgh pressure field in the start-time
directory.
fluid
Solver module for steady or transient turbulent flow of compressible fluids
with heat-transfer for HVAC and similar applications, with optional
mesh motion and mesh topology changes.
Derived from the isothermalFluid solver module with the addition of the
energy equation from the rhoSimpleFoam, rhoPimpleFoam and buoyantFoam
solvers, thus providing the equivalent functionality of these three solvers.
multicomponentFluid
Solver module for steady or transient turbulent flow of compressible
reacting fluids with optional mesh motion and mesh topology changes.
Derived from the isothermalFluid solver module with the addition of
multicomponent thermophysical properties energy and specie mass-fraction
equations from the reactingFoam solver, thus providing the equivalent
functionality in reactingFoam and buoyantReactingFoam. Chemical reactions
and/or combustion modelling may be optionally selected to simulate reacting
systems including fires, explosions etc.
solid
Solver module for turbulent flow of compressible fluids for conjugate heat
transfer, HVAC and similar applications, with optional mesh motion and mesh
topology changes.
The solid solver module may be selected in solid regions of a CHT case, with
either the fluid or multicomponentFluid solver module in the fluid regions
and executed with foamMultiRun to provide functionality equivalent
chtMultiRegionFoam but in a flexible and extensible framework for future
extension to more complex coupled problems.
All the usual fvModels, fvConstraints, functionObjects etc. are available with
these solver modules to support simulations including body-forces, local sources,
Lagrangian clouds, liquid films etc. etc.
Converting compressibleInterFoam and multiphaseEulerFoam into solver modules
would provide a significant enhancement to the CHT capability and incompressible
solvers like pimpleFoam run in conjunction with solidDisplacementFoam in
foamMultiRun would be useful for a range of FSI problems. Many other
combinations of existing solvers converted into solver modules could prove
useful for a very wide range of complex combined physics simulations.
All tutorials from the rhoSimpleFoam, rhoPimpleFoam, buoyantFoam, reactingFoam,
buoyantReactingFoam and chtMultiRegionFoam solver applications replaced by
solver modules have been updated and moved into the tutorials/modules directory:
modules
├── CHT
│ ├── coolingCylinder2D
│ ├── coolingSphere
│ ├── heatedDuct
│ ├── heatExchanger
│ ├── reverseBurner
│ └── shellAndTubeHeatExchanger
├── fluid
│ ├── aerofoilNACA0012
│ ├── aerofoilNACA0012Steady
│ ├── angledDuct
│ ├── angledDuctExplicitFixedCoeff
│ ├── angledDuctLTS
│ ├── annularThermalMixer
│ ├── BernardCells
│ ├── blockedChannel
│ ├── buoyantCavity
│ ├── cavity
│ ├── circuitBoardCooling
│ ├── decompressionTank
│ ├── externalCoupledCavity
│ ├── forwardStep
│ ├── helmholtzResonance
│ ├── hotRadiationRoom
│ ├── hotRadiationRoomFvDOM
│ ├── hotRoom
│ ├── hotRoomBoussinesq
│ ├── hotRoomBoussinesqSteady
│ ├── hotRoomComfort
│ ├── iglooWithFridges
│ ├── mixerVessel2DMRF
│ ├── nacaAirfoil
│ ├── pitzDaily
│ ├── prism
│ ├── shockTube
│ ├── squareBend
│ ├── squareBendLiq
│ └── squareBendLiqSteady
└── multicomponentFluid
├── aachenBomb
├── counterFlowFlame2D
├── counterFlowFlame2D_GRI
├── counterFlowFlame2D_GRI_TDAC
├── counterFlowFlame2DLTS
├── counterFlowFlame2DLTS_GRI_TDAC
├── cylinder
├── DLR_A_LTS
├── filter
├── hotBoxes
├── membrane
├── parcelInBox
├── rivuletPanel
├── SandiaD_LTS
├── simplifiedSiwek
├── smallPoolFire2D
├── smallPoolFire3D
├── splashPanel
├── verticalChannel
├── verticalChannelLTS
└── verticalChannelSteady
Also redirection scripts are provided for the replaced solvers which call
foamRun -solver <solver module name> or foamMultiRun in the case of
chtMultiRegionFoam for backward-compatibility.
Documentation for foamRun and foamMultiRun:
Application
foamRun
Description
Loads and executes an OpenFOAM solver module either specified by the
optional \c solver entry in the \c controlDict or as a command-line
argument.
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Usage
\b foamRun [OPTION]
- \par -solver <name>
Solver name
- \par -libs '(\"lib1.so\" ... \"libN.so\")'
Specify the additional libraries loaded
Example usage:
- To run a \c rhoPimpleFoam case by specifying the solver on the
command line:
\verbatim
foamRun -solver fluid
\endverbatim
- To update and run a \c rhoPimpleFoam case add the following entries to
the controlDict:
\verbatim
application foamRun;
solver fluid;
\endverbatim
then execute \c foamRun
Application
foamMultiRun
Description
Loads and executes an OpenFOAM solver modules for each region of a
multiregion simulation e.g. for conjugate heat transfer.
The region solvers are specified in the \c regionSolvers dictionary entry in
\c controlDict, containing a list of pairs of region and solver names,
e.g. for a two region case with one fluid region named
liquid and one solid region named tubeWall:
\verbatim
regionSolvers
{
liquid fluid;
tubeWall solid;
}
\endverbatim
The \c regionSolvers entry is a dictionary to support name substitutions to
simplify the specification of a single solver type for a set of
regions, e.g.
\verbatim
fluidSolver fluid;
solidSolver solid;
regionSolvers
{
tube1 $fluidSolver;
tubeWall1 solid;
tube2 $fluidSolver;
tubeWall2 solid;
tube3 $fluidSolver;
tubeWall3 solid;
}
\endverbatim
Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-resolved and
pseudo-transient and steady simulations.
Usage
\b foamMultiRun [OPTION]
- \par -libs '(\"lib1.so\" ... \"libN.so\")'
Specify the additional libraries loaded
Example usage:
- To update and run a \c chtMultiRegion case add the following entries to
the controlDict:
\verbatim
application foamMultiRun;
regionSolvers
{
fluid fluid;
solid solid;
}
\endverbatim
then execute \c foamMultiRun
Full backward-compatibility is provided which support for both multiComponentMixture and
multiComponentPhaseModel provided but all tutorials have been updated.
The cellProc field is the field of cell-processor labels.
The names "distribution" and "dist" have been removed as these are
ambiguous in relation to other forms of distribution and to distance.
The reconstructPar utility now reconstructs the mesh if and when it is
necessary to do so. The reconstructParMesh utility is therefore no
longer necessary and has been removed.
It was necessary/advantagous to consolidate these utilities into one
because in the case of mesh changes it becomes increasingly less clear
which of the separate utilities is responsible for reconstructing data
that is neither clearly physical field nor mesh topology; e.g., moving
points, sets, refinement data, and so on.
If the sequence of meshes are decomposed independently the number, order and
potentially type of processor patches is likely to change. Thus the processor
patches and patch fields must be replaced with those of the new mesh.
and moveDynamicMesh renamed to moveMesh
Description
Mesh motion and topological mesh change utility.
Executes the mover, topoChanger and distributor specified in the
dynamicMeshDict in a time-loop.
This utility now always creates two patches, and only creates duplicate
faces when they connect to different cells and point in opposite
directions. Now that ACMI has been removed, there is no need to create
duplicate faces on the same cell and with similar orientations. This is
unituitive and is now considered an invalid mesh topology.
The preferred syntax for createBaffles is now as follows:
internalFacesOnly true;
baffles
{
cyclics
{
type faceZone;
zoneName cyclicFaces;
owner
{
name cyclicLeft;
type cyclic;
neighbourPatch cyclicRight;
}
neighbour
{
name cyclicRight;
type cyclic;
neighbourPatch cyclicLeft;
}
}
}
Note that the 'patches' sub-dictionary is not needed any more; the
'owner' and 'neighbour' sub-dictionaries can be in the same dictionary
as the parameters with which faces are selected. For backwards
compatibility, however, a 'patches' sub-dictionary is still permitted,
as are keywords 'master' and 'slave' (in place of 'owner' and
'neighbour', respectively).
The 'patchPairs' syntax has been removed. Whilst consise, this syntax
made a number of assumptions and decisions regarding naming conventions
that were not sufficiently intuitive for the user to understand without
extensive reference to the code. If identical boundaries are desired on
both sides of the patch, dictionary substitution provides a more
intuitive way of minimising the amount of specifiection required. For
example, to create two back-to-back walls, the following specification
could be used:
internalFacesOnly true;
fields true;
baffles
{
walls
{
type faceZone;
zoneName wallFaces;
owner
{
name baffleWallLeft;
type wall;
patchFields
{
p
{
type zeroGradient;
}
U
{
type noSlip;
}
}
}
neighbour
{
name baffleWallRight;
$owner; // <-- Use the same settings as for the owner
}
}
}
This boundary condition no longer stores its own mapping. It now has to
be applied to a mapped wall (or equivalent) patch, which does the
mapping for it. This ensures that mapping information is shared between
multiple fields, and that redundant copies are not generated.
to ensure complex BCs are selected and initialised correctly.
All mixture fields are now constructed and read as required in the construction
of the liquid (phase 1) mixtureKEpsilon model to ensure they are read before
time-increment and possible mesh topology change.
The 'pointSync' setting in createPatchDict is now optional and defaults
to false. This setting is very rarely used. A number of unused
'createPatchDict' files have also been removed and obsolete information
has been removed from the annotated example dictionaries.
The following examples in the tutorials ($FOAM_TUTORIALS) directory have
been converted from using AMI to the new NCC system:
+ compressible/rhoPimpleFoam/RAS/annularThermalMixer
+ incompressible/pimpleFoam/RAS/propeller
+ lagrangian/particleFoam/mixerVessel2D (formerly mixerVesselAMI2D)
+ multiphase/interFoam/RAS/mixerVessel
+ multiphase/interFoam/RAS/propeller
+ multiphase/multiphaseEulerFoam/laminar/mixerVessel2D (formerly mixerVesselAMI2D)
The following tutorial has been converted from using ACMI:
+ incompressible/pimpleFoam/RAS/oscillatingInlet
The following tutorial has been converted from using Repeat AMI:
+ incompressible/pimpleFoam/RAS/impeller
The following tutorial has been added to demonstrate NCC's ability to
create a sufficiently conservative solution in a closed domain to
maintain phase fraction boundedness:
+ multiphase/interFoam/laminar/mixerVessel2D
The following tutorials have been added to demonstrate NCC's ability to
simulate partially overlapping couples on curved surfaces:
+ incompressible/pimpleFoam/RAS/ballValve
+ multiphase/compressibleInterFoam/RAS/ballValve
The following tutorial has been added to provide a simple comparison of
the conservation behaviour of AMI and NCC:
+ incompressible/pimpleFoam/laminar/nonConformalChannel
The following tutorial has been removed, as there were sufficiently many
examples involving this geometry:
+ incompressible/pimpleFoam/laminar/mixerVesselAMI2D
This tutorial simulates solid particle coalescence and breakage through
a 90 degree pipe bend.
Patch contributed by Kasper Gram Bilde and Institute of Fluid Dynamics,
Helmholtz-Zentrum Dresden - Rossendorf (HZDR)
On unstructured collocated meshes the Reynolds stress tends to decouple from the
velocity creating pronounced staggering patterns in the solution. This effect
is reduced or eliminated by a special coupling algorithm which replaces the
gradient diffusion component of the Reynolds stress with the equivalent compact
representation on the mesh, i.e. div-grad with Laplacian in the DivDevRhoReff function:
template<class BasicMomentumTransportModel>
template<class RhoFieldType>
Foam::tmp<Foam::fvVectorMatrix>
Foam::ReynoldsStress<BasicMomentumTransportModel>::DivDevRhoReff
(
const RhoFieldType& rho,
volVectorField& U
) const
{
tmp<volTensorField> tgradU = fvc::grad(U);
const volTensorField& gradU = tgradU();
const surfaceTensorField gradUf(fvc::interpolate(gradU));
// Interpolate Reynolds stress to the faces
// with either a stress or velocity coupling correction
const surfaceVectorField Refff
(
(this->mesh().Sf() & fvc::interpolate(R_))
// Stress coupling
+ couplingFactor_
*(this->mesh().Sf() & fvc::interpolate(this->nut()*gradU))
// or velocity gradient coupling
// + couplingFactor_
// *fvc::interpolate(this->nut())*(this->mesh().Sf() & gradUf)
- fvc::interpolate(couplingFactor_*this->nut() + this->nu())
*this->mesh().magSf()*fvc::snGrad(U)
- fvc::interpolate(this->nu())*(this->mesh().Sf() & dev2(gradUf.T()))
);
return
(
fvc::div(fvc::interpolate(this->alpha_*rho)*Refff)
- correction(fvm::laplacian(this->alpha_*rho*this->nuEff(), U))
);
}
In the above two options for the coupling term are provided, one based on the
stress correction (un-commented) and an alternative based an the velocity
gradient correction (commented). Tests run so far indicate that the stress
correction provides better coupling while minimising the error introduced.
A new tutorial case ductSecondaryFlow is provided which demonstrates the updated
coupling algorithm on the simulation of the classic secondary flow generated in
rectangular ducts.
The population balance model considers dilatation originating from density
change and mass transfer via source terms describing nucleation as well as
"drift" of the size distribution to smaller or larger sizes. Numerically, the
treatment does not necessarily equal the total dilatation, hence a correction is
introduced to ensure boundedness of the size group fractions.
Patch contributed by Institute of Fluid Dynamics,
Helmholtz-Zentrum Dresden - Rossendorf (HZDR)
and VTT Technical Research Centre of Finland Ltd.
The refinement cell set is now generated directly using boxToCell. The
mesh now uses cyclic, rather than cyclicAMI, patches so that propagation
of the refinement across the coupling can be tested. Field files have
been simplified by using #includeEtc to set constraints. A best practice
velocity/pressure specification has been set for the outlet boundary.
Unused fields and settings have been removed.
epsilonm is obtained by combining epsilon.gas and epsilon.liquid in a two-phase
system, each of which will apply the epsilonWallFunction at walls; the
epsilonmWallFunction propagates the resulting wall epsilonm into the near-wall
cells.
If the 0/epsilonm file is provided the epsilonmWallFunction should be specified
for walls, if the 0/epsilonm file is not provided it will be generated
automatically and the epsilonmWallFunction applied to walls for which the
epsilonWallFunction is specified in the epsilon.liquid file.
fvMesh::update() now executes at the beginning of the time-step, before time is
incremented and handles topology change, mesh to mesh mapping and redistribution
without point motion. Following each of these mesh changes fields are mapped
from the previous mesh state to new mesh state in a conservative manner. These
mesh changes not occur at most once per time-step.
fvMesh::move() is executed after time is incremented and handles point motion
mesh morphing during the time-step in an Arbitrary Lagrangian Eulerian approach
requiring the mesh motion flux to match the cell volume change. fvMesh::move()
can be called any number of times during the time-step to allow iterative update
of the coupling between the mesh motion and field solution.
With fvMeshTopoChangers::meshToMesh it is now possible to map the solution to a
specified sequence of pre-generated meshes at run-time to support arbitrary mesh
changes, refinements, un-refinements, changes in region topology, geometry,
etc. Additionally mesh-motion between the sequence of meshes is supported to
allow for e.g. piston and valve motion in engines.
The tutorials/incompressible/pimpleFoam/laminar/movingCone case has been updated
to provide a demonstration of the advantages of this run-time mesh-mapping by
mapping to meshes that are finer behind the cone and coarser in front of the
cone as the cone approaches the end of the domain, thus maintaining good
resolution while avoiding excessive cell aspect ratio as the mesh is squeezed.
The dynamicMeshDict for the movingCone case is;
mover
{
type motionSolver;
libs ("libfvMeshMovers.so" "libfvMotionSolvers.so");
motionSolver velocityComponentLaplacian;
component x;
diffusivity directional (1 200 0);
}
topoChanger
{
type meshToMesh;
libs ("libmeshToMeshTopoChanger.so");
times (0.0015 0.003);
timeDelta 1e-6;
}
which lists the mesh mapping times 0.0015s 0.003s and meshes for these times in
directories constant/meshToMesh_0.0015 and constant/meshToMesh_0.003 are
generated in the Allrun script before the pimpleFoam run:
runApplication -a blockMesh -dict blockMeshDict.2
rm -rf constant/meshToMesh_0.0015
mkdir constant/meshToMesh_0.0015
mv constant/polyMesh constant/meshToMesh_0.0015
runApplication -a blockMesh -dict blockMeshDict.3
rm -rf constant/meshToMesh_0.003
mkdir constant/meshToMesh_0.003
mv constant/polyMesh constant/meshToMesh_0.003
runApplication -a blockMesh -dict blockMeshDict.1
runApplication $application
Note: This functionality is experimental and has only undergone basic testing.
It is likely that it does not yet work with all functionObject, fvModels
etc. which will need updating to support this form of mesh topology change.