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