1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "extendedUpwindCellToFaceStencil.H"
27 #include "cellToFaceStencil.H"
28 #include "syncTools.H"
29 #include "SortableList.H"
30 #include "dummyTransform.H"
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 void Foam::extendedUpwindCellToFaceStencil::selectOppositeFaces
36 const boolList& nonEmptyFace,
37 const scalar minOpposedness,
40 DynamicList<label>& oppositeFaces
43 const vectorField& areas = mesh_.faceAreas();
44 const labelList& own = mesh_.faceOwner();
45 const cell& cFaces = mesh_.cells()[cellI];
47 SortableList<scalar> opposedness(cFaces.size(), -GREAT);
49 // Pick up all the faces that oppose this one.
52 label otherFaceI = cFaces[i];
54 if (otherFaceI != faceI && nonEmptyFace[otherFaceI])
56 if ((own[otherFaceI] == cellI) == (own[faceI] == cellI))
58 opposedness[i] = -(areas[otherFaceI] & areas[faceI]);
62 opposedness[i] = (areas[otherFaceI] & areas[faceI]);
67 label sz = opposedness.size();
69 oppositeFaces.clear();
71 scalar myAreaSqr = magSqr(areas[faceI]);
73 if (myAreaSqr > VSMALL)
75 forAll(opposedness, i)
77 opposedness[i] /= myAreaSqr;
79 // Sort in incrementing order
82 // Pick largest no matter what
83 oppositeFaces.append(cFaces[opposedness.indices()[sz-1]]);
85 for (label i = sz-2; i >= 0; --i)
87 if (opposedness[i] < minOpposedness)
91 oppositeFaces.append(cFaces[opposedness.indices()[i]]);
96 // Sort in incrementing order
99 // Tiny face. Do what?
100 // Pick largest no matter what
101 oppositeFaces.append(cFaces[opposedness.indices()[sz-1]]);
106 void Foam::extendedUpwindCellToFaceStencil::transportStencil
108 const boolList& nonEmptyFace,
109 const labelListList& faceStencil,
110 const scalar minOpposedness,
113 const bool stencilHasNeighbour,
115 DynamicList<label>& oppositeFaces,
116 labelHashSet& faceStencilSet,
117 labelList& transportedStencil
120 label globalOwn = faceStencil[faceI][0];
121 label globalNei = -1;
122 if (stencilHasNeighbour && faceStencil[faceI].size() >= 2)
124 globalNei = faceStencil[faceI][1];
137 // Collect all stencils of oppositefaces
138 faceStencilSet.clear();
139 forAll(oppositeFaces, i)
141 const labelList& fStencil = faceStencil[oppositeFaces[i]];
145 label globalI = fStencil[j];
147 if (globalI != globalOwn && globalI != globalNei)
149 faceStencilSet.insert(globalI);
154 // Add my owner and neighbour first.
155 if (stencilHasNeighbour)
157 transportedStencil.setSize(faceStencilSet.size()+2);
159 transportedStencil[n++] = globalOwn;
160 transportedStencil[n++] = globalNei;
162 forAllConstIter(labelHashSet, faceStencilSet, iter)
164 if (iter.key() != globalOwn && iter.key() != globalNei)
166 transportedStencil[n++] = iter.key();
169 if (n != transportedStencil.size())
173 "extendedUpwindCellToFaceStencil::transportStencil(..)"
174 ) << "problem:" << faceStencilSet
175 << abort(FatalError);
180 transportedStencil.setSize(faceStencilSet.size()+1);
182 transportedStencil[n++] = globalOwn;
184 forAllConstIter(labelHashSet, faceStencilSet, iter)
186 if (iter.key() != globalOwn)
188 transportedStencil[n++] = iter.key();
191 if (n != transportedStencil.size())
195 "extendedUpwindCellToFaceStencil::transportStencil(..)"
196 ) << "problem:" << faceStencilSet
197 << abort(FatalError);
203 void Foam::extendedUpwindCellToFaceStencil::transportStencils
205 const labelListList& faceStencil,
206 const scalar minOpposedness,
207 labelListList& ownStencil,
208 labelListList& neiStencil
211 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
212 const label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
213 const labelList& own = mesh_.faceOwner();
214 const labelList& nei = mesh_.faceNeighbour();
217 DynamicList<label> oppositeFaces;
218 labelHashSet faceStencilSet;
221 // For quick detection of empty faces
222 boolList nonEmptyFace(mesh_.nFaces(), true);
223 forAll(patches, patchI)
225 const polyPatch& pp = patches[patchI];
227 if (isA<emptyPolyPatch>(pp))
229 label faceI = pp.start();
232 nonEmptyFace[faceI++] = false;
240 // stencil is synchronised at entry so no need to swap.
242 ownStencil.setSize(mesh_.nFaces());
245 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
247 // Get stencil as owner + neighbour + stencil from 'opposite' faces
255 true, //stencilHasNeighbour
262 forAll(patches, patchI)
264 const polyPatch& pp = patches[patchI];
265 label faceI = pp.start();
278 true, //stencilHasNeighbour
287 else if (!isA<emptyPolyPatch>(pp))
291 // faceStencil does not contain neighbour
299 false, //stencilHasNeighbour
311 // Swap coupled boundary stencil
312 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314 labelListList neiBndStencil(nBnd);
315 for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
317 neiBndStencil[faceI-mesh_.nInternalFaces()] = ownStencil[faceI];
319 //syncTools::swapBoundaryFaceList(mesh_, neiBndStencil);
320 syncTools::syncBoundaryFaceList
330 // Do the neighbour side
331 // ~~~~~~~~~~~~~~~~~~~~~
332 // - internal faces : get opposite faces on neighbour side
333 // - boundary faces : empty
334 // - coupled faces : in neiBndStencil
336 neiStencil.setSize(mesh_.nFaces());
339 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
348 true, //stencilHasNeighbour
357 forAll(patches, patchI)
359 const polyPatch& pp = patches[patchI];
360 label faceI = pp.start();
366 neiStencil[faceI].transfer
368 neiBndStencil[faceI-mesh_.nInternalFaces()]
375 // Boundary has empty neighbour stencil
381 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
383 Foam::extendedUpwindCellToFaceStencil::extendedUpwindCellToFaceStencil
385 const cellToFaceStencil& stencil,
386 const bool pureUpwind,
387 const scalar minOpposedness
390 extendedCellToFaceStencil(stencil.mesh()),
391 pureUpwind_(pureUpwind)
393 //forAll(stencil, faceI)
395 // const labelList& fCells = stencil[faceI];
397 // Pout<< "Face:" << faceI << " at:" << mesh_.faceCentres()[faceI]
402 // label globalI = fCells[i];
404 // if (globalI < mesh_.nCells())
406 // Pout<< " cell:" << globalI
407 // << " at:" << mesh_.cellCentres()[globalI] << endl;
411 // label faceI = globalI-mesh_.nCells() + mesh_.nInternalFaces();
413 // Pout<< " boundary:" << faceI
414 // << " at:" << mesh_.faceCentres()[faceI] << endl;
418 //Pout<< endl << endl;
421 // Transport centred stencil to upwind/downwind face
431 List<Map<label> > compactMap(Pstream::nProcs());
436 stencil.globalNumbering(),
445 List<Map<label> > compactMap(Pstream::nProcs());
450 stencil.globalNumbering(),
457 // stencil now in compact form
460 const fvMesh& mesh = dynamic_cast<const fvMesh&>(stencil.mesh());
462 List<List<point> > stencilPoints(ownStencil_.size());
467 collectData(ownMapPtr_(), ownStencil_, mesh.C(), stencilPoints);
469 // Mask off all stencil points on wrong side of face
470 forAll(stencilPoints, faceI)
472 const point& fc = mesh.faceCentres()[faceI];
473 const vector& fArea = mesh.faceAreas()[faceI];
475 const List<point>& points = stencilPoints[faceI];
476 const labelList& stencil = ownStencil_[faceI];
478 DynamicList<label> newStencil(stencil.size());
481 if (((points[i]-fc) & fArea) < 0)
483 newStencil.append(stencil[i]);
486 if (newStencil.size() != stencil.size())
488 ownStencil_[faceI].transfer(newStencil);
496 collectData(neiMapPtr_(), neiStencil_, mesh.C(), stencilPoints);
498 // Mask off all stencil points on wrong side of face
499 forAll(stencilPoints, faceI)
501 const point& fc = mesh.faceCentres()[faceI];
502 const vector& fArea = mesh.faceAreas()[faceI];
504 const List<point>& points = stencilPoints[faceI];
505 const labelList& stencil = neiStencil_[faceI];
507 DynamicList<label> newStencil(stencil.size());
510 if (((points[i]-fc) & fArea) > 0)
512 newStencil.append(stencil[i]);
515 if (newStencil.size() != stencil.size())
517 neiStencil_[faceI].transfer(newStencil);
521 // Note: could compact schedule as well. for if cells are not needed
522 // across any boundary anymore. However relatively rare.
527 Foam::extendedUpwindCellToFaceStencil::extendedUpwindCellToFaceStencil
529 const cellToFaceStencil& stencil
532 extendedCellToFaceStencil(stencil.mesh()),
535 // Calculate stencil points with full stencil
537 ownStencil_ = stencil;
540 List<Map<label> > compactMap(Pstream::nProcs());
545 stencil.globalNumbering(),
552 const fvMesh& mesh = dynamic_cast<const fvMesh&>(stencil.mesh());
554 List<List<point> > stencilPoints(ownStencil_.size());
555 collectData(ownMapPtr_(), ownStencil_, mesh.C(), stencilPoints);
557 // Split stencil into owner and neighbour
558 neiStencil_.setSize(ownStencil_.size());
560 forAll(stencilPoints, faceI)
562 const point& fc = mesh.faceCentres()[faceI];
563 const vector& fArea = mesh.faceAreas()[faceI];
565 const List<point>& points = stencilPoints[faceI];
566 const labelList& stencil = ownStencil_[faceI];
568 DynamicList<label> newOwnStencil(stencil.size());
569 DynamicList<label> newNeiStencil(stencil.size());
572 if (((points[i]-fc) & fArea) > 0)
574 newNeiStencil.append(stencil[i]);
578 newOwnStencil.append(stencil[i]);
581 if (newNeiStencil.size() > 0)
583 ownStencil_[faceI].transfer(newOwnStencil);
584 neiStencil_[faceI].transfer(newNeiStencil);
588 // Should compact schedule. Or have both return the same schedule.
589 neiMapPtr_.reset(new mapDistribute(ownMapPtr_()));
593 // ************************************************************************* //