/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright held by original author \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Description \*---------------------------------------------------------------------------*/ #include "vtkPV3Foam.H" // Foam includes #include "fvMesh.H" #include "cellModeller.H" #include "vtkPV3FoamPoints.H" // VTK includes #include "vtkCellArray.h" #include "vtkUnstructuredGrid.h" // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // vtkUnstructuredGrid* Foam::vtkPV3Foam::volumeVTKMesh ( const fvMesh& mesh, polyDecomp& decompInfo ) { vtkUnstructuredGrid* vtkmesh = vtkUnstructuredGrid::New(); if (debug) { Info<< " Foam::vtkPV3Foam::volumeVTKMesh" << endl; printMemory(); } // Number of additional points needed by the decomposition of polyhedra label nAddPoints = 0; // Number of additional cells generated by the decomposition of polyhedra label nAddCells = 0; labelList& superCells = decompInfo.superCells(); labelList& addPointCellLabels = decompInfo.addPointCellLabels(); const cellModel& tet = *(cellModeller::lookup("tet")); const cellModel& pyr = *(cellModeller::lookup("pyr")); const cellModel& prism = *(cellModeller::lookup("prism")); const cellModel& wedge = *(cellModeller::lookup("wedge")); const cellModel& tetWedge = *(cellModeller::lookup("tetWedge")); const cellModel& hex = *(cellModeller::lookup("hex")); // Scan for cells which need to be decomposed and count additional points // and cells if (debug) { Info<< "... building cell-shapes" << endl; } const cellShapeList& cellShapes = mesh.cellShapes(); if (debug) { Info<< "... scanning" << endl; } forAll(cellShapes, cellI) { const cellModel& model = cellShapes[cellI].model(); if ( model != hex && model != wedge && model != prism && model != pyr && model != tet && model != tetWedge ) { const cell& cFaces = mesh.cells()[cellI]; forAll(cFaces, cFaceI) { const face& f = mesh.faces()[cFaces[cFaceI]]; label nFacePoints = f.size(); label nQuads = (nFacePoints - 2)/2; label nTris = (nFacePoints - 2)%2; nAddCells += nQuads + nTris; } nAddCells--; nAddPoints++; } } // Set size of additional point addressing array // (from added point to original cell) addPointCellLabels.setSize(nAddPoints); // Set size of additional cells mapping array // (from added cell to original cell) if (debug) { Info<<" mesh nCells = " << mesh.nCells() << nl <<" nPoints = " << mesh.nPoints() << nl <<" nAddCells = " << nAddCells << nl <<" nAddPoints = " << nAddPoints << endl; } superCells.setSize(mesh.nCells() + nAddCells); if (debug) { Info<< "... converting points" << endl; } // Convert Foam mesh vertices to VTK vtkPoints *vtkpoints = vtkPoints::New(); vtkpoints->Allocate( mesh.nPoints() + nAddPoints ); const Foam::pointField& points = mesh.points(); forAll(points, i) { vtkPV3FoamInsertNextPoint(vtkpoints, points[i]); } if (debug) { Info<< "... converting cells" << endl; } vtkmesh->Allocate( mesh.nCells() + nAddCells ); // Set counters for additional points and additional cells label addPointI = 0, addCellI = 0; // Create storage for points - needed for mapping from Foam to VTK // data types - max 'order' = hex = 8 points vtkIdType nodeIds[8]; forAll(cellShapes, cellI) { const cellShape& cellShape = cellShapes[cellI]; const cellModel& cellModel = cellShape.model(); superCells[addCellI++] = cellI; if (cellModel == tet) { for (int j = 0; j < 4; j++) { nodeIds[j] = cellShape[j]; } vtkmesh->InsertNextCell ( VTK_TETRA, 4, nodeIds ); } else if (cellModel == pyr) { for (int j = 0; j < 5; j++) { nodeIds[j] = cellShape[j]; } vtkmesh->InsertNextCell ( VTK_PYRAMID, 5, nodeIds ); } else if (cellModel == prism) { for (int j = 0; j < 6; j++) { nodeIds[j] = cellShape[j]; } vtkmesh->InsertNextCell ( VTK_WEDGE, 6, nodeIds ); } else if (cellModel == tetWedge) { // Treat as squeezed prism nodeIds[0] = cellShape[0]; nodeIds[1] = cellShape[2]; nodeIds[2] = cellShape[1]; nodeIds[3] = cellShape[3]; nodeIds[4] = cellShape[4]; nodeIds[5] = cellShape[4]; vtkmesh->InsertNextCell ( VTK_WEDGE, 6, nodeIds ); } else if (cellModel == wedge) { // Treat as squeezed hex nodeIds[0] = cellShape[0]; nodeIds[1] = cellShape[1]; nodeIds[2] = cellShape[2]; nodeIds[3] = cellShape[2]; nodeIds[4] = cellShape[3]; nodeIds[5] = cellShape[4]; nodeIds[6] = cellShape[5]; nodeIds[7] = cellShape[6]; vtkmesh->InsertNextCell ( VTK_HEXAHEDRON, 8, nodeIds ); } else if (cellModel == hex) { for (int j = 0; j < 8; j++) { nodeIds[j] = cellShape[j]; } vtkmesh->InsertNextCell ( VTK_HEXAHEDRON, 8, nodeIds ); } else { // Polyhedral cell. Decompose into tets + prisms. // Mapping from additional point to cell addPointCellLabels[addPointI] = cellI; // Insert the new vertex from the cell-centre label newVertexLabel = mesh.nPoints() + addPointI; vtkPV3FoamInsertNextPoint(vtkpoints, mesh.C()[cellI]); // Whether to insert cell in place of original or not. bool substituteCell = true; const labelList& cFaces = mesh.cells()[cellI]; forAll(cFaces, cFaceI) { const face& f = mesh.faces()[cFaces[cFaceI]]; label nFacePoints = f.size(); label nQuads = (nFacePoints - 2)/2; label nTris = (nFacePoints - 2)%2; label qpi = 0; for (label quadi=0; quadiInsertNextCell ( VTK_PYRAMID, 5, nodeIds ); qpi += 2; } if (nTris) { label thisCellI = -1; if (substituteCell) { thisCellI = cellI; substituteCell = false; } else { thisCellI = mesh.nCells() + addCellI; superCells[addCellI++] = cellI; } nodeIds[0] = f[0]; nodeIds[1] = f[qpi + 1]; nodeIds[2] = f[qpi + 2]; nodeIds[3] = newVertexLabel; vtkmesh->InsertNextCell ( VTK_TETRA, 4, nodeIds ); } } addPointI++; } } vtkmesh->SetPoints(vtkpoints); vtkpoints->Delete(); if (debug) { Info<< " Foam::vtkPV3Foam::volumeVTKMesh" << endl; printMemory(); } return vtkmesh; } // ************************************************************************* //