genericPatches is linked into mesh generation and manipulation utilities but not
solvers so that the solvers now check for the availability of the specified
patch types. Bugs in the tutorials exposed by this check have been corrected.
e.g. in extrudeToRegionMeshDict:
// Generate the region named film
region film;
// from the patch extrudeWall
patches (extrudeWall);
// generating mapped patches for the extruded region
adaptMesh yes;
// New options:
// Set the type of the mapped patch on the existing mesh to mappedWall ...
patchTypes (mappedWall);
// ... and name to wall
patchNames (wall);
// Set the type of the mapped patch on the region mesh to mappedFilmWall ...
regionPatchTypes (mappedFilmWall);
// ... and name to wall
regionPatchNames (wall);
// Set the type of the opposite patch on the region mesh to empty ...
regionOppositePatchTypes (empty);
// ... and name to empty
regionOppositePatchNames (empty);
All the above entries are optional and if not present the previous behaviour is
reproduced.
Replaces MeshObject, providing a formalised method for creating demand-driven
mesh objects, optionally supporting update functions called by the mesh
following mesh changes.
Class
Foam::DemandDrivenMeshObject
Description
Templated abstract base-class for demand-driven mesh objects used to
automate their allocation to the mesh database and the mesh-modifier
event-loop.
DemandDrivenMeshObject is templated on the type of mesh it is allocated
to, the type of the mesh object (TopologicalMeshObject, GeometricMeshObject,
MoveableMeshObject, DistributeableMeshObject, UpdateableMeshObject) and the
type of the actual object it is created for example:
\verbatim
class leastSquaresVectors
:
public DemandDrivenMeshObject
<
fvMesh,
MoveableMeshObject,
leastSquaresVectors
>
{
.
.
.
//- Delete the least square vectors when the mesh moves
virtual bool movePoints();
};
\endverbatim
MeshObject types:
- TopologicalMeshObject: mesh object to be deleted on topology change
- GeometricMeshObject: mesh object to be deleted on geometry change
- MoveableMeshObject: mesh object to be updated in movePoints
- UpdateableMeshObject: mesh object to be updated in topoChange or
movePoints
- PatchMeshObject: mesh object to be additionally updated patch changes
DemandDrivenMeshObject should always be constructed and accessed via the New
methods provided so that they are held and maintained by the objectRegistry.
To ensure this use constructors of the concrete derived types should be
private or protected and friendship with the DemandDrivenMeshObject
base-class declared so that the New functions can call the the constructors.
Additionally the mesh-object types (TopologicalMeshObject, GeometricMeshObject,
MoveableMeshObject, DistributeableMeshObject, UpdateableMeshObject) can now be
used as mix-in types for normally allocated objects providing the same interface
to mesh-change update functions, see the Fickian fluid
thermophysicalTransportModel or anisotropic solid thermophysicalTransportModel.
This new approach to adding mesh-update functions to classes will be applied to
other existing classes and future developments to simplify the support and
maintenance of run-time mesh changes, in particular mesh refinement/unrefinement
and mesh-to-mesh mapping.
The timeName() function simply returns the dimensionedScalar::name() which holds
the user-time name of the current time and now that timeName() is no longer
virtual the dimensionedScalar::name() can be called directly. The timeName()
function implementation is maintained for backward-compatibility.
A set of routines for cutting polyhedra have been added. These can cut
polyhedral cells based on the adjacent point values and an iso-value
which defines the surface. The method operates directly on the
polyhedral cells; it does not decompose them into tetrahedra at any
point. The routines can compute the cut topology as well as integrals of
properties above and below the cut surface.
An iso-surface algorithm has been added based on these polyhedral
cutting routines. It is significantly more robust than the previous
algorithm, and produces compact surfaces equivalent to the previous
algorithm's maximum filtering level. It is also approximately 3 times
faster than the previous algorithm, and 10 times faster when run
repeatedly on the same set of cells (this is because some addressing is
cached and reused).
This algorithm is used by the 'isoSurface', 'distanceSurface' and
'cutPlane' sampled surfaces.
The 'cutPlane' sampled surface is a renaming of 'cuttingPlane' to make
it consistent with the corresponding packaged function. The name
'cuttingPlane' has been retained for backwards compatibility and can
still be used to select a 'cutPlane' surface. The legacy 'plane' surface
has been removed.
The 'average' keyword has been removed from specification of these
sampled surfaces as cell-centred values are no longer used in the
generation of or interpolation to an iso-surface. The 'filtering'
keyword has also been removed as it relates to options within the
previous algorithm. Zone support has been reinstated into the
'isoSurface' sampled surface. Interpolation to all these sampled
surfaces has been corrected to exactly match the user-selected
interpolation scheme, and the interpolation procedure no longer
unnecessarily re-generates data that is already available.
If checkMesh is executed with the -allGeometry option, then surface
files containing the NCC coverage will now be written out. Coverage is
the ratio between coupled area magnitude and total area magnitude. This
is useful for locating parts of the boundary mesh that are in error.
Errors (such as folds and pinches) typically manifest as a coverage
value that deviates significantly from a value of one.
This is comparable to the writing of AMI patches's weight sums, which
also used to occur when the -allGeometry option was selected.
Function objects now write to the following path when applied to a
non-default region of a multi-region case:
postProcessing/<regionName>/<functionName>/<time>/
Previously the order of <regionName> and <functionName> was not
consistent between the various function objects.
Resolves bug report https://bugs.openfoam.org/view.php?id=3907
This allows for partial specialisation, so the different variants of the
global IO containers do not need the function to be overloaded for each
contained type. This also fixes an ommission in providing overloads of
these functions for some of the global IO containers.
Resolves bug report https://bugs.openfoam.org/view.php?id=3890
This reduces duplication and inconsistency between the List, Field, Map,
and PtrList variants. It also allows for future extension to other
container types such as DynamicList.
The mappedPatchBase has been separated into a type which maps from
another patch (still called mappedPatchBase) and one that maps from
internal cell values (mappedInternalPatchBase). This prevents the user
needing to specify settings for mapping procedures that are not being
used, and potentially don't even make sense given the context in which
they are being applied. It also removes a lot of fragile logic and error
states in the mapping engine and its derivatives regarding the mode of
operation. Mapping from any face in the boundary is no longer supported.
Most region-coupling mapping patches are generated automatically by
utilities like splitMeshRegions and extrudeToRegionMesh. Cases which
create region-coupling mapped patches in this way will likely require no
modification.
Explicitly user-specified mapping will need modifying, however. For
example, where an inlet boundary is mapped to a downstream position in
order to evolve a developed profile. Or if a multi-region simulation is
constructed manually, without using one of the region-generating
utilities.
The available mapped patch types are now as follows:
- mapped: Maps values from one patch to another. Typically used for
inlets and outlets; to map values from an outlet patch to an inlet
patch in order to evolve a developed inlet profile, or to permit
flow between regions. Example specification in blockMesh:
inlet
{
type mapped;
neighbourRegion region0; // Optional. Defaults to the same
// region as the patch.
neighbourPatch outlet;
faces ( ... );
}
Note that any transformation between the patches is now determined
automatically. Alternatively, it can be explicitly specified using
the same syntax as for cyclic patches. The "offset" and "distance"
keywords are no longer used.
- mappedWall: As mapped, but treated as a wall for the purposes of
modelling (wall distance). No transformation. Typically used for
thermally coupling different regions. Usually created automatically
by meshing utilities. Example:
fluid_to_solid
{
type mappedWall;
neighbourRegion solid;
neighbourPatch solid_to_fluid;
method intersection; // The patchToPatch method. See
// below.
faces ( ... );
}
- mappedExtrudedWall: As mapped wall, but with corrections to account
for the thickness of an extruded mesh. Used for region coupling
involving film and thermal baffle models. Almost always generated
automatically by extrudeToRegionMesh (so no example given).
- mappedInternal: Map values from internal cells to a patch. Typically
used for inlets; to map values from internal cells to the inlet in
order to evolve a developed inlet profile. Example:
inlet
{
type mappedInternal;
distance 0.05; // Normal distance from the patch
// from which to map cell values
//offset (0.05 0 0); // Offset from the patch from
// which to map cell values
faces ( ... );
}
Note that an "offsetMode" entry is no longer necessary. The mode
will be inferred from the presence of the distance or offset
entries. If both are provided, then offsetMode will also be required
to choose which setting applies.
The mapped, mappedWall and mappedExtrudedWall patches now permit
specification of a "method". This selects a patchToPatch object and
therefore determines how values are transferred or interpolated between
the patches. Valid options are:
- nearest: Copy the value from the nearest face in the neighbouring
patch.
- matching: As nearest, but with checking to make sure that the
mapping is one-to-one. This is appropriate for patches that are
identically meshed.
- inverseDistance: Inverse distance weighting from a small stencil of
nearby faces in the neighbouring patch.
- intersection: Weighting based on the overlapping areas with faces in
the neighbouring patch. Equivalent to the previous AMI-based mapping
mode.
If a method is not specfied, then the pre-existing approach will apply.
This should be equivalent to the "nearest" method (though in most such
cases, "matching" is probably more appropriate). This fallback may be
removed in the future once the patchToPatch methods have been proven
robust.
The important mapped boundary conditions are now as follows:
- mappedValue: Maps values from one patch to another, and optionally
modify the mapped values to recover a specified average. Example:
inlet
{
type mappedValue;
field U; // Optional. Defaults to the same
// as this field.
average (10 0 0); // The presence of this entry now
// enables setting of the average,
// so "setAverage" is not needed
value uniform 0.1;
}
- mappedInternalValue: Map values from cells to a patch, and
optionally specify the average as in mappedValue. Example:
inlet
{
type mappedValue;
field k; // Optional. Defaults to the same
// as this field.
interpolationScheme cell;
value uniform 0.1;
}
- mappedFlowRateVelocity: Maps the flow rate from one patch to
another, and use this to set a patch-normal velocity. Example:
inlet
{
type mappedFlowRate;
value uniform (0 0 0);
}
Of these, mappedValue and mappedInternalValue can override the
underlying mapped patch's settings by additionally specifying mapping
information (i.e., the neighbourPatch, offset, etc... settings usually
supplied for the patch). This also means these boundary condtions can be
applied to non-mapped patches. This functionality used to be provided
with a separate "mappedField" boundary condition, which has been removed
as it is no longer necessary.
Other mapped boundary conditions are either extremely niche (e.g.,
mappedVelocityFlux), are always automatically generated (e.g.,
mappedValueAndPatchInternalValue), or their usage has not changed (e.g.,
compressible::turbulentTemperatureCoupledBaffleMixed and
compressible::turbulentTemperatureRadCoupledMixed). Use foamInfo to
obtain further details about these conditions.
This greatly simplifies most setups in which it is a patch (or patches)
of the original mesh which are extruded. It prevents the need for a
topoSet configuration to convert the patch into a zone or set.
Poly patches should not hold non-uniform physical data that needs
mapping on mesh changes (decomposition, reconstruction, topology change,
etc ...). They should only hold uniform data that can be user-specified,
or non-uniform data that can be constructed on the fly from the poly
mesh.
With the recent changes to mappedPatchBase and extrudeToRegionMesh, this
has now been consistenly enforced, and a number of incomplete
implementations of poly patch mapping have therefore been removed.
An extruded region is now contiguous even when specified with multiple
face zones. Edges that border faces in different zones now extrude into
internal faces, rather than a pair of boundary faces. Different zones
now result only in different mapped patches in the extruded and primary
meshes. This means a mesh can be created for a single contiguous
extruded region spanning multiple patches. This might be necessary if,
for example, a film region is needed across multiple walls with
differing thermal boundary conditions.
Disconnected extruded regions can still be constructed by running the
extrudeToRegionMesh utility muiliple times.
The mapped patches created to couple the extruded regions now have
symmetric names similar to those created by splitMeshRegions. For
example, if the mapped patch in the primary region is called
"region0_to_extrudedRegion_f0", then the corresponding patch in the
extruded region is called "extrudedRegion_to_region0_f0" (f0, in this
example is the face zone from which the region was extruded).
Offsetting of the top patch is now handled automatically by a new
mappedExtrudedWallPolyPatch. This refers to the bottom patch and
automatically calculates the sampling offsets by doing a wave across the
extruded mesh layers. This prevents the need to store the offsets in the
patch itself, and makes it possible for the patch to undergo mesh
changes without adding additional functions to the polyPatch (mapping
constructors, autoMap and rmap methods, etc ...).
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.
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
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.
When this option is enabled, non-conformal boundary conditions will be
added to all the fields. It enables exactly the same behaviour as the
"fields" entry that is available when using this utility with a settings
dictionary (system/createNonConformalCouplesDict).
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
}
}
}
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.
This utility can now add boundary conditions to fields which correspond
to the non-conformal patches that it adds to the mesh. This action is
enabled by means of a 'fields true;' flag which can be added to the
'system/createNonConformalCouplesDict'. No additional control is needed,
because all patches created by this utility are of constraint type.