Multiple bug fixes: wet-on-cut faces must be wet; iteration in cut; consistent cut on processor boundary; adjust cut for 2-D geometries in case STL is not normal; report zero area IBM face

This commit is contained in:
Hrvoje Jasak 2019-04-05 15:31:52 +01:00
parent 39501b9254
commit 9bdc8ce728

View file

@ -270,21 +270,22 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
// the tri surface. The cause of this can either be a stl that is not // the tri surface. The cause of this can either be a stl that is not
// perfect or ther was an error in the inside/outside tri-search for other // perfect or ther was an error in the inside/outside tri-search for other
// reasons. Look at the neigbours that are not CUT and assign their status. // reasons. Look at the neigbours that are not CUT and assign their status.
const cellList& meshCells = mesh.cells(); const cellList& cells = mesh.cells();
forAll (intersectedCell, cellI) forAll (intersectedCell, cellI)
{ {
if (intersectedCell[cellI] == immersedPoly::UNKNOWN) if (intersectedCell[cellI] == immersedPoly::UNKNOWN)
{ {
// Check the neigbours // Check the neigbours
const cell& curCell = meshCells[cellI]; const cell& curCell = cells[cellI];
Switch foundWetNei = false; Switch foundWetNei = false;
Switch foundDryNei = false; Switch foundDryNei = false;
forAll (curCell, faceI) forAll (curCell, faceI)
{ {
// Only do the check for internal faces. If the face is boundary // Only do the check for internal faces. If the face is boundary
// face then there is nothing to do. NOTE: parallelisation // face then there is nothing to do.
// needed? // NOTE: parallelisation needed?
if (mesh.isInternalFace(curCell[faceI])) if (mesh.isInternalFace(curCell[faceI]))
{ {
label own = intersectedCell[owner[curCell[faceI]]]; label own = intersectedCell[owner[curCell[faceI]]];
@ -403,7 +404,7 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
tss, tss,
2*span, 2*span,
internalFlow(), internalFlow(),
false // iterate intersection true // iterate intersection
); );
// Calculate the intersection // Calculate the intersection
@ -727,7 +728,7 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
// Check tri addressing // Check tri addressing
if (min(nearestTri) == -1) if (min(nearestTri) == -1)
{ {
FatalErrorIn("immersedBoundaryPolyPatch::calcImmersedBoundary() const") FatalErrorInFunction
<< "Cannot find nearestTri for all points" << "Cannot find nearestTri for all points"
<< abort(FatalError); << abort(FatalError);
} }
@ -857,6 +858,7 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
// Internal faces // Internal faces
forAll (neighbour, faceI) forAll (neighbour, faceI)
{ {
// Wet on wet
if if
( (
intersectedCell[owner[faceI]] == immersedPoly::WET intersectedCell[owner[faceI]] == immersedPoly::WET
@ -866,6 +868,7 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
intersectedFace[faceI] = immersedPoly::WET; intersectedFace[faceI] = immersedPoly::WET;
} }
// Dry on dry
if if
( (
intersectedCell[owner[faceI]] == immersedPoly::DRY intersectedCell[owner[faceI]] == immersedPoly::DRY
@ -875,6 +878,23 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
intersectedFace[faceI] = immersedPoly::DRY; intersectedFace[faceI] = immersedPoly::DRY;
} }
// Wet on cut face must remain wet. Error in cut cell is fixed
// by the Marooney Maneouvre. HJ, 5/Apr/2019
if
(
(
intersectedCell[owner[faceI]] == immersedPoly::WET
&& intersectedCell[neighbour[faceI]] == immersedPoly::CUT
)
|| (
intersectedCell[owner[faceI]] == immersedPoly::CUT
&& intersectedCell[neighbour[faceI]] == immersedPoly::WET
)
)
{
intersectedFace[faceI] = immersedPoly::WET;
}
// Special check for directly cut faces // Special check for directly cut faces
// Wet-to-dry and dry-to-wet is a direct face cut // Wet-to-dry and dry-to-wet is a direct face cut
// Dry-to-cut or cut-to-dry are cutting errors. They will be // Dry-to-cut or cut-to-dry are cutting errors. They will be
@ -922,6 +942,51 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
forAll (curOwnCut, patchFaceI) forAll (curOwnCut, patchFaceI)
{ {
// Wet on wet
if
(
intersectedCell[patchFaceI] == immersedPoly::WET
&& intersectedCell[patchFaceI] == immersedPoly::WET
)
{
intersectedFace[patchStart + patchFaceI] =
immersedPoly::WET;
}
// Dry on dry
if
(
intersectedCell[patchFaceI] == immersedPoly::DRY
&& intersectedCell[patchFaceI] == immersedPoly::DRY
)
{
intersectedFace[patchStart + patchFaceI] =
immersedPoly::DRY;
}
// Wet on cut face must remain wet. Error in cut cell is fixed
// by the Marooney Maneouvre. HJ, 5/Apr/2019
if
(
(
intersectedCell[patchFaceI] == immersedPoly::WET
&& intersectedCell[patchFaceI] == immersedPoly::CUT
)
|| (
intersectedCell[patchFaceI] == immersedPoly::CUT
&& intersectedCell[patchFaceI] == immersedPoly::WET
)
)
{
intersectedFace[patchStart + patchFaceI] =
immersedPoly::WET;
}
// Special check for directly cut faces
// Wet-to-dry and dry-to-wet is a direct face cut
// Dry-to-cut or cut-to-dry are cutting errors. They will be
// corrected later in corrected face areas, based on closed cell
// tolerance. HJ, 11/Dec/2017
if if
( (
( (
@ -1040,7 +1105,7 @@ void Foam::immersedBoundaryPolyPatch::calcImmersedBoundary() const
tss, tss,
span, span,
internalFlow(), internalFlow(),
false // iterate intersection true // iterate intersection
); );
// Calculate the intersection // Calculate the intersection
@ -1234,6 +1299,18 @@ void Foam::immersedBoundaryPolyPatch::calcCorrectedGeometry() const
label nMarooneyCells = 0; label nMarooneyCells = 0;
// Get valid directions to avoid round-off errors in 2-D cases
const Vector<label> dirs = mesh.geometricD();
vector validDirs = vector::zero;
for (direction cmpt = 0; cmpt < Vector<label>::nComponents; cmpt++)
{
if (dirs[cmpt] > 0)
{
validDirs[cmpt] = 1;
}
}
forAll (cutCells, cutCellI) forAll (cutCells, cutCellI)
{ {
const label ccc = cutCells[cutCellI]; const label ccc = cutCells[cutCellI];
@ -1274,15 +1351,15 @@ void Foam::immersedBoundaryPolyPatch::calcCorrectedGeometry() const
if (mag(curSumSf + ibSf[cutCellI]) > primitiveMesh::closedThreshold_) if (mag(curSumSf + ibSf[cutCellI]) > primitiveMesh::closedThreshold_)
{ {
// Info<< "Marooney Maneouvre for cell " << ccc // Info<< "Marooney Maneouvre for cell " << ccc
// << " error: " << mag(curSumSf + ibSf[cutCellI]) << " " // << " error: " << curSumSf + ibSf[cutCellI] << " "
// << " S: " << curSumMagSf
// << " V: " << cutCellVolumes[cutCellI] // << " V: " << cutCellVolumes[cutCellI]
// << " Sf: " << ibSf[cutCellI] << endl; // << " Sf: " << ibSf[cutCellI]
// << " corr S: " << curSumSf << endl;
nMarooneyCells++; nMarooneyCells++;
// Create IB face to ideally close the cell // Create IB face to ideally close the cell
ibSf[cutCellI] = -curSumSf; ibSf[cutCellI] = cmptMultiply(validDirs, -curSumSf);
} }
} }
@ -1298,6 +1375,15 @@ void Foam::immersedBoundaryPolyPatch::calcCorrectedGeometry() const
<< endl; << endl;
} }
} }
if (min(mag(ibSf)) < SMALL)
{
WarningInFunction
<< "Minimum IB face area for patch " << name()
<< ": " << min(mag(ibSf)) << ". Possible cutting error. "
<< "Review immersed boundary tolerances."
<< endl;
}
} }