Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "QuadraticMesh.hpp" 00037 #include "OutputFileHandler.hpp" 00038 #include "TrianglesMeshReader.hpp" 00039 #include "Warnings.hpp" 00040 #include "QuadraticMeshHelper.hpp" 00041 00042 //Jonathan Shewchuk's triangle and Hang Si's tetgen 00043 #define REAL double 00044 #define VOID void 00045 #include "triangle.h" 00046 #include "tetgen.h" 00047 #undef REAL 00048 #undef VOID 00049 00050 template<unsigned DIM> 00051 void QuadraticMesh<DIM>::CountAndCheckVertices() 00052 { 00053 // count the number of vertices, and also check all vertices come before the 00054 // rest of the nodes (as this is assumed in 00055 // AbstractNonlinearElasticitySolver<DIM>::AllocateMatrixMemory() ) 00056 // 00057 mNumVertices = 0; 00058 for (unsigned i=0; i<this->GetNumNodes(); i++) 00059 { 00060 bool is_internal = this->GetNode(i)->IsInternal(); 00061 if (is_internal==false) 00062 { 00063 mNumVertices++; 00064 } 00065 } 00066 } 00067 00068 template<unsigned DIM> 00069 QuadraticMesh<DIM>::QuadraticMesh(double spaceStep, double width, double height, double depth) 00070 { 00071 this->ConstructRegularSlabMesh(spaceStep, width, height, depth); 00072 } 00073 00074 template<unsigned DIM> 00075 void QuadraticMesh<DIM>::ConstructLinearMesh(unsigned numElemX) 00076 { 00077 AbstractTetrahedralMesh<DIM,DIM>::ConstructLinearMesh(numElemX); 00078 assert (this->mNodes.size() == numElemX+1); 00079 mNumVertices = numElemX+1; 00080 this->mNodes.resize(2*numElemX+1); 00081 00082 for (unsigned element_index=0; element_index<numElemX; element_index++) 00083 { 00084 unsigned mid_node_index = mNumVertices + element_index; 00085 double x_value_mid_node = element_index+0.5; 00086 00087 //Make internal node 00088 Node<DIM>* p_mid_node = new Node<DIM>(mid_node_index, false, x_value_mid_node); 00089 p_mid_node->MarkAsInternal(); 00090 //Put in mesh 00091 this->mNodes[mid_node_index] = p_mid_node; 00092 //Put in element and cross-reference 00093 this->mElements[element_index]->AddNode(p_mid_node); 00094 p_mid_node->AddElement(element_index); 00095 00096 } 00097 00098 this->RefreshMesh(); 00099 } 00100 00101 00102 00103 00104 template<unsigned DIM> 00105 void QuadraticMesh<DIM>::ConstructRectangularMesh(unsigned numElemX, unsigned numElemY, bool unused) 00106 { 00107 assert(DIM==2); 00108 00109 assert(numElemX > 0); 00110 assert(numElemY > 0); 00111 assert(unused); 00112 00113 this->mMeshIsLinear=false; 00114 unsigned num_nodes=(numElemX+1)*(numElemY+1); 00115 struct triangulateio mesher_input; 00116 00117 this->InitialiseTriangulateIo(mesher_input); 00118 mesher_input.pointlist = (double *) malloc( num_nodes * DIM * sizeof(double)); 00119 mesher_input.numberofpoints = num_nodes; 00120 00121 unsigned new_index = 0; 00122 for (unsigned j=0; j<=numElemY; j++) 00123 { 00124 double y = j; 00125 for (unsigned i=0; i<=numElemX; i++) 00126 { 00127 double x = i; 00128 00129 mesher_input.pointlist[DIM*new_index] = x; 00130 mesher_input.pointlist[DIM*new_index + 1] = y; 00131 new_index++; 00132 } 00133 } 00134 00135 // Make structure for output 00136 struct triangulateio mesher_output; 00137 00138 this->InitialiseTriangulateIo(mesher_output); 00139 00140 // Library call 00141 triangulate((char*)"Qzeo2", &mesher_input, &mesher_output, NULL); 00142 00143 assert(mesher_output.numberofcorners == (DIM+1)*(DIM+2)/2);//Nodes per element (including internals, one per edge) 00144 00145 this->ImportFromMesher(mesher_output, mesher_output.numberoftriangles, mesher_output.trianglelist, mesher_output.numberofedges, mesher_output.edgelist, mesher_output.edgemarkerlist); 00146 00147 CountAndCheckVertices(); 00148 QuadraticMeshHelper<DIM>::AddNodesToBoundaryElements(this, NULL); 00149 00150 this->FreeTriangulateIo(mesher_input); 00151 this->FreeTriangulateIo(mesher_output); 00152 } 00153 00154 00155 00156 template<unsigned DIM> 00157 void QuadraticMesh<DIM>::ConstructCuboid(unsigned numElemX, unsigned numElemY, unsigned numElemZ) 00158 { 00159 assert(DIM==3); 00160 00161 assert(numElemX > 0); 00162 assert(numElemY > 0); 00163 assert(numElemZ > 0); 00164 this->mMeshIsLinear = false; 00165 unsigned num_nodes = (numElemX+1)*(numElemY+1)*(numElemZ+1); 00166 00167 struct tetgen::tetgenio mesher_input; 00168 mesher_input.pointlist = new double[num_nodes * DIM]; 00169 mesher_input.numberofpoints = num_nodes; 00170 unsigned new_index = 0; 00171 for (unsigned k=0; k<=numElemZ; k++) 00172 { 00173 double z = k; 00174 for (unsigned j=0; j<=numElemY; j++) 00175 { 00176 double y = j; 00177 for (unsigned i=0; i<=numElemX; i++) 00178 { 00179 double x = i; 00180 mesher_input.pointlist[DIM*new_index] = x; 00181 mesher_input.pointlist[DIM*new_index + 1] = y; 00182 mesher_input.pointlist[DIM*new_index + 2] = z; 00183 new_index++; 00184 } 00185 } 00186 } 00187 00188 // Library call 00189 struct tetgen::tetgenio mesher_output; 00190 tetgen::tetrahedralize((char*)"Qo2", &mesher_input, &mesher_output, NULL); 00191 00192 assert(mesher_output.numberofcorners == (DIM+1)*(DIM+2)/2);//Nodes per element (including internals, one per edge) 00193 00194 this->ImportFromMesher(mesher_output, mesher_output.numberoftetrahedra, mesher_output.tetrahedronlist, mesher_output.numberoftrifaces, mesher_output.trifacelist, NULL); 00195 00196 CountAndCheckVertices(); 00197 QuadraticMeshHelper<DIM>::AddNodesToBoundaryElements(this, NULL); 00198 } 00199 00200 00201 template<unsigned DIM> 00202 unsigned QuadraticMesh<DIM>::GetNumVertices() const 00203 { 00204 return mNumVertices; 00205 } 00206 00207 00208 template<unsigned DIM> 00209 void QuadraticMesh<DIM>::ConstructFromLinearMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader) 00210 { 00211 assert(DIM != 1); 00212 00213 //Make a linear mesh 00214 TetrahedralMesh<DIM,DIM>::ConstructFromMeshReader(rMeshReader); 00215 00216 NodeMap unused_map(this->GetNumNodes()); 00217 00218 if (DIM==2) // In 2D, remesh using triangle via library calls 00219 { 00220 struct triangulateio mesher_input, mesher_output; 00221 this->InitialiseTriangulateIo(mesher_input); 00222 this->InitialiseTriangulateIo(mesher_output); 00223 00224 mesher_input.numberoftriangles = this->GetNumElements(); 00225 mesher_input.trianglelist = (int *) malloc(this->GetNumElements() * (DIM+1) * sizeof(int)); 00226 this->ExportToMesher(unused_map, mesher_input, mesher_input.trianglelist); 00227 00228 // Library call 00229 triangulate((char*)"Qzero2", &mesher_input, &mesher_output, NULL); 00230 00231 this->ImportFromMesher(mesher_output, mesher_output.numberoftriangles, mesher_output.trianglelist, mesher_output.numberofedges, mesher_output.edgelist, mesher_output.edgemarkerlist); 00232 CountAndCheckVertices(); 00233 QuadraticMeshHelper<DIM>::AddNodesToBoundaryElements(this, NULL); 00234 00235 //Tidy up triangle 00236 this->FreeTriangulateIo(mesher_input); 00237 this->FreeTriangulateIo(mesher_output); 00238 } 00239 else // in 3D, remesh using tetgen 00240 { 00241 00242 struct tetgen::tetgenio mesher_input, mesher_output; 00243 00244 mesher_input.numberoftetrahedra = this->GetNumElements(); 00245 mesher_input.tetrahedronlist = new int[this->GetNumElements() * (DIM+1)]; 00246 this->ExportToMesher(unused_map, mesher_input, mesher_input.tetrahedronlist); 00247 00248 // Library call 00249 tetgen::tetrahedralize((char*)"Qzro2", &mesher_input, &mesher_output); 00250 00251 this->ImportFromMesher(mesher_output, mesher_output.numberoftetrahedra, mesher_output.tetrahedronlist, mesher_output.numberoftrifaces, mesher_output.trifacelist, NULL); 00252 CountAndCheckVertices(); 00253 QuadraticMeshHelper<DIM>::AddNodesToBoundaryElements(this, NULL); 00254 } 00255 } 00256 00257 00258 template<unsigned DIM> 00259 void QuadraticMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rAbsMeshReader) 00260 { 00261 TrianglesMeshReader<DIM, DIM>* p_mesh_reader=dynamic_cast<TrianglesMeshReader<DIM, DIM>*>(&rAbsMeshReader); 00262 00263 unsigned order_of_elements = 1; 00264 if (p_mesh_reader) 00265 { 00266 //A triangles mesh reader will let you read with non-linear elements 00267 order_of_elements = p_mesh_reader->GetOrderOfElements(); 00268 } 00269 00270 // If it is a linear TrianglesMeshReader or any other reader (which are all linear) 00271 if (order_of_elements == 1) 00272 { 00273 WARNING("Reading a (linear) tetrahedral mesh and converting it to a QuadraticMesh. This involves making an external library call to Triangle/Tetgen in order to compute internal nodes"); 00274 ConstructFromLinearMeshReader(rAbsMeshReader); 00275 return; 00276 } 00277 00278 TetrahedralMesh<DIM,DIM>::ConstructFromMeshReader(*p_mesh_reader); 00279 assert(this->GetNumBoundaryElements() > 0); 00280 00281 QuadraticMeshHelper<DIM>::AddInternalNodesToElements(this, p_mesh_reader); 00282 CountAndCheckVertices(); 00283 QuadraticMeshHelper<DIM>::AddInternalNodesToBoundaryElements(this, p_mesh_reader); 00284 QuadraticMeshHelper<DIM>::CheckBoundaryElements(this); 00285 } 00286 00288 // Explicit instantiation 00290 00291 00292 template class QuadraticMesh<1>; 00293 template class QuadraticMesh<2>; 00294 template class QuadraticMesh<3>; 00295 00296 00297 // Serialization for Boost >= 1.36 00298 #include "SerializationExportWrapperForCpp.hpp" 00299 EXPORT_TEMPLATE_CLASS_SAME_DIMS(QuadraticMesh)