singleProcessorFaceSetsConstraint.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2015-2016 OpenFOAM Foundation
9  Copyright (C) 2018-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
31 #include "syncTools.H"
32 #include "faceSet.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace decompositionConstraints
39 {
40  defineTypeName(singleProcessorFaceSets);
41 
43  (
44  decompositionConstraint,
45  singleProcessorFaceSets,
46  dictionary
47  );
48 }
49 }
50 
51 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 
53 void Foam::decompositionConstraints::singleProcessorFaceSets::printInfo() const
54 {
55  for (const auto& nameAndProc : setNameAndProcs_)
56  {
57  Info<< " all cells connected to faceSet "
58  << nameAndProc.first()
59  << " on processor " << nameAndProc.second() << endl;
60  }
61 }
62 
63 
64 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
65 
68 (
69  const dictionary& dict
70 )
71 :
72  decompositionConstraint(dict, typeName),
73  setNameAndProcs_
74  (
75  coeffDict_.lookupCompat("sets", {{"singleProcessorFaceSets", 1806}})
76  )
77 {
79  {
80  Info<< type()
81  << " : adding constraints to keep" << endl;
82 
83  printInfo();
84  }
85 }
86 
87 
90 (
91  const List<Tuple2<word, label>>& setNameAndProcs
92 )
93 :
95  setNameAndProcs_(setNameAndProcs)
96 {
98  {
99  Info<< type()
100  << " : adding constraints to keep" << endl;
101 
102  printInfo();
103  }
104 }
105 
106 
109 (
110  Istream& is
111 )
112 :
113  decompositionConstraint(dictionary(), typeName),
114  setNameAndProcs_(is)
115 {
117  {
118  Info<< type()
119  << " : adding constraints to keep" << endl;
120 
121  printInfo();
122  }
123 }
124 
125 
126 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
127 
129 (
130  const polyMesh& mesh,
131  boolList& blockedFace,
132  PtrList<labelList>& specifiedProcessorFaces,
133  labelList& specifiedProcessor,
134  List<labelPair>& explicitConnections
135 ) const
136 {
137  blockedFace.resize(mesh.nFaces(), true);
138 
139  // Mark faces already in set
140  labelList faceToSet(mesh.nFaces(), -1);
141  forAll(specifiedProcessorFaces, setI)
142  {
143  const labelList& faceLabels = specifiedProcessorFaces[setI];
144  for (const label facei : faceLabels)
145  {
146  if (faceToSet[facei] == -1)
147  {
148  faceToSet[facei] = setI;
149  }
150  else if (faceToSet[facei] != setI)
151  {
152  WarningInFunction << "Face " << facei
153  << " at " << mesh.faceCentres()[facei]
154  << " is already in existing constraint "
155  << faceToSet[facei]
156  << endl;
157  }
158  }
159  }
160 
161  forAll(setNameAndProcs_, setI)
162  {
163  //Info<< "Keeping all cells connected to faceSet "
164  // << setNameAndProcs_[setI].first()
165  // << " on processor " << setNameAndProcs_[setI].second() << endl;
166 
167  const label destProcI = setNameAndProcs_[setI].second();
168 
169  // Read faceSet
170  const faceSet fz(mesh, setNameAndProcs_[setI].first());
171 
172  // Check that it does not overlap with existing specifiedProcessorFaces
173  labelList nMatch(specifiedProcessorFaces.size(), Zero);
174  for (const label facei : fz)
175  {
176  const label seti = faceToSet[facei];
177  if (seti != -1)
178  {
179  ++nMatch[seti];
180  }
181  }
182 
183 
184  // Only store if all faces are not yet in specifiedProcessorFaces
185  // (on all processors)
186  bool store = true;
187 
188  forAll(nMatch, setI)
189  {
190  if (nMatch[setI] == fz.size())
191  {
192  // Full match
193  store = false;
194  break;
195  }
196  else if (nMatch[setI] > 0)
197  {
198  // Partial match
199  store = false;
200  break;
201  }
202  }
203 
204  if (returnReduceOr(store))
205  {
206  specifiedProcessorFaces.append(new labelList(fz.sortedToc()));
207  specifiedProcessor.append(destProcI);
208  }
209  }
210 
211 
212  // Unblock all point connected faces
213  // 1. Mark all points on specifiedProcessorFaces
214  boolList procFacePoint(mesh.nPoints(), false);
215  forAll(specifiedProcessorFaces, setI)
216  {
217  const labelList& faceLabels = specifiedProcessorFaces[setI];
218  for (const label facei : faceLabels)
219  {
220  const face& f = mesh.faces()[facei];
221 
222  for (const label pointi : f)
223  {
224  procFacePoint[pointi] = true;
225  }
226  }
227  }
228  syncTools::syncPointList(mesh, procFacePoint, orEqOp<bool>(), false);
229 
230  // 2. Unblock all faces on procFacePoint
231 
232  label nUnblocked = 0;
233 
234  forAll(procFacePoint, pointi)
235  {
236  if (procFacePoint[pointi])
237  {
238  const labelList& pFaces = mesh.pointFaces()[pointi];
239  forAll(pFaces, i)
240  {
241  if (blockedFace[pFaces[i]])
242  {
243  blockedFace[pFaces[i]] = false;
244  ++nUnblocked;
245  }
246  }
247  }
248  }
249 
251  {
252  Info<< type() << " : unblocked "
253  << returnReduce(nUnblocked, sumOp<label>()) << " faces" << endl;
254  }
255 
256  syncTools::syncFaceList(mesh, blockedFace, andEqOp<bool>());
257 }
258 
259 
261 (
262  const polyMesh& mesh,
263  const boolList& blockedFace,
264  const PtrList<labelList>& specifiedProcessorFaces,
265  const labelList& specifiedProcessor,
266  const List<labelPair>& explicitConnections,
267  labelList& decomposition
268 ) const
269 {
270  // For specifiedProcessorFaces rework the cellToProc to enforce
271  // all on one processor since we can't guarantee that the input
272  // to regionSplit was a single region.
273  // E.g. faceSet 'a' with the cells split into two regions
274  // by a notch formed by two walls
275  //
276  // \ /
277  // \ /
278  // ---a----+-----a-----
279  //
280  //
281  // Note that reworking the cellToProc might make the decomposition
282  // unbalanced.
283  label nChanged = 0;
284 
285  forAll(specifiedProcessorFaces, setI)
286  {
287  const labelList& set = specifiedProcessorFaces[setI];
288 
289  // Get the processor to use for the set
290  label procI = specifiedProcessor[setI];
291  if (procI == -1)
292  {
293  // If no processor specified use the one from the
294  // 0th element
295  if (set.size())
296  {
297  procI = decomposition[mesh.faceOwner()[set[0]]];
298  }
299  reduce(procI, maxOp<label>());
300  }
301 
302  // Get all points on the sets
303  boolList procFacePoint(mesh.nPoints(), false);
304  forAll(set, fI)
305  {
306  const face& f = mesh.faces()[set[fI]];
307  forAll(f, fp)
308  {
309  procFacePoint[f[fp]] = true;
310  }
311  }
312  syncTools::syncPointList(mesh, procFacePoint, orEqOp<bool>(), false);
313 
314  // 2. Unblock all faces on procFacePoint
315  forAll(procFacePoint, pointi)
316  {
317  if (procFacePoint[pointi])
318  {
319  const labelList& pFaces = mesh.pointFaces()[pointi];
320  for (const label faceI : pFaces)
321  {
322  const label own = mesh.faceOwner()[faceI];
323 
324  if (decomposition[own] != procI)
325  {
326  decomposition[own] = procI;
327  ++nChanged;
328  }
329 
330  if (mesh.isInternalFace(faceI))
331  {
332  const label nei = mesh.faceNeighbour()[faceI];
333  if (decomposition[nei] != procI)
334  {
335  decomposition[nei] = procI;
336  ++nChanged;
337  }
338  }
339  }
340  }
341  }
342  }
343 
345  {
346  Info<< type() << " : changed decomposition on "
347  << returnReduce(nChanged, sumOp<label>()) << " cells" << endl;
348  }
349 }
350 
351 
352 // ************************************************************************* //
Abstract class for handling decomposition constraints.
dictionary dict
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:54
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:432
labelList faceLabels(nFaceLabels)
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
dynamicFvMesh & mesh
virtual void add(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections) const
Add this constraint to list of constraints.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
singleProcessorFaceSets(const dictionary &dict)
Construct with constraint dictionary.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
virtual void apply(const polyMesh &mesh, const boolList &blockedFace, const PtrList< labelList > &specifiedProcessorFaces, const labelList &specifiedProcessor, const List< labelPair > &explicitConnections, labelList &decomposition) const
Add this constraint post-decomposition.
int debug
Static debugging option.
labelList f(nPoints)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
void append(autoPtr< T > &ptr)
Move append an element to the end of the list.
Definition: PtrList.H:344
#define WarningInFunction
Report a warning using Foam::Warning.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
addToRunTimeSelectionTable(decompositionConstraint, geometric, dictionary)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< bool > boolList
A List of bools.
Definition: List.H:60
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127