syncToolsTemplates.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-2017 OpenFOAM Foundation
9 Copyright (C) 2015-2022 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
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
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "syncTools.H"
30#include "polyMesh.H"
31#include "processorPolyPatch.H"
32#include "cyclicPolyPatch.H"
33#include "globalMeshData.H"
34#include "transformList.H"
35
36// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37
38template<class T, class CombineOp>
40(
41 Map<T>& pointValues,
42 const CombineOp& cop,
43 const label index,
44 const T& val
45)
46{
47 auto iter = pointValues.find(index);
48
49 if (iter.found())
50 {
51 cop(*iter, val);
52 }
53 else
54 {
55 pointValues.insert(index, val);
56 }
57}
58
59
60template<class T, class CombineOp>
62(
63 EdgeMap<T>& edgeValues,
64 const CombineOp& cop,
65 const edge& index,
66 const T& val
67)
68{
69 auto iter = edgeValues.find(index);
70
71 if (iter.found())
72 {
73 cop(*iter, val);
74 }
75 else
76 {
77 edgeValues.insert(index, val);
78 }
79}
80
81
82template<class T, class CombineOp, class TransformOp>
84(
85 const polyMesh& mesh,
86 Map<T>& pointValues, // from mesh point label to value
87 const CombineOp& cop,
88 const TransformOp& top
89)
90{
92
93 // Synchronize multiple shared points.
94 const globalMeshData& pd = mesh.globalData();
95
96 // Values on shared points. Keyed on global shared index.
97 Map<T> sharedPointValues(0);
98
99 if (pd.nGlobalPoints() > 0)
100 {
101 // meshPoint per local index
102 const labelList& sharedPtLabels = pd.sharedPointLabels();
103
104 // global shared index per local index
105 const labelList& sharedPtAddr = pd.sharedPointAddr();
106
107 sharedPointValues.resize(sharedPtAddr.size());
108
109 // Fill my entries in the shared points
110 forAll(sharedPtLabels, i)
111 {
112 const auto fnd = pointValues.cfind(sharedPtLabels[i]);
113
114 if (fnd.found())
115 {
116 combine
117 (
118 sharedPointValues,
119 cop,
120 sharedPtAddr[i], // index
121 *fnd // value
122 );
123 }
124 }
125 }
126
127
128 if (Pstream::parRun())
129 {
130 DynamicList<label> neighbProcs;
132
133 // Send
134 for (const polyPatch& pp : patches)
135 {
136 const auto* ppp = isA<processorPolyPatch>(pp);
137
138 if (ppp && pp.nPoints())
139 {
140 const auto& procPatch = *ppp;
141 const label nbrProci = procPatch.neighbProcNo();
142
143 // Get data per patchPoint in neighbouring point numbers.
144
145 const labelList& meshPts = procPatch.meshPoints();
146 const labelList& nbrPts = procPatch.neighbPoints();
147
148 // Extract local values. Create map from nbrPoint to value.
149 // Note: how small initial size?
150 Map<T> patchInfo(meshPts.size() / 20);
151
152 forAll(meshPts, i)
153 {
154 const auto iter = pointValues.cfind(meshPts[i]);
155
156 if (iter.found())
157 {
158 patchInfo.insert(nbrPts[i], *iter);
159 }
160 }
161
162 neighbProcs.append(nbrProci);
163 UOPstream toNbr(nbrProci, pBufs);
164 toNbr << patchInfo;
165 }
166 }
167
168 // Limit exchange to involved procs
169 pBufs.finishedNeighbourSends(neighbProcs);
170
171 // Receive and combine.
172 for (const polyPatch& pp : patches)
173 {
174 const auto* ppp = isA<processorPolyPatch>(pp);
175
176 if (ppp && pp.nPoints())
177 {
178 const auto& procPatch = *ppp;
179 const label nbrProci = procPatch.neighbProcNo();
180
181 UIPstream fromNbr(nbrProci, pBufs);
182 Map<T> nbrPatchInfo(fromNbr);
183
184 // Transform
185 top(procPatch, nbrPatchInfo);
186
187 const labelList& meshPts = procPatch.meshPoints();
188
189 // Only update those values which come from neighbour
190 forAllConstIters(nbrPatchInfo, nbrIter)
191 {
192 combine
193 (
194 pointValues,
195 cop,
196 meshPts[nbrIter.key()],
197 nbrIter.val()
198 );
199 }
200 }
201 }
202 }
203
204 // Do the cyclics.
205 for (const polyPatch& pp : patches)
206 {
207 const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
208
209 if (cpp && cpp->owner())
210 {
211 // Owner does all.
212
213 const cyclicPolyPatch& cycPatch = *cpp;
214 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
215
216 const edgeList& coupledPoints = cycPatch.coupledPoints();
217 const labelList& meshPtsA = cycPatch.meshPoints();
218 const labelList& meshPtsB = nbrPatch.meshPoints();
219
220 // Extract local values. Create map from coupled-edge to value.
221 Map<T> half0Values(meshPtsA.size() / 20);
222 Map<T> half1Values(half0Values.size());
223
224 forAll(coupledPoints, i)
225 {
226 const edge& e = coupledPoints[i];
227
228 const auto point0Fnd = pointValues.cfind(meshPtsA[e[0]]);
229
230 if (point0Fnd.found())
231 {
232 half0Values.insert(i, *point0Fnd);
233 }
234
235 const auto point1Fnd = pointValues.cfind(meshPtsB[e[1]]);
236
237 if (point1Fnd.found())
238 {
239 half1Values.insert(i, *point1Fnd);
240 }
241 }
242
243 // Transform to receiving side
244 top(cycPatch, half1Values);
245 top(nbrPatch, half0Values);
246
247 forAll(coupledPoints, i)
248 {
249 const edge& e = coupledPoints[i];
250
251 const auto half0Fnd = half0Values.cfind(i);
252
253 if (half0Fnd.found())
254 {
255 combine
256 (
257 pointValues,
258 cop,
259 meshPtsB[e[1]],
260 *half0Fnd
261 );
262 }
263
264 const auto half1Fnd = half1Values.cfind(i);
265
266 if (half1Fnd.found())
267 {
268 combine
269 (
270 pointValues,
271 cop,
272 meshPtsA[e[0]],
273 *half1Fnd
274 );
275 }
276 }
277 }
278 }
279
280 // Synchronize multiple shared points.
281 if (pd.nGlobalPoints() > 0)
282 {
283 // meshPoint per local index
284 const labelList& sharedPtLabels = pd.sharedPointLabels();
285 // global shared index per local index
286 const labelList& sharedPtAddr = pd.sharedPointAddr();
287
288 // Reduce on master.
289
290 if (Pstream::parRun())
291 {
292 if (Pstream::master())
293 {
294 // Receive the edges using shared points from other procs
295 for (const int proci : Pstream::subProcs())
296 {
298 Map<T> nbrValues(fromProc);
299
300 // Merge neighbouring values with my values
301 forAllConstIters(nbrValues, iter)
302 {
303 combine
304 (
305 sharedPointValues,
306 cop,
307 iter.key(), // edge
308 iter.val() // value
309 );
310 }
311 }
312 }
313 else
314 {
315 // Send to master
316 OPstream toMaster
317 (
320 );
321 toMaster << sharedPointValues;
322 }
323
324 // Broadcast: send merged values to all
325 Pstream::scatter(sharedPointValues);
326 }
327
328 // Merge sharedPointValues (keyed on sharedPointAddr) into
329 // pointValues (keyed on mesh points).
330
331 // Map from global shared index to meshpoint
332 Map<label> sharedToMeshPoint(2*sharedPtAddr.size());
333 forAll(sharedPtAddr, i)
334 {
335 sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
336 }
337
338 forAllConstIters(sharedToMeshPoint, iter)
339 {
340 // Do I have a value for my shared point
341 const auto sharedFnd = sharedPointValues.cfind(iter.key());
342
343 if (sharedFnd.found())
344 {
345 pointValues.set(*iter, *sharedFnd);
346 }
347 }
348 }
349}
350
351
352template<class T, class CombineOp, class TransformOp>
354(
355 const polyMesh& mesh,
356 EdgeMap<T>& edgeValues,
357 const CombineOp& cop,
358 const TransformOp& top
359)
360{
362
363
364 // Do synchronisation without constructing globalEdge addressing
365 // (since this constructs mesh edge addressing)
366
367
368 // Swap proc patch info
369 // ~~~~~~~~~~~~~~~~~~~~
370
371 if (Pstream::parRun())
372 {
373 DynamicList<label> neighbProcs;
375
376 // Send
377 for (const polyPatch& pp : patches)
378 {
379 const auto* ppp = isA<processorPolyPatch>(pp);
380
381 if (ppp && pp.nEdges())
382 {
383 const auto& procPatch = *ppp;
384 const label nbrProci = procPatch.neighbProcNo();
385
386 // Get data per patch edge in neighbouring edge.
387
388 const edgeList& edges = procPatch.edges();
389 const labelList& meshPts = procPatch.meshPoints();
390 const labelList& nbrPts = procPatch.neighbPoints();
391
392 EdgeMap<T> patchInfo(edges.size() / 20);
393
394 for (const edge& e : edges)
395 {
396 const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
397
398 const auto iter = edgeValues.cfind(meshEdge);
399
400 if (iter.found())
401 {
402 const edge nbrEdge(nbrPts[e[0]], nbrPts[e[1]]);
403 patchInfo.insert(nbrEdge, *iter);
404 }
405 }
406
407 neighbProcs.append(nbrProci);
408 UOPstream toNbr(nbrProci, pBufs);
409 toNbr << patchInfo;
410 }
411 }
412
413 // Limit exchange to involved procs
414 pBufs.finishedNeighbourSends(neighbProcs);
415
416
417 // Receive and combine.
418 for (const polyPatch& pp : patches)
419 {
420 const auto* ppp = isA<processorPolyPatch>(pp);
421
422 if (ppp && pp.nEdges())
423 {
424 const auto& procPatch = *ppp;
425
426 EdgeMap<T> nbrPatchInfo;
427 {
428 UIPstream fromNbr(procPatch.neighbProcNo(), pBufs);
429 fromNbr >> nbrPatchInfo;
430 }
431
432 // Apply transform to convert to this side properties.
433 top(procPatch, nbrPatchInfo);
434
435
436 // Only update those values which come from neighbour
437 const labelList& meshPts = procPatch.meshPoints();
438
439 forAllConstIters(nbrPatchInfo, nbrIter)
440 {
441 const edge& e = nbrIter.key();
442 const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
443
444 combine
445 (
446 edgeValues,
447 cop,
448 meshEdge, // edge
449 nbrIter.val() // value
450 );
451 }
452 }
453 }
454 }
455
456
457 // Swap cyclic info
458 // ~~~~~~~~~~~~~~~~
459
460 for (const polyPatch& pp : patches)
461 {
462 const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
463
464 if (cpp && cpp->owner())
465 {
466 // Owner does all.
467
468 const cyclicPolyPatch& cycPatch = *cpp;
469 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
470
471 const edgeList& coupledEdges = cycPatch.coupledEdges();
472
473 const labelList& meshPtsA = cycPatch.meshPoints();
474 const edgeList& edgesA = cycPatch.edges();
475
476 const labelList& meshPtsB = nbrPatch.meshPoints();
477 const edgeList& edgesB = nbrPatch.edges();
478
479 // Extract local values. Create map from edge to value.
480 Map<T> half0Values(edgesA.size() / 20);
481 Map<T> half1Values(half0Values.size());
482
483 forAll(coupledEdges, edgei)
484 {
485 const edge& twoEdges = coupledEdges[edgei];
486
487 {
488 const edge& e0 = edgesA[twoEdges[0]];
489 const edge meshEdge0(meshPtsA[e0[0]], meshPtsA[e0[1]]);
490
491 const auto iter = edgeValues.cfind(meshEdge0);
492
493 if (iter.found())
494 {
495 half0Values.insert(edgei, *iter);
496 }
497 }
498 {
499 const edge& e1 = edgesB[twoEdges[1]];
500 const edge meshEdge1(meshPtsB[e1[0]], meshPtsB[e1[1]]);
501
502 const auto iter = edgeValues.cfind(meshEdge1);
503
504 if (iter.found())
505 {
506 half1Values.insert(edgei, *iter);
507 }
508 }
509 }
510
511 // Transform to this side
512 top(cycPatch, half1Values);
513 top(nbrPatch, half0Values);
514
515
516 // Extract and combine information
517
518 forAll(coupledEdges, edgei)
519 {
520 const edge& twoEdges = coupledEdges[edgei];
521
522 const auto half1Fnd = half1Values.cfind(edgei);
523
524 if (half1Fnd.found())
525 {
526 const edge& e0 = edgesA[twoEdges[0]];
527 const edge meshEdge0(meshPtsA[e0[0]], meshPtsA[e0[1]]);
528
529 combine
530 (
531 edgeValues,
532 cop,
533 meshEdge0, // edge
534 *half1Fnd // value
535 );
536 }
537
538 const auto half0Fnd = half0Values.cfind(edgei);
539
540 if (half0Fnd.found())
541 {
542 const edge& e1 = edgesB[twoEdges[1]];
543 const edge meshEdge1(meshPtsB[e1[0]], meshPtsB[e1[1]]);
544
545 combine
546 (
547 edgeValues,
548 cop,
549 meshEdge1, // edge
550 *half0Fnd // value
551 );
552 }
553 }
554 }
555 }
556
557 // Synchronize multiple shared points.
558 // Problem is that we don't want to construct shared edges so basically
559 // we do here like globalMeshData but then using sparse edge representation
560 // (EdgeMap instead of mesh.edges())
561
562 const globalMeshData& pd = mesh.globalData();
563 const labelList& sharedPtAddr = pd.sharedPointAddr();
564 const labelList& sharedPtLabels = pd.sharedPointLabels();
565
566 // 1. Create map from meshPoint to globalShared index.
567 Map<label> meshToShared(2*sharedPtLabels.size());
568 forAll(sharedPtLabels, i)
569 {
570 meshToShared.insert(sharedPtLabels[i], sharedPtAddr[i]);
571 }
572
573 // Values on shared points. From two sharedPtAddr indices to a value.
574 EdgeMap<T> sharedEdgeValues(meshToShared.size());
575
576 // From shared edge to mesh edge. Used for merging later on.
577 EdgeMap<edge> potentialSharedEdge(meshToShared.size());
578
579 // 2. Find any edges using two global shared points. These will always be
580 // on the outside of the mesh. (though might not be on coupled patch
581 // if is single edge and not on coupled face)
582 // Store value (if any) on sharedEdgeValues
583 for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
584 {
585 const face& f = mesh.faces()[facei];
586
587 forAll(f, fp)
588 {
589 const label v0 = f[fp];
590 const label v1 = f[f.fcIndex(fp)];
591
592 const auto v0Fnd = meshToShared.cfind(v0);
593
594 if (v0Fnd.found())
595 {
596 const auto v1Fnd = meshToShared.cfind(v1);
597
598 if (v1Fnd.found())
599 {
600 const edge meshEdge(v0, v1);
601
602 // edge in shared point labels
603 const edge sharedEdge(*v0Fnd, *v1Fnd);
604
605 // Store mesh edge as a potential shared edge.
606 potentialSharedEdge.insert(sharedEdge, meshEdge);
607
608 const auto edgeFnd = edgeValues.cfind(meshEdge);
609
610 if (edgeFnd.found())
611 {
612 // edge exists in edgeValues. See if already in map
613 // (since on same processor, e.g. cyclic)
614 combine
615 (
616 sharedEdgeValues,
617 cop,
618 sharedEdge, // edge
619 *edgeFnd // value
620 );
621 }
622 }
623 }
624 }
625 }
626
627
628 // Now sharedEdgeValues will contain per potential sharedEdge the value.
629 // (potential since an edge having two shared points is not necessary a
630 // shared edge).
631 // Reduce this on the master.
632
633 if (Pstream::parRun())
634 {
635 if (Pstream::master())
636 {
637 // Receive the edges using shared points from other procs
638 for (const int proci : Pstream::subProcs())
639 {
641 EdgeMap<T> nbrValues(fromProc);
642
643 // Merge neighbouring values with my values
644 forAllConstIters(nbrValues, iter)
645 {
646 combine
647 (
648 sharedEdgeValues,
649 cop,
650 iter.key(), // edge
651 iter.val() // value
652 );
653 }
654 }
655 }
656 else
657 {
658 // Send to master
659 {
660 OPstream toMaster
661 (
664 );
665 toMaster << sharedEdgeValues;
666 }
667 }
668
669 // Broadcast: send merged values to all
670 Pstream::scatter(sharedEdgeValues);
671 }
672
673
674 // Merge sharedEdgeValues (keyed on sharedPointAddr) into edgeValues
675 // (keyed on mesh points).
676
677 // Loop over all my shared edges.
678 forAllConstIters(potentialSharedEdge, iter)
679 {
680 const edge& sharedEdge = iter.key();
681 const edge& meshEdge = iter.val();
682
683 // Do I have a value for the shared edge?
684 const auto sharedFnd = sharedEdgeValues.cfind(sharedEdge);
685
686 if (sharedFnd.found())
687 {
688 combine
689 (
690 edgeValues,
691 cop,
692 meshEdge, // edge
693 *sharedFnd // value
694 );
695 }
696 }
697}
698
699
700template<class T, class CombineOp, class TransformOp>
702(
703 const polyMesh& mesh,
704 List<T>& pointValues,
705 const CombineOp& cop,
706 const T& nullValue,
707 const TransformOp& top
708)
709{
710 if (pointValues.size() != mesh.nPoints())
711 {
713 << "Number of values " << pointValues.size()
714 << " is not equal to the number of points in the mesh "
715 << mesh.nPoints() << abort(FatalError);
716 }
717
718 mesh.globalData().syncPointData(pointValues, cop, top);
719}
720
721
722template<class T, class CombineOp, class TransformOp>
724(
725 const polyMesh& mesh,
726 const labelUList& meshPoints,
727 List<T>& pointValues,
728 const CombineOp& cop,
729 const T& nullValue,
730 const TransformOp& top
731)
732{
733 if (pointValues.size() != meshPoints.size())
734 {
736 << "Number of values " << pointValues.size()
737 << " is not equal to the number of meshPoints "
738 << meshPoints.size() << abort(FatalError);
739 }
740 const globalMeshData& gd = mesh.globalData();
741 const indirectPrimitivePatch& cpp = gd.coupledPatch();
742 const Map<label>& mpm = cpp.meshPointMap();
743
744 List<T> cppFld(cpp.nPoints(), nullValue);
745
746 forAll(meshPoints, i)
747 {
748 const auto iter = mpm.cfind(meshPoints[i]);
749
750 if (iter.found())
751 {
752 cppFld[*iter] = pointValues[i];
753 }
754 }
755
757 (
758 cppFld,
762 gd.globalTransforms(),
763 cop,
764 top
765 );
766
767 forAll(meshPoints, i)
768 {
769 const auto iter = mpm.cfind(meshPoints[i]);
770
771 if (iter.found())
772 {
773 pointValues[i] = cppFld[*iter];
774 }
775 }
776}
777
778
779template<class T, class CombineOp, class TransformOp, class FlipOp>
781(
782 const polyMesh& mesh,
783 List<T>& edgeValues,
784 const CombineOp& cop,
785 const T& nullValue,
786 const TransformOp& top,
787 const FlipOp& fop
788)
789{
790 if (edgeValues.size() != mesh.nEdges())
791 {
793 << "Number of values " << edgeValues.size()
794 << " is not equal to the number of edges in the mesh "
795 << mesh.nEdges() << abort(FatalError);
796 }
797
798 const edgeList& edges = mesh.edges();
799 const globalMeshData& gd = mesh.globalData();
800 const labelList& meshEdges = gd.coupledPatchMeshEdges();
801 const indirectPrimitivePatch& cpp = gd.coupledPatch();
802 const edgeList& cppEdges = cpp.edges();
803 const labelList& mp = cpp.meshPoints();
805 const mapDistribute& edgeMap = gd.globalEdgeSlavesMap();
806 const bitSet& orientation = gd.globalEdgeOrientation();
807
808 List<T> cppFld(meshEdges.size());
809 forAll(meshEdges, i)
810 {
811 const edge& cppE = cppEdges[i];
812 const label meshEdgei = meshEdges[i];
813 const edge& meshE = edges[meshEdgei];
814
815 // 1. is cpp edge oriented as mesh edge
816 // 2. is cpp edge oriented same as master edge
817
818 const int dir = edge::compare(meshE, edge(mp, cppE));
819 if (dir == 0)
820 {
821 FatalErrorInFunction<< "Problem:"
822 << " mesh edge:" << meshE.line(mesh.points())
823 << " coupled edge:" << cppE.line(cpp.localPoints())
824 << exit(FatalError);
825 }
826
827 const bool sameOrientation = ((dir == 1) == orientation[i]);
828
829 if (sameOrientation)
830 {
831 cppFld[i] = edgeValues[meshEdgei];
832 }
833 else
834 {
835 cppFld[i] = fop(edgeValues[meshEdgei]);
836 }
837 }
838
839
841 (
842 cppFld,
843 gd.globalEdgeSlaves(),
845 edgeMap,
846 git,
847 cop,
848 top
849 );
850
851 // Extract back onto mesh
852 forAll(meshEdges, i)
853 {
854 const edge& cppE = cppEdges[i];
855 const label meshEdgei = meshEdges[i];
856 const edge& meshE = edges[meshEdgei];
857
858 // 1. is cpp edge oriented as mesh edge
859 // 2. is cpp edge oriented same as master edge
860
861 const int dir = edge::compare(meshE, edge(mp, cppE));
862 const bool sameOrientation = ((dir == 1) == orientation[i]);
863
864 if (sameOrientation)
865 {
866 edgeValues[meshEdges[i]] = cppFld[i];
867 }
868 else
869 {
870 edgeValues[meshEdges[i]] = fop(cppFld[i]);
871 }
872 }
873}
874
875
876template<class T, class CombineOp, class TransformOp, class FlipOp>
878(
879 const polyMesh& mesh,
880 const labelList& meshEdges,
881 List<T>& edgeValues,
882 const CombineOp& cop,
883 const T& nullValue,
884 const TransformOp& top,
885 const FlipOp& fop
886)
887{
888 if (edgeValues.size() != meshEdges.size())
889 {
891 << "Number of values " << edgeValues.size()
892 << " is not equal to the number of meshEdges "
893 << meshEdges.size() << abort(FatalError);
894 }
895 const edgeList& edges = mesh.edges();
896 const globalMeshData& gd = mesh.globalData();
897 const indirectPrimitivePatch& cpp = gd.coupledPatch();
898 const edgeList& cppEdges = cpp.edges();
899 const labelList& mp = cpp.meshPoints();
900 const Map<label>& mpm = gd.coupledPatchMeshEdgeMap();
901 const bitSet& orientation = gd.globalEdgeOrientation();
902
903 List<T> cppFld(cpp.nEdges(), nullValue);
904
905 forAll(meshEdges, i)
906 {
907 const label meshEdgei = meshEdges[i];
908 const auto iter = mpm.cfind(meshEdgei);
909 if (iter.found())
910 {
911 const label cppEdgei = iter();
912 const edge& cppE = cppEdges[cppEdgei];
913 const edge& meshE = edges[meshEdgei];
914
915 // 1. is cpp edge oriented as mesh edge
916 // 2. is cpp edge oriented same as master edge
917
918 const int dir = edge::compare(meshE, edge(mp, cppE));
919 if (dir == 0)
920 {
921 FatalErrorInFunction<< "Problem:"
922 << " mesh edge:" << meshE.line(mesh.points())
923 << " coupled edge:" << cppE.line(cpp.localPoints())
924 << exit(FatalError);
925 }
926
927 const bool sameOrientation = ((dir == 1) == orientation[i]);
928
929 if (sameOrientation)
930 {
931 cppFld[cppEdgei] = edgeValues[i];
932 }
933 else
934 {
935 cppFld[cppEdgei] = fop(edgeValues[i]);
936 }
937 }
938 }
939
941 (
942 cppFld,
943 gd.globalEdgeSlaves(),
946 gd.globalTransforms(),
947 cop,
948 top
949 );
950
951 forAll(meshEdges, i)
952 {
953 label meshEdgei = meshEdges[i];
954 Map<label>::const_iterator iter = mpm.find(meshEdgei);
955 if (iter != mpm.end())
956 {
957 label cppEdgei = iter();
958 const edge& cppE = cppEdges[cppEdgei];
959 const edge& meshE = edges[meshEdgei];
960
961 const int dir = edge::compare(meshE, edge(mp, cppE));
962 const bool sameOrientation = ((dir == 1) == orientation[i]);
963
964 if (sameOrientation)
965 {
966 edgeValues[i] = cppFld[cppEdgei];
967 }
968 else
969 {
970 edgeValues[i] = fop(cppFld[cppEdgei]);
971 }
972 }
973 }
974}
975
976
977template<class T, class CombineOp, class TransformOp>
979(
980 const polyMesh& mesh,
981 UList<T>& faceValues,
982 const CombineOp& cop,
983 const TransformOp& top,
984 const bool parRun
985)
986{
987 // Offset (global to local) for start of boundaries
988 const label boundaryOffset = mesh.nInternalFaces();
989
990 if (faceValues.size() != mesh.nBoundaryFaces())
991 {
993 << "Number of values " << faceValues.size()
994 << " is not equal to the number of boundary faces in the mesh "
995 << mesh.nBoundaryFaces() << nl
996 << abort(FatalError);
997 }
998
1000
1001 if (parRun)
1002 {
1003 // Avoid mesh.globalData() - possible race condition
1004
1005 if
1006 (
1009 )
1010 {
1011 const label startRequest = UPstream::nRequests();
1012
1013 // Receive buffer
1014 List<T> receivedValues(mesh.nBoundaryFaces());
1015
1016 // Set up reads
1017 for (const polyPatch& pp : patches)
1018 {
1019 const auto* ppp = isA<processorPolyPatch>(pp);
1020
1021 if (ppp && pp.size())
1022 {
1023 const auto& procPatch = *ppp;
1024
1026 (
1027 receivedValues,
1028 pp.size(),
1029 pp.start()-boundaryOffset
1030 );
1031
1033 (
1035 procPatch.neighbProcNo(),
1036 fld.data_bytes(),
1037 fld.size_bytes()
1038 );
1039 }
1040 }
1041
1042 // Set up writes
1043 for (const polyPatch& pp : patches)
1044 {
1045 const auto* ppp = isA<processorPolyPatch>(pp);
1046
1047 if (ppp && pp.size())
1048 {
1049 const auto& procPatch = *ppp;
1050
1051 const SubList<T> fld
1052 (
1053 faceValues,
1054 pp.size(),
1055 pp.start()-boundaryOffset
1056 );
1057
1059 (
1061 procPatch.neighbProcNo(),
1062 fld.cdata_bytes(),
1063 fld.size_bytes()
1064 );
1065 }
1066 }
1067
1068 // Wait for all comms to finish
1069 Pstream::waitRequests(startRequest);
1070
1071 // Combine with existing data
1072 for (const polyPatch& pp : patches)
1073 {
1074 const auto* ppp = isA<processorPolyPatch>(pp);
1075
1076 if (ppp && pp.size())
1077 {
1078 const auto& procPatch = *ppp;
1079
1080 SubList<T> recvFld
1081 (
1082 receivedValues,
1083 pp.size(),
1084 pp.start()-boundaryOffset
1085 );
1086 const List<T>& fakeList = recvFld;
1087 top(procPatch, const_cast<List<T>&>(fakeList));
1088
1089 SubList<T> patchValues
1090 (
1091 faceValues,
1092 pp.size(),
1093 pp.start()-boundaryOffset
1094 );
1095
1096 forAll(patchValues, i)
1097 {
1098 cop(patchValues[i], recvFld[i]);
1099 }
1100 }
1101 }
1102 }
1103 else
1104 {
1105 DynamicList<label> neighbProcs;
1107
1108 // Send
1109 for (const polyPatch& pp : patches)
1110 {
1111 const auto* ppp = isA<processorPolyPatch>(pp);
1112
1113 if (ppp && pp.size())
1114 {
1115 const auto& procPatch = *ppp;
1116 const label nbrProci = procPatch.neighbProcNo();
1117
1118 const SubList<T> fld
1119 (
1120 faceValues,
1121 pp.size(),
1122 pp.start()-boundaryOffset
1123 );
1124
1125 neighbProcs.append(nbrProci);
1126 UOPstream toNbr(nbrProci, pBufs);
1127 toNbr << fld;
1128 }
1129 }
1130
1131 // Limit exchange to involved procs
1132 pBufs.finishedNeighbourSends(neighbProcs);
1133
1134
1135 // Receive and combine.
1136 for (const polyPatch& pp : patches)
1137 {
1138 const auto* ppp = isA<processorPolyPatch>(pp);
1139
1140 if (ppp && pp.size())
1141 {
1142 const auto& procPatch = *ppp;
1143
1144 List<T> recvFld(pp.size());
1145
1146 UIPstream fromNbr(procPatch.neighbProcNo(), pBufs);
1147 fromNbr >> recvFld;
1148
1149 top(procPatch, recvFld);
1150
1151 SubList<T> patchValues
1152 (
1153 faceValues,
1154 pp.size(),
1155 pp.start()-boundaryOffset
1156 );
1157
1158 forAll(patchValues, i)
1159 {
1160 cop(patchValues[i], recvFld[i]);
1161 }
1162 }
1163 }
1164 }
1165 }
1166
1167 // Do the cyclics.
1168 for (const polyPatch& pp : patches)
1169 {
1170 const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
1171
1172 if (cpp && cpp->owner())
1173 {
1174 // Owner does all.
1175
1176 const cyclicPolyPatch& cycPatch = *cpp;
1177 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
1178 const label patchSize = cycPatch.size();
1179
1180 SubList<T> ownPatchValues
1181 (
1182 faceValues,
1183 patchSize,
1184 cycPatch.start()-boundaryOffset
1185 );
1186
1187 SubList<T> nbrPatchValues
1188 (
1189 faceValues,
1190 patchSize,
1191 nbrPatch.start()-boundaryOffset
1192 );
1193
1194 // Transform (copy of) data on both sides
1195 List<T> ownVals(ownPatchValues);
1196 top(nbrPatch, ownVals);
1197
1198 List<T> nbrVals(nbrPatchValues);
1199 top(cycPatch, nbrVals);
1200
1201 forAll(ownPatchValues, i)
1202 {
1203 cop(ownPatchValues[i], nbrVals[i]);
1204 }
1205
1206 forAll(nbrPatchValues, i)
1207 {
1208 cop(nbrPatchValues[i], ownVals[i]);
1209 }
1210 }
1211 }
1212}
1213
1214
1215// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1216
1217template<unsigned Width, class CombineOp>
1219(
1220 const polyMesh& mesh,
1221 const bool isBoundaryOnly,
1222 PackedList<Width>& faceValues,
1223 const CombineOp& cop,
1224 const bool parRun
1225)
1226{
1227 // Offset (global to local) for start of boundaries
1228 const label boundaryOffset = (isBoundaryOnly ? mesh.nInternalFaces() : 0);
1229
1230 // Check size
1231 if (faceValues.size() != (mesh.nFaces() - boundaryOffset))
1232 {
1234 << "Number of values " << faceValues.size()
1235 << " is not equal to the number of "
1236 << (isBoundaryOnly ? "boundary" : "mesh") << " faces "
1237 << ((mesh.nFaces() - boundaryOffset)) << nl
1238 << abort(FatalError);
1239 }
1240
1242
1243 if (parRun)
1244 {
1245 const label startRequest = UPstream::nRequests();
1246
1247 // Receive buffers
1249
1250 // Set up reads
1251 for (const polyPatch& pp : patches)
1252 {
1253 const auto* ppp = isA<processorPolyPatch>(pp);
1254
1255 if (ppp && pp.size())
1256 {
1257 const auto& procPatch = *ppp;
1258 const label patchi = pp.index();
1259 const label patchSize = pp.size();
1260
1261 recvInfos.set(patchi, new PackedList<Width>(patchSize));
1262 PackedList<Width>& recvInfo = recvInfos[patchi];
1263
1265 (
1267 procPatch.neighbProcNo(),
1268 recvInfo.data_bytes(),
1269 recvInfo.size_bytes()
1270 );
1271 }
1272 }
1273
1274 // Send buffers
1276
1277 // Set up writes
1278 for (const polyPatch& pp : patches)
1279 {
1280 const auto* ppp = isA<processorPolyPatch>(pp);
1281
1282 if (ppp && pp.size())
1283 {
1284 const auto& procPatch = *ppp;
1285 const label patchi = pp.index();
1286
1287 const labelRange range
1288 (
1289 pp.start()-boundaryOffset,
1290 pp.size()
1291 );
1292 sendInfos.set
1293 (
1294 patchi,
1295 new PackedList<Width>(faceValues, range)
1296 );
1297 PackedList<Width>& sendInfo = sendInfos[patchi];
1298
1300 (
1302 procPatch.neighbProcNo(),
1303 sendInfo.cdata_bytes(),
1304 sendInfo.size_bytes()
1305 );
1306 }
1307 }
1308
1309 // Wait for all comms to finish
1310 Pstream::waitRequests(startRequest);
1311
1312 // Combine with existing data
1313 for (const polyPatch& pp : patches)
1314 {
1315 const auto* ppp = isA<processorPolyPatch>(pp);
1316
1317 if (ppp && pp.size())
1318 {
1319 const label patchi = pp.index();
1320 const label patchSize = pp.size();
1321
1322 const PackedList<Width>& recvInfo = recvInfos[patchi];
1323
1324 // Combine (bitwise)
1325 label bFacei = pp.start()-boundaryOffset;
1326 for (label i = 0; i < patchSize; ++i)
1327 {
1328 unsigned int recvVal = recvInfo[i];
1329 unsigned int faceVal = faceValues[bFacei];
1330
1331 cop(faceVal, recvVal);
1332 faceValues.set(bFacei, faceVal);
1333
1334 ++bFacei;
1335 }
1336 }
1337 }
1338 }
1339
1340
1341 // Do the cyclics.
1342 for (const polyPatch& pp : patches)
1343 {
1344 const cyclicPolyPatch* cpp = isA<cyclicPolyPatch>(pp);
1345
1346 if (cpp && cpp->owner())
1347 {
1348 // Owner does all.
1349
1350 const cyclicPolyPatch& cycPatch = *cpp;
1351 const cyclicPolyPatch& nbrPatch = cycPatch.neighbPatch();
1352 const label patchSize = cycPatch.size();
1353
1354 label face0 = cycPatch.start()-boundaryOffset;
1355 label face1 = nbrPatch.start()-boundaryOffset;
1356 for (label i = 0; i < patchSize; ++i)
1357 {
1358 unsigned int val0 = faceValues[face0];
1359 unsigned int val1 = faceValues[face1];
1360
1361 unsigned int t = val0;
1362 cop(t, val1);
1363 faceValues[face0] = t;
1364
1365 cop(val1, val0);
1366 faceValues[face1] = val1;
1367
1368 ++face0;
1369 ++face1;
1370 }
1371 }
1372 }
1373}
1374
1375
1376template<class T>
1378(
1379 const polyMesh& mesh,
1380 const UList<T>& cellData,
1381 List<T>& neighbourCellData
1382)
1383{
1384 if (cellData.size() != mesh.nCells())
1385 {
1387 << "Number of cell values " << cellData.size()
1388 << " is not equal to the number of cells in the mesh "
1389 << mesh.nCells() << abort(FatalError);
1390 }
1391
1393
1394 neighbourCellData.resize(mesh.nBoundaryFaces());
1395
1396 for (const polyPatch& pp : patches)
1397 {
1398 label bFacei = pp.offset();
1399
1400 for (const label celli : pp.faceCells())
1401 {
1402 neighbourCellData[bFacei] = cellData[celli];
1403 ++bFacei;
1404 }
1405 }
1406 syncTools::swapBoundaryFaceList(mesh, neighbourCellData);
1407}
1408
1409
1410template<unsigned Width, class CombineOp>
1412(
1413 const polyMesh& mesh,
1414 PackedList<Width>& faceValues,
1415 const CombineOp& cop,
1416 const bool parRun
1417)
1418{
1419 syncFaceList(mesh, false, faceValues, cop, parRun);
1420}
1421
1422
1423template<unsigned Width, class CombineOp>
1425(
1426 const polyMesh& mesh,
1427 PackedList<Width>& faceValues,
1428 const CombineOp& cop,
1429 const bool parRun
1430)
1431{
1432 syncFaceList(mesh, true, faceValues, cop, parRun);
1433}
1434
1435
1436template<unsigned Width>
1438(
1439 const polyMesh& mesh,
1440 PackedList<Width>& faceValues
1441)
1442{
1443 syncFaceList(mesh, faceValues, eqOp<unsigned int>());
1444}
1445
1446
1447template<unsigned Width>
1449(
1450 const polyMesh& mesh,
1451 PackedList<Width>& faceValues
1452)
1453{
1454 syncBoundaryFaceList(mesh, faceValues, eqOp<unsigned int>());
1455}
1456
1457
1458template<unsigned Width, class CombineOp>
1460(
1461 const polyMesh& mesh,
1462 PackedList<Width>& pointValues,
1463 const CombineOp& cop,
1464 const unsigned int nullValue
1465)
1466{
1467 if (pointValues.size() != mesh.nPoints())
1468 {
1470 << "Number of values " << pointValues.size()
1471 << " is not equal to the number of points in the mesh "
1472 << mesh.nPoints() << abort(FatalError);
1473 }
1474
1475 const globalMeshData& gd = mesh.globalData();
1476 const labelList& meshPoints = gd.coupledPatch().meshPoints();
1477
1479 forAll(meshPoints, i)
1480 {
1481 cppFld[i] = pointValues[meshPoints[i]];
1482 }
1483
1485 (
1486 cppFld,
1487 gd.globalPointSlaves(),
1490 cop
1491 );
1492
1493 // Extract back to mesh
1494 forAll(meshPoints, i)
1495 {
1496 pointValues[meshPoints[i]] = cppFld[i];
1497 }
1498}
1499
1500
1501template<unsigned Width, class CombineOp>
1503(
1504 const polyMesh& mesh,
1505 PackedList<Width>& edgeValues,
1506 const CombineOp& cop,
1507 const unsigned int nullValue
1508)
1509{
1510 if (edgeValues.size() != mesh.nEdges())
1511 {
1513 << "Number of values " << edgeValues.size()
1514 << " is not equal to the number of edges in the mesh "
1515 << mesh.nEdges() << abort(FatalError);
1516 }
1517
1518 const globalMeshData& gd = mesh.globalData();
1519 const labelList& meshEdges = gd.coupledPatchMeshEdges();
1520
1522 forAll(meshEdges, i)
1523 {
1524 cppFld[i] = edgeValues[meshEdges[i]];
1525 }
1526
1528 (
1529 cppFld,
1530 gd.globalEdgeSlaves(),
1533 cop
1534 );
1535
1536 // Extract back to mesh
1537 forAll(meshEdges, i)
1538 {
1539 edgeValues[meshEdges[i]] = cppFld[i];
1540 }
1541}
1542
1543
1544// ************************************************************************* //
scalar range
Info<< nl<< "Wrote faMesh in vtk format: "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.mesh().time().globalPath()/"finiteArea-edges"));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
Map from edge (expressed as its endpoints) to value. For easier forward declaration it is currently i...
Definition: EdgeMap.H:54
bool set(const Key &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
Definition: HashTableI.H:202
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:141
void resize(const label sz)
Resize the hash table for efficiency.
Definition: HashTable.C:601
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:180
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
Definition: HashTableI.H:114
iterator end() noexcept
iterator to signal the end (for any HashTable)
Input inter-processor communications stream.
Definition: IPstream.H:57
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
typename parent_type::const_iterator const_iterator
Definition: Map.H:70
Output inter-processor communications stream.
Definition: OPstream.H:57
A dynamic list of packed unsigned integers, with the number of bits per item specified by the <Width>...
Definition: PackedList.H:129
char * data_bytes() noexcept
A pointer to the raw storage, reinterpreted as byte data.
Definition: PackedListI.H:582
label size() const noexcept
Number of entries.
Definition: PackedListI.H:377
bool set(const label i, unsigned int val=~0u)
Set value at index i, default value set is the max_value.
Definition: PackedListI.H:653
const char * cdata_bytes() const noexcept
A const pointer to the raw storage, reinterpreted as byte data.
Definition: PackedListI.H:575
std::streamsize size_bytes() const noexcept
Definition: PackedListI.H:589
A list of faces which address into the list of points.
label nEdges() const
Number of edges in patch.
label nPoints() const
Number of points supporting patch faces.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const Map< label > & meshPointMap() const
Mesh point map.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const Field< point_type > & localPoints() const
Return pointField of points in patch.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void finishedNeighbourSends(const labelUList &neighProcs, const bool wait=true)
UPstream::rangeType subProcs() const noexcept
Range of sub-processes indices associated with PstreamBuffers.
static void scatter(const List< commsStruct > &comms, T &value, const int tag, const label comm)
Broadcast data: Distribute without modification.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
virtual bool read()
Re-read model coefficients if they have changed.
A List obtained as a section of another List.
Definition: SubList.H:70
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
label fcIndex(const label i) const noexcept
Definition: UListI.H:60
@ nonBlocking
"nonBlocking"
static constexpr int masterNo() noexcept
Process index of the master (always 0)
Definition: UPstream.H:451
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:90
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:100
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:281
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
Cyclic plane patch.
virtual bool owner() const
Does this side own the patch ?
const edgeList & coupledEdges() const
Return connected edges (from patch local to neighbour patch local).
const edgeList & coupledPoints() const
Return connected points (from patch local to neighbour patch local)
const cyclicPolyPatch & neighbPatch() const
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:66
static int compare(const edge &a, const edge &b)
Compare edges.
Definition: edgeI.H:33
linePointRef line(const UList< point > &pts) const
Return edge line.
Definition: edgeI.H:456
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
virtual bool write()
Write the output fields.
Determination and storage of the possible independent transforms introduced by coupledPolyPatches,...
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
const bitSet & globalEdgeOrientation() const
Is my edge same orientation as master edge.
const labelListList & globalEdgeTransformedSlaves() const
const Map< label > & coupledPatchMeshEdgeMap() const
Return map from mesh edges to coupledPatch edges.
label nGlobalPoints() const
Return number of globally shared points.
const mapDistribute & globalPointSlavesMap() const
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
const mapDistribute & globalEdgeSlavesMap() const
static void syncData(List< Type > &elems, const labelListList &slaves, const labelListList &transformedSlaves, const mapDistribute &slavesMap, const globalIndexAndTransform &, const CombineOp &cop, const TransformOp &top)
Helper: synchronise data with transforms.
const labelList & coupledPatchMeshEdges() const
Return map from coupledPatch edges to mesh edges.
void syncPointData(List< Type > &pointData, const CombineOp &cop, const TransformOp &top) const
Helper to synchronise coupled patch point data.
const labelListList & globalPointSlaves() const
const globalIndexAndTransform & globalTransforms() const
Global transforms numbering.
const labelListList & globalPointTransformedSlaves() const
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
const labelListList & globalEdgeSlaves() const
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:58
label constructSize() const noexcept
Constructed data size.
Class containing processor-to-processor mapping information.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1310
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1083
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:364
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
label nInternalFaces() const noexcept
Number of internal faces.
label nPoints() const noexcept
Number of mesh points.
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
label nEdges() const
Number of mesh edges.
splitCell * master() const
Definition: splitCell.H:113
static void syncEdgeMap(const polyMesh &mesh, EdgeMap< T > &edgeValues, const CombineOp &cop, const TransformOp &top)
Synchronize values on selected edges.
static void syncPointMap(const polyMesh &mesh, Map< T > &pointValues, const CombineOp &cop, const TransformOp &top)
Synchronize values on selected points.
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled face values. Uses eqOp.
Definition: syncTools.H:478
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:396
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:445
static void swapBoundaryCellList(const polyMesh &mesh, const UList< T > &cellData, List< T > &neighbourCellData)
Swap to obtain neighbour cell values for all boundary faces.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
static void syncEdgeList(const polyMesh &mesh, List< T > &edgeValues, const CombineOp &cop, const T &nullValue, const TransformOp &top, const FlipOp &fop)
Synchronize values on all mesh edges.
static void syncBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const TransformOp &top, const bool parRun=Pstream::parRun())
Synchronize values on boundary faces only.
const volScalarField & T
const polyBoundaryMesh & patches
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition: stdFoam.H:278
Definition: ops.H:71
A template class to specify that a data type can be considered as being contiguous in memory.
Definition: contiguous.H:78
Spatial transformation functions for list of values and primitive fields.