1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
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
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "PointEdgeWave.H"
29 #include "processorPolyPatch.H"
30 #include "cyclicPolyPatch.H"
33 #include "PstreamCombineReduceOps.H"
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 Foam::scalar Foam::PointEdgeWave<Type>::propagationTol_ = 0.01;
43 // Offset labelList. Used for transferring from one cyclic half to the other.
45 void Foam::PointEdgeWave<Type>::offset(const label val, labelList& elems)
54 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 // Gets point-point correspondence. Is
57 // - list of halfA points (in cyclic patch points)
58 // - list of halfB points (can overlap with A!)
59 // - for every patchPoint its corresponding point
61 void Foam::PointEdgeWave<Type>::calcCyclicAddressing()
65 forAll(mesh_.boundaryMesh(), patchI)
67 const polyPatch& patch = mesh_.boundaryMesh()[patchI];
69 if (isA<cyclicPolyPatch>(patch))
71 label halfSize = patch.size()/2;
73 SubList<face> halfAFaces
83 new primitivePatch(halfAFaces, mesh_.points())
86 SubList<face> halfBFaces
90 patch.start() + halfSize
96 new primitivePatch(halfBFaces, mesh_.points())
103 // Handle leaving domain. Implementation referred to Type
104 template <class Type>
105 void Foam::PointEdgeWave<Type>::leaveDomain
107 const polyPatch& meshPatch,
108 const primitivePatch& patch,
109 const labelList& patchPointLabels,
110 List<Type>& pointInfo
113 const labelList& meshPoints = patch.meshPoints();
115 forAll(patchPointLabels, i)
117 label patchPointI = patchPointLabels[i];
119 const point& pt = patch.points()[meshPoints[patchPointI]];
121 pointInfo[i].leaveDomain(meshPatch, patchPointI, pt);
126 // Handle entering domain. Implementation referred to Type
127 template <class Type>
128 void Foam::PointEdgeWave<Type>::enterDomain
130 const polyPatch& meshPatch,
131 const primitivePatch& patch,
132 const labelList& patchPointLabels,
133 List<Type>& pointInfo
136 const labelList& meshPoints = patch.meshPoints();
138 forAll(patchPointLabels, i)
140 label patchPointI = patchPointLabels[i];
142 const point& pt = patch.points()[meshPoints[patchPointI]];
144 pointInfo[i].enterDomain(meshPatch, patchPointI, pt);
149 // Transform. Implementation referred to Type
150 template <class Type>
151 void Foam::PointEdgeWave<Type>::transform
153 const tensorField& rotTensor,
154 List<Type>& pointInfo
157 if (rotTensor.size() == 1)
159 const tensor& T = rotTensor[0];
163 pointInfo[i].transform(T);
170 "PointEdgeWave<Type>::transform(const tensorField&, List<Type>&)"
171 ) << "Parallel cyclics not supported"
172 << abort(FatalError);
176 pointInfo[i].transform(rotTensor[i]);
182 // Update info for pointI, at position pt, with information from
183 // neighbouring edge.
185 // - changedPoint_, changedPoints_, nChangedPoints_,
186 // - statistics: nEvals_, nUnvisitedPoints_
187 template <class Type>
188 bool Foam::PointEdgeWave<Type>::updatePoint
191 const label neighbourEdgeI,
192 const Type& neighbourInfo,
199 bool wasValid = pointInfo.valid();
202 pointInfo.updatePoint
213 if (!changedPoint_[pointI])
215 changedPoint_[pointI] = true;
216 changedPoints_[nChangedPoints_++] = pointI;
220 if (!wasValid && pointInfo.valid())
229 // Update info for pointI, at position pt, with information from
232 // - changedPoint_, changedPoints_, nChangedPoints_,
233 // - statistics: nEvals_, nUnvisitedPoints_
234 template <class Type>
235 bool Foam::PointEdgeWave<Type>::updatePoint
238 const Type& neighbourInfo,
245 bool wasValid = pointInfo.valid();
248 pointInfo.updatePoint
258 if (!changedPoint_[pointI])
260 changedPoint_[pointI] = true;
261 changedPoints_[nChangedPoints_++] = pointI;
265 if (!wasValid && pointInfo.valid())
274 // Update info for edgeI, at position pt, with information from
275 // neighbouring point.
277 // - changedEdge_, changedEdges_, nChangedEdges_,
278 // - statistics: nEvals_, nUnvisitedEdge_
279 template <class Type>
280 bool Foam::PointEdgeWave<Type>::updateEdge
283 const label neighbourPointI,
284 const Type& neighbourInfo,
291 bool wasValid = edgeInfo.valid();
305 if (!changedEdge_[edgeI])
307 changedEdge_[edgeI] = true;
308 changedEdges_[nChangedEdges_++] = edgeI;
312 if (!wasValid && edgeInfo.valid())
321 // Check if patches of given type name are present
322 template <class Type>
323 template <class PatchType>
324 Foam::label Foam::PointEdgeWave<Type>::countPatchType() const
328 forAll(mesh_.boundaryMesh(), patchI)
330 if (isA<PatchType>(mesh_.boundaryMesh()[patchI]))
339 // Collect changed patch points
340 template <class Type>
341 void Foam::PointEdgeWave<Type>::getChangedPatchPoints
343 const primitivePatch& patch,
345 DynamicList<Type>& patchInfo,
346 DynamicList<label>& patchPoints,
347 DynamicList<label>& owner,
348 DynamicList<label>& ownerIndex
351 const labelList& meshPoints = patch.meshPoints();
352 const faceList& localFaces = patch.localFaces();
353 const labelListList& pointFaces = patch.pointFaces();
355 forAll(meshPoints, patchPointI)
357 label meshPointI = meshPoints[patchPointI];
359 if (changedPoint_[meshPointI])
361 patchInfo.append(allPointInfo_[meshPointI]);
362 patchPoints.append(patchPointI);
364 label patchFaceI = pointFaces[patchPointI][0];
366 const face& f = localFaces[patchFaceI];
368 label index = findIndex(f, patchPointI);
370 owner.append(patchFaceI);
371 ownerIndex.append(index);
376 patchPoints.shrink();
382 // Update overall for changed patch points
383 template <class Type>
384 void Foam::PointEdgeWave<Type>::updateFromPatchInfo
386 const polyPatch& meshPatch,
387 const primitivePatch& patch,
388 const labelList& owner,
389 const labelList& ownerIndex,
390 List<Type>& patchInfo
393 const faceList& localFaces = patch.localFaces();
394 const labelList& meshPoints = patch.meshPoints();
396 // Get patch and mesh points.
397 labelList changedPatchPoints(patchInfo.size());
398 labelList changedMeshPoints(patchInfo.size());
402 label faceI = owner[i];
404 const face& f = localFaces[faceI];
406 label index = (f.size() - ownerIndex[i]) % f.size();
408 changedPatchPoints[i] = f[index];
409 changedMeshPoints[i] = meshPoints[f[index]];
412 // Adapt for entering domain
413 enterDomain(meshPatch, patch, changedPatchPoints, patchInfo);
415 // Merge received info
420 changedMeshPoints[i],
423 allPointInfo_[changedMeshPoints[i]]
430 // Transfer all the information to/from neighbouring processors
431 template <class Type>
432 void Foam::PointEdgeWave<Type>::handleProcPatches()
434 // 1. Send all point info on processor patches. Send as
435 // face label + offset in face.
437 forAll(mesh_.boundaryMesh(), patchI)
439 const polyPatch& patch = mesh_.boundaryMesh()[patchI];
441 if (isA<processorPolyPatch>(patch))
443 // Get all changed points in relative addressing
445 DynamicList<Type> patchInfo(patch.nPoints());
446 DynamicList<label> patchPoints(patch.nPoints());
447 DynamicList<label> owner(patch.nPoints());
448 DynamicList<label> ownerIndex(patch.nPoints());
450 getChangedPatchPoints
459 // Adapt for leaving domain
460 leaveDomain(patch, patch, patchPoints, patchInfo);
462 const processorPolyPatch& procPatch =
463 refCast<const processorPolyPatch>(patch);
467 Pout<< "Processor patch " << patchI << ' ' << patch.name()
468 << " communicating with " << procPatch.neighbProcNo()
469 << " Sending:" << patchInfo.size() << endl;
476 procPatch.neighbProcNo()
479 toNeighbour << owner << ownerIndex << patchInfo;
486 // 2. Receive all point info on processor patches.
489 forAll(mesh_.boundaryMesh(), patchI)
491 const polyPatch& patch = mesh_.boundaryMesh()[patchI];
493 if (isA<processorPolyPatch>(patch))
495 const processorPolyPatch& procPatch =
496 refCast<const processorPolyPatch>(patch);
498 List<Type> patchInfo;
500 labelList ownerIndex;
502 IPstream fromNeighbour
505 procPatch.neighbProcNo()
508 fromNeighbour >> owner >> ownerIndex >> patchInfo;
513 Pout<< "Processor patch " << patchI << ' ' << patch.name()
514 << " communicating with " << procPatch.neighbProcNo()
515 << " Received:" << patchInfo.size() << endl;
518 // Apply transform to received data for non-parallel planes
519 if (!procPatch.parallel())
521 transform(procPatch.forwardT(), patchInfo);
538 // 3. Handle all shared points
539 // (Note:irrespective if changed or not for now)
542 const globalMeshData& pd = mesh_.globalData();
544 List<Type> sharedData(pd.nGlobalPoints());
546 forAll(pd.sharedPointLabels(), i)
548 label meshPointI = pd.sharedPointLabels()[i];
550 // Fill my entries in the shared points
551 sharedData[pd.sharedPointAddr()[i]] = allPointInfo_[meshPointI];
554 // Combine on master. Reduce operator has to handle a list and call
555 // Type.updatePoint for all elements
556 combineReduce(sharedData, listUpdateOp<Type>());
558 forAll(pd.sharedPointLabels(), i)
560 label meshPointI = pd.sharedPointLabels()[i];
562 // Retrieve my entries from the shared points
566 sharedData[pd.sharedPointAddr()[i]],
568 allPointInfo_[meshPointI]
574 template <class Type>
575 void Foam::PointEdgeWave<Type>::handleCyclicPatches()
577 // 1. Send all point info on cyclic patches. Send as
578 // face label + offset in face.
582 forAll(mesh_.boundaryMesh(), patchI)
584 const polyPatch& patch = mesh_.boundaryMesh()[patchI];
586 if (isA<cyclicPolyPatch>(patch))
588 const primitivePatch& halfA = cycHalves_[cycHalf++];
589 const primitivePatch& halfB = cycHalves_[cycHalf++];
591 // HalfA : get all changed points in relative addressing
593 DynamicList<Type> halfAInfo(halfA.nPoints());
594 DynamicList<label> halfAPoints(halfA.nPoints());
595 DynamicList<label> halfAOwner(halfA.nPoints());
596 DynamicList<label> halfAIndex(halfA.nPoints());
598 getChangedPatchPoints
607 // HalfB : get all changed points in relative addressing
609 DynamicList<Type> halfBInfo(halfB.nPoints());
610 DynamicList<label> halfBPoints(halfB.nPoints());
611 DynamicList<label> halfBOwner(halfB.nPoints());
612 DynamicList<label> halfBIndex(halfB.nPoints());
614 getChangedPatchPoints
624 // HalfA : adapt for leaving domain
625 leaveDomain(patch, halfA, halfAPoints, halfAInfo);
627 // HalfB : adapt for leaving domain
628 leaveDomain(patch, halfB, halfBPoints, halfBInfo);
631 // Apply rotation for non-parallel planes
632 const cyclicPolyPatch& cycPatch =
633 refCast<const cyclicPolyPatch>(patch);
635 if (!cycPatch.parallel())
637 // received data from half1
638 transform(cycPatch.forwardT(), halfAInfo);
640 // received data from half2
641 transform(cycPatch.forwardT(), halfBInfo);
646 Pout<< "Cyclic patch " << patchI << ' ' << patch.name()
647 << " Changed on first half : " << halfAInfo.size()
648 << " Changed on second half : " << halfBInfo.size()
652 // Half1: update with data from halfB
662 // Half2: update with data from halfA
674 //checkCyclic(patch);
681 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
683 // Iterate, propagating changedPointsInfo across mesh, until no change (or
684 // maxIter reached). Initial point values specified.
685 template <class Type>
686 Foam::PointEdgeWave<Type>::PointEdgeWave
688 const polyMesh& mesh,
689 const labelList& changedPoints,
690 const List<Type>& changedPointsInfo,
692 List<Type>& allPointInfo,
693 List<Type>& allEdgeInfo,
699 allPointInfo_(allPointInfo),
700 allEdgeInfo_(allEdgeInfo),
701 changedPoint_(mesh_.nPoints(), false),
702 changedPoints_(mesh_.nPoints()),
704 changedEdge_(mesh_.nEdges(), false),
705 changedEdges_(mesh_.nEdges()),
707 nCyclicPatches_(countPatchType<cyclicPolyPatch>()),
708 cycHalves_(2*nCyclicPatches_),
710 nUnvisitedPoints_(mesh_.nPoints()),
711 nUnvisitedEdges_(mesh_.nEdges())
713 if (allPointInfo_.size() != mesh_.nPoints())
717 "PointEdgeWave<Type>::PointEdgeWave"
718 "(const polyMesh&, const labelList&, const List<Type>,"
719 " List<Type>&, List<Type>&, const label maxIter)"
720 ) << "size of pointInfo work array is not equal to the number"
721 << " of points in the mesh" << endl
722 << " pointInfo :" << allPointInfo_.size() << endl
723 << " mesh.nPoints:" << mesh_.nPoints()
726 if (allEdgeInfo_.size() != mesh_.nEdges())
730 "PointEdgeWave<Type>::PointEdgeWave"
731 "(const polyMesh&, const labelList&, const List<Type>,"
732 " List<Type>&, List<Type>&, const label maxIter)"
733 ) << "size of edgeInfo work array is not equal to the number"
734 << " of edges in the mesh" << endl
735 << " edgeInfo :" << allEdgeInfo_.size() << endl
736 << " mesh.nEdges:" << mesh_.nEdges()
741 // Calculate cyclic halves addressing.
742 if (nCyclicPatches_ > 0)
744 calcCyclicAddressing();
748 // Set from initial changed points data
749 setPointInfo(changedPoints, changedPointsInfo);
753 Pout<< "Seed points : " << nChangedPoints_ << endl;
756 // Iterate until nothing changes
757 label iter = iterate(maxIter);
759 if ((maxIter > 0) && (iter >= maxIter))
763 "PointEdgeWave<Type>::PointEdgeWave"
764 "(const polyMesh&, const labelList&, const List<Type>,"
765 " List<Type>&, List<Type>&, const label maxIter)"
766 ) << "Maximum number of iterations reached. Increase maxIter." << nl
767 << " maxIter:" << maxIter << endl
768 << " nChangedPoints:" << nChangedPoints_ << endl
769 << " nChangedEdges:" << nChangedEdges_ << endl
775 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
777 template <class Type>
778 Foam::PointEdgeWave<Type>::~PointEdgeWave()
782 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
785 template <class Type>
786 Foam::label Foam::PointEdgeWave<Type>::getUnsetPoints() const
788 return nUnvisitedPoints_;
792 template <class Type>
793 Foam::label Foam::PointEdgeWave<Type>::getUnsetEdges() const
795 return nUnvisitedEdges_;
799 // Copy point information into member data
800 template <class Type>
801 void Foam::PointEdgeWave<Type>::setPointInfo
803 const labelList& changedPoints,
804 const List<Type>& changedPointsInfo
807 forAll(changedPoints, changedPointI)
809 label pointI = changedPoints[changedPointI];
811 bool wasValid = allPointInfo_[pointI].valid();
813 // Copy info for pointI
814 allPointInfo_[pointI] = changedPointsInfo[changedPointI];
816 // Maintain count of unset points
817 if (!wasValid && allPointInfo_[pointI].valid())
822 // Mark pointI as changed, both on list and on point itself.
824 if (!changedPoint_[pointI])
826 changedPoint_[pointI] = true;
827 changedPoints_[nChangedPoints_++] = pointI;
833 // Propagate information from edge to point. Return number of points changed.
834 template <class Type>
835 Foam::label Foam::PointEdgeWave<Type>::edgeToPoint()
839 label changedEdgeI = 0;
840 changedEdgeI < nChangedEdges_;
844 label edgeI = changedEdges_[changedEdgeI];
846 if (!changedEdge_[edgeI])
848 FatalErrorIn("PointEdgeWave<Type>::edgeToPoint()")
850 << " not marked as having been changed" << nl
851 << "This might be caused by multiple occurences of the same"
852 << " seed point." << abort(FatalError);
856 const Type& neighbourWallInfo = allEdgeInfo_[edgeI];
858 // Evaluate all connected points (= edge endpoints)
859 const edge& e = mesh_.edges()[edgeI];
863 Type& currentWallInfo = allPointInfo_[e[eI]];
865 if (currentWallInfo != neighbourWallInfo)
878 // Reset status of edge
879 changedEdge_[edgeI] = false;
882 // Handled all changed edges by now
885 if (nCyclicPatches_ > 0)
887 // Transfer changed points across cyclic halves
888 handleCyclicPatches();
890 if (Pstream::parRun())
892 // Transfer changed points from neighbouring processors.
898 Pout<< "Changed points : " << nChangedPoints_ << endl;
901 // Sum nChangedPoints over all procs
902 label totNChanged = nChangedPoints_;
904 reduce(totNChanged, sumOp<label>());
910 // Propagate information from point to edge. Return number of edges changed.
911 template <class Type>
912 Foam::label Foam::PointEdgeWave<Type>::pointToEdge()
914 const labelListList& pointEdges = mesh_.pointEdges();
918 label changedPointI = 0;
919 changedPointI < nChangedPoints_;
923 label pointI = changedPoints_[changedPointI];
925 if (!changedPoint_[pointI])
927 FatalErrorIn("PointEdgeWave<Type>::pointToEdge()")
928 << "Point " << pointI
929 << " not marked as having been changed" << nl
930 << "This might be caused by multiple occurences of the same"
931 << " seed point." << abort(FatalError);
934 const Type& neighbourWallInfo = allPointInfo_[pointI];
936 // Evaluate all connected edges
938 const labelList& edgeLabels = pointEdges[pointI];
939 forAll(edgeLabels, edgeLabelI)
941 label edgeI = edgeLabels[edgeLabelI];
943 Type& currentWallInfo = allEdgeInfo_[edgeI];
945 if (currentWallInfo != neighbourWallInfo)
958 // Reset status of point
959 changedPoint_[pointI] = false;
962 // Handled all changed points by now
967 Pout<< "Changed edges : " << nChangedEdges_ << endl;
970 // Sum nChangedPoints over all procs
971 label totNChanged = nChangedEdges_;
973 reduce(totNChanged, sumOp<label>());
980 template <class Type>
981 Foam::label Foam::PointEdgeWave<Type>::iterate(const label maxIter)
983 if (nCyclicPatches_ > 0)
985 // Transfer changed points across cyclic halves
986 handleCyclicPatches();
988 if (Pstream::parRun())
990 // Transfer changed points from neighbouring processors.
998 while(iter < maxIter)
1002 Pout<< "Iteration " << iter << endl;
1005 label nEdges = pointToEdge();
1009 Pout<< "Total changed edges : " << nEdges << endl;
1017 label nPoints = edgeToPoint();
1021 Pout<< "Total changed points : " << nPoints << endl;
1023 Pout<< "Total evaluations : " << nEvals_ << endl;
1025 Pout<< "Remaining unvisited points: " << nUnvisitedPoints_ << endl;
1027 Pout<< "Remaining unvisited edges : " << nUnvisitedEdges_ << endl;
1044 // ************************************************************************* //