00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <OctreeMeshBuilder.hpp>
00021 #include <Structured3DMesh.hpp>
00022
00023 #include <ErrorHandler.hpp>
00024
00025 void OctreeMeshBuilder::
00026 buildMesh()
00027 {
00028 if (__mesh->type() != Mesh::cartesianHexahedraMesh) {
00029 throw ErrorHandler(__FILE__,__LINE__,
00030 "cannot build octree mesh on "
00031 +__mesh->typeName()
00032 +": structured mesh is mandatory!",
00033 ErrorHandler::normal);
00034 }
00035
00036 const Structured3DMesh& mesh
00037 = dynamic_cast<const Structured3DMesh&>(*__mesh);
00038 const Domain& domain = *__domain;
00039
00040 ffout(2) << "Starting Octree mesh builder\n";
00041 Vector<bool> domainVertex(mesh.numberOfVertices());
00042
00043 for (size_t i=0; i<mesh.numberOfVertices(); ++i) {
00044 domainVertex[i] = domain.inside(mesh.vertex(i));
00045 }
00046
00047 std::vector<size_t> inCells;
00048 std::vector<size_t> outCells;
00049 std::vector<size_t> boundaryCells;
00050
00051 for(Structured3DMesh::const_iterator icell(mesh); not icell.end(); ++icell) {
00052 bool allIn = true;
00053 bool allOut = true;
00054 const CartesianHexahedron& K = *icell;
00055 for (size_t i=0; i<CartesianHexahedron::NumberOfVertices; ++i) {
00056 size_t vertexNumber = mesh.vertexNumber(K(i));
00057 if (domainVertex[vertexNumber]) {
00058 allOut = false;
00059 } else {
00060 allIn = false;
00061 }
00062 }
00063 if (allIn) {
00064 inCells.push_back(icell.number());
00065 } else if (allOut) {
00066 outCells.push_back(icell.number());
00067 } else {
00068 boundaryCells.push_back(icell.number());
00069 }
00070 }
00071
00072 typedef std::map<size_t, TinyVector<3,real_t> > VerticesList;
00073 VerticesList verticesList;
00074
00075 typedef TinyVector<3, size_t> NodeIndex;
00076 typedef TinyVector<3, real_t> NodeCoord;
00077 typedef TinyVector<8, NodeIndex> CellDescriptor;
00078 typedef std::map<NodeIndex, NodeCoord> NodeList;
00079 typedef std::map<NodeIndex, size_t> NodeNumber;
00080 typedef std::vector<CellDescriptor> CellList;
00081
00082 std::vector<NodeList> nodeListSet(__maximumLevel+1);
00083 std::vector<CellList> cellListSet(__maximumLevel+1);
00084
00085 {
00086 NodeList& nodeList = nodeListSet[0];
00087 CellList& cellList = cellListSet[0];
00088
00089 for(size_t i=0; i<inCells.size(); ++i) {
00090 CellDescriptor cell;
00091 const CartesianHexahedron& H = mesh.cell(inCells[i]);
00092 for(size_t j=0; j<CartesianHexahedron::NumberOfVertices; ++j) {
00093 NodeIndex nodeIndex = mesh.vertexIndex(H(j))*(1<<__maximumLevel);
00094
00095 cell[j] = nodeIndex;
00096
00097 NodeCoord nodeCoord;
00098 nodeCoord[0] = nodeIndex[0]*mesh.shape().hx()/(1<<__maximumLevel)+mesh.shape().a()[0];
00099 nodeCoord[1] = nodeIndex[1]*mesh.shape().hy()/(1<<__maximumLevel)+mesh.shape().a()[1];
00100 nodeCoord[2] = nodeIndex[2]*mesh.shape().hz()/(1<<__maximumLevel)+mesh.shape().a()[2];
00101
00102 nodeList[nodeIndex] = nodeCoord;
00103 }
00104 cellList.push_back(cell);
00105 }
00106 }
00107
00108
00109 CellList cellToCut;
00110 cellToCut.reserve(boundaryCells.size());
00111
00112 NodeList cellToCutNode;
00113
00114 {
00115 for(size_t i=0; i<boundaryCells.size(); ++i) {
00116 const CartesianHexahedron& H = mesh.cell(boundaryCells[i]);
00117 CellDescriptor cell;
00118 Index index0 = mesh.vertexIndex(H(0));
00119 for(size_t j=0; j<CartesianHexahedron::NumberOfVertices; ++j) {
00120 Index index = mesh.vertexIndex(H(j));
00121 NodeIndex nodeIndex = mesh.vertexIndex(H(j))*(1<<__maximumLevel);
00122
00123 NodeCoord nodeCoord;
00124 nodeCoord[0] = nodeIndex[0]*mesh.shape().hx()/(1<<__maximumLevel)+mesh.shape().a()[0];
00125 nodeCoord[1] = nodeIndex[1]*mesh.shape().hy()/(1<<__maximumLevel)+mesh.shape().a()[1];
00126 nodeCoord[2] = nodeIndex[2]*mesh.shape().hz()/(1<<__maximumLevel)+mesh.shape().a()[2];
00127
00128 cell[j] = nodeIndex;
00129
00130 cellToCutNode[nodeIndex] = nodeCoord;
00131 cellToCut.push_back(nodeIndex);
00132 }
00133 }
00134 }
00135
00136 TinyVector<8,TinyVector<3,size_t> > shift;
00137 shift[0] = TinyVector<3,size_t>(0,0,0);
00138 shift[1] = TinyVector<3,size_t>(1,0,0);
00139 shift[2] = TinyVector<3,size_t>(1,1,0);
00140 shift[3] = TinyVector<3,size_t>(0,1,0);
00141 shift[4] = TinyVector<3,size_t>(0,0,1);
00142 shift[5] = TinyVector<3,size_t>(1,0,1);
00143 shift[6] = TinyVector<3,size_t>(1,1,1);
00144 shift[7] = TinyVector<3,size_t>(0,1,1);
00145
00146
00147 const TinyVector<3,real_t> meshStep(mesh.shape().hx()/(1<<(__maximumLevel)),
00148 mesh.shape().hy()/(1<<(__maximumLevel)),
00149 mesh.shape().hz()/(1<<(__maximumLevel)));
00150
00151 for (size_t level=1; level<=__maximumLevel; ++level) {
00152 NodeList& nodeList = nodeListSet[level];
00153 CellList& cellList = cellListSet[level];
00154
00155 ffout(3) << "- Creating level " << level << '\n';
00156 CellList cuttedCell;
00157 NodeList cuttedCellNode;
00158 for (CellList::const_iterator icell = cellToCut.begin();
00159 icell != cellToCut.end(); ++icell) {
00160 const CellDescriptor& oldCell = *icell;
00161 const NodeIndex& baseNode = oldCell[0];
00162 for (size_t i=0; i<8; ++i) {
00163 CellDescriptor cell;
00164 for (size_t j=0; j<8; ++j) {
00165 const NodeIndex newNode = baseNode+(shift[i]+shift[j])*(1<<(__maximumLevel-level));
00166 cell[j] = newNode;
00167 NodeCoord nodeCoord;
00168 nodeCoord[0] = newNode[0]*meshStep[0] + mesh.shape().a()[0];
00169 nodeCoord[1] = newNode[1]*meshStep[1] + mesh.shape().a()[1];
00170 nodeCoord[2] = newNode[2]*meshStep[2] + mesh.shape().a()[2];
00171
00172 cuttedCellNode[newNode] = nodeCoord;
00173 }
00174 cuttedCell.push_back(cell);
00175 }
00176 }
00177
00178
00179 cellToCut.clear();
00180
00181
00182 typedef std::map<NodeIndex, bool> NodeInside;
00183 NodeInside nodeInside;
00184 for (NodeList::const_iterator inode = cuttedCellNode.begin();
00185 inode != cuttedCellNode.end(); ++inode) {
00186 nodeInside[inode->first] = domain.inside(inode->second);
00187 }
00188
00189 for(CellList::const_iterator icell = cuttedCell.begin();
00190 icell != cuttedCell.end(); ++icell) {
00191 bool allIn = true;
00192 bool allOut = true;
00193 const CellDescriptor& cell = *icell;
00194
00195 for (size_t i=0; i<CartesianHexahedron::NumberOfVertices; ++i) {
00196 if (nodeInside[cell[i]]) {
00197 allOut = false;
00198 } else {
00199 allIn = false;
00200 }
00201 }
00202 if (allIn) {
00203 cellList.push_back(cell);
00204 for (size_t i=0; i<CartesianHexahedron::NumberOfVertices; ++i) {
00205 nodeList[cell[i]] = cuttedCellNode[cell[i]];
00206 }
00207 } else if ((not allOut) and (level<__maximumLevel)) {
00208 cellToCut.push_back(cell);
00209 }
00210 }
00211 }
00212
00213 std::vector<NodeNumber> nodeNumberSet(__maximumLevel+1);
00214
00215 size_t numberOfNodes=0;
00216 {
00217 for(size_t level = 0; level<__maximumLevel+1; ++level) {
00218 NodeNumber& nodeNumber = nodeNumberSet[level];
00219 NodeList& nodeList = nodeListSet[level];
00220 for (NodeList::const_iterator i=nodeList.begin();
00221 i != nodeList.end(); ++i) {
00222 nodeNumber[i->first] = numberOfNodes;
00223 numberOfNodes++;
00224 }
00225 }
00226 }
00227
00228 ReferenceCounting<VerticesSet> pVerticesSet;
00229 ReferenceCounting<VerticesCorrespondance> pVerticesCorrespondance;
00230
00231 {
00232 pVerticesSet = new VerticesSet(numberOfNodes);
00233 VerticesSet& verticesSet = *pVerticesSet;
00234 size_t k=0;
00235 for(size_t level = 0; level<__maximumLevel+1; ++level) {
00236 NodeList& nodeList = nodeListSet[level];
00237 for (NodeList::const_iterator i=nodeList.begin();
00238 i != nodeList.end(); ++i) {
00239 verticesSet[k] = i->second;
00240 k++;
00241 }
00242 }
00243
00244 pVerticesCorrespondance
00245 = new VerticesCorrespondance(verticesList.size());
00246 }
00247
00248 VerticesSet& verticesSet = *pVerticesSet;
00249
00250 size_t numberOfCells = 0;
00251 for(size_t level = 0; level<__maximumLevel+1; ++level) {
00252 const CellList& cellList = cellListSet[level];
00253 numberOfCells += cellList.size();
00254 }
00255
00256 ReferenceCounting<Vector<CartesianHexahedron> > pCellsSet
00257 = new Vector<CartesianHexahedron>(numberOfCells);
00258 Vector<CartesianHexahedron>& cellsSet = *pCellsSet;
00259 {
00260 size_t k=0;
00261 for(size_t level = 0; level<__maximumLevel+1; ++level) {
00262 CellList& cellList = cellListSet[level];
00263 NodeNumber& nodeNumber = nodeNumberSet[level];
00264 for (size_t i=0; i<cellList.size();++i) {
00265 const CellDescriptor& cell = cellList[i];
00266
00267 cellsSet[k] = CartesianHexahedron(verticesSet[nodeNumber[cell[0]]],
00268 verticesSet[nodeNumber[cell[1]]],
00269 verticesSet[nodeNumber[cell[2]]],
00270 verticesSet[nodeNumber[cell[3]]],
00271 verticesSet[nodeNumber[cell[4]]],
00272 verticesSet[nodeNumber[cell[5]]],
00273 verticesSet[nodeNumber[cell[6]]],
00274 verticesSet[nodeNumber[cell[7]]]);
00275 ++k;
00276 }
00277 }
00278 }
00279
00280 for (size_t level=0; level<__maximumLevel+1; ++level) {
00281 ffout(4) << " - Level " << level << '\n';
00282 ffout(4) << " - Number of cells: " << cellListSet[level].size() << '\n';
00283 ffout(4) << " - Number of nodes: " << nodeNumberSet[level].size() << '\n';
00284 }
00285
00286 ffout(3) << "- Number of cells: " << cellsSet.size() << '\n';
00287 ffout(3) << "- Number of nodes: " << verticesSet.numberOfVertices() << '\n';
00288
00289 __octreeMesh = new OctreeMesh(pVerticesSet,
00290 pVerticesCorrespondance,
00291 pCellsSet);
00292
00293 ffout(2) << "Octree mesh builder finished\n";
00294 }