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