From 4497ddb9557c1ee8a4f08e2262f3e21bf17a8a65 Mon Sep 17 00:00:00 2001 From: Hrvoje Jasak Date: Tue, 15 May 2018 16:41:41 +0100 Subject: [PATCH] MERGE: GGI handling of partially overlapped faces. Vuko Vukcevic --- .../constraint/cyclicGgi/cyclicGgiFvPatch.C | 91 ++++++++----- .../fvPatches/constraint/ggi/ggiFvPatch.C | 120 +++++++++++------- 2 files changed, 128 insertions(+), 83 deletions(-) diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicGgi/cyclicGgiFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicGgi/cyclicGgiFvPatch.C index 849b9394d..5a3b15ebd 100644 --- a/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicGgi/cyclicGgiFvPatch.C +++ b/src/finiteVolume/fvMesh/fvPatches/constraint/cyclicGgi/cyclicGgiFvPatch.C @@ -79,17 +79,14 @@ void Foam::cyclicGgiFvPatch::makeWeights(fvsPatchScalarField& w) const n & (cyclicGgiPolyPatch_.reconFaceCellCentres() - Cf()) ); - w = nfc/(mag(n & (Cf() - Cn())) + nfc); - - if (bridgeOverlap()) - { - // Set overlap weights to 0.5 and use mirrored neighbour field - // for interpolation. HJ, 21/Jan/2009 - bridge(scalarField(size(), 0.5), w); - } + w = nfc/(mag(n & (Cf() - Cn())) + nfc + SMALL); } else { + // Slave side. Interpolate the master side weights, scale them for + // partially covered faces and set weights for fully uncovered faces if + // the bridge overlap is switched on. VV, 15/Feb/2018. + // Pick up weights from the master side fvsPatchScalarField masterWeights ( @@ -99,14 +96,23 @@ void Foam::cyclicGgiFvPatch::makeWeights(fvsPatchScalarField& w) const shadow().makeWeights(masterWeights); - w = interpolate(1 - masterWeights); + // Interpolate master weights to this side + w = interpolate(masterWeights); if (bridgeOverlap()) { - // Set overlap weights to 0.5 and use mirrored neighbour field - // for interpolation. HJ, 21/Jan/2009 - bridge(scalarField(size(), 0.5), w); + // Weights for fully uncovered faces + const scalarField uncoveredWeights(w.size(), 0.5); + + // Set weights for uncovered faces + setUncoveredFaces(uncoveredWeights, w); + + // Scale partially overlapping faces + scalePartialFaces(w); } + + // Finally construct these weights as 1 - master weights + w = 1 - w; } } @@ -116,20 +122,21 @@ void Foam::cyclicGgiFvPatch::makeDeltaCoeffs(fvsPatchScalarField& dc) const { if (cyclicGgiPolyPatch_.master()) { + // Master side. No need to scale partially uncovered or set fully + // uncovered faces since delta already takes it into account. + // VV, 25/Feb/2018. + // Stabilised form for bad meshes. HJ, 24/Aug/2011 - vectorField d = delta(); + const vectorField d = delta(); dc = 1.0/max(nf() & d, 0.05*mag(d)); - - if (bridgeOverlap()) - { - scalarField bridgeDeltas = nf() & fvPatch::delta(); - - bridge(bridgeDeltas, dc); - } } else { + // Slave side. Interpolate the master side, scale it for partially + // covered faces and set deltaCoeffs for fully uncovered faces if the + // bridge overlap is switched on. VV, 15/Feb/2018. + fvsPatchScalarField masterDeltas ( shadow(), @@ -142,9 +149,17 @@ void Foam::cyclicGgiFvPatch::makeDeltaCoeffs(fvsPatchScalarField& dc) const if (bridgeOverlap()) { - scalarField bridgeDeltas = nf() & fvPatch::delta(); + // Delta coeffs for fully uncovered faces obtained from deltas on + // this side + const vectorField d = delta(); + const scalarField uncoveredDeltaCoeffs = + 1.0/max(nf() & d, 0.05*mag(d)); - bridge(bridgeDeltas, dc); + // Set delta coeffs for uncovered faces + setUncoveredFaces(uncoveredDeltaCoeffs, dc); + + // Scale partially overlapping faces + scalePartialFaces(dc); } } } @@ -162,33 +177,39 @@ Foam::tmp Foam::cyclicGgiFvPatch::delta() const { if (cyclicGgiPolyPatch_.master()) { - tmp tDelta = + // Master side. Note: scaling partially covered faces and setting deltas + // to fully uncovered faces correctly taken into account in + // reconFaceCellCentres function. VV, 15/Feb/2018. + + tmp tdelta = cyclicGgiPolyPatch_.reconFaceCellCentres() - Cn(); - if (bridgeOverlap()) - { - vectorField bridgeDeltas = Cf() - Cn(); - - bridge(bridgeDeltas, tDelta()); - } - - return tDelta; + return tdelta; } else { - tmp tDelta = interpolate + // Slave side. Interpolate the master side, scale it for partially + // covered faces and set deltas for fully uncovered faces if the bridge + // overlap is switched on. VV, 15/Feb/2018. + + tmp tdelta = interpolate ( shadow().Cn() - cyclicGgiPolyPatch_.shadow().reconFaceCellCentres() ); if (bridgeOverlap()) { - vectorField bridgeDeltas = Cf() - Cn(); + // Deltas for fully uncovered faces + const vectorField uncoveredDeltas(2.0*fvPatch::delta()); - bridge(bridgeDeltas, tDelta()); + // Set deltas for fully uncovered faces + setUncoveredFaces(uncoveredDeltas, tdelta()); + + // Scale for partially covered faces + scalePartialFaces(tdelta()); } - return tDelta; + return tdelta; } } diff --git a/src/finiteVolume/fvMesh/fvPatches/constraint/ggi/ggiFvPatch.C b/src/finiteVolume/fvMesh/fvPatches/constraint/ggi/ggiFvPatch.C index 539c75655..79f69eb04 100644 --- a/src/finiteVolume/fvMesh/fvPatches/constraint/ggi/ggiFvPatch.C +++ b/src/finiteVolume/fvMesh/fvPatches/constraint/ggi/ggiFvPatch.C @@ -63,6 +63,9 @@ void Foam::ggiFvPatch::makeWeights(fvsPatchScalarField& w) const // HJ, 2/Aug/2007 if (ggiPolyPatch_.master()) { + // Master side. No need to scale partially uncovered or set fully + // uncovered faces since delta already takes it into account. + // VV, 25/Feb/2018. const vectorField n = nf(); // Note: mag in the dot-product. @@ -73,19 +76,14 @@ void Foam::ggiFvPatch::makeWeights(fvsPatchScalarField& w) const const scalarField nfc = mag(n & (ggiPolyPatch_.reconFaceCellCentres() - Cf())); - w = nfc/(mag(n & (Cf() - Cn())) + nfc); - - if (bridgeOverlap()) - { - // Set overlap weights to 0.5 and use mirrored neighbour field - // for interpolation. HJ, 21/Jan/2009 - const scalarField bridgedField(size(), 0.5); - - bridge(bridgedField, w); - } + w = nfc/(mag(n & (Cf() - Cn())) + nfc + SMALL); } else { + // Slave side. Interpolate the master side weights, scale them for + // partially covered faces and set weights for fully uncovered faces if + // the bridge overlap is switched on. VV, 15/Feb/2018. + // Pick up weights from the master side fvsPatchScalarField masterWeights ( @@ -95,18 +93,23 @@ void Foam::ggiFvPatch::makeWeights(fvsPatchScalarField& w) const shadow().makeWeights(masterWeights); - const scalarField oneMinusW = 1 - masterWeights; - - w = interpolate(oneMinusW); + // Interpolate master weights to this side + w = interpolate(masterWeights); if (bridgeOverlap()) { - // Set overlap weights to 0.5 and use mirrored neighbour field - // for interpolation. HJ, 21/Jan/2009 - const scalarField bridgedField(size(), 0.5); + // Weights for fully uncovered faces + const scalarField uncoveredWeights(w.size(), 0.5); - bridge(bridgedField, w); + // Set weights for uncovered faces + setUncoveredFaces(uncoveredWeights, w); + + // Scale partially overlapping faces + scalePartialFaces(w); } + + // Finally construct these weights as 1 - master weights + w = 1 - w; } } @@ -116,6 +119,10 @@ void Foam::ggiFvPatch::makeDeltaCoeffs(fvsPatchScalarField& dc) const { if (ggiPolyPatch_.master()) { + // Master side. No need to scale partially uncovered or set fully + // uncovered faces since delta already takes it into account. + // VV, 25/Feb/2018. + // Stabilised form for bad meshes. HJ, 24/Aug/2011 const vectorField d = delta(); @@ -126,6 +133,10 @@ void Foam::ggiFvPatch::makeDeltaCoeffs(fvsPatchScalarField& dc) const } else { + // Slave side. Interpolate the master side, scale it for partially + // covered faces and set deltaCoeffs for fully uncovered faces if the + // bridge overlap is switched on. VV, 15/Feb/2018. + fvsPatchScalarField masterDeltas ( shadow(), @@ -138,13 +149,17 @@ void Foam::ggiFvPatch::makeDeltaCoeffs(fvsPatchScalarField& dc) const if (bridgeOverlap()) { - // Note: double the deltaCoeffs because this is symmetry treatment - // and fvPatch::deltaCoeffs() is cell to face inverse distance, - // while we need cell to "symmetry neighbour cell" distance. - // VV, 18/Oct/2017. - const scalarField bridgeDeltas = 2.0*fvPatch::deltaCoeffs(); + // Delta coeffs for fully uncovered faces obtained from deltas on + // this side + const vectorField d = delta(); + const scalarField uncoveredDeltaCoeffs = + 1.0/max(nf() & d, 0.05*mag(d)); - bridge(bridgeDeltas, dc); + // Set delta coeffs for uncovered faces + setUncoveredFaces(uncoveredDeltaCoeffs, dc); + + // Scale partially overlapping faces + scalePartialFaces(dc); } } } @@ -156,15 +171,24 @@ void Foam::ggiFvPatch::makeCorrVecs(fvsPatchVectorField& cv) const // Non-orthogonality correction on a ggi interface // MB, 7/April/2009 - // Calculate correction vectors on coupled patches - const scalarField& patchDeltaCoeffs = deltaCoeffs(); + // No non-orthogonal correction if the bridge overlap is switched on to + // ensure conservative interpolation for partially overlapping faces + if (bridgeOverlap()) + { + cv = vector::zero; + } + else + { + // Calculate correction vectors on coupled patches + const scalarField& patchDeltaCoeffs = deltaCoeffs(); - const vectorField patchDeltas = delta(); - const vectorField n = nf(); + const vectorField patchDeltas = delta(); + const vectorField n = nf(); - // If non-orthogonality is over 90 deg, kill correction vector - // HJ, 6/Jan/2011 - cv = pos(patchDeltas & n)*(n - patchDeltas*patchDeltaCoeffs); + // If non-orthogonality is over 90 deg, kill correction vector + // HJ, 6/Jan/2011 + cv = pos(patchDeltas & n)*(n - patchDeltas*patchDeltaCoeffs); + } } @@ -173,38 +197,38 @@ Foam::tmp Foam::ggiFvPatch::delta() const { if (ggiPolyPatch_.master()) { - tmp tDelta = ggiPolyPatch_.reconFaceCellCentres() - Cn(); + // Master side. Note: scaling partially covered faces and setting deltas + // to fully uncovered faces correctly taken into account in + // reconFaceCellCentres function. VV, 15/Feb/2018. - if (bridgeOverlap()) - { - // Note: double the deltas because this is symmetry treatment and - // fvPatch::delta() is cell to face distance, while we need cell to - // "symmetry neighbour cell" distance. VV, 18/Oct/2017. - const vectorField bridgeDeltas = 2.0*fvPatch::delta(); + tmp tdelta = ggiPolyPatch_.reconFaceCellCentres() - Cn(); - bridge(bridgeDeltas, tDelta()); - } - - return tDelta; + return tdelta; } else { - tmp tDelta = interpolate + // Slave side. Interpolate the master side, scale it for partially + // covered faces and set deltas for fully uncovered faces if the bridge + // overlap is switched on. VV, 15/Feb/2018. + + tmp tdelta = interpolate ( shadow().Cn() - ggiPolyPatch_.shadow().reconFaceCellCentres() ); if (bridgeOverlap()) { - // Note: double the deltas because this is symmetry treatment and - // fvPatch::delta() is cell to face distance, while we need cell to - // "symmetry neighbour cell" distance. VV, 18/Oct/2017. - const vectorField bridgeDeltas = 2.0*fvPatch::delta(); + // Deltas for fully uncovered faces + const vectorField uncoveredDeltas(2.0*fvPatch::delta()); - bridge(bridgeDeltas, tDelta()); + // Set deltas for fully uncovered faces + setUncoveredFaces(uncoveredDeltas, tdelta()); + + // Scale for partially covered faces + scalePartialFaces(tdelta()); } - return tDelta; + return tdelta; } }