1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
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 "primitiveMesh.H"
28 #include "DynamicList.H"
29 #include "demandDrivenData.H"
30 #include "SortableList.H"
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 // Returns edgeI between two points.
36 Foam::label Foam::primitiveMesh::getEdge
38 List<DynamicList<label> >& pe,
39 DynamicList<edge>& es,
42 const label nextPointI
45 // Find connection between pointI and nextPointI
46 forAll(pe[pointI], ppI)
48 label eI = pe[pointI][ppI];
50 const edge& e = es[eI];
52 if (e.start() == nextPointI || e.end() == nextPointI)
59 label edgeI = es.size();
60 pe[pointI].append(edgeI);
61 pe[nextPointI].append(edgeI);
62 if (pointI < nextPointI)
64 es.append(edge(pointI, nextPointI));
68 es.append(edge(nextPointI, pointI));
74 void Foam::primitiveMesh::calcEdges(const bool doFaceEdges) const
78 Pout<< "primitiveMesh::calcEdges(const bool) : "
79 << "calculating edges, pointEdges and optionally faceEdges"
83 // It is an error to attempt to recalculate edges
84 // if the pointer is already set
85 if ((edgesPtr_ || pePtr_) || (doFaceEdges && fePtr_))
87 FatalErrorIn("primitiveMesh::calcEdges(const bool) const")
88 << "edges or pointEdges or faceEdges already calculated"
94 // Go through the faces list. Search pointEdges for existing edge.
95 // If not found create edge and add to pointEdges.
96 // In second loop sort edges in order of increasing neighbouring
98 // This algorithm replaces the one using pointFaces which used more
99 // allocations but less memory and was on practical cases
100 // quite a bit slower.
102 const faceList& fcs = faces();
107 // Estimate pointEdges storage
108 List<DynamicList<label> > pe(nPoints());
111 pe[pointI].setCapacity(primitiveMesh::edgesPerPoint_);
114 // Estimate edges storage
115 DynamicList<edge> es(pe.size()*primitiveMesh::edgesPerPoint_/2);
117 // Estimate faceEdges storage
120 fePtr_ = new labelListList(fcs.size());
121 labelListList& faceEdges = *fePtr_;
124 faceEdges[faceI].setSize(fcs[faceI].size());
129 // Find consecutive face points in edge list
130 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132 // Edges on boundary faces
134 // Edges using no boundary point
135 nInternal0Edges_ = 0;
136 // Edges using 1 boundary point
137 label nInt1Edges = 0;
138 // Edges using two boundary points but not on boundary face:
139 // edges.size()-nExtEdges-nInternal0Edges_-nInt1Edges
141 // Ordering is different if points are ordered.
142 if (nInternalPoints_ == -1)
144 // No ordering. No distinction between types.
147 const face& f = fcs[faceI];
151 label pointI = f[fp];
152 label nextPointI = f[f.fcIndex(fp)];
154 label edgeI = getEdge(pe, es, pointI, nextPointI);
158 (*fePtr_)[faceI][fp] = edgeI;
162 // Assume all edges internal
164 nInternal0Edges_ = es.size();
169 // 1. Do external faces first. This creates external edges.
170 for (label faceI = nInternalFaces_; faceI < fcs.size(); faceI++)
172 const face& f = fcs[faceI];
176 label pointI = f[fp];
177 label nextPointI = f[f.fcIndex(fp)];
179 label oldNEdges = es.size();
180 label edgeI = getEdge(pe, es, pointI, nextPointI);
182 if (es.size() > oldNEdges)
188 (*fePtr_)[faceI][fp] = edgeI;
193 // 2. Do internal faces. This creates internal edges.
194 for (label faceI = 0; faceI < nInternalFaces_; faceI++)
196 const face& f = fcs[faceI];
200 label pointI = f[fp];
201 label nextPointI = f[f.fcIndex(fp)];
203 label oldNEdges = es.size();
204 label edgeI = getEdge(pe, es, pointI, nextPointI);
206 if (es.size() > oldNEdges)
208 if (pointI < nInternalPoints_)
210 if (nextPointI < nInternalPoints_)
221 if (nextPointI < nInternalPoints_)
227 // Internal edge with two points on boundary
233 (*fePtr_)[faceI][fp] = edgeI;
240 // For unsorted meshes the edges will be in order of occurrence inside
241 // the faces. For sorted meshes the first nExtEdges will be the external
244 if (nInternalPoints_ != -1)
246 nInternalEdges_ = es.size()-nExtEdges;
247 nInternal1Edges_ = nInternal0Edges_+nInt1Edges;
249 //Pout<< "Edge overview:" << nl
250 // << " total number of edges : " << es.size()
252 // << " boundary edges : " << nExtEdges
254 // << " edges using no boundary point : "
255 // << nInternal0Edges_
257 // << " edges using one boundary points : " << nInt1Edges
259 // << " edges using two boundary points : "
260 // << es.size()-nExtEdges-nInternal0Edges_-nInt1Edges << endl;
264 // Like faces sort edges in order of increasing neigbouring point.
265 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
266 // Automatically if points are sorted into internal and external points
267 // the edges will be sorted into
268 // - internal point to internal point
269 // - internal point to external point
270 // - external point to external point
271 // The problem is that the last one mixes external edges with internal
272 // edges with two points on the boundary.
275 // Map to sort into new upper-triangular order
276 labelList oldToNew(es.size());
282 // start of edges with 0 boundary points
283 label internal0EdgeI = 0;
285 // start of edges with 1 boundary points
286 label internal1EdgeI = nInternal0Edges_;
288 // start of edges with 2 boundary points
289 label internal2EdgeI = nInternal1Edges_;
291 // start of external edges
292 label externalEdgeI = nInternalEdges_;
295 // To sort neighbouring points in increasing order. Defined outside
296 // for optimisation reasons: if all connectivity size same will need
298 SortableList<label> nbrPoints(primitiveMesh::edgesPerPoint_);
302 const DynamicList<label>& pEdges = pe[pointI];
304 nbrPoints.setSize(pEdges.size());
308 const edge& e = es[pEdges[i]];
310 label nbrPointI = e.otherVertex(pointI);
312 if (nbrPointI < pointI)
318 nbrPoints[i] = nbrPointI;
324 if (nInternalPoints_ == -1)
326 // Sort all upper-triangular
329 if (nbrPoints[i] != -1)
331 label edgeI = pEdges[nbrPoints.indices()[i]];
333 oldToNew[edgeI] = internal0EdgeI++;
339 if (pointI < nInternalPoints_)
343 label nbrPointI = nbrPoints[i];
345 label edgeI = pEdges[nbrPoints.indices()[i]];
349 if (edgeI < nExtEdges)
352 oldToNew[edgeI] = externalEdgeI++;
354 else if (nbrPointI < nInternalPoints_)
356 // Both points inside
357 oldToNew[edgeI] = internal0EdgeI++;
361 // One points inside, one outside
362 oldToNew[edgeI] = internal1EdgeI++;
371 label nbrPointI = nbrPoints[i];
373 label edgeI = pEdges[nbrPoints.indices()[i]];
377 if (edgeI < nExtEdges)
380 oldToNew[edgeI] = externalEdgeI++;
382 else if (nbrPointI < nInternalPoints_)
385 FatalErrorIn("primitiveMesh::calcEdges(..)")
386 << abort(FatalError);
390 // Both points outside
391 oldToNew[edgeI] = internal2EdgeI++;
402 label edgeI = findIndex(oldToNew, -1);
406 const edge& e = es[edgeI];
408 FatalErrorIn("primitiveMesh::calcEdges(..)")
409 << "Did not sort edge " << edgeI << " points:" << e
410 << " coords:" << points()[e[0]] << points()[e[1]]
412 << "Current buckets:" << endl
413 << " internal0EdgeI:" << internal0EdgeI << endl
414 << " internal1EdgeI:" << internal1EdgeI << endl
415 << " internal2EdgeI:" << internal2EdgeI << endl
416 << " externalEdgeI:" << externalEdgeI << endl
417 << abort(FatalError);
423 // Renumber and transfer.
426 edgesPtr_ = new edgeList(es.size());
427 edgeList& edges = *edgesPtr_;
430 edges[oldToNew[edgeI]] = es[edgeI];
434 pePtr_ = new labelListList(nPoints());
435 labelListList& pointEdges = *pePtr_;
438 DynamicList<label>& pEdges = pe[pointI];
440 inplaceRenumber(oldToNew, pEdges);
441 pointEdges[pointI].transfer(pEdges);
442 Foam::sort(pointEdges[pointI]);
448 labelListList& faceEdges = *fePtr_;
449 forAll(faceEdges, faceI)
451 inplaceRenumber(oldToNew, faceEdges[faceI]);
458 Foam::label Foam::primitiveMesh::findFirstCommonElementFromSortedLists
460 const labelList& list1,
461 const labelList& list2
466 labelList::const_iterator iter1 = list1.begin();
467 labelList::const_iterator iter2 = list2.begin();
469 while (iter1 != list1.end() && iter2 != list2.end())
475 else if (*iter1 > *iter2)
489 "primitiveMesh::findFirstCommonElementFromSortedLists"
490 "(const labelList&, const labelList&)"
491 ) << "No common elements in lists " << list1 << " and " << list2
492 << abort(FatalError);
498 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
500 const Foam::edgeList& Foam::primitiveMesh::edges() const
511 const Foam::labelListList& Foam::primitiveMesh::pointEdges() const
523 const Foam::labelListList& Foam::primitiveMesh::faceEdges() const
529 Pout<< "primitiveMesh::faceEdges() : "
530 << "calculating faceEdges" << endl;
534 const faceList& fcs = faces();
535 const labelListList& pe = pointEdges();
536 const edgeList& es = edges();
538 fePtr_ = new labelListList(fcs.size());
539 labelListList& faceEdges = *fePtr_;
543 const face& f = fcs[faceI];
545 labelList& fEdges = faceEdges[faceI];
546 fEdges.setSize(f.size());
550 label pointI = f[fp];
551 label nextPointI = f[f.fcIndex(fp)];
553 // Find edge between pointI, nextPontI
554 const labelList& pEdges = pe[pointI];
558 label edgeI = pEdges[i];
560 if (es[edgeI].otherVertex(pointI) == nextPointI)
574 void Foam::primitiveMesh::clearOutEdges()
576 deleteDemandDrivenData(edgesPtr_);
577 deleteDemandDrivenData(pePtr_);
578 deleteDemandDrivenData(fePtr_);
584 const Foam::labelList& Foam::primitiveMesh::faceEdges
587 DynamicList<label>& storage
592 return faceEdges()[faceI];
596 const labelListList& pointEs = pointEdges();
597 const face& f = faces()[faceI];
600 if (f.size() > storage.capacity())
602 storage.setCapacity(f.size());
609 findFirstCommonElementFromSortedLists
612 pointEs[f.nextLabel(fp)]
622 const Foam::labelList& Foam::primitiveMesh::faceEdges(const label faceI) const
624 return faceEdges(faceI, labels_);
628 const Foam::labelList& Foam::primitiveMesh::cellEdges
631 DynamicList<label>& storage
636 return cellEdges()[cellI];
640 const labelList& cFaces = cells()[cellI];
646 const labelList& fe = faceEdges(cFaces[i]);
650 labelSet_.insert(fe[feI]);
656 if (labelSet_.size() > storage.capacity())
658 storage.setCapacity(labelSet_.size());
661 forAllConstIter(labelHashSet, labelSet_, iter)
663 storage.append(iter.key());
671 const Foam::labelList& Foam::primitiveMesh::cellEdges(const label cellI) const
673 return cellEdges(cellI, labels_);
677 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
679 // ************************************************************************* //