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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "tetPolyMesh.H"
27 #include "tetPointRef.H"
28 #include "tetPointRef.H"
29 #include "SquareMatrix.H"
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38 label tetPolyMesh::nPoints() const
52 label tetPolyMesh::nEdges() const
56 nEdges_ = mesh_.nEdges();
58 const labelListList& pf = mesh_.pointFaces();
60 const labelListList& pc = mesh_.pointCells();
64 nEdges_ += pf[pointI].size();
66 nEdges_ += pc[pointI].size();
69 const cellList& cellFaces = mesh_.cells();
71 forAll (cellFaces, cellI)
73 nEdges_ += cellFaces[cellI].size();
81 label tetPolyMesh::nTets() const
88 const cellList& polyCells = mesh_.cells();
90 forAll (polyCells, cellI)
92 nTets_ += nTetsForCell(cellI);
100 // Return number of tetrahedra in decomposition for cell
101 label tetPolyMesh::nTetsForCell(const label cellID) const
103 const unallocFaceList& f = mesh_.faces();
105 label nTetrasForCell = 0;
107 const labelList& cellFaces = mesh_.cells()[cellID];
109 forAll (cellFaces, faceI)
111 nTetrasForCell += f[cellFaces[faceI]].nEdges();
114 return nTetrasForCell;
118 tmp<pointField> tetPolyMesh::points() const
120 tmp<pointField> ttetPoints(new pointField(nPoints()));
121 pointField& tetPoints = ttetPoints();
123 const pointField& points = mesh_.points();
125 const pointField& faceCentres = mesh_.faceCentres();
127 const pointField& cellCentres = mesh_.cellCentres();
131 forAll (points, pointI)
133 tetPoints[tetPointI] = points[pointI];
137 forAll (faceCentres, faceI)
139 tetPoints[tetPointI] = faceCentres[faceI];
143 forAll (cellCentres, cellI)
145 tetPoints[tetPointI] = cellCentres[cellI];
153 cellShapeList tetPolyMesh::tetCells() const
155 cellShapeList t(nTets());
157 const cellList& polyCells = mesh_.cells();
161 forAll (polyCells, cellI)
163 tetCellList cellTets = tets(cellI);
165 forAll (cellTets, tetI)
167 t[nTetCells] = cellTets[tetI].tetCellShape();
176 // Return tetrahedral decomposition for cell
177 tetCellList tetPolyMesh::tets(const label cellID) const
179 const unallocFaceList& f = mesh_.faces();
181 const unallocLabelList& owner = mesh_.faceOwner();
183 // Initialise the size of the return
184 tetCellList t(nTetsForCell(cellID));
188 const labelList& cellFaces = mesh_.cells()[cellID];
190 // A tet is created from the face edge, face centre and cell centre
191 forAll (cellFaces, faceI)
193 const label curFace = cellFaces[faceI];
197 // Take care of owner/neighbour face reversal
198 if (cellID == owner[curFace])
200 faceEdges = f[curFace].reverseFace().edges();
204 faceEdges = f[curFace].edges();
207 forAll (faceEdges, edgeI)
209 // Face is assumed to be inward-pointing
213 faceEdges[edgeI].start(),
214 faceEdges[edgeI].end(),
215 curFace + faceOffset_,
227 void tetPolyMesh::gradNiDotGradNj
230 SquareMatrix<scalar>& denseMatrix,
231 const labelList& globalToLocalBuffer
234 const unallocFaceList& meshFaces = mesh_.faces();
235 const unallocLabelList& owner = mesh_.faceOwner();
236 const labelList& cellFaces = mesh_.cells()[cellID];
238 const pointField& points = mesh_.points();
239 const pointField& faceCentres = mesh_.faceCentres();
240 const pointField& cellCentres = mesh_.cellCentres();
242 scalarField tetBuffer(tetPointRef::nEdges);
244 // For optimisation, point allocation is taken out of the loop
245 label vertexI, edgeI, localI, localJ;
248 forAll (cellFaces, faceI)
250 const label curFaceID = cellFaces[faceI];
254 if (cellID == owner[curFaceID])
256 faceEdges = meshFaces[curFaceID].reverseFace().edges();
260 faceEdges = meshFaces[curFaceID].edges();
263 forAll (faceEdges, i)
267 faceEdges[i].start(),
269 faceOffset() + curFaceID,
270 cellOffset() + cellID
275 points[faceEdges[i].start()],
276 points[faceEdges[i].end()],
277 faceCentres[curFaceID],
281 // Calculate the diagonal and insert into local matrix
282 tpr.gradNiSquared(tetBuffer);
287 vertexI < tetPointRef::nVertices;
291 localI = globalToLocalBuffer[curTet[vertexI]];
293 denseMatrix[localI][localI] += tetBuffer[vertexI];
296 tpr.gradNiDotGradNj(tetBuffer);
298 for (edgeI = 0; edgeI < tetPointRef::nEdges; edgeI++)
300 curEdge = curTet.tetEdge(edgeI);
302 localI = globalToLocalBuffer[curEdge.start()];
303 localJ = globalToLocalBuffer[curEdge.end()];
305 // Insert the coefficient into upper and lower triangle
307 denseMatrix[localI][localJ] += tetBuffer[edgeI];
308 denseMatrix[localJ][localI] += tetBuffer[edgeI];
315 void tetPolyMesh::gradNiGradNj
318 SquareMatrix<tensor>& denseMatrix,
319 const labelList& globalToLocalBuffer
322 const unallocFaceList& meshFaces = mesh_.faces();
323 const unallocLabelList& owner = mesh_.faceOwner();
324 const labelList& cellFaces = mesh_.cells()[cellID];
326 const pointField& points = mesh_.points();
327 const pointField& faceCentres = mesh_.faceCentres();
328 const pointField& cellCentres = mesh_.cellCentres();
330 tensorField tetBuffer(tetPointRef::nEdges);
332 // For optimisation, point allocation is taken out of the loop
333 label vertexI, edgeI, localI, localJ;
336 forAll (cellFaces, faceI)
338 const label curFaceID = cellFaces[faceI];
342 if (cellID == owner[curFaceID])
344 faceEdges = meshFaces[curFaceID].reverseFace().edges();
348 faceEdges = meshFaces[curFaceID].edges();
351 forAll (faceEdges, i)
355 faceEdges[i].start(),
357 faceOffset() + curFaceID,
358 cellOffset() + cellID
363 points[faceEdges[i].start()],
364 points[faceEdges[i].end()],
365 faceCentres[curFaceID],
369 // Calculate the diagonal and insert into local matrix
370 tpr.gradNiGradNi(tetBuffer);
375 vertexI < tetPointRef::nVertices;
379 localI = globalToLocalBuffer[curTet[vertexI]];
381 denseMatrix[localI][localI] += tetBuffer[vertexI];
384 tpr.gradNiGradNj(tetBuffer);
386 for (edgeI = 0; edgeI < tetPointRef::nEdges; edgeI++)
388 curEdge = curTet.tetEdge(edgeI);
390 localI = globalToLocalBuffer[curEdge.start()];
391 localJ = globalToLocalBuffer[curEdge.end()];
393 // Add coefficient and its transpose to upper and lower
394 // triangle. HJ, 4/Dec/2006
395 denseMatrix[localI][localJ] += tetBuffer[edgeI];
396 denseMatrix[localJ][localI] += tetBuffer[edgeI].T();
403 // Fill buffer with the volume integral distributed into vertices
404 void tetPolyMesh::volIntegral
408 const labelList& globalToLocalBuffer
411 // The addressing and volume distribution has been done tet-by-tet
412 // and the combination is done later for the whole cell.
414 const unallocFaceList& meshFaces = mesh_.faces();
415 const unallocLabelList& owner = mesh_.faceOwner();
416 const labelList& cellFaces = mesh_.cells()[cellID];
418 const pointField& points = mesh_.points();
419 const pointField& faceCentres = mesh_.faceCentres();
420 const pointField& cellCentres = mesh_.cellCentres();
422 label vertexI, localI;
424 forAll (cellFaces, faceI)
426 const label curFaceID = cellFaces[faceI];
430 // Take care of owner/neighbour face reversal
431 if (cellID == owner[curFaceID])
433 faceEdges = meshFaces[curFaceID].reverseFace().edges();
437 faceEdges = meshFaces[curFaceID].edges();
440 forAll (faceEdges, edgeI)
442 // Face is assumed to be inward-pointing
445 faceEdges[edgeI].start(),
446 faceEdges[edgeI].end(),
447 faceOffset() + curFaceID,
448 cellOffset() + cellID
451 scalar quarterVolume =
455 points[faceEdges[edgeI].start()],
456 points[faceEdges[edgeI].end()],
457 faceCentres[curFaceID],
464 vertexI < tetPointRef::nVertices;
468 localI = globalToLocalBuffer[curTet[vertexI]];
470 // Accumulate the diagonal
471 buffer[localI] += quarterVolume;
478 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
480 } // End namespace Foam
482 // ************************************************************************* //