PatchEdgeFaceWave.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 | Copyright (C) 2011 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "PatchEdgeFaceWave.H"
27 #include "polyMesh.H"
28 #include "globalMeshData.H"
29 #include "PatchTools.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 template
34 <
35  class PrimitivePatchType,
36  class Type,
37  class TrackingData
38 >
40 propagationTol_ = 0.01;
41 
42 template
43 <
44  class PrimitivePatchType,
45  class Type,
46  class TrackingData
47 >
50 dummyTrackData_ = 12345;
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 // Update info for edgeI, at position pt, with information from
56 // neighbouring face.
57 // Updates:
58 // - changedEdge_, changedEdges_,
59 // - statistics: nEvals_, nUnvisitedEdges_
60 template
61 <
62  class PrimitivePatchType,
63  class Type,
64  class TrackingData
65 >
68 (
69  const label edgeI,
70  const label neighbourFaceI,
71  const Type& neighbourInfo,
72  Type& edgeInfo
73 )
74 {
75  nEvals_++;
76 
77  bool wasValid = edgeInfo.valid(td_);
78 
79  bool propagate =
80  edgeInfo.updateEdge
81  (
82  mesh_,
83  patch_,
84  edgeI,
85  neighbourFaceI,
86  neighbourInfo,
87  propagationTol_,
88  td_
89  );
90 
91  if (propagate)
92  {
93  if (!changedEdge_[edgeI])
94  {
95  changedEdge_[edgeI] = true;
96  changedEdges_.append(edgeI);
97  }
98  }
99 
100  if (!wasValid && edgeInfo.valid(td_))
101  {
102  --nUnvisitedEdges_;
103  }
104 
105  return propagate;
106 }
107 
108 
109 // Update info for faceI, at position pt, with information from
110 // neighbouring edge.
111 // Updates:
112 // - changedFace_, changedFaces_,
113 // - statistics: nEvals_, nUnvisitedFace_
114 template
115 <
116  class PrimitivePatchType,
117  class Type,
118  class TrackingData
119 >
122 (
123  const label faceI,
124  const label neighbourEdgeI,
125  const Type& neighbourInfo,
126  Type& faceInfo
127 )
128 {
129  nEvals_++;
130 
131  bool wasValid = faceInfo.valid(td_);
132 
133  bool propagate =
134  faceInfo.updateFace
135  (
136  mesh_,
137  patch_,
138  faceI,
139  neighbourEdgeI,
140  neighbourInfo,
141  propagationTol_,
142  td_
143  );
144 
145  if (propagate)
146  {
147  if (!changedFace_[faceI])
148  {
149  changedFace_[faceI] = true;
150  changedFaces_.append(faceI);
151  }
152  }
153 
154  if (!wasValid && faceInfo.valid(td_))
155  {
156  --nUnvisitedFaces_;
157  }
158 
159  return propagate;
160 }
161 
162 
163 template
164 <
165  class PrimitivePatchType,
166  class Type,
167  class TrackingData
168 >
170 syncEdges()
171 {
172  const globalMeshData& globalData = mesh_.globalData();
173  const mapDistribute& map = globalData.globalEdgeSlavesMap();
174  const PackedBoolList& cppOrientation = globalData.globalEdgeOrientation();
175 
176  // Convert patch-edge data into cpp-edge data
177  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
178 
179  //- Construct with all data in consistent orientation
180  List<Type> cppEdgeData(map.constructSize());
181 
182  forAll(patchEdges_, i)
183  {
184  label patchEdgeI = patchEdges_[i];
185  label coupledEdgeI = coupledEdges_[i];
186 
187  if (changedEdge_[patchEdgeI])
188  {
189  const Type& data = allEdgeInfo_[patchEdgeI];
190 
191  // Patch-edge data needs to be converted into coupled-edge data
192  // (optionally flipped) and consistent in orientation with
193  // master of coupled edge (optionally flipped)
194  bool sameOrientation =
195  (
196  sameEdgeOrientation_[i]
197  == cppOrientation[coupledEdgeI]
198  );
199 
200  cppEdgeData[coupledEdgeI].updateEdge
201  (
202  mesh_,
203  patch_,
204  data,
205  sameOrientation,
206  propagationTol_,
207  td_
208  );
209  }
210  }
211 
212 
213  // Synchronise
214  // ~~~~~~~~~~~
215 
216  globalData.syncData
217  (
218  cppEdgeData,
219  globalData.globalEdgeSlaves(),
220  globalData.globalEdgeTransformedSlaves(),
221  map,
222  globalData.globalTransforms(),
223  updateOp<PrimitivePatchType, Type, TrackingData>
224  (
225  mesh_,
226  patch_,
227  propagationTol_,
228  td_
229  ),
230  transformOp<PrimitivePatchType, Type, TrackingData>
231  (
232  mesh_,
233  patch_,
234  propagationTol_,
235  td_
236  )
237  );
238 
239 
240  // Back from cpp-edge to patch-edge data
241  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242 
243  forAll(patchEdges_, i)
244  {
245  label patchEdgeI = patchEdges_[i];
246  label coupledEdgeI = coupledEdges_[i];
247 
248  const Type& data = cppEdgeData[coupledEdgeI];
249 
250  if (data.valid(td_))
251  {
252  bool sameOrientation =
253  (
254  sameEdgeOrientation_[i]
255  == cppOrientation[coupledEdgeI]
256  );
257 
258  allEdgeInfo_[patchEdgeI].updateEdge
259  (
260  mesh_,
261  patch_,
262  data,
263  sameOrientation,
264  propagationTol_,
265  td_
266  );
267 
268  if (!changedEdge_[patchEdgeI])
269  {
270  changedEdges_.append(patchEdgeI);
271  changedEdge_[patchEdgeI] = true;
272  }
273  }
274  }
275 }
276 
277 
278 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
279 
280 // Iterate, propagating changedEdgesInfo across patch, until no change (or
281 // maxIter reached). Initial edge values specified.
282 template
283 <
284  class PrimitivePatchType,
285  class Type,
286  class TrackingData
287 >
290 (
291  const polyMesh& mesh,
292  const PrimitivePatchType& patch,
293  const labelList& changedEdges,
294  const List<Type>& changedEdgesInfo,
295 
296  UList<Type>& allEdgeInfo,
297  UList<Type>& allFaceInfo,
298 
299  const label maxIter,
300  TrackingData& td
301 )
302 :
303  mesh_(mesh),
304  patch_(patch),
305  allEdgeInfo_(allEdgeInfo),
306  allFaceInfo_(allFaceInfo),
307  td_(td),
308  changedEdge_(patch_.nEdges()),
309  changedEdges_(patch_.size()),
310  changedFace_(patch_.size()),
311  changedFaces_(patch_.size()),
312  nEvals_(0),
313  nUnvisitedEdges_(patch_.nEdges()),
314  nUnvisitedFaces_(patch_.size())
315 {
316  // Calculate addressing between patch_ and mesh.globalData().coupledPatch()
317  // for ease of synchronisation
318  PatchTools::matchEdges
319  (
320  patch_,
321  mesh_.globalData().coupledPatch(),
322 
323  patchEdges_,
324  coupledEdges_,
325  sameEdgeOrientation_
326  );
327 
328 
329  if (allEdgeInfo_.size() != patch_.nEdges())
330  {
332  (
333  "PatchEdgeFaceWave<Type, TrackingData>::PatchEdgeFaceWave"
334  "(const polyMesh&, const labelList&, const List<Type>,"
335  " List<Type>&, List<Type>&, const label maxIter)"
336  ) << "size of edgeInfo work array is not equal to the number"
337  << " of edges in the patch" << endl
338  << " edgeInfo :" << allEdgeInfo_.size() << endl
339  << " patch.nEdges:" << patch_.nEdges()
340  << exit(FatalError);
341  }
342  if (allFaceInfo_.size() != patch_.size())
343  {
345  (
346  "PatchEdgeFaceWave<Type, TrackingData>::PatchEdgeFaceWave"
347  "(const polyMesh&, const labelList&, const List<Type>,"
348  " List<Type>&, List<Type>&, const label maxIter)"
349  ) << "size of edgeInfo work array is not equal to the number"
350  << " of faces in the patch" << endl
351  << " faceInfo :" << allFaceInfo_.size() << endl
352  << " patch.size:" << patch_.size()
353  << exit(FatalError);
354  }
355 
356 
357  // Set from initial changed edges data
358  setEdgeInfo(changedEdges, changedEdgesInfo);
359 
360  if (debug)
361  {
362  Pout<< "Seed edges : " << changedEdges_.size() << endl;
363  }
364 
365  // Iterate until nothing changes
366  label iter = iterate(maxIter);
367 
368  if ((maxIter > 0) && (iter >= maxIter))
369  {
371  (
372  "PatchEdgeFaceWave<Type, TrackingData>::PatchEdgeFaceWave"
373  "(const polyMesh&, const labelList&, const List<Type>,"
374  " List<Type>&, List<Type>&, const label maxIter)"
375  ) << "Maximum number of iterations reached. Increase maxIter." << endl
376  << " maxIter:" << maxIter << endl
377  << " changedEdges:" << changedEdges_.size() << endl
378  << " changedFaces:" << changedFaces_.size() << endl
379  << exit(FatalError);
380  }
381 }
382 
383 
384 template
385 <
386  class PrimitivePatchType,
387  class Type,
388  class TrackingData
389 >
392 (
393  const polyMesh& mesh,
394  const PrimitivePatchType& patch,
395  UList<Type>& allEdgeInfo,
396  UList<Type>& allFaceInfo,
397  TrackingData& td
398 )
399 :
400  mesh_(mesh),
401  patch_(patch),
402  allEdgeInfo_(allEdgeInfo),
403  allFaceInfo_(allFaceInfo),
404  td_(td),
405  changedEdge_(patch_.nEdges()),
406  changedEdges_(patch_.nEdges()),
407  changedFace_(patch_.size()),
408  changedFaces_(patch_.size()),
409  nEvals_(0),
410  nUnvisitedEdges_(patch_.nEdges()),
411  nUnvisitedFaces_(patch_.size())
412 {
413  // Calculate addressing between patch_ and mesh.globalData().coupledPatch()
414  // for ease of synchronisation
415  PatchTools::matchEdges
416  (
417  patch_,
418  mesh_.globalData().coupledPatch(),
419 
420  patchEdges_,
421  coupledEdges_,
422  sameEdgeOrientation_
423  );
424 }
425 
426 
427 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
428 
429 template
430 <
431  class PrimitivePatchType,
432  class Type,
433  class TrackingData
434 >
437 {
438  return nUnvisitedEdges_;
439 }
440 
441 
442 template
443 <
444  class PrimitivePatchType,
445  class Type,
446  class TrackingData
447 >
450 {
451  return nUnvisitedFaces_;
452 }
453 
454 
455 // Copy edge information into member data
456 template
457 <
458  class PrimitivePatchType,
459  class Type,
460  class TrackingData
461 >
464 (
465  const labelList& changedEdges,
466  const List<Type>& changedEdgesInfo
467 )
468 {
469  forAll(changedEdges, changedEdgeI)
470  {
471  label edgeI = changedEdges[changedEdgeI];
472 
473  bool wasValid = allEdgeInfo_[edgeI].valid(td_);
474 
475  // Copy info for edgeI
476  allEdgeInfo_[edgeI] = changedEdgesInfo[changedEdgeI];
477 
478  // Maintain count of unset edges
479  if (!wasValid && allEdgeInfo_[edgeI].valid(td_))
480  {
481  --nUnvisitedEdges_;
482  }
483 
484  // Mark edgeI as changed, both on list and on edge itself.
485 
486  if (!changedEdge_[edgeI])
487  {
488  changedEdge_[edgeI] = true;
489  changedEdges_.append(edgeI);
490  }
491  }
492 }
493 
494 
495 // Propagate information from face to edge. Return number of edges changed.
496 template
497 <
498  class PrimitivePatchType,
499  class Type,
500  class TrackingData
501 >
504 {
505  changedEdges_.clear();
506  changedEdge_ = false;
507 
508  forAll(changedFaces_, changedFaceI)
509  {
510  label faceI = changedFaces_[changedFaceI];
511 
512  if (!changedFace_[faceI])
513  {
514  FatalErrorIn("PatchEdgeFaceWave<Type, TrackingData>::faceToEdge()")
515  << "face " << faceI
516  << " not marked as having been changed" << nl
517  << "This might be caused by multiple occurences of the same"
518  << " seed edge." << abort(FatalError);
519  }
520 
521  const Type& neighbourWallInfo = allFaceInfo_[faceI];
522 
523  // Evaluate all connected edges
524  const labelList& fEdges = patch_.faceEdges()[faceI];
525 
526  forAll(fEdges, fEdgeI)
527  {
528  label edgeI = fEdges[fEdgeI];
529 
530  Type& currentWallInfo = allEdgeInfo_[edgeI];
531 
532  if (!currentWallInfo.equal(neighbourWallInfo, td_))
533  {
534  updateEdge
535  (
536  edgeI,
537  faceI,
538  neighbourWallInfo,
539  currentWallInfo
540  );
541  }
542  }
543  }
544 
545 
546  syncEdges();
547 
548 
549  if (debug)
550  {
551  Pout<< "Changed edges : " << changedEdges_.size() << endl;
552  }
553 
554  return returnReduce(changedEdges_.size(), sumOp<label>());
555 }
556 
557 
558 // Propagate information from edge to face. Return number of faces changed.
559 template
560 <
561  class PrimitivePatchType,
562  class Type,
563  class TrackingData
564 >
567 {
568  changedFaces_.clear();
569  changedFace_ = false;
570 
571  const labelListList& edgeFaces = patch_.edgeFaces();
572 
573  forAll(changedEdges_, changedEdgeI)
574  {
575  label edgeI = changedEdges_[changedEdgeI];
576 
577  if (!changedEdge_[edgeI])
578  {
579  FatalErrorIn("PatchEdgeFaceWave<Type, TrackingData>::edgeToFace()")
580  << "edge " << edgeI
581  << " not marked as having been changed" << nl
582  << "This might be caused by multiple occurences of the same"
583  << " seed edge." << abort(FatalError);
584  }
585 
586  const Type& neighbourWallInfo = allEdgeInfo_[edgeI];
587 
588  // Evaluate all connected faces
589 
590  const labelList& eFaces = edgeFaces[edgeI];
591  forAll(eFaces, eFaceI)
592  {
593  label faceI = eFaces[eFaceI];
594 
595  Type& currentWallInfo = allFaceInfo_[faceI];
596 
597  if (!currentWallInfo.equal(neighbourWallInfo, td_))
598  {
599  updateFace
600  (
601  faceI,
602  edgeI,
603  neighbourWallInfo,
604  currentWallInfo
605  );
606  }
607  }
608  }
609 
610  if (debug)
611  {
612  Pout<< "Changed faces : " << changedFaces_.size() << endl;
613  }
614 
615  return returnReduce(changedFaces_.size(), sumOp<label>());
616 }
617 
618 
619 // Iterate
620 template
621 <
622  class PrimitivePatchType,
623  class Type,
624  class TrackingData
625 >
627 iterate
628 (
629  const label maxIter
630 )
631 {
632  // Make sure coupled edges contain same info
633  syncEdges();
634 
635  nEvals_ = 0;
636 
637  label iter = 0;
638 
639  while (iter < maxIter)
640  {
641  if (debug)
642  {
643  Pout<< "Iteration " << iter << endl;
644  }
645 
646  label nFaces = edgeToFace();
647 
648  if (debug)
649  {
650  Pout<< "Total changed faces : " << nFaces << endl;
651  }
652 
653  if (nFaces == 0)
654  {
655  break;
656  }
657 
658  label nEdges = faceToEdge();
659 
660  if (debug)
661  {
662  Pout<< "Total changed edges : " << nEdges << nl
663  << "Total evaluations : " << nEvals_ << nl
664  << "Remaining unvisited edges : " << nUnvisitedEdges_ << nl
665  << "Remaining unvisited faces : " << nUnvisitedFaces_ << nl
666  << endl;
667  }
668 
669  if (nEdges == 0)
670  {
671  break;
672  }
673 
674  iter++;
675  }
676 
677  return iter;
678 }
679 
680 
681 // ************************************************************************* //
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const char nl
Definition: Ostream.H:260
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
label iterate(const label maxIter)
Iterate until no changes or maxIter reached. Returns actual.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
label edgeToFace()
Propagate from edge to face. Returns total number of faces.
#define forAll(list, i)
Definition: UList.H:421
errorManip< error > abort(error &err)
Definition: errorManip.H:131
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
void setEdgeInfo(const labelList &changedEdges, const List< Type > &changedEdgesInfo)
Copy initial data into allEdgeInfo_.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
error FatalError
label getUnsetFaces() const
Get number of unvisited faces, i.e. faces that were not (yet)
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:97
label faceToEdge()
Propagate from face to edge. Returns total number of edges.
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53