Commit 1584f28e authored by mattijs's avatar mattijs
Browse files

ENH: blockMesh: generate duplicate boundary faces. Fixes #1516

parent bb13d27d
......@@ -285,6 +285,7 @@ void Foam::polyMesh::setTopology
}
// Do boundary faces
const label nInternalFaces = nFaces;
patchSizes.setSize(boundaryFaces.size(), -1);
patchStarts.setSize(boundaryFaces.size(), -1);
......@@ -305,6 +306,9 @@ void Foam::polyMesh::setTopology
// Grab the start label
label curPatchStart = nFaces;
// Suppress multiple warnings per patch
bool patchWarned = false;
forAll(patchFaces, facei)
{
const face& curFace = patchFaces[facei];
......@@ -320,25 +324,75 @@ void Foam::polyMesh::setTopology
{
if (face::sameVertices(facesOfCellInside[cellFacei], curFace))
{
if (cells[cellInside][cellFacei] >= 0)
found = true;
const label meshFacei = cells[cellInside][cellFacei];
if (meshFacei >= 0)
{
FatalErrorInFunction
<< "Trying to specify a boundary face " << curFace
<< " on the face on cell " << cellInside
<< " which is either an internal face or already "
<< "belongs to some other patch. This is face "
<< facei << " of patch "
<< patchi << " named "
<< boundaryPatchNames[patchi] << "."
<< abort(FatalError);
}
// Already have mesh face for this side of the
// cellshape. This can happen for duplicate faces.
// It might be
// an error or explicitly desired (e.g. duplicate
// baffles or acmi). We could have a special 7-faced
// hex shape instead so we can have additional patches
// but that would be unworkable.
// So now either
// - exit with error
// - or warn and append face to addressing
// Note that duplicate baffles
// - cannot be on an internal faces
// - cannot be on the same patch (for now?)
if
(
meshFacei < nInternalFaces
|| meshFacei >= curPatchStart
)
{
FatalErrorInFunction
<< "Trying to specify a boundary face "
<< curFace
<< " on the face on cell " << cellInside
<< " which is either an internal face"
<< " or already belongs to the same patch."
<< " This is face " << facei << " of patch "
<< patchi << " named "
<< boundaryPatchNames[patchi] << "."
<< exit(FatalError);
}
found = true;
// Set the patch face to corresponding cell-face
faces_[nFaces] = facesOfCellInside[cellFacei];
if (!patchWarned)
{
WarningInFunction
<< "Trying to specify a boundary face "
<< curFace
<< " on the face on cell " << cellInside
<< " which is either an internal face"
<< " or already belongs to some other patch."
<< " This is face " << facei << " of patch "
<< patchi << " named "
<< boundaryPatchNames[patchi] << "."
//<< abort(FatalError);
<< endl;
patchWarned = true;
}
faces_.setSize(faces_.size()+1);
// Set the patch face to corresponding cell-face
faces_[nFaces] = facesOfCellInside[cellFacei];
cells[cellInside].append(nFaces);
}
else
{
// Set the patch face to corresponding cell-face
faces_[nFaces] = facesOfCellInside[cellFacei];
cells[cellInside][cellFacei] = nFaces;
cells[cellInside][cellFacei] = nFaces;
}
break;
}
......@@ -384,8 +438,6 @@ void Foam::polyMesh::setTopology
// Reset the size of the face list
faces_.setSize(nFaces);
return ;
}
......
......@@ -21,6 +21,8 @@ internalField uniform (0 0 0);
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
type fixedValue;
......@@ -37,28 +39,14 @@ boundaryField
type movingWallVelocity;
value uniform (0 0 0);
}
defaultFaces
{
type empty;
}
ACMI1_blockage
{
type noSlip;
}
ACMI1_couple
{
type cyclicACMI;
value uniform (0 0 0);
}
ACMI2_blockage
{
type noSlip;
}
ACMI2_couple
{
type cyclicACMI;
value uniform (0 0 0);
}
}
......
......@@ -21,6 +21,8 @@ internalField uniform 1.8e-3;
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
type fixedValue;
......@@ -37,30 +39,16 @@ boundaryField
type epsilonWallFunction;
value $internalField;
}
defaultFaces
{
type empty;
}
ACMI1_blockage
{
type epsilonWallFunction;
value $internalField;
}
ACMI1_couple
{
type cyclicACMI;
value $internalField;
}
ACMI2_blockage
{
type epsilonWallFunction;
value $internalField;
}
ACMI2_couple
{
type cyclicACMI;
value $internalField;
}
}
......
......@@ -21,6 +21,8 @@ internalField uniform 3.75e-3;
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
type fixedValue;
......@@ -37,30 +39,16 @@ boundaryField
type kqRWallFunction;
value $internalField;
}
defaultFaces
{
type empty;
}
ACMI1_blockage
{
type kqRWallFunction;
value $internalField;
}
ACMI1_couple
{
type cyclicACMI;
value $internalField;
}
ACMI2_blockage
{
type kqRWallFunction;
value $internalField;
}
ACMI2_couple
{
type cyclicACMI;
value $internalField;
}
}
......
......@@ -21,6 +21,8 @@ internalField uniform 0;
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
type fixedValue;
......@@ -37,30 +39,16 @@ boundaryField
type nutkWallFunction;
value $internalField;
}
defaultFaces
{
type empty;
}
ACMI1_blockage
{
type nutkWallFunction;
value $internalField;
}
ACMI1_couple
{
type cyclicACMI;
value $internalField;
}
ACMI2_blockage
{
type nutkWallFunction;
value $internalField;
}
ACMI2_couple
{
type cyclicACMI;
value $internalField;
}
}
......
......@@ -21,6 +21,8 @@ internalField uniform 0;
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
type zeroGradient;
......@@ -42,28 +44,14 @@ boundaryField
{
type zeroGradient;
}
defaultFaces
{
type empty;
}
ACMI1_blockage
{
type zeroGradient;
}
ACMI1_couple
{
type cyclicACMI;
value uniform 0;
}
ACMI2_blockage
{
type zeroGradient;
}
ACMI2_couple
{
type cyclicACMI;
value uniform 0;
}
}
......
#!/bin/sh
cd "${0%/*}" || exit # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions # Tutorial clean functions
#------------------------------------------------------------------------------
cleanCase0
#------------------------------------------------------------------------------
#!/bin/sh
cd "${0%/*}" || exit # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions
#------------------------------------------------------------------------------
./Allrun.pre
runApplication $(getApplication)
#------------------------------------------------------------------------------
......@@ -3,7 +3,7 @@ cd "${0%/*}" || exit # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions
#------------------------------------------------------------------------------
./Allrun.pre
runApplication blockMesh
runApplication decomposePar
runParallel $(getApplication)
......
#!/bin/sh
cd "${0%/*}" || exit # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions
#------------------------------------------------------------------------------
runApplication blockMesh
runApplication topoSet -constant
# Split the mesh to generate the ACMI coupled patches
runApplication createBaffles -overwrite
restore0Dir
#------------------------------------------------------------------------------
......@@ -52,7 +52,17 @@ In the above, the ACMI1_blockage and ACMI1_couple patches occupy the same space,
with duplicate points, edges and faces. The ACMI2_blockage and ACMI2_couple
patches are created similarly.
The duplicate patches are initially created using the createBaffles utility.
The duplicate patches are either created within blockMesh or using the
createBaffles utility. Using the blockMesh path will result in a warning
message of the form
'Trying to specify a boundary face '
'already belongs to some other patch'
since there are now in total 7 faces defined for the hex shape and blockMesh
does not yet know whether the definition is incorrect.
Using the createBaffles utility is slightly more work.
Firstly, the original (non-duplicated) patch faces are collected into zones
using the topoSet utility.
......@@ -109,8 +119,8 @@ the same as when operating in serial mode.
checkMesh
---------
checkMesh will see the 'duplicate' boundary faces but does not know about
the area factors so will complain:
Older versions of checkMesh would see the 'duplicate' boundary faces before
the area factors were know so would complain:
***Boundary openness (-0.0103092 2.3845e-17 3.80774e-17) possible hole in boundary description.
***Open cells found, max cell openness: 0.333333, number of open cells 136
......@@ -118,6 +128,25 @@ the area factors so will complain:
As long as these non-closed cells are on the ACMI they can be ignored.
In current checkMesh the area factors are updated before the check:
AMI: Creating addressing and weights between 40 source faces and 96 target faces
AMI: Patch source sum(weights) min:1 max:1 average:1
AMI: Patch target sum(weights) min:0 max:1 average:0.4
ACMI: Patch source uncovered/blended/covered = 0, 0, 40
ACMI: Patch target uncovered/blended/covered = 56, 2, 38
pimpleFoam
----------
In the 'createBaffles' method the ACMI patches would be created after
the 'empty' patch. In the 'blockMesh' method however the 'empty' patch
will be last. This results in a slight difference in face ordering which
is enough to give a slightly different truncation error in the geometry
calculation and hence in the results. For all practical purposes however the
results are the same. For cases which do not have 'empty' patches (i.e. 2D)
this limitation does not apply.
paraFoam
--------
......
......@@ -41,7 +41,7 @@ blocks
(
// hex (0 1 2 3 4 5 6 7) (20 20 1) simpleGrading (1 1 1)
// hex (8 9 10 11 12 13 14 15) (40 48 1) simpleGrading (1 1 1)
hex (0 1 2 3 4 5 6 7) (80 40 1) simpleGrading (1 1 1)
hex (0 1 2 3 4 5 6 7) inletChannel (80 40 1) simpleGrading (1 1 1)
hex (8 9 10 11 12 13 14 15) (80 96 1) simpleGrading (1 1 1)
);
......@@ -78,17 +78,37 @@ boundary
(9 13 12 8)
);
}
couple1
ACMI1_couple
{
type patch;
type cyclicACMI;
neighbourPatch ACMI2_couple;
nonOverlapPatch ACMI1_blockage;
faces
(
(2 6 5 1)
);
}
couple2
ACMI1_blockage
{
type patch;
type wall;
faces
(
(2 6 5 1)
);
}
ACMI2_couple
{
type cyclicACMI;
neighbourPatch ACMI1_couple;
nonOverlapPatch ACMI2_blockage;
faces
(
(8 12 15 11)
);
}
ACMI2_blockage
{
type wall;
faces
(
(8 12 15 11)
......@@ -96,8 +116,5 @@ boundary
}
);
mergePatchPairs
(
);
// ************************************************************************* //
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment