1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 An implementation of dynamic changes to mesh-topology
32 University of Massachusetts Amherst
35 \*---------------------------------------------------------------------------*/
39 #include "tetPointRef.H"
40 #include "linePointRef.H"
41 #include "lengthScaleEstimator.H"
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
50 // Return if mesh is 2D
51 inline bool dynamicTopoFvMesh::is2D() const
57 // Return if mesh is 3D
58 inline bool dynamicTopoFvMesh::is3D() const
64 // Return a non-const reference to the lengthScaleEstimator
65 inline lengthScaleEstimator&
66 dynamicTopoFvMesh::lengthEstimator()
68 if (!lengthEstimator_.valid())
72 "inline lengthScaleEstimator& "
73 "dynamicTopoFvMesh::lengthEstimator()"
75 << " Invalid request. Length scale estimator was not loaded. "
79 return lengthEstimator_();
83 // Return a const reference to the lengthScaleEstimator
84 inline const lengthScaleEstimator&
85 dynamicTopoFvMesh::lengthEstimator() const
87 if (!lengthEstimator_.valid())
91 "inline const lengthScaleEstimator& "
92 "dynamicTopoFvMesh::lengthEstimator() const"
94 << " Invalid request. Length scale estimator was not loaded. "
98 return lengthEstimator_();
102 // Return a const reference to the multiThreader
103 inline const multiThreader&
104 dynamicTopoFvMesh::threader() const
106 if (!threader_.valid())
110 "inline const multiThreader& "
111 "dynamicTopoFvMesh::threader() const"
113 << " Invalid request. multiThreader was not loaded. "
114 << abort(FatalError);
121 // Return a reference to the entity mutexes.
122 // The index 'entity' ranges from 0 to 3 for point/edge/face/cell.
123 inline const Mutex& dynamicTopoFvMesh::entityMutex
128 return entityMutex_[entity];
132 // Return the edge index for a provided edge
133 inline label dynamicTopoFvMesh::getEdgeIndex
135 const edge& edgeToCheck
140 // No efficient search method. Loop through all edges.
141 forAll(edges_, edgeI)
143 if (edges_[edgeI] == edgeToCheck)
151 // Look througg pointEdges list
152 const labelList& pEdges = pointEdges_[edgeToCheck.start()];
154 forAll(pEdges, edgeI)
156 if (edges_[pEdges[edgeI]] == edgeToCheck)
158 return pEdges[edgeI];
163 // Probably not a valid edge.
166 "inline label dynamicTopoFvMesh::getEdgeIndex"
167 "(const edge& edgeToCheck) const"
169 << "Could not find an appropriate edge index for edge:"
171 << abort(FatalError);
177 // Given any quad face, pick out a boundary edge that
178 // contains a triangular face. For 2D simplical meshes only.
179 inline label dynamicTopoFvMesh::getTriBoundaryEdge
184 const labelList& fEdges = faceEdges_[fIndex];
186 forAll(fEdges, edgeI)
188 // Obtain edgeFaces for this edge
189 const labelList& eFaces = edgeFaces_[fEdges[edgeI]];
191 forAll(eFaces, faceI)
193 if (faces_[eFaces[faceI]].size() == 3)
195 // Found a triangular face. Return this edge.
196 return fEdges[edgeI];
201 // This bit should never happen.
204 "inline label dynamicTopoFvMesh::getTriBoundaryEdge"
205 "(const label fIndex) const"
207 << "Cannot find a triangular face bordering face: "
208 << fIndex << " :: " << faces_[fIndex]
209 << abort(FatalError);
215 // Check for edge bisection
216 inline bool dynamicTopoFvMesh::checkBisection
221 scalar length = 0.0, scale = 0.0;
225 // If this entity was deleted, skip it.
226 if (faces_[index].empty())
232 const edge& edgeToCheck = edges_[getTriBoundaryEdge(index)];
234 // Measure the boundary edge-length of the face in question
239 points_[edgeToCheck.start()],
240 points_[edgeToCheck.end()]
244 // Determine the length-scale at this face
245 scale = faceLengthScale(index);
249 // If this entity was deleted, skip it.
250 if (edgeFaces_[index].empty())
256 const edge& edgeToCheck = edges_[index];
258 // Measure the edge-length
263 points_[edgeToCheck.start()],
264 points_[edgeToCheck.end()]
268 // Determine the length-scale at this point in the mesh
269 scale = edgeLengthScale(index);
272 if (length > lengthEstimator().ratioMax() * scale)
283 // Check for edge collapse
284 inline bool dynamicTopoFvMesh::checkCollapse
289 scalar length = 0.0, scale = 0.0;
293 // If this entity was deleted, skip it.
294 if (faces_[index].empty())
300 const edge& edgeToCheck = edges_[getTriBoundaryEdge(index)];
302 // Measure the boundary edge-length of the face in question
307 points_[edgeToCheck.start()],
308 points_[edgeToCheck.end()]
312 // Determine the length-scale at this face
313 scale = faceLengthScale(index);
317 // If this entity was deleted, skip it.
318 if (edgeFaces_[index].empty())
324 const edge& edgeToCheck = edges_[index];
326 // Measure the edge-length
331 points_[edgeToCheck.start()],
332 points_[edgeToCheck.end()]
336 // Determine the length-scale at this point in the mesh
337 scale = edgeLengthScale(index);
340 if (length < lengthEstimator().ratioMin() * scale)
351 // Return the entity stack
352 inline Stack& dynamicTopoFvMesh::stack
357 return entityStack_[threadID];
361 // Return the integer ID for a given thread
362 // Return zero for single-threaded operation
363 inline label dynamicTopoFvMesh::self() const
365 if (threader_->multiThreaded())
367 for (label i = 1; i <= threader_->getNumThreads(); i++)
369 if (handlerPtr_[i].self())
380 // Initialize edge-stacks
381 inline void dynamicTopoFvMesh::initStacks
383 const labelHashSet& entities
386 forAll(entityStack_, stackI)
388 entityStack_[stackI].clear();
391 // Prepare a filling sequence based on threading operation
393 labelList tID(threader().getNumThreads());
395 if (threader_->multiThreaded())
409 forAll(faces_, faceI)
411 // For coupled meshes, avoid certain faces.
412 if (patchCoupling_.size() || procIndices_.size())
414 if (entities.found(faceI))
420 if (faces_[faceI].size() == 4)
422 stack(tID[tIndex]).insert(faceI);
424 tIndex = tID.fcIndex(tIndex);
430 forAll(edges_, edgeI)
432 // For coupled meshes, avoid certain edges.
433 if (patchCoupling_.size() || procIndices_.size())
435 if (entities.found(edgeI))
441 if (edgeFaces_[edgeI].size())
443 stack(tID[tIndex]).insert(edgeI);
445 tIndex = tID.fcIndex(tIndex);
450 if (debug > 3 && Pstream::parRun())
452 Pout<< nl << "Stack size: " << stack(0).size() << endl;
456 // Write out stack entities
457 labelList stackElements(stack(0).size(), -1);
459 forAll(stackElements, elemI)
461 stackElements[elemI] = stack(0)[elemI];
464 label elemType = is2D() ? 2 : 1;
469 + Foam::name(Pstream::myProcNo()),
478 // Method to determine the old boundary patch index for a given face
479 // Similar to the polyBoundaryMesh routine, but works on local information
480 inline label dynamicTopoFvMesh::whichPatch
485 if (index < nOldInternalFaces_)
490 for (label i = 0; i < boundaryMesh().size(); i++)
494 index >= oldPatchStarts_[i]
495 && index < oldPatchStarts_[i] + oldPatchSizes_[i]
502 // If not in any of the above, it's possible that the face was added
503 // at the end of the list. Check addedFacePatches_ for the patch info
504 Map<label>::const_iterator it = addedFacePatches_.find(index);
506 if (it != addedFacePatches_.end())
514 "label dynamicTopoFvMesh::whichPatch"
515 "(const label index) const"
517 << "Cannot find patch information for face index: "
519 << " It appears that face ordering is"
520 << " inconsistent with patch information." << nl
521 << " Mesh info: " << nl
522 << " nOldInternalFaces: " << nOldInternalFaces_ << nl
523 << " oldPatchStarts: " << oldPatchStarts_ << nl
524 << " oldPatchSizes: " << oldPatchSizes_ << nl
525 << abort(FatalError);
532 // Method to determine the old boundary patch index for a given edge
533 inline label dynamicTopoFvMesh::whichEdgePatch
538 if (index < nOldInternalEdges_)
543 for (label i = 0; i < boundaryMesh().size(); i++)
547 index >= oldEdgePatchStarts_[i]
548 && index < oldEdgePatchStarts_[i] + oldEdgePatchSizes_[i]
555 // If not in any of the above, it's possible that the edge was added
556 // at the end of the list. Check addedEdgePatches_ for the patch info
557 Map<label>::const_iterator it = addedEdgePatches_.find(index);
559 if (it != addedEdgePatches_.end())
567 "label dynamicTopoFvMesh::whichEdgePatch"
568 "(const label index) const"
570 << "Cannot find patch information for edge index: "
572 << " It appears that edge ordering is"
573 << " inconsistent with patch information." << nl
574 << " Mesh info: " << nl
575 << " nOldInternalEdges: " << nOldInternalEdges_ << nl
576 << " oldEdgePatchStarts: " << oldEdgePatchStarts_ << nl
577 << " oldEdgePatchSizes: " << oldEdgePatchSizes_ << nl
578 << abort(FatalError);
585 // Report or alter topo-modification status
586 inline label& dynamicTopoFvMesh::status(const label type)
588 if (type < 0 || type >= TOTAL_OP_TYPES)
592 "inline label& dynamicTopoFvMesh::status(const label type)"
594 << " Unknown type: " << type << nl
595 << abort(FatalError);
598 return statistics_[type];
602 // Set a particular face index as flipped.
603 inline void dynamicTopoFvMesh::setFlip(const label fIndex)
605 if (fIndex < nOldFaces_)
607 labelHashSet::iterator it = flipFaces_.find(fIndex);
609 if (it == flipFaces_.end())
611 flipFaces_.insert(fIndex);
615 flipFaces_.erase(it);
621 // Check for processor priority
622 template <class BinaryOp>
623 inline bool dynamicTopoFvMesh::priority
630 return bop(procPriority_[first], procPriority_[second]);
634 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
636 } // End namespace Foam
638 // ************************************************************************* //