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 #include <cassert> 00036 #include <sstream> 00037 #include <iostream> 00038 00039 #include "TrianglesMeshReader.hpp" 00040 #include "Exception.hpp" 00041 00042 static const char* NODES_FILE_EXTENSION = ".node"; 00043 static const char* ELEMENTS_FILE_EXTENSION = ".ele"; 00044 static const char* FACES_FILE_EXTENSION = ".face"; 00045 static const char* EDGES_FILE_EXTENSION = ".edge"; 00046 static const char* NCL_FILE_EXTENSION = ".ncl"; 00047 static const char* CABLE_FILE_EXTENSION = ".cable"; 00048 00050 // Implementation 00052 00053 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00054 TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::TrianglesMeshReader(std::string pathBaseName, 00055 unsigned orderOfElements, 00056 unsigned orderOfBoundaryElements, 00057 bool readContainingElementForBoundaryElements) 00058 : mFilesBaseName(pathBaseName), 00059 mNodeItemWidth(0), 00060 mElementItemWidth(0), 00061 mFaceItemWidth(0), 00062 mNumNodes(0), 00063 mNumElements(0), 00064 mNumFaces(0), 00065 mNumCableElements(0), 00066 mNodesRead(0), 00067 mElementsRead(0), 00068 mCableElementsRead(0), 00069 mFacesRead(0), 00070 mBoundaryFacesRead(0), 00071 mNumNodeAttributes(0), 00072 mNumElementAttributes(0), 00073 mNumFaceAttributes(0), 00074 mNumCableElementAttributes(0), 00075 mOrderOfElements(orderOfElements), 00076 mOrderOfBoundaryElements(orderOfBoundaryElements), 00077 mEofException(false), 00078 mReadContainingElementOfBoundaryElement(readContainingElementForBoundaryElements), 00079 mFilesAreBinary(false), 00080 mMeshIsHexahedral(false), 00081 mNodeFileReadBuffer(NULL), 00082 mElementFileReadBuffer(NULL), 00083 mFaceFileReadBuffer(NULL), 00084 mNodePermutationDefined(false) 00085 { 00086 // Only linear and quadratic elements 00087 assert(orderOfElements==1 || orderOfElements==2); 00088 if ( mOrderOfBoundaryElements == 2 && mReadContainingElementOfBoundaryElement) 00089 { 00090 EXCEPTION("Boundary element file should not have containing element info if it is quadratic"); 00091 } 00092 if (mOrderOfElements==1) 00093 { 00094 mNodesPerElement = ELEMENT_DIM+1; 00095 } 00096 else 00097 { 00098 #define COVERAGE_IGNORE 00099 assert(SPACE_DIM==ELEMENT_DIM); 00100 #undef COVERAGE_IGNORE 00101 mNodesPerElement = (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; 00102 } 00103 00104 if (mOrderOfBoundaryElements==1) 00105 { 00106 mNodesPerBoundaryElement = ELEMENT_DIM; 00107 } 00108 else 00109 { 00110 #define COVERAGE_IGNORE 00111 assert(SPACE_DIM==ELEMENT_DIM); 00112 #undef COVERAGE_IGNORE 00113 mNodesPerBoundaryElement = ELEMENT_DIM*(ELEMENT_DIM+1)/2; 00114 } 00115 00116 mIndexFromZero = false; // Initially assume that nodes are not numbered from zero 00117 00118 OpenFiles(); 00119 ReadHeaders(); 00120 } 00121 00122 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00123 TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::~TrianglesMeshReader() 00124 { 00125 delete[] mNodeFileReadBuffer; 00126 delete[] mElementFileReadBuffer; 00127 delete[] mFaceFileReadBuffer; 00128 } 00129 00130 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00131 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const 00132 { 00133 return mNumElements; 00134 } 00135 00136 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00137 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const 00138 { 00139 return mNumNodes; 00140 } 00141 00142 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00143 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const 00144 { 00145 return mNumFaces; 00146 } 00147 00148 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00149 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumCableElements() const 00150 { 00151 return mNumCableElements; 00152 } 00153 00154 00155 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00156 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumElementAttributes() const 00157 { 00158 return mNumElementAttributes; 00159 } 00160 00161 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00162 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumFaceAttributes() const 00163 { 00164 return mNumFaceAttributes; 00165 } 00166 00167 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00168 unsigned TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNumCableElementAttributes() const 00169 { 00170 return mNumCableElementAttributes; 00171 } 00172 00173 00174 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00175 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::Reset() 00176 { 00177 CloseFiles(); 00178 00179 mNodesRead = 0; 00180 mElementsRead = 0; 00181 mFacesRead = 0; 00182 mBoundaryFacesRead = 0; 00183 mCableElementsRead = 0; 00184 mEofException = false; 00185 00186 OpenFiles(); 00187 ReadHeaders(); 00188 } 00189 00190 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00191 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextNode() 00192 { 00193 std::vector<double> ret_coords(SPACE_DIM); 00194 00195 mNodeAttributes.clear(); // clear attributes for this node 00196 GetNextItemFromStream(mNodesFile, mNodesRead, ret_coords, mNumNodeAttributes, mNodeAttributes); 00197 00198 mNodesRead++; 00199 return ret_coords; 00200 } 00201 00202 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00203 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextElementData() 00204 { 00205 ElementData element_data; 00206 element_data.NodeIndices.resize(mNodesPerElement); 00207 element_data.AttributeValue = 0.0; // If an attribute is not read this stays as zero, otherwise overwritten. 00208 00209 std::vector<unsigned> element_attributes; 00210 GetNextItemFromStream(mElementsFile, mElementsRead, element_data.NodeIndices, mNumElementAttributes, element_attributes); 00211 if (mNumElementAttributes > 0) 00212 { 00213 element_data.AttributeValue = (double) element_attributes[0]; 00214 } 00215 00216 EnsureIndexingFromZero(element_data.NodeIndices); 00217 00218 mElementsRead++; 00219 00220 if (mNodePermutationDefined) 00221 { 00222 for (std::vector<unsigned>::iterator node_it = element_data.NodeIndices.begin(); 00223 node_it != element_data.NodeIndices.end(); 00224 ++ node_it) 00225 { 00226 assert(*node_it < mPermutationVector.size()); 00227 *node_it = mPermutationVector[*node_it]; 00228 } 00229 } 00230 00231 return element_data; 00232 } 00233 00234 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00235 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextCableElementData() 00236 { 00237 ElementData element_data; 00238 element_data.NodeIndices.resize(2u); 00239 element_data.AttributeValue = 0; // If an attribute is not read this stays as zero, otherwise overwritten. 00240 00241 std::vector<double> cable_element_attributes; 00242 GetNextItemFromStream(mCableElementsFile, mCableElementsRead, element_data.NodeIndices, mNumCableElementAttributes, cable_element_attributes); 00243 if (mNumCableElementAttributes > 0) 00244 { 00245 element_data.AttributeValue = cable_element_attributes[0]; 00246 } 00247 00248 EnsureIndexingFromZero(element_data.NodeIndices); 00249 00250 mCableElementsRead++; 00251 00252 // Node permutation can only be done with binary data... 00253 // if (mNodePermutationDefined) 00254 // { 00255 // for (std::vector<unsigned>::iterator node_it = element_data.NodeIndices.begin(); 00256 // node_it != element_data.NodeIndices.end(); 00257 // ++ node_it) 00258 // { 00259 // assert(*node_it < mPermutationVector.size()); 00260 // *node_it = mPermutationVector[*node_it]; 00261 // } 00262 // } 00263 00264 return element_data; 00265 } 00266 00267 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00268 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextFaceData() 00269 { 00270 ElementData face_data; 00271 std::vector<unsigned> ret_indices; 00272 00273 // In the first case there's no file, all the nodes are set as faces 00274 if (ELEMENT_DIM == 1) 00275 { 00276 ret_indices.push_back( mOneDimBoundary[mBoundaryFacesRead] ); 00277 } 00278 else 00279 { 00280 ret_indices.resize(mNodesPerBoundaryElement); 00281 00282 assert(ELEMENT_DIM != 0); //Covered in earlier exception, but needed in loop guard here. 00283 do 00284 { 00285 face_data.AttributeValue = 1.0; // If an attribute is not read this stays as one, otherwise overwritten. 00286 00287 std::vector<unsigned> face_attributes; //will store face attributes, if any 00288 if (mReadContainingElementOfBoundaryElement) 00289 { 00290 assert(mNumFaceAttributes == 0); 00291 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, 1, face_attributes); 00292 00293 if (face_attributes.size() > 0) 00294 { 00295 face_data.ContainingElement = face_attributes[0];// only one face attribute registered for the moment 00296 } 00297 00298 } 00299 else 00300 { 00301 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, mNumFaceAttributes, 00302 face_attributes); 00303 00304 if (mNumFaceAttributes > 0) 00305 { 00306 face_data.AttributeValue = (double) face_attributes[0]; //only one face attribute registered for the moment 00307 } 00308 } 00309 00310 EnsureIndexingFromZero(ret_indices); 00311 00312 mFacesRead++; 00313 } 00314 while (ELEMENT_DIM==2 && face_data.AttributeValue==0); //In triangles format we ignore internal edges (which are marked with attribute 0) 00315 } 00316 00317 mBoundaryFacesRead++; 00318 00319 if (mNodePermutationDefined) 00320 { 00321 for (std::vector<unsigned>::iterator node_it = ret_indices.begin(); 00322 node_it != ret_indices.end(); 00323 ++ node_it) 00324 { 00325 assert(*node_it < mPermutationVector.size()); 00326 *node_it = mPermutationVector[*node_it]; 00327 } 00328 } 00329 00330 face_data.NodeIndices = ret_indices; 00331 00332 return face_data; 00333 } 00334 00335 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00336 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNode(unsigned index) 00337 { 00338 if (!mFilesAreBinary) 00339 { 00340 EXCEPTION("Random access is only implemented in mesh readers for binary mesh files."); 00341 } 00342 if (index >= mNumNodes) 00343 { 00344 EXCEPTION("Node does not exist - not enough nodes."); 00345 } 00346 00347 if (mNodePermutationDefined) 00348 { 00349 assert(index<mInversePermutationVector.size()); 00350 index = mInversePermutationVector[index]; 00351 } 00352 00353 // Put the file stream pointer to the right location 00354 mNodesFile.seekg(mNodeFileDataStart + mNodeItemWidth*index, std::ios_base::beg); 00355 00356 // Read the next item. 00357 return GetNextNode(); 00358 } 00359 00360 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00361 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetElementData(unsigned index) 00362 { 00363 if (!mFilesAreBinary) 00364 { 00365 EXCEPTION("Random access is only implemented in mesh readers for binary mesh files."); 00366 } 00367 if (index >=mNumElements) 00368 { 00369 EXCEPTION("Element " << index << " does not exist - not enough elements (only " << mNumElements << ")."); 00370 } 00371 00372 // Put the file stream pointer to the right location 00373 mElementsFile.seekg(mElementFileDataStart + mElementItemWidth*index, std::ios_base::beg); 00374 00375 // Read the next item. 00376 return GetNextElementData(); 00377 } 00378 00379 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00380 ElementData TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetFaceData(unsigned index) 00381 { 00382 if (!mFilesAreBinary) 00383 { 00384 EXCEPTION("Random access is only implemented in mesh readers for binary mesh files."); 00385 } 00386 if (index >=mNumFaces) 00387 { 00388 EXCEPTION("Face does not exist - not enough faces."); 00389 } 00390 00391 // Put the file stream pointer to the right location 00392 mFacesFile.seekg(mFaceFileDataStart + mFaceItemWidth*index, std::ios_base::beg); 00393 00394 // Read the next item 00395 return GetNextFaceData(); 00396 } 00397 00398 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00399 std::vector<unsigned> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndices(unsigned index) 00400 { 00401 if (!mFilesAreBinary) 00402 { 00403 EXCEPTION("NCL file functionality is only implemented in mesh readers for binary mesh files."); 00404 } 00405 00406 if (!mNclFileAvailable) 00407 { 00408 EXCEPTION("No NCL file available for this mesh."); 00409 } 00410 if (index >= mNumNodes) 00411 { 00412 EXCEPTION("Connectivity list does not exist - not enough nodes."); 00413 } 00414 00415 if (mNodePermutationDefined) 00416 { 00417 assert(index < mInversePermutationVector.size()); 00418 index = mInversePermutationVector[index]; 00419 } 00420 00421 // Put the file stream pointer to the right location 00422 mNclFile.seekg(mNclFileDataStart + mNclItemWidth*index, std::ios_base::beg); 00423 00424 // Read the next item 00425 std::vector<unsigned> containing_element_indices; 00426 containing_element_indices.resize(mMaxContainingElements); 00427 00428 std::vector<unsigned> dummy; // unused here 00429 GetNextItemFromStream(mNclFile, index, containing_element_indices, 0, dummy); 00430 00431 EnsureIndexingFromZero(containing_element_indices); 00432 00433 unsigned num_containing_elements = mMaxContainingElements; 00434 while ( containing_element_indices[num_containing_elements-1] == UINT_MAX ) 00435 { 00436 num_containing_elements--; 00437 } 00438 00439 containing_element_indices.resize(num_containing_elements); 00440 00441 return containing_element_indices; 00442 } 00443 00444 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00445 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFiles() 00446 { 00447 OpenNodeFile(); 00448 OpenElementsFile(); 00449 OpenFacesFile(); 00450 OpenNclFile(); 00451 OpenCableElementsFile(); 00452 } 00453 00454 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00455 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenNodeFile() 00456 { 00457 // Nodes definition 00458 std::string file_name = mFilesBaseName + NODES_FILE_EXTENSION; 00459 mNodesFile.open(file_name.c_str()); 00460 if (!mNodesFile.is_open()) 00461 { 00462 EXCEPTION("Could not open data file: " + file_name); 00463 } 00464 } 00465 00466 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00467 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenElementsFile() 00468 { 00469 // Elements definition 00470 std::string file_name; 00471 if (ELEMENT_DIM == SPACE_DIM) 00472 { 00473 file_name = mFilesBaseName + ELEMENTS_FILE_EXTENSION; 00474 } 00475 else 00476 { 00477 if (ELEMENT_DIM == 1) 00478 { 00479 file_name = mFilesBaseName + EDGES_FILE_EXTENSION; 00480 } 00481 else if (ELEMENT_DIM == 2) 00482 { 00483 file_name = mFilesBaseName + FACES_FILE_EXTENSION; 00484 } 00485 else 00486 { 00487 EXCEPTION("Can't have a zero-dimensional mesh in a one-dimensional space"); 00488 } 00489 } 00490 00491 mElementsFile.open(file_name.c_str()); 00492 if (!mElementsFile.is_open()) 00493 { 00494 EXCEPTION("Could not open data file: " + file_name); 00495 } 00496 } 00497 00498 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00499 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenFacesFile() 00500 { 00501 // Faces/edges definition 00502 std::string file_name; 00503 if (ELEMENT_DIM == 3) 00504 { 00505 file_name = mFilesBaseName + FACES_FILE_EXTENSION; 00506 } 00507 else if (ELEMENT_DIM == 2) 00508 { 00509 file_name = mFilesBaseName + EDGES_FILE_EXTENSION; 00510 } 00511 else //if (ELEMENT_DIM == 1) 00512 { 00513 // There is no file, data will be read from the node file (with boundaries marked) 00514 return; 00515 } 00516 00517 mFacesFile.open(file_name.c_str()); 00518 if (!mFacesFile.is_open()) 00519 { 00520 EXCEPTION("Could not open data file: " + file_name); 00521 } 00522 } 00523 00524 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00525 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenNclFile() 00526 { 00527 std::string file_name = mFilesBaseName + NCL_FILE_EXTENSION; 00528 mNclFile.open(file_name.c_str()); 00529 00530 mNclFileAvailable = mNclFile.is_open(); 00531 } 00532 00533 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00534 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::OpenCableElementsFile() 00535 { 00536 std::string file_name = mFilesBaseName + CABLE_FILE_EXTENSION; 00537 mCableElementsFile.open(file_name.c_str()); 00538 if (!mCableElementsFile.is_open()) 00539 { 00540 mNumCableElements = 0u; 00541 mNumCableElementAttributes = 0u; 00542 } 00543 } 00544 00545 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00546 std::vector<double> TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNodeAttributes() 00547 { 00548 return mNodeAttributes; 00549 } 00550 00551 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00552 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::ReadHeaders() 00553 { 00554 /* 00555 * Reading node file header 00556 */ 00557 std::string buffer; 00558 GetNextLineFromStream(mNodesFile, buffer); 00559 std::stringstream node_header_line(buffer); 00560 unsigned dimension; 00561 node_header_line >> mNumNodes >> dimension >> mNumNodeAttributes >> mMaxNodeBdyMarker; 00562 if (SPACE_DIM != dimension) 00563 { 00564 EXCEPTION("SPACE_DIM != dimension read from file "); 00565 } 00566 00567 // Is there anything else on the header line? 00568 std::string extras; 00569 node_header_line >> extras; 00570 if (extras == "BIN") 00571 { 00572 mFilesAreBinary = true; 00573 mNodeFileDataStart = mNodesFile.tellg(); // Record the position of the first byte after the header. 00574 mNodeItemWidth = SPACE_DIM * sizeof(double); 00575 00576 // We enforce that all binary files (written by Chaste) are indexed from zero 00577 mIndexFromZero = true; 00578 } 00579 else 00580 { 00581 // #1621 - ncl files are only supported in binary read mode. 00582 assert(!mNclFileAvailable); 00583 00584 // Get the next line to see if it is indexed from zero or not 00585 GetNextLineFromStream(mNodesFile, buffer); 00586 std::stringstream node_first_line(buffer); 00587 unsigned first_index; 00588 node_first_line >> first_index; 00589 assert(first_index == 0 || first_index == 1); 00590 mIndexFromZero = (first_index == 0); 00591 00592 // Close, reopen, skip header 00593 mNodesFile.close(); 00594 OpenNodeFile(); 00595 GetNextLineFromStream(mNodesFile, buffer); 00596 } 00597 00598 /* 00599 * Reading element file header 00600 */ 00601 GetNextLineFromStream(mElementsFile, buffer); 00602 std::stringstream element_header_line(buffer); 00603 00604 unsigned extra_attributes = 0; 00605 00606 if (ELEMENT_DIM == SPACE_DIM) 00607 { 00608 element_header_line >> mNumElements >> mNumElementNodes >> mNumElementAttributes; 00609 00610 extra_attributes = mNumElementAttributes; 00611 00612 // Is there anything else on the header line? 00613 std::string element_extras; 00614 element_header_line >> element_extras; 00615 if (element_extras == "BIN") 00616 { 00617 // Double check for binaryness 00618 assert (mFilesAreBinary); 00619 } 00620 else if (element_extras == "HEX") 00621 { 00622 mMeshIsHexahedral = true; 00623 if ( ELEMENT_DIM == 2 ) 00624 { 00625 mNodesPerElement = 4; 00626 mNodesPerBoundaryElement = 2; 00627 } 00628 if ( ELEMENT_DIM == 3 ) 00629 { 00630 mNodesPerElement = 8; 00631 mNodesPerBoundaryElement = 4; 00632 } 00633 } 00634 else 00635 { 00636 assert (element_extras == ""); 00637 } 00638 00639 // The condition below allows the writer to cope with a NodesOnlyMesh 00640 if (mNumElements != 0) 00641 { 00642 if (mNumElementNodes != mNodesPerElement) 00643 { 00644 EXCEPTION("Number of nodes per elem, " << mNumElementNodes << ", does not match " 00645 << "expected number, " << mNodesPerElement << " (which is calculated given " 00646 << "the order of elements chosen, " << mOrderOfElements << " (1=linear, 2=quadratics)"); 00647 } 00648 } 00649 } 00650 else 00651 { 00652 element_header_line >> mNumElements >> mNumFaceAttributes; 00653 00654 extra_attributes = mNumFaceAttributes; 00655 00656 // Is there anything else on the header line? 00657 std::string element_extras; 00658 element_header_line >> element_extras; 00659 if (element_extras == "BIN") 00660 { 00661 // Double check for binaryness 00662 assert (mFilesAreBinary); 00663 } 00664 00665 mNodesPerElement = ELEMENT_DIM+1; 00666 } 00667 00668 00669 if (mFilesAreBinary) 00670 { 00671 mElementFileDataStart = mElementsFile.tellg(); // Record the position of the first byte after the header. 00672 mElementItemWidth = (mNodesPerElement + extra_attributes) * sizeof(unsigned); 00673 } 00674 00675 /* 00676 * Reading face/edge file header. 00677 * The condition below allows the writer to cope with a NodesOnlyMesh. 00678 */ 00679 if (mNumElements != 0) 00680 { 00681 if (ELEMENT_DIM == 1) 00682 { 00683 GetOneDimBoundary(); 00684 mNumFaces = mOneDimBoundary.size(); 00685 } 00686 else 00687 { 00688 GetNextLineFromStream(mFacesFile, buffer); 00689 std::stringstream face_header_line(buffer); 00690 00691 face_header_line >> mNumFaces >> mNumFaceAttributes; 00692 assert(mNumFaceAttributes==0 || mNumFaceAttributes==1); 00693 00694 /* 00695 * If mNumFaceAttributes=1 then loop over and set mNumFaces to be 00696 * the number of faces which are marked as boundary faces. 00697 * Double check for binaryness. 00698 */ 00699 std::string face_extras; 00700 face_header_line >> face_extras; 00701 assert (mFilesAreBinary == (face_extras == "BIN")); 00702 if ((mNumFaceAttributes==1)) 00703 { 00704 unsigned num_boundary_faces = 0; 00705 bool end_of_file=false; 00706 while (!end_of_file) 00707 { 00708 try 00709 { 00710 GetNextFaceData(); 00711 num_boundary_faces++; 00712 } 00713 catch(Exception& e) 00714 { 00715 if (mEofException) 00716 { 00717 end_of_file = true; 00718 } 00719 else 00720 { 00721 throw e; 00722 } 00723 } 00724 } 00725 mNumFaces = num_boundary_faces; 00726 00729 // if (mNumFaces==0) 00730 // { 00731 // EXCEPTION("No boundary elements found. NOTE: elements in face/edge file with an attribute value of 0 are considered to be internal (non-boundary) elements"); 00732 // } 00733 00734 // close the file, reopen, and skip the header again 00735 mFacesFile.close(); 00736 mFacesFile.clear(); // Older versions of gcc don't explicitly reset "fail" and "eof" flags in std::ifstream after calling close() 00737 OpenFacesFile(); 00738 GetNextLineFromStream(mFacesFile, buffer); 00739 mFacesRead = 0; 00740 mBoundaryFacesRead = 0; 00741 } 00742 } 00743 } 00744 00745 if (mFilesAreBinary) 00746 { 00747 mFaceFileDataStart = mFacesFile.tellg(); // Record the position of the first byte after the header. 00748 mFaceItemWidth = (ELEMENT_DIM + mNumFaceAttributes) * sizeof(unsigned); 00749 } 00750 00751 /* 00752 * Read NCL file (if one is available) 00753 */ 00754 if (mNclFileAvailable) 00755 { 00756 GetNextLineFromStream(mNclFile, buffer); 00757 std::stringstream ncl_header_line(buffer); 00758 unsigned num_nodes_in_file; 00759 ncl_header_line >> num_nodes_in_file >> mMaxContainingElements; 00760 00761 if ( mNumNodes != num_nodes_in_file ) 00762 { 00763 EXCEPTION("NCL file does not contain the correct number of nodes for mesh"); 00764 } 00765 00766 mNclFileDataStart = mNclFile.tellg(); // Record the position of the first byte after the header 00767 mNclItemWidth = mMaxContainingElements * sizeof(unsigned); 00768 } 00769 00770 /* 00771 * Read cable file (if one is available) 00772 */ 00773 if (mCableElementsFile.is_open()) 00774 { 00775 GetNextLineFromStream(mCableElementsFile, buffer); 00776 std::stringstream cable_header_line(buffer); 00777 unsigned num_nodes_per_cable_element; 00778 cable_header_line >> mNumCableElements >> num_nodes_per_cable_element >> mNumCableElementAttributes; 00779 assert(num_nodes_per_cable_element == 2u); 00780 mCableElementsRead = 0u; 00781 } 00782 } 00783 00784 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00785 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::CloseFiles() 00786 { 00787 mNodesFile.close(); 00788 mElementsFile.close(); 00789 mFacesFile.close(); 00790 mNclFile.close(); 00791 mCableElementsFile.close(); 00792 } 00793 00794 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00795 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextLineFromStream(std::ifstream& rFileStream, std::string& rRawLine) 00796 { 00797 bool line_is_blank; 00798 mEofException = false; 00799 do 00800 { 00801 getline(rFileStream, rRawLine); 00802 if (rFileStream.eof()) 00803 { 00804 mEofException = true; 00805 EXCEPTION("File contains incomplete data: unexpected end of file."); 00806 } 00807 00808 // Get rid of any comment 00809 rRawLine = rRawLine.substr(0, rRawLine.find('#',0)); 00810 00811 line_is_blank = (rRawLine.find_first_not_of(" \t",0) == std::string::npos); 00812 } 00813 while (line_is_blank); 00814 } 00815 00816 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00817 template<class T_DATA, class T_ATTR> 00818 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetNextItemFromStream(std::ifstream& rFileStream, unsigned expectedItemNumber, 00819 std::vector<T_DATA>& rDataPacket, const unsigned& rNumAttributes, std::vector<T_ATTR>& rAttributes) 00820 { 00821 if (mFilesAreBinary) 00822 { 00823 rFileStream.read((char*)&rDataPacket[0], rDataPacket.size()*sizeof(T_DATA)); 00824 if (rNumAttributes > 0) 00825 { 00826 for (unsigned i = 0; i < rNumAttributes; i++) 00827 { 00828 T_ATTR attribute; 00829 rFileStream.read((char*) &attribute, sizeof(T_ATTR)); 00830 rAttributes.push_back(attribute); 00831 } 00832 } 00833 } 00834 else 00835 { 00836 std::string buffer; 00837 GetNextLineFromStream(rFileStream,buffer); 00838 std::stringstream buffer_stream(buffer); 00839 00840 unsigned item_index; 00841 buffer_stream >> item_index; 00842 00843 // If we are indexing from zero our expected item number is one larger 00844 expectedItemNumber += mIndexFromZero ? 0 : 1; 00845 00846 if (item_index != expectedItemNumber) 00847 { 00848 if (!mIndexFromZero) 00849 { 00850 // To fix the exception message to agree with file format 00851 expectedItemNumber--; 00852 } 00853 EXCEPTION("Data for item " << expectedItemNumber << " missing"); 00854 } 00855 00856 for (unsigned i=0; i<rDataPacket.size(); i++) 00857 { 00858 buffer_stream >> rDataPacket[i]; 00859 } 00860 00861 if (rNumAttributes > 0) 00862 { 00863 for (unsigned i = 0; i < rNumAttributes; i++) 00864 { 00865 T_ATTR attribute; 00866 buffer_stream >> attribute; 00867 if (buffer_stream.fail()) 00868 { 00869 EXCEPTION("Error in reading attribute index " << i << " (out of " << rNumAttributes << ") in one of the files in " << mFilesBaseName); 00870 } 00871 rAttributes.push_back(attribute); 00872 } 00873 } 00874 } 00875 } 00876 00877 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00878 std::string TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetMeshFileBaseName() 00879 { 00880 return mFilesBaseName; 00881 } 00882 00883 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00884 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::GetOneDimBoundary() 00885 { 00886 assert(ELEMENT_DIM == 1); 00887 mNumFaceAttributes = 0; 00888 if (!mOneDimBoundary.empty()) 00889 { 00890 // We have already read this and have reset the reader (probably from the mesh class) 00891 return; 00892 } 00893 std::vector<unsigned> node_indices(2); 00894 std::vector<unsigned> dummy_attribute; // unused 00895 00896 // Count how many times we see each node 00897 std::vector<unsigned> node_count(mNumNodes); // Covers the case if it's indexed from 1 00898 for (unsigned element_index=0; element_index<mNumElements;element_index++) 00899 { 00900 GetNextItemFromStream(mElementsFile, element_index, node_indices, mNumElementAttributes, dummy_attribute); 00901 if (!mIndexFromZero) 00902 { 00903 // Adjust so we are indexing from zero 00904 node_indices[0]--; 00905 node_indices[1]--; 00906 } 00907 node_count[node_indices[0]]++; 00908 node_count[node_indices[1]]++; 00909 } 00910 00911 // Find the ones which are terminals (only one mention) 00912 for (unsigned node_index=0; node_index<mNumNodes;node_index++) 00913 { 00914 if (node_count[node_index] == 1u) 00915 { 00916 mOneDimBoundary.push_back(node_index); 00917 } 00918 } 00919 00920 // Close the file, reopen, and skip the header again 00921 mElementsFile.close(); 00922 mElementsFile.clear(); // Older versions of gcc don't explicitly reset "fail" and "eof" flags in std::ifstream after calling close() 00923 OpenElementsFile(); 00924 std::string buffer; 00925 GetNextLineFromStream(mElementsFile, buffer); 00926 } 00927 00928 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00929 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::EnsureIndexingFromZero(std::vector<unsigned>& rNodeIndices) 00930 { 00931 if (!mIndexFromZero) // If node indices do not start at zero move them all down one so they do 00932 { 00933 for (unsigned i=0; i<rNodeIndices.size(); i++) 00934 { 00935 rNodeIndices[i]--; 00936 } 00937 } 00938 } 00939 00940 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00941 bool TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::IsFileFormatBinary() 00942 { 00943 return mFilesAreBinary; 00944 } 00945 00946 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00947 bool TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::HasNclFile() 00948 { 00949 return mNclFileAvailable; 00950 } 00951 00952 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00953 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::SetReadBufferSize(unsigned bufferSize) 00954 { 00955 mNodeFileReadBuffer = new char[bufferSize]; 00956 mElementFileReadBuffer = new char[bufferSize]; 00957 mFaceFileReadBuffer = new char[bufferSize]; 00958 00959 mNodesFile.rdbuf()->pubsetbuf(mNodeFileReadBuffer, bufferSize); 00960 mElementsFile.rdbuf()->pubsetbuf(mElementFileReadBuffer, bufferSize); 00961 mFacesFile.rdbuf()->pubsetbuf(mFaceFileReadBuffer, bufferSize); 00962 } 00963 00964 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00965 void TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM>::SetNodePermutation(std::vector<unsigned>& rPermutationVector) 00966 { 00967 if ( !mFilesAreBinary ) 00968 { 00969 // It would be too inefficient otherwise... 00970 EXCEPTION("Permuted read can only be used with binary files since it requires random access to the node file."); 00971 } 00972 00973 mNodePermutationDefined = true; 00974 mPermutationVector = rPermutationVector; 00975 mInversePermutationVector.resize(mPermutationVector.size()); 00976 for (unsigned index=0; index<mPermutationVector.size(); index++) 00977 { 00978 mInversePermutationVector[mPermutationVector[index]]=index; 00979 } 00980 } 00981 00983 // Explicit instantiation 00985 00986 template class TrianglesMeshReader<0,1>; 00987 template class TrianglesMeshReader<1,1>; 00988 template class TrianglesMeshReader<1,2>; 00989 template class TrianglesMeshReader<1,3>; 00990 template class TrianglesMeshReader<2,2>; 00991 template class TrianglesMeshReader<2,3>; 00992 template class TrianglesMeshReader<3,3>; 00993 00998 template void TrianglesMeshReader<0,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 00999 template void TrianglesMeshReader<0,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&); 01000 template void TrianglesMeshReader<1,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 01001 template void TrianglesMeshReader<1,1>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&); 01002 template void TrianglesMeshReader<1,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 01003 template void TrianglesMeshReader<1,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&); 01004 template void TrianglesMeshReader<1,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 01005 template void TrianglesMeshReader<1,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&); 01006 template void TrianglesMeshReader<2,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 01007 template void TrianglesMeshReader<2,2>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&); 01008 template void TrianglesMeshReader<2,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 01009 template void TrianglesMeshReader<2,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&); 01010 template void TrianglesMeshReader<3,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<unsigned>&, const unsigned&, std::vector<unsigned>&); 01011 template void TrianglesMeshReader<3,3>::GetNextItemFromStream(std::ifstream&, unsigned, std::vector<double> &, const unsigned&, std::vector<double>&);