All Classes Namespaces Files Functions Variables Typedefs Friends Macros Groups
extendedFaceStencilFindNeighbours.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019 OpenCFD Ltd.
10  Copyright (C) 2016-2019 ISP RAS (www.ispras.ru) UniCFD Group (www.unicfd.ru)
11 -------------------------------------------------------------------------------
12 License
13  This file is part of QGDsolver library, based on OpenFOAM+.
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  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22  You should have received a copy of the GNU General Public License
23  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 Class
25  Foam::fvsc::leastSquares::extendedFaceStencilFindNeighbours
26 Description
27  Base methods for finding neighbours
28 \*---------------------------------------------------------------------------*/
29 #include "leastSquaresBase.H"
30 #include "processorFvPatch.H"
31 #include "polyMesh.H"
32 #include "fvMesh.H"
33 #include "word.H"
34 #include "IOstream.H"
35 #include "Ostream.H"
36 #include <HashTable.H>
37 
38 //- Find neighbour cells for each face (throught face points).
40 {
41  // List of faces
42  const faceList& faces = cMesh_.faces();
43  labelListList neighbourCellsForFace(cMesh_.nInternalFaces());
44 
45  //Step 1. Find neighbours for internal faces
46  forAll(faces, facei)
47  {
48  if(cMesh_.isInternalFace(facei))
49  {
50  labelList neighbourCells;
51  labelList pointsFacei = faces[facei];
52 
53  forAll(pointsFacei, k)
54  {
55  label pointi = pointsFacei[k];
56  // cells should be added to list if it wasn't contain in the list yet
57  labelList neighbourCellsForPointI = cMesh_.pointCells()[pointi];
58 
59  forAll(neighbourCellsForPointI, j)
60  {
61  label celli = neighbourCellsForPointI[j];
62 
63  bool contained = false;
64 
65  forAll(neighbourCells, f)
66  {
67  label ncell=neighbourCells[f];
68  if(ncell==celli)
69  {
70  contained = true;
71  }
72  }
73 
74  if(!contained)
75  {
76  neighbourCells.append(celli);
77  }
78  }
79  }
80  neighbourCellsForFace[facei].append(neighbourCells);
81  }
82  }
83 
84  neighbourCells_ = neighbourCellsForFace;
85 
86  //Step 2. Find neighbours for processors faces
87  if (Pstream::parRun())
88  {
89  //Step 2.1 Load processor addresing
90  labelIOList localPointProcAddr
91  (
92  IOobject
93  (
94  "pointProcAddressing",
95  cMesh_.facesInstance(),
96  cMesh_.meshSubDir,
97  cMesh_,
98  IOobject::MUST_READ,
99  IOobject::NO_WRITE
100  )
101  );
102  labelHashTable<label> globalPointProcAddr; //reverse g==>l point addr
103  forAll(localPointProcAddr, iPoint)
104  {
105  globalPointProcAddr.insert
106  (
107  localPointProcAddr[iPoint],
108  iPoint
109  );
110  }
111 
112  labelIOList localCellProcAddr
113  (
114  IOobject
115  (
116  "cellProcAddressing",
117  cMesh_.facesInstance(),
118  cMesh_.meshSubDir,
119  cMesh_,
120  IOobject::MUST_READ,
121  IOobject::NO_WRITE
122  )
123  );
124  labelHashTable<label> globalCellProcAddr; //reverse g==>l cell addr
125  forAll(localCellProcAddr, iCell)
126  {
127  globalCellProcAddr.insert
128  (
129  localCellProcAddr[iCell],
130  iCell
131  );
132  }
133 
134  forAll(cMesh_.boundary(), patchIndex)
135  {
136  if (isType<processorFvPatch>(cMesh_.boundary()[patchIndex]))
137  {
138  procPairs_.append(patchIndex);
139  idProcPatchPairs_.insert
140  (
141  patchIndex,
142  procPairs_.size() - 1
143  );
144  }
145  }
146  nProcPatches_ = procPairs_.size();
147  procGdf_.resize(nProcPatches_);
148  procWf2_.resize(nProcPatches_);
149  neigProcs_.resize(nProcPatches_);
150 
151  labelHashTable<labelHashSet> locPointProcs;
152  forAll(procPairs_, iProcPair)
153  {
154  const label iProcPatchId = procPairs_[iProcPair];
155  const fvPatch& fvp = cMesh_.boundary()[iProcPatchId];
156  const processorFvPatch& procp = refCast<const processorFvPatch>(fvp);
157  procGdf_[iProcPair].resize(fvp.size());
158  procWf2_[iProcPair].resize(fvp.size());
159  neigProcs_[iProcPair] = procp.neighbProcNo();
160  }
161 
163  forAll(myProcPatchCells_, iProcPatch)
164  {
165  //looking for cells connected to procesorPatch
166  if (procPairs_[iProcPatch] > -1)
167  {
168  const label iProcPatchId = procPairs_[iProcPatch];
169  const fvPatch& fvp = cMesh_.boundary()[iProcPatchId];
170  const polyPatch& pp = fvp.patch(); //list of faces from which the patch is build up
171  myProcPatchCells_[iProcPatch].resize(fvp.size());
172 
173  label pointId = -1;
174  label gPointId = -1;
175  forAll(pp, facei)
176  {
177  labelList& faceCells = myProcPatchCells_[iProcPatch][facei];
178  labelHashSet vCells;
179  forAll(pp[facei], pointi)
180  {
181  pointId = pp[facei][pointi];
182  //add only unique cells ids
183  vCells.insert(cMesh_.pointCells()[pointId]);
184  //take global point id
185  gPointId = localPointProcAddr[pointId];
186  //
187  if (locPointProcs.found(gPointId))
188  {
189  locPointProcs[gPointId].insert(neigProcs_[iProcPatch]);
190  }
191  else
192  {
193  locPointProcs.insert(gPointId, labelHashSet());
194  locPointProcs[gPointId].insert(neigProcs_[iProcPatch]);
195  }
196  }
197  faceCells.append(vCells.toc());
198  }
199  }
200  }
201 
202  //create and distribute internal addressing
203  ownEnd_.resize(nProcPatches_);
204  neiStart_.resize(nProcPatches_);
205  neiEnd_.resize(nProcPatches_);
206  corStart_.resize(nProcPatches_);
207  corEnd_.resize(nProcPatches_);
208 
209  //Pout << "Addressing for patch neigbours created" << endl;
210 
211  {
212  PstreamBuffers pBuffers (Pstream::commsTypes::nonBlocking);
213 
214  //Set and send
215  forAll(myProcPatchCells_, iProcPatch)
216  {
217  if (procPairs_[iProcPatch] > -1)
218  {
219  label nFaces = myProcPatchCells_[iProcPatch].size();
220  ownEnd_[iProcPatch].resize(nFaces);
221  neiStart_[iProcPatch].resize(nFaces);
222  forAll(myProcPatchCells_[iProcPatch], iFace)
223  {
224  ownEnd_[iProcPatch][iFace] = myProcPatchCells_[iProcPatch][iFace].size() - 1;
225  neiStart_[iProcPatch][iFace] = ownEnd_[iProcPatch][iFace] + 1;
226  }
227 
228  UOPstream oProcStr(neigProcs_[iProcPatch], pBuffers);
229  oProcStr << neiStart_[iProcPatch];
230  }
231  }
232 
233  pBuffers.finishedSends();
234 
235  //Recieve
236  forAll(myProcPatchCells_, iProcPatch)
237  {
238  if (procPairs_[iProcPatch] > -1)
239  {
240  label nFaces = myProcPatchCells_[iProcPatch].size();
241  List<label> neiLen (nFaces, 0);
242  neiEnd_[iProcPatch].resize(nFaces);
243  corStart_[iProcPatch].resize(nFaces);
244  corEnd_[iProcPatch].resize(nFaces);
245 
246  UIPstream iProcStr(neigProcs_[iProcPatch], pBuffers);
247  iProcStr >> neiLen;
248 
249  neiEnd_[iProcPatch] = ownEnd_[iProcPatch] + neiLen;
250  corStart_[iProcPatch] = neiEnd_[iProcPatch] + 1;
251  corEnd_[iProcPatch] = corStart_[iProcPatch] - 1;
252  }
253  }
254  }
255 
256  //select point which belongs to more than 2 processors
257 
258  DynamicList<label> multipleProcsPoints;
259 
260  forAllConstIter(labelHashTable<labelHashSet>, locPointProcs, iter)
261  {
262  if (iter().size() > 1) //point at multiple processor's boundaries
263  {
264  multipleProcsPoints.append(iter.key());
265  }
266  }
267 
268  //accumulate cell id's for each corner point
269  //at master process
270  //fill cell-to-processor table
271  {
272  label gPointId = -1;
273  label lPointId = -1;
274  List<label> gPointCells;
275 
276  /* Select cells for each processor */
277  forAll(multipleProcsPoints, iPoint)
278  {
279  gPointId = multipleProcsPoints[iPoint];
280  lPointId = globalPointProcAddr[gPointId];
281  const List<label>& lPointCells = cMesh_.pointCells(lPointId);
282  gPointCells.resize(lPointCells.size());
283 
284  forAll(lPointCells, iCell)
285  {
286  gPointCells[iCell] = localCellProcAddr[lPointCells[iCell]];
287  if (!cellProc_.found(gPointCells[iCell]))
288  {
289  cellProc_.insert(gPointCells[iCell], Pstream::myProcNo());
290  }
291  }
292 
293  if (pointCells_.found(gPointId))
294  {
295  pointCells_[gPointId].append(gPointCells);
296  }
297  else
298  {
299  pointCells_.insert(gPointId,gPointCells);
300  }
301  }
302 
303  if (Pstream::master())
304  {
305 
306  for (label proci = Pstream::firstSlave(); proci <= Pstream::lastSlave(); proci++)
307  {
308  IPstream fromSlave(Pstream::commsTypes::scheduled, proci);
309  labelHashTable<List<label> > slaveCells;
310  labelHashTable<label> slaveCellProc;
311 
312  //gather pointCells_ table
313  fromSlave >> slaveCells;
314 
315  //copy data from slave to master array
316  forAllConstIter(labelHashTable<List<label> >, slaveCells, iter)
317  {
318  if (pointCells_.found(iter.key()))
319  {
320  pointCells_[iter.key()].append(iter());
321  }
322  else
323  {
324  pointCells_.insert(iter.key(), iter());
325  }
326  }
327 
328  //gather cellProc_ table
329  fromSlave >> slaveCellProc;
330  forAllConstIter(labelHashTable<label>, slaveCellProc, iter)
331  {
332  if (!cellProc_.found(iter.key()))
333  {
334  cellProc_.insert(iter.key(), iter());
335  }
336  else
337  {
338  if (iter() != proci)
339  {
340  Info << "Same cell located at two or more processors!" << endl;
341  }
342  }
343  }
344  }
345  }
346  else
347  {
348  OPstream toMaster(Pstream::commsTypes::scheduled, Pstream::masterNo());
349  toMaster << pointCells_;
350  toMaster << cellProc_;
351  }
352  }
353 
354 
355  //send accumulated data to slave processes
356  if (Pstream::master())
357  {
358  for(label proci = Pstream::firstSlave(); proci <= Pstream::lastSlave(); proci++)
359  {
360  OPstream toSlave(Pstream::commsTypes::scheduled, proci);
361  //toSlave << pointProcs_;
362  toSlave << pointCells_;
363  toSlave << cellProc_;
364  }
365  }
366  else
367  {
368  //pointProcs_.clearStorage();
369  pointCells_.clearStorage();
370  cellProc_.clearStorage();
371 
372  IPstream fromMaster(Pstream::commsTypes::scheduled, Pstream::masterNo());
373  //fromMaster >> pointProcs_;
374  fromMaster >> pointCells_;
375  fromMaster >> cellProc_;
376  }
377 
378  Info << "Data redistributed" << endl;
379 
380  //loop over multiple processor vertices and find corresponding faces and patch id's
381 
382  labelHashTable<List<label> > faceIds;
383  labelHashTable<label> faceProcPatch;
384  labelHashTable<List<label> > faceNeigCells;
385  labelHashTable<labelHashSet> neigProcFaces;
386  List<DynamicList<label> > globalCorCellIds;
387  labelHashTable<label> globalCorProcIds;
388  //labelHashTable<List<label> > globalCellIds;
389 
390  {
391  label gPointId = -1;
392  label pointId = -1;
393  label faceId = -1;
394  label fPatchId = -1;
395  //Pout << "multipleProcsPoints = " << multipleProcsPoints << endl;
396  forAll(multipleProcsPoints, iPoint)
397  {
398  gPointId = multipleProcsPoints[iPoint];
399  pointId = globalPointProcAddr[gPointId];
400  labelList locFaceIds = cMesh_.pointFaces()[pointId];
401  forAll(locFaceIds, iFace)
402  {
403  faceId = locFaceIds[iFace];
404  if (cMesh_.isInternalFace(faceId)) //do nothing within this implementation
405  {
406  }
407  else
408  {
409 
410  bool isProcPatch = false;
411  fPatchId = cMesh_.boundaryMesh().whichPatch(faceId);
412  forAll(procPairs_, iPatch)
413  {
414  if (fPatchId == procPairs_[iPatch])
415  {
416  isProcPatch = true;
417  break;
418  }
419  }
420  if (isProcPatch)
421  {
422  if (faceIds.found(faceId))
423  {
424  faceIds[faceId].append(pointId);
425  }
426  else
427  {
428  faceIds.insert
429  (
430  faceId,
431  List<label>(1, pointId)
432  );
433  faceProcPatch.insert
434  (
435  faceId,
436  fPatchId
437  );
438  }
439  }
440  }
441  }
442  }
443  }
444 
445  //store for each face - global cell id at neighbouring process
446  {
447  label lPointId = -1;
448  label gPointId = -1;
449  label gCellId = -1;
450  label procId = -1;
451  label patchId = -1;
452  forAllConstIter(labelHashTable<List<label> >, faceIds, iter)
453  {
454  List<label> pIds = iter();
455  labelHashSet fCells;
456  forAll (pIds, iPoint)
457  {
458  lPointId = pIds[iPoint];
459  gPointId = localPointProcAddr[lPointId];
460  List<label> pCells = pointCells_[gPointId];
461  //store only uniqe cells and only from corner-neighbouring processes
462  forAll(pCells, iCell)
463  {
464  gCellId = pCells[iCell];
465  procId = cellProc_[gCellId];
466  //check that cell at "corner" process
467  //not self process or process connected through patch
468  bool cornerProcess = true;
469  if (Pstream::myProcNo() == procId)
470  {
471  cornerProcess = false;
472  }
473  patchId = cMesh_.boundaryMesh().whichPatch(iter.key());
474  if (neigProcs_[idProcPatchPairs_[patchId]] == procId)
475  {
476  cornerProcess = false;
477  }
478 
479  if (cornerProcess) // "corner" process
480  {
481  fCells.insert(gCellId); //make sure cell ids are unique
482  if (neigProcFaces.found(procId))
483  {
484  neigProcFaces[procId].insert(iter.key());
485  }
486  else
487  {
488  neigProcFaces.insert(procId, labelHashSet());
489  neigProcFaces[procId].insert(iter.key());
490  }
491  }
492  }
493  }
494  faceNeigCells.insert
495  (
496  iter.key(),
497  fCells.toc()
498  );
499  }
500  }
501 
502  //and create the list of cells ids, requested from neigb. process and addresing
503  //table from these cells to current proc. patch faces
504  {
505  corAddr_.resize(neigProcFaces.toc().size());
506  globalCorCellIds.resize(corAddr_.size());
507 
508  label iNeiProc = 0;
509  label patchId = -1;
510  label patchNo = -1;
511  label faceId = -1;
512  label faceNo = -1;
513  label gCellId = -1;
514  labelHashTable<label> cellk;
515  //Pout << "faceIds.toc() " << faceIds.toc() << endl;
516  forAll(faceIds.toc(), iFaceId)
517  {
518  cellk.insert
519  (
520  faceIds.toc()[iFaceId],
521  0
522  );
523  }
524 
525  forAllConstIter(labelHashTable<labelHashSet>, neigProcFaces, iter)
526  {
527  neigProcs_.append(iter.key());
528  procPairs_.append(-1); //corner pair
529  globalCorProcIds.insert(iter.key(),iNeiProc);
530 
531  List<label> procFaceIds = iter().toc();
532 
533  forAll(procFaceIds, iFace)
534  {
535  faceId = procFaceIds[iFace];
536  patchId= cMesh_.boundaryMesh().whichPatch(faceId);
537  patchNo= idProcPatchPairs_[patchId];
538  faceNo = cMesh_.boundaryMesh()[patchId].whichFace(faceId);
539 
540  List<label> cellIds = faceNeigCells[faceId];
541 
542  forAll(cellIds, iCell)
543  {
544  gCellId = cellIds[iCell];
545 
546  if (cellProc_[gCellId] == iter.key())
547  {
548  globalCorCellIds[iNeiProc].append(gCellId);
549  corAddr_[iNeiProc].append
550  (
552  ()
553  );
554 
555  corAddr_[iNeiProc].last()[0] =
556  patchNo; // # patch
557  corAddr_[iNeiProc].last()[1] =
558  faceNo; // # face at patch
559  corAddr_[iNeiProc].last()[2] =
560  cellk[faceId]; // # cell for face
561  cellk[faceId]++;
562  }
563  }
564  corEnd_[patchNo][faceNo] = corStart_[patchNo][faceNo] + cellk[faceId] - 1;
565  }
566  iNeiProc++; //next proc
567  }
568  }
569 
570  //redistribute global cell ids amongth other processors
571  //and convert global addressing to local addressing
572  forAll(neigProcs_, iProc)
573  {
574  if (procPairs_[iProc] < 0)
575  {
576  label procId = neigProcs_[iProc];
577  label id = globalCorProcIds[procId];
578 
579  OPstream oStream (Pstream::commsTypes::scheduled, procId);
580  oStream << globalCorCellIds[id];
581  }
582  }
583 
584  corCellIds_.resize(corAddr_.size());
585  label iCorProc = 0;
586  forAll(neigProcs_, iProc)
587  {
588  if (procPairs_[iProc] < 0)
589  {
590  label procId = neigProcs_[iProc];
591  IPstream iStream (Pstream::commsTypes::scheduled, procId);
592  List<label> neiGlobalCellIds (iStream);
593 
594  corProcIds_.insert
595  (
596  procId,
597  iCorProc
598  );
599 
600  corCellIds_[iCorProc].resize(neiGlobalCellIds.size());
601 
602  forAll(neiGlobalCellIds, iCell)
603  {
604  corCellIds_[iCorProc][iCell] =
605  globalCellProcAddr[neiGlobalCellIds[iCell]];
606  }
607 
608  iCorProc++;
609  }
610  }
611 
612  }
613 
614 };
615 
616 //
617 //END-OF-FILE
618 //
619 
HashTable< T, label, Hash< label >> labelHashTable
labelHashTable< label > cellProc_
labelHashTable< label > corProcIds_
List< face > faceList
labelHashTable< label > idProcPatchPairs_
HashSet< label, Hash< label > > labelHashSet
List2< Triple< label > > corAddr_
forAll(Y, i)
Definition: QGDYEqn.H:36
void findNeighbours()
Find neighbour cells for each face (throught face points).
labelHashTable< List< label > > pointCells_