PatchEdgeFaceWave.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2018 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  << "size of edgeInfo work array is not equal to the number"
333  << " of edges in the patch" << endl
334  << " edgeInfo :" << allEdgeInfo_.size() << endl
335  << " patch.nEdges:" << patch_.nEdges()
336  << exit(FatalError);
337  }
338  if (allFaceInfo_.size() != patch_.size())
339  {
341  << "size of edgeInfo work array is not equal to the number"
342  << " of faces in the patch" << endl
343  << " faceInfo :" << allFaceInfo_.size() << endl
344  << " patch.size:" << patch_.size()
345  << exit(FatalError);
346  }
347 
348 
349  // Set from initial changed edges data
350  setEdgeInfo(changedEdges, changedEdgesInfo);
351 
352  if (debug)
353  {
354  Pout<< "Seed edges : " << changedEdges_.size() << endl;
355  }
356 
357  // Iterate until nothing changes
358  label iter = iterate(maxIter);
359 
360  if ((maxIter > 0) && (iter >= maxIter))
361  {
363  << "Maximum number of iterations reached. Increase maxIter." << endl
364  << " maxIter:" << maxIter << endl
365  << " changedEdges:" << changedEdges_.size() << endl
366  << " changedFaces:" << changedFaces_.size() << endl
367  << exit(FatalError);
368  }
369 }
370 
371 
372 template
373 <
374  class PrimitivePatchType,
375  class Type,
376  class TrackingData
377 >
380 (
381  const polyMesh& mesh,
382  const PrimitivePatchType& patch,
383  UList<Type>& allEdgeInfo,
384  UList<Type>& allFaceInfo,
385  TrackingData& td
386 )
387 :
388  mesh_(mesh),
389  patch_(patch),
390  allEdgeInfo_(allEdgeInfo),
391  allFaceInfo_(allFaceInfo),
392  td_(td),
393  changedEdge_(patch_.nEdges()),
394  changedEdges_(patch_.nEdges()),
395  changedFace_(patch_.size()),
396  changedFaces_(patch_.size()),
397  nEvals_(0),
398  nUnvisitedEdges_(patch_.nEdges()),
399  nUnvisitedFaces_(patch_.size())
400 {
401  // Calculate addressing between patch_ and mesh.globalData().coupledPatch()
402  // for ease of synchronisation
403  PatchTools::matchEdges
404  (
405  patch_,
406  mesh_.globalData().coupledPatch(),
407 
408  patchEdges_,
409  coupledEdges_,
410  sameEdgeOrientation_
411  );
412 }
413 
414 
415 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
416 
417 template
418 <
419  class PrimitivePatchType,
420  class Type,
421  class TrackingData
422 >
425 {
426  return nUnvisitedEdges_;
427 }
428 
429 
430 template
431 <
432  class PrimitivePatchType,
433  class Type,
434  class TrackingData
435 >
438 {
439  return nUnvisitedFaces_;
440 }
441 
442 
443 // Copy edge information into member data
444 template
445 <
446  class PrimitivePatchType,
447  class Type,
448  class TrackingData
449 >
452 (
453  const labelList& changedEdges,
454  const List<Type>& changedEdgesInfo
455 )
456 {
457  forAll(changedEdges, changedEdgeI)
458  {
459  label edgeI = changedEdges[changedEdgeI];
460 
461  bool wasValid = allEdgeInfo_[edgeI].valid(td_);
462 
463  // Copy info for edgeI
464  allEdgeInfo_[edgeI] = changedEdgesInfo[changedEdgeI];
465 
466  // Maintain count of unset edges
467  if (!wasValid && allEdgeInfo_[edgeI].valid(td_))
468  {
469  --nUnvisitedEdges_;
470  }
471 
472  // Mark edgeI as changed, both on list and on edge itself.
473 
474  if (!changedEdge_[edgeI])
475  {
476  changedEdge_[edgeI] = true;
477  changedEdges_.append(edgeI);
478  }
479  }
480 }
481 
482 
483 // Propagate information from face to edge. Return number of edges changed.
484 template
485 <
486  class PrimitivePatchType,
487  class Type,
488  class TrackingData
489 >
492 {
493  changedEdges_.clear();
494  changedEdge_ = false;
495 
496  forAll(changedFaces_, changedFacei)
497  {
498  label facei = changedFaces_[changedFacei];
499 
500  if (!changedFace_[facei])
501  {
503  << "face " << facei
504  << " not marked as having been changed" << nl
505  << "This might be caused by multiple occurrences of the same"
506  << " seed edge." << abort(FatalError);
507  }
508 
509  const Type& neighbourWallInfo = allFaceInfo_[facei];
510 
511  // Evaluate all connected edges
512  const labelList& fEdges = patch_.faceEdges()[facei];
513 
514  forAll(fEdges, fEdgeI)
515  {
516  label edgeI = fEdges[fEdgeI];
517 
518  Type& currentWallInfo = allEdgeInfo_[edgeI];
519 
520  if (!currentWallInfo.equal(neighbourWallInfo, td_))
521  {
522  updateEdge
523  (
524  edgeI,
525  facei,
526  neighbourWallInfo,
527  currentWallInfo
528  );
529  }
530  }
531  }
532 
533 
534  syncEdges();
535 
536 
537  if (debug)
538  {
539  Pout<< "Changed edges : " << changedEdges_.size() << endl;
540  }
541 
542  return returnReduce(changedEdges_.size(), sumOp<label>());
543 }
544 
545 
546 // Propagate information from edge to face. Return number of faces changed.
547 template
548 <
549  class PrimitivePatchType,
550  class Type,
551  class TrackingData
552 >
555 {
556  changedFaces_.clear();
557  changedFace_ = false;
558 
559  const labelListList& edgeFaces = patch_.edgeFaces();
560 
561  forAll(changedEdges_, changedEdgeI)
562  {
563  label edgeI = changedEdges_[changedEdgeI];
564 
565  if (!changedEdge_[edgeI])
566  {
568  << "edge " << edgeI
569  << " not marked as having been changed" << nl
570  << "This might be caused by multiple occurrences of the same"
571  << " seed edge." << abort(FatalError);
572  }
573 
574  const Type& neighbourWallInfo = allEdgeInfo_[edgeI];
575 
576  // Evaluate all connected faces
577 
578  const labelList& eFaces = edgeFaces[edgeI];
579  forAll(eFaces, eFacei)
580  {
581  label facei = eFaces[eFacei];
582 
583  Type& currentWallInfo = allFaceInfo_[facei];
584 
585  if (!currentWallInfo.equal(neighbourWallInfo, td_))
586  {
587  updateFace
588  (
589  facei,
590  edgeI,
591  neighbourWallInfo,
592  currentWallInfo
593  );
594  }
595  }
596  }
597 
598  if (debug)
599  {
600  Pout<< "Changed faces : " << changedFaces_.size() << endl;
601  }
602 
603  return returnReduce(changedFaces_.size(), sumOp<label>());
604 }
605 
606 
607 // Iterate
608 template
609 <
610  class PrimitivePatchType,
611  class Type,
612  class TrackingData
613 >
615 iterate
616 (
617  const label maxIter
618 )
619 {
620  // Make sure coupled edges contain same info
621  syncEdges();
622 
623  nEvals_ = 0;
624 
625  label iter = 0;
626 
627  while (iter < maxIter)
628  {
629  if (debug)
630  {
631  Pout<< "Iteration " << iter << endl;
632  }
633 
634  label nFaces = edgeToFace();
635 
636  if (debug)
637  {
638  Pout<< "Total changed faces : " << nFaces << endl;
639  }
640 
641  if (nFaces == 0)
642  {
643  break;
644  }
645 
646  label nEdges = faceToEdge();
647 
648  if (debug)
649  {
650  Pout<< "Total changed edges : " << nEdges << nl
651  << "Total evaluations : " << nEvals_ << nl
652  << "Remaining unvisited edges : " << nUnvisitedEdges_ << nl
653  << "Remaining unvisited faces : " << nUnvisitedFaces_ << nl
654  << endl;
655  }
656 
657  if (nEdges == 0)
658  {
659  break;
660  }
661 
662  iter++;
663  }
664 
665  return iter;
666 }
667 
668 
669 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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
label getUnsetFaces() const
Get number of unvisited faces, i.e. faces that were not (yet)
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Wave propagation of information along patch. Every iteration information goes through one layer of fa...
label faceToEdge()
Propagate from face to edge. Returns total number of edges.
label edgeToFace()
Propagate from edge to face. Returns total number of faces.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
PatchEdgeFaceWave(const polyMesh &mesh, const PrimitivePatchType &patch, const labelList &initialEdges, const List< Type > &initialEdgesInfo, UList< Type > &allEdgeInfo, UList< Type > &allFaceInfo, const label maxIter, TrackingData &td=dummyTrackData_)
Construct from patch, list of changed edges with the Type.
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:177
errorManip< error > abort(error &err)
Definition: errorManip.H:131
label iterate(const label maxIter)
Iterate until no changes or maxIter reached. Returns actual.
static const char nl
Definition: Ostream.H:265
void setEdgeInfo(const labelList &changedEdges, const List< Type > &changedEdgesInfo)
Copy initial data into allEdgeInfo_.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74