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.
This major development provides coupling of patches which are
non-conformal, i.e. where the faces of one patch do not match the faces
of the other. The coupling is fully conservative and second order
accurate in space, unlike the Arbitrary Mesh Interface (AMI) and
associated ACMI and Repeat AMI methods which NCC replaces.
Description:
A non-conformal couple is a connection between a pair of boundary
patches formed by projecting one patch onto the other in a way that
fills the space between them. The intersection between the projected
surface and patch forms new faces that are incorporated into the finite
volume mesh. These new faces are created identically on both sides of
the couple, and therefore become equivalent to internal faces within the
mesh. The affected cells remain closed, meaning that the area vectors
sum to zero for all the faces of each cell. Consequently, the main
benefits of the finite volume method, i.e. conservation and accuracy,
are not undermined by the coupling.
A couple connects parts of mesh that are otherwise disconnected and can
be used in the following ways:
+ to simulate rotating geometries, e.g. a propeller or stirrer, in which
a part of the mesh rotates with the geometry and connects to a
surrounding mesh which is not moving;
+ to connect meshes that are generated separately, which do not conform
at their boundaries;
+ to connect patches which only partially overlap, in which the
non-overlapped section forms another boundary, e.g. a wall;
+ to simulate a case with a geometry which is periodically repeating by
creating multiple couples with different transformations between
patches.
The capability for simulating partial overlaps replaces the ACMI
functionality, currently provided by the 'cyclicACMI' patch type, and
which is unreliable unless the couple is perfectly flat. The capability
for simulating periodically repeating geometry replaces the Repeat AMI
functionality currently provided by the 'cyclicRepeatAMI' patch type.
Usage:
The process of meshing for NCC is very similar to existing processes for
meshing for AMI. Typically, a mesh is generated with an identifiable set
of internal faces which coincide with the surface through which the mesh
will be coupled. These faces are then duplicated by running the
'createBaffles' utility to create two boundary patches. The points are
then split using 'splitBaffles' in order to permit independent motion of
the patches.
In AMI, these patches are assigned the 'cyclicAMI' patch type, which
couples them using AMI interpolation methods.
With NCC, the patches remain non-coupled, e.g. a 'wall' type. Coupling
is instead achieved by running the new 'createNonConformalCouples'
utility, which creates additional coupled patches of type
'nonConformalCyclic'. These appear in the 'constant/polyMesh/boundary'
file with zero faces; they are populated with faces in the finite volume
mesh during the connection process in NCC.
For a single couple, such as that which separates the rotating and
stationary sections of a mesh, the utility can be called using the
non-coupled patch names as arguments, e.g.
createNonConformalCouples -overwrite rotatingZoneInner rotatingZoneOuter
where 'rotatingZoneInner' and 'rotatingZoneOuter' are the names of the
patches.
For multiple couples, and/or couples with transformations,
'createNonConformalCouples' should be run without arguments. Settings
will then be read from a configuration file named
'system/createNonConformalCouplesDict'. See
'$FOAM_ETC/caseDicts/annotated/createNonConformalCouplesDict' for
examples.
Boundary conditions must be specified for the non-coupled patches. For a
couple where the patches fully overlap, boundary conditions
corresponding to a slip wall are typically applied to fields, i.e
'movingWallSlipVelocity' (or 'slip' if the mesh is stationary) for
velocity U, 'zeroGradient' or 'fixedFluxPressure' for pressure p, and
'zeroGradient' for other fields. For a couple with
partially-overlapping patches, boundary conditions are applied which
physically represent the non-overlapped region, e.g. a no-slip wall.
Boundary conditions also need to be specified for the
'nonConformalCyclic' patches created by 'createNonConformalCouples'. It
is generally recommended that this is done by including the
'$FOAM_ETC/caseDicts/setConstraintTypes' file in the 'boundaryField'
section of each of the field files, e.g.
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
...
}
...
}
For moving mesh cases, it may be necessary to correct the mesh fluxes
that are changed as a result of the connection procedure. If the
connected patches do not conform perfectly to the mesh motion, then
failure to correct the fluxes can result in noise in the pressure
solution.
Correction for the mesh fluxes is enabled by the 'correctMeshPhi' switch
in the 'PIMPLE' (or equivalent) section of 'system/fvSolution'. When it
is enabled, solver settings are required for 'MeshPhi'. The solution
just needs to distribute the error enough to dissipate the noise. A
smooth solver with a loose tolerance is typically sufficient, e.g. the
settings in 'system/fvSolution' shown below:
solvers
{
MeshPhi
{
solver smoothSolver;
smoother symGaussSeidel;
tolerance 1e-2;
relTol 0;
}
...
}
PIMPLE
{
correctMeshPhi yes;
...
}
The solution of 'MeshPhi' is an inexpensive computation since it is
applied only to a small subset of the mesh adjacent to the
couple. Conservation is maintained whether or not the mesh flux
correction is enabled, and regardless of the solution tolerance for
'MeshPhi'.
Advantages of NCC:
+ NCC maintains conservation which is required for many numerical
schemes and algorithms to operate effectively, in particular those
designed to maintain boundedness of a solution.
+ Closed-volume systems no longer suffer from accumulation or loss of
mass, poor convergence of the pressure equation, and/or concentration
of error in the reference cell.
+ Partially overlapped simulations are now possible on surfaces that are
not perfectly flat. The projection fills space so no overlaps or
spaces are generated inside contiguously overlapping sections, even if
those sections have sharp angles.
+ The finite volume faces created by NCC have geometrically accurate
centres. This makes the method second order accurate in space.
+ The polyhedral mesh no longer requires duplicate boundary faces to be
generated in order to run a partially overlapped simulation.
+ Lagrangian elements can now transfer across non-conformal couplings in
parallel.
+ Once the intersection has been computed and applied to the finite
volume mesh, it can use standard cyclic or processor cyclic finite
volume boundary conditions, with no need for additional patch types or
matrix interfaces.
+ Parallel communication is done using the standard
processor-patch-field system. This is more efficient than alternative
systems since it has been carefully optimised for use within the
linear solvers.
+ Coupled patches are disconnected prior to mesh motion and topology
change and reconnected afterwards. This simplifies the boundary
condition specification for mesh motion fields.
Resolved Bug Reports:
+ https://bugs.openfoam.org/view.php?id=663
+ https://bugs.openfoam.org/view.php?id=883
+ https://bugs.openfoam.org/view.php?id=887
+ https://bugs.openfoam.org/view.php?id=1337
+ https://bugs.openfoam.org/view.php?id=1388
+ https://bugs.openfoam.org/view.php?id=1422
+ https://bugs.openfoam.org/view.php?id=1829
+ https://bugs.openfoam.org/view.php?id=1841
+ https://bugs.openfoam.org/view.php?id=2274
+ https://bugs.openfoam.org/view.php?id=2561
+ https://bugs.openfoam.org/view.php?id=3817
Deprecation:
NCC replaces the functionality provided by AMI, ACMI and Repeat AMI.
ACMI and Repeat AMI are insufficiently reliable to warrant further
maintenance so are removed in an accompanying commit to OpenFOAM-dev.
AMI is more widely used so will be retained alongside NCC for the next
version release of OpenFOAM and then subsequently removed from
OpenFOAM-dev.
Transformation can now be restricted to a specific point set by means of
a new -pointSet option. For example, to move the rotating part of a
geometry through 45 degrees around the Z axis, the following command
could be used:
transformPoints -pointSet rotating "Rz=45"
This assumes a point set called "rotating" has been defined during
meshing or by calling topoSet.
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.
so that the input is now dictionary rather than list of dictionaries which
provides support for dictionary substitutions within the motionSolver
sub-dictionaries and also simplifies lookup of specific motionSolvers within the
list. For example the dynamicMeshDict for the floatingObject case with a second
floating object would be:
mover
{
type motionSolver;
libs ("libfvMeshMovers.so" "librigidBodyMeshMotion.so");
motionSolver motionSolverList;
solvers
{
floatingObject
{
motionSolver rigidBodyMotion;
report on;
solver
{
type Newmark;
}
accelerationRelaxation 0.7;
bodies
{
floatingObject
{
type cuboid;
parent root;
// Cuboid dimensions
Lx 0.3;
Ly 0.2;
Lz 0.5;
// Density of the cuboid
rho 500;
// Cuboid mass
mass #calc "$rho*$Lx*$Ly*$Lz";
L ($Lx $Ly $Lz);
centreOfMass (0 0 0.25);
transform (1 0 0 0 1 0 0 0 1) (0.5 0.45 0.1);
joint
{
type composite;
joints
(
{
type Py;
}
{
type Ry;
}
);
}
patches (floatingObject);
innerDistance 0.05;
outerDistance 0.35;
}
}
}
anotherFloatingObject
{
.
.
.
}
}
}
This new mapping structure is designed to support run-time mesh-to-mesh mapping
to allow arbitrary changes to the mesh structure, for example during extreme
motion requiring significant topology change including region disconnection etc.
The polyTopoChangeMap is the map specifically relating to polyMesh topological
changes generated by polyTopoChange and used to update and map mesh related
types and fields following the topo-change.
fvMesh is no longer derived from fvSchemes and fvSolution, these are now
demand-driven and accessed by the member functions schemes() and solution()
respectively. This means that the system/fvSchemes and system/fvSolution files
are no longer required during fvMesh constructions simplifying the mesh
generation and manipulation phase; theses files are read on the first call of
their access functions.
The fvSchemes member function names have also been simplified taking advantage
of the context in which they are called, for example
mesh.ddtScheme(fieldName) -> mesh.schemes().ddt(fieldName)
The template parameters were only ever polyBoundaryMesh and
processorPolyPatch. Un-templating makes mainteance and bug-fixing
quicker as it means minor modifications no longer cause a full rebuild
of OpenFOAM.
boundaryProcAddressing has been removed. This has not been needed for a
long time. decomposePar has been optimised for mininum IO, rather than
minimum memory usage. decomposePar has also been corrected so that it
can decompose sequences of time-varying meshes.
also adding optional "libs" entry to renumberMeshDict so that the
libzoltanRenumber.so can be loaded at run-time rather than having to recompile
and relink the renumberMesh utility to support it.
When snappyHexMesh is run in parallel it re-balances the mesh during refinement
and layer addition by redistribution which requires a decomposition method
that operates in parallel, e.g. hierachical or ptscotch. decomposePar uses a
decomposition method which operates in serial e.g. hierachical but NOT
ptscotch. In order to run decomposePar followed by snappyHexMesh in parallel it
has been necessary to change the method specified in decomposeParDict but now
this is avoided by separately specifying the decomposition and distribution
methods, e.g. in the incompressible/simpleFoam/motorBike case:
numberOfSubdomains 6;
decomposer hierarchical;
distributor ptscotch;
hierarchicalCoeffs
{
n (3 2 1);
order xyz;
}
The distributor entry is also used for run-time mesh redistribution, e.g. in the
multiphase/interFoam/RAS/floatingObject case re-distribution for load-balancing
is enabled in constant/dynamicMeshDict:
distributor
{
type distributor;
libs ("libfvMeshDistributors.so");
redistributionInterval 10;
}
which uses the distributor specified in system/decomposeParDict:
distributor hierarchical;
This rationalisation provides the structure for development of mesh
redistribution and load-balancing.
Sampled sets and streamlines now write all their fields to the same
file. This prevents excessive duplication of the geometry and makes
post-processing tasks more convenient.
"axis" entries are now optional in sampled sets and streamlines. When
omitted, a default entry will be used, which is chosen appropriately for
the coordinate set and the write format. Some combinations are not
supported. For example, a scalar ("x", "y", "z" or "distance") axis
cannot be used to write in the vtk format, as vtk requires 3D locations
with which to associate data. Similarly, a point ("xyz") axis cannot be
used with the gnuplot format, as gnuplot needs a single scalar to
associate with the x-axis.
Streamlines can now write out fields of any type, not just scalars and
vectors, and there is no longer a strict requirement for velocity to be
one of the fields.
Streamlines now output to postProcessing/<functionName>/time/<file> in
the same way as other functions. The additional "sets" subdirectory has
been removed.
The raw set writer now aligns columns correctly.
The handling of segments in coordSet and sampledSet has been
fixed/completed. Segments mean that a coordinate set can represent a
number of contiguous lines, disconnected points, or some combination
thereof. This works in parallel; segments remain contiguous across
processor boundaries. Set writers now only need one write method, as the
previous "writeTracks" functionality is now handled by streamlines
providing the writer with the appropriate segment structure.
Coordinate sets and set writers now have a convenient programmatic
interface. To write a graph of A and B against some coordinate X, in
gnuplot format, we can call the following:
setWriter::New("gnuplot")->write
(
directoryName,
graphName,
coordSet(true, "X", X), // <-- "true" indicates a contiguous
"A", // line, "false" would mean
A, // disconnected points
"B",
B
);
This write function is variadic. It supports any number of
field-name-field pairs, and they can be of any primitive type.
Support for Jplot and Xmgrace formats has been removed. Raw, CSV,
Gnuplot, VTK and Ensight formats are all still available.
The old "graph" functionality has been removed from the code, with the
exception of the randomProcesses library and associated applications
(noise, DNSFoam and boxTurb). The intention is that these should also
eventually be converted to use the setWriters. For now, so that it is
clear that the "graph" functionality is not to be used elsewhere, it has
been moved into a subdirectory of the randomProcesses library.
This prevents excessive duplication of surface geometry and makes
post-processing tasks in paraview more convenient.
The Nastran and Star-CD surface formats were found not to work, so
support for these output types has been removed. Raw, VTK, Foam and
Ensight formats are all still available.
with the run-time selectable engine userTime embedded in Time.
All parts of the original engineTime relating to the engine geometry have been
moved to engineMesh. This is part of the process of integrating engine
simulations within the standard moving-mesh solvers.
replacing the virtual functions overridden in engineTime.
Now the userTime conversion function in Time is specified in system/controlDict
such that the solver as well as all pre- and post-processing tools also operate
correctly with the chosen user-time.
For example the user-time and rpm in the tutorials/combustion/XiEngineFoam/kivaTest case are
now specified in system/controlDict:
userTime
{
type engine;
rpm 1500;
}
The default specification is real-time:
userTime
{
type real;
}
but this entry can be omitted as the real-time class is instantiated
automatically if the userTime entry is not present in system/controlDict.
Mesh motion and topology change are now combinable run-time selectable options
within fvMesh, replacing the restrictive dynamicFvMesh which supported only
motion OR topology change.
All solvers which instantiated a dynamicFvMesh now instantiate an fvMesh which
reads the optional constant/dynamicFvMeshDict to construct an fvMeshMover and/or
an fvMeshTopoChanger. These two are specified within the optional mover and
topoChanger sub-dictionaries of dynamicFvMeshDict.
When the fvMesh is updated the fvMeshTopoChanger is first executed which can
change the mesh topology in anyway, adding or removing points as required, for
example for automatic mesh refinement/unrefinement, and all registered fields
are mapped onto the updated mesh. The fvMeshMover is then executed which moved
the points only and calculates the cell volume change and corresponding
mesh-fluxes for conservative moving mesh transport. If multiple topological
changes or movements are required these would be combined into special
fvMeshMovers and fvMeshTopoChangers which handle the processing of a list of
changes, e.g. solidBodyMotionFunctions:multiMotion.
The tutorials/multiphase/interFoam/laminar/sloshingTank3D3DoF case has been
updated to demonstrate this new functionality by combining solid-body motion
with mesh refinement/unrefinement:
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Version: dev
\\/ M anipulation |
\*---------------------------------------------------------------------------*/
FoamFile
{
format ascii;
class dictionary;
location "constant";
object dynamicMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
mover
{
type motionSolver;
libs ("libfvMeshMovers.so" "libfvMotionSolvers.so");
motionSolver solidBody;
solidBodyMotionFunction SDA;
CofG (0 0 0);
lamda 50;
rollAmax 0.2;
rollAmin 0.1;
heaveA 4;
swayA 2.4;
Q 2;
Tp 14;
Tpn 12;
dTi 0.06;
dTp -0.001;
}
topoChanger
{
type refiner;
libs ("libfvMeshTopoChangers.so");
// How often to refine
refineInterval 1;
// Field to be refinement on
field alpha.water;
// Refine field in between lower..upper
lowerRefineLevel 0.001;
upperRefineLevel 0.999;
// Have slower than 2:1 refinement
nBufferLayers 1;
// Refine cells only up to maxRefinement levels
maxRefinement 1;
// Stop refinement if maxCells reached
maxCells 200000;
// Flux field and corresponding velocity field. Fluxes on changed
// faces get recalculated by interpolating the velocity. Use 'none'
// on surfaceScalarFields that do not need to be reinterpolated.
correctFluxes
(
(phi none)
(nHatf none)
(rhoPhi none)
(alphaPhi.water none)
(meshPhi none)
(meshPhi_0 none)
(ghf none)
);
// Write the refinement level as a volScalarField
dumpLevel true;
}
// ************************************************************************* //
Note that currently this is the only working combination of mesh-motion with
topology change within the new framework and further development is required to
update the set of topology changers so that topology changes with mapping are
separated from the mesh-motion so that they can be combined with any of the
other movements or topology changes in any manner.
All of the solvers and tutorials have been updated to use the new form of
dynamicMeshDict but backward-compatibility was not practical due to the complete
reorganisation of the mesh change structure.
used to check the existence of and open an object file, read and check the
header without constructing the object.
'typeIOobject' operates in an equivalent and consistent manner to 'regIOobject'
but the type information is provided by the template argument rather than via
virtual functions for which the derived object would need to be constructed,
which is the case for 'regIOobject'.
'typeIOobject' replaces the previous separate functions 'typeHeaderOk' and
'typeFilePath' with a single consistent interface.
now all path functions in 'IOobject' are either templated on the type or require a
'globalFile' argument to specify if the type is case global e.g. 'IOdictionary' or
decomposed in parallel, e.g. almost everything else.
The 'global()' and 'globalFile()' virtual functions are now in 'regIOobject'
abstract base-class and overridden as required by derived classes. The path
functions using 'global()' and 'globalFile()' to differentiate between global
and processor local objects are now also in 'regIOobject' rather than 'IOobject'
to ensure the path returned is absolutely consistent with the type.
Unfortunately there is still potential for unexpected IO behaviour inconsistent
with the global/local nature of the type due to the 'fileOperation' classes
searching the processor directory for case global objects before searching the
case directory. This approach appears to be a work-around for incomplete
integration with and rationalisation of 'IOobject' but with the changes above it
is no longer necessary. Unfortunately this "up" searching is baked-in at a low
level and mixed-up with various complex ways to pick the processor directory
name out of the object path and will take some unravelling but this work will
undertaken as time allows.
and only needed if there is a name clash between entries in the source
specification and the set specification, e.g. "name":
{
name rotorCells;
type cellSet;
action new;
source zoneToCell;
sourceInfo
{
name cylinder;
}
}
topoSet is a more flexible and extensible replacement for setSet using standard
OpenFOAM dictionary input format rather than the limited command-line input
format developed specifically for setSet. This replacement allows for the
removal of a significant amount of code simplifying maintenance and the addition
of more topoSet sources.
The -dict option is now handled correctly and consistently across all
applications with -dict options. The logic associated with doing so has
been centralised.
If a relative path is given to the -dict option, then it is assumed to
be relative to the case directory. If an absolute path is given, then it
is used without reference to the case directory. In both cases, if the
path is found to be a directory, then the standard dictionary name is
appended to the path.
Resolves bug report http://bugs.openfoam.org/view.php?id=3692
splitBaffles identifies baffle faces; i.e., faces on the mesh boundary
which share the exact same set of points as another boundary face. It
then splits the points to convert these faces into completely separate
boundary patches. This functionality was previously provided by calling
mergeOrSplitBaffles with the "-split" option.
mergeBaffles also identifes the duplicate baffle faces, but then merges
them, converting them into a single set of internal faces. This
functionality was previously provided by calling mergeOrSplitBaffles
without the "-split" option.
The writer class has been renamed setWriter in order to clarify its
usage. The coordSet and setWriter classes have been moved into the
sampling library, as this fits their usage.
The new write functions are currently being utilised by setSet and the
vtkSurfaceWriter, but it should eventually be possible for more examples
of VTK poly data writing to be converted to use these functions.
the previous naming tan1, tan2, normal was non-intuitive and very confusing.
It was not practical to maintain backward compatibility but all tutorials and
example refineMeshDict files have been updated to provide examples of the
change.
This makes usage of transformPoints the same as for
surfaceTransformPoints. Transformations are supplied as a string and are
applied in sequence.
Usage
transformPoints "\<transformations\>" [OPTION]
Supported transformations:
- "translate=<translation vector>"
Translational transformation by given vector
- "rotate=(<n1 vector> <n2 vector>)"
Rotational transformation from unit vector n1 to n2
- "Rx=<angle [deg] about x-axis>"
Rotational transformation by given angle about x-axis
- "Ry=<angle [deg] about y-axis>"
Rotational transformation by given angle about y-axis
- "Rz=<angle [deg] about z-axis>"
Rotational transformation by given angle about z-axis
- "Ra=<axis vector> <angle [deg] about axis>"
Rotational transformation by given angle about given axis
- "scale=<x-y-z scaling vector>"
Anisotropic scaling by the given vector in the x, y, z
coordinate directions
Example usage:
transformPoints \
"translate=(-0.05 -0.05 0), \
Rz=45, \
translate=(0.05 0.05 0)"
Originally the only supported geometry specification were triangulated surfaces,
hence the name of the directory: constant/triSurface, however now that other
surface specifications are supported and provided it is much more logical that
the directory is named accordingly: constant/geometry. All tutorial and
template cases have been updated.
Note that backward compatibility is provided such that if the constant/geometry
directory does not exist but constant/triSurface does then the geometry files
are read from there.
so that it can be included directly into the wmake Makefile to allow full
support of gmake syntax, variables, functions etc.
The Make/files file handled in the same manner as the Make/options file if it
contains the SOURCE entry otherwise it is first processed by cpp for backward
compatibility.
This improves paraview's handling of VTK files which only contain
points. It means the points are visible without glyph-ing, and provides
the necessary input for some filters to operate correctly.
For many information and diagnostic messages the absolute path of the object is
not required and the local path relative to the current case is sufficient; the
new localObjectPath() member function of IOobject provides a convenient way of
printing this.