39 #include "TrianglesMeshReader.hpp"
42 static const char* NODES_FILE_EXTENSION =
".node";
43 static const char* ELEMENTS_FILE_EXTENSION =
".ele";
44 static const char* FACES_FILE_EXTENSION =
".face";
45 static const char* EDGES_FILE_EXTENSION =
".edge";
46 static const char* NCL_FILE_EXTENSION =
".ncl";
47 static const char* CABLE_FILE_EXTENSION =
".cable";
53 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
55 unsigned orderOfElements,
56 unsigned orderOfBoundaryElements,
57 bool readContainingElementForBoundaryElements)
58 : mFilesBaseName(pathBaseName),
68 mCableElementsRead(0),
70 mBoundaryFacesRead(0),
72 mNumNodeAttributes(0),
73 mNumElementAttributes(0),
74 mNumFaceAttributes(0),
75 mNumCableElementAttributes(0),
76 mOrderOfElements(orderOfElements),
77 mOrderOfBoundaryElements(orderOfBoundaryElements),
79 mReadContainingElementOfBoundaryElement(readContainingElementForBoundaryElements),
80 mFilesAreBinary(false),
81 mMeshIsHexahedral(false),
82 mNodeFileReadBuffer(NULL),
83 mElementFileReadBuffer(NULL),
84 mFaceFileReadBuffer(NULL),
85 mNodePermutationDefined(false)
88 assert(orderOfElements==1 || orderOfElements==2);
91 EXCEPTION(
"Boundary element file should not have containing element info if it is quadratic");
99 #define COVERAGE_IGNORE
100 assert(SPACE_DIM==ELEMENT_DIM);
101 #undef COVERAGE_IGNORE
111 #define COVERAGE_IGNORE
112 assert(SPACE_DIM==ELEMENT_DIM);
113 #undef COVERAGE_IGNORE
123 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
126 delete[] mNodeFileReadBuffer;
127 delete[] mElementFileReadBuffer;
128 delete[] mFaceFileReadBuffer;
131 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
137 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
143 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
149 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
152 return mNumCableElements;
156 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
159 return mNumElementAttributes;
162 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
165 return mNumFaceAttributes;
168 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
171 return mNumCableElementAttributes;
175 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
183 mBoundaryFacesRead = 0;
184 mCableElementsRead = 0;
186 mEofException =
false;
192 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
195 std::vector<double> ret_coords(SPACE_DIM);
197 mNodeAttributes.clear();
198 GetNextItemFromStream(mNodesFile, mNodesRead, ret_coords, mNumNodeAttributes, mNodeAttributes);
204 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
211 std::vector<double> element_attributes;
212 GetNextItemFromStream(mElementsFile, mElementsRead, element_data.
NodeIndices, mNumElementAttributes, element_attributes);
214 if (mNumElementAttributes > 0)
223 if (mNodePermutationDefined)
225 for (std::vector<unsigned>::iterator node_it = element_data.
NodeIndices.begin();
229 assert(*node_it < mPermutationVector.size());
230 *node_it = mPermutationVector[*node_it];
237 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
244 std::vector<double> cable_element_attributes;
245 GetNextItemFromStream(mCableElementsFile, mCableElementsRead, element_data.
NodeIndices, mNumCableElementAttributes, cable_element_attributes);
246 if (mNumCableElementAttributes > 0)
253 mCableElementsRead++;
270 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
274 std::vector<unsigned> ret_indices;
277 if (ELEMENT_DIM == 1)
279 ret_indices.push_back( mOneDimBoundary[mBoundaryFacesRead] );
283 ret_indices.resize(mNodesPerBoundaryElement);
285 assert(ELEMENT_DIM != 0);
290 std::vector<double> face_attributes;
291 if (mReadContainingElementOfBoundaryElement)
293 assert(mNumFaceAttributes == 0);
294 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, 1, face_attributes);
296 if (face_attributes.size() > 0)
304 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, mNumFaceAttributes,
307 if (mNumFaceAttributes > 0)
313 EnsureIndexingFromZero(ret_indices);
320 mBoundaryFacesRead++;
322 if (mNodePermutationDefined)
324 for (std::vector<unsigned>::iterator node_it = ret_indices.begin();
325 node_it != ret_indices.end();
328 assert(*node_it < mPermutationVector.size());
329 *node_it = mPermutationVector[*node_it];
338 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
341 if (!mFilesAreBinary)
343 EXCEPTION(
"Random access is only implemented in mesh readers for binary mesh files.");
345 if (index >= mNumNodes)
347 EXCEPTION(
"Node does not exist - not enough nodes.");
350 if (mNodePermutationDefined)
352 assert(index<mInversePermutationVector.size());
353 index = mInversePermutationVector[index];
357 if ( index > mNodesRead )
361 mNodesFile.seekg( mNodeItemWidth*(index-mNodesRead), std::ios_base::cur);
363 else if ( mNodesRead != index )
365 mNodesFile.seekg(mNodeFileDataStart + mNodeItemWidth*index, std::ios_base::beg);
370 return GetNextNode();
373 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
376 if (!mFilesAreBinary)
378 EXCEPTION(
"Random access is only implemented in mesh readers for binary mesh files.");
380 if (index >= mNumElements)
382 EXCEPTION(
"Element " << index <<
" does not exist - not enough elements (only " << mNumElements <<
").");
386 if ( index > mElementsRead )
390 mElementsFile.seekg( mElementItemWidth*(index-mElementsRead), std::ios_base::cur);
392 else if ( mElementsRead != index )
394 mElementsFile.seekg(mElementFileDataStart + mElementItemWidth*index, std::ios_base::beg);
397 mElementsRead = index;
399 return GetNextElementData();
402 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
405 if (!mFilesAreBinary)
407 EXCEPTION(
"Random access is only implemented in mesh readers for binary mesh files.");
409 if (index >=mNumFaces)
411 EXCEPTION(
"Face does not exist - not enough faces.");
425 if ( mFacesRead != index )
427 mFacesFile.seekg(mFaceFileDataStart + mFaceItemWidth*index, std::ios_base::beg);
432 return GetNextFaceData();
435 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
438 if (!mFilesAreBinary)
440 EXCEPTION(
"NCL file functionality is only implemented in mesh readers for binary mesh files.");
443 if (!mNclFileAvailable)
445 EXCEPTION(
"No NCL file available for this mesh.");
447 if (index >= mNumNodes)
449 EXCEPTION(
"Connectivity list does not exist - not enough nodes.");
452 if (mNodePermutationDefined)
454 assert(index < mInversePermutationVector.size());
455 index = mInversePermutationVector[index];
459 if ( index > mNclItemsRead )
463 mNclFile.seekg( mNclItemWidth*(index-mNclItemsRead), std::ios_base::cur);
465 else if ( mNclItemsRead != index )
467 mNclFile.seekg(mNclFileDataStart + mNclItemWidth*index, std::ios_base::beg);
471 std::vector<unsigned> containing_element_indices;
472 containing_element_indices.resize(mMaxContainingElements);
474 std::vector<double> dummy;
475 GetNextItemFromStream(mNclFile, index, containing_element_indices, 0, dummy);
476 mNclItemsRead = index + 1;
478 EnsureIndexingFromZero(containing_element_indices);
480 unsigned num_containing_elements = mMaxContainingElements;
481 while ( containing_element_indices[num_containing_elements-1] == UINT_MAX )
483 num_containing_elements--;
486 containing_element_indices.resize(num_containing_elements);
488 return containing_element_indices;
491 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
498 OpenCableElementsFile();
501 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
505 std::string file_name = mFilesBaseName + NODES_FILE_EXTENSION;
506 mNodesFile.open(file_name.c_str(), std::ios::binary);
507 if (!mNodesFile.is_open())
509 EXCEPTION(
"Could not open data file: " + file_name);
513 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
517 std::string file_name;
518 if (ELEMENT_DIM == SPACE_DIM)
520 file_name = mFilesBaseName + ELEMENTS_FILE_EXTENSION;
524 if (ELEMENT_DIM == 1)
526 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
528 else if (ELEMENT_DIM == 2)
530 file_name = mFilesBaseName + FACES_FILE_EXTENSION;
534 EXCEPTION(
"Can't have a zero-dimensional mesh in a one-dimensional space");
538 mElementsFile.open(file_name.c_str(), std::ios::binary);
539 if (!mElementsFile.is_open())
541 EXCEPTION(
"Could not open data file: " + file_name);
545 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
549 std::string file_name;
550 if (ELEMENT_DIM == 3)
552 file_name = mFilesBaseName + FACES_FILE_EXTENSION;
554 else if (ELEMENT_DIM == 2)
556 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
564 mFacesFile.open(file_name.c_str(), std::ios::binary);
565 if (!mFacesFile.is_open())
567 EXCEPTION(
"Could not open data file: " + file_name);
571 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
574 std::string file_name = mFilesBaseName + NCL_FILE_EXTENSION;
575 mNclFile.open(file_name.c_str(), std::ios::binary);
577 mNclFileAvailable = mNclFile.is_open();
580 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
583 std::string file_name = mFilesBaseName + CABLE_FILE_EXTENSION;
584 mCableElementsFile.open(file_name.c_str(), std::ios::binary);
585 if (!mCableElementsFile.is_open())
587 mNumCableElements = 0u;
588 mNumCableElementAttributes = 0u;
592 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
595 return mNodeAttributes;
598 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
605 GetNextLineFromStream(mNodesFile, buffer);
606 std::stringstream node_header_line(buffer);
608 node_header_line >> mNumNodes >> dimension >> mNumNodeAttributes >> mMaxNodeBdyMarker;
609 if (SPACE_DIM != dimension)
611 EXCEPTION(
"SPACE_DIM != dimension read from file ");
616 node_header_line >> extras;
619 mFilesAreBinary =
true;
620 mNodeFileDataStart = mNodesFile.tellg();
621 mNodeItemWidth = SPACE_DIM *
sizeof(
double);
624 mIndexFromZero =
true;
629 assert(!mNclFileAvailable);
632 GetNextLineFromStream(mNodesFile, buffer);
633 std::stringstream node_first_line(buffer);
634 unsigned first_index;
635 node_first_line >> first_index;
636 assert(first_index == 0 || first_index == 1);
637 mIndexFromZero = (first_index == 0);
642 GetNextLineFromStream(mNodesFile, buffer);
648 GetNextLineFromStream(mElementsFile, buffer);
649 std::stringstream element_header_line(buffer);
651 unsigned extra_attributes = 0;
653 if (ELEMENT_DIM == SPACE_DIM)
655 element_header_line >> mNumElements >> mNumElementNodes >> mNumElementAttributes;
657 extra_attributes = mNumElementAttributes;
660 std::string element_extras;
661 element_header_line >> element_extras;
662 if (element_extras ==
"BIN")
665 assert (mFilesAreBinary);
667 else if (element_extras ==
"HEX")
669 mMeshIsHexahedral =
true;
670 if ( ELEMENT_DIM == 2 )
672 mNodesPerElement = 4;
673 mNodesPerBoundaryElement = 2;
675 if ( ELEMENT_DIM == 3 )
677 mNodesPerElement = 8;
678 mNodesPerBoundaryElement = 4;
683 assert (element_extras ==
"");
687 if (mNumElements != 0)
689 if (mNumElementNodes != mNodesPerElement)
691 EXCEPTION(
"Number of nodes per elem, " << mNumElementNodes <<
", does not match "
692 <<
"expected number, " << mNodesPerElement <<
" (which is calculated given "
693 <<
"the order of elements chosen, " << mOrderOfElements <<
" (1=linear, 2=quadratics)");
700 element_header_line >> mNumElements >> mNumFaceAttributes;
702 extra_attributes = mNumFaceAttributes;
704 if (ELEMENT_DIM == 1 || ELEMENT_DIM == 2)
706 mNumElementAttributes = mNumFaceAttributes;
710 std::string element_extras;
711 element_header_line >> element_extras;
712 if (element_extras ==
"BIN")
715 assert (mFilesAreBinary);
718 mNodesPerElement = ELEMENT_DIM+1;
723 mElementFileDataStart = mElementsFile.tellg();
724 mElementItemWidth = mNodesPerElement*
sizeof(
unsigned) + extra_attributes*
sizeof(
double) ;
731 if (mNumElements != 0)
733 if (ELEMENT_DIM == 1)
736 mNumFaces = mOneDimBoundary.size();
740 GetNextLineFromStream(mFacesFile, buffer);
741 std::stringstream face_header_line(buffer);
743 face_header_line >> mNumFaces >> mNumFaceAttributes;
744 assert(mNumFaceAttributes==0 || mNumFaceAttributes==1);
751 std::string face_extras;
752 face_header_line >> face_extras;
753 assert (mFilesAreBinary == (face_extras ==
"BIN"));
754 if (mNumFaceAttributes==1)
756 unsigned num_boundary_faces = 0;
757 bool end_of_file=
false;
763 num_boundary_faces++;
777 mNumFaces = num_boundary_faces;
790 GetNextLineFromStream(mFacesFile, buffer);
792 mBoundaryFacesRead = 0;
799 mFaceFileDataStart = mFacesFile.tellg();
800 mFaceItemWidth = ELEMENT_DIM*
sizeof(
unsigned) + mNumFaceAttributes*
sizeof(
double);
806 if (mNclFileAvailable)
808 GetNextLineFromStream(mNclFile, buffer);
809 std::stringstream ncl_header_line(buffer);
810 unsigned num_nodes_in_file;
811 ncl_header_line >> num_nodes_in_file >> mMaxContainingElements;
813 if ( mNumNodes != num_nodes_in_file )
815 EXCEPTION(
"NCL file does not contain the correct number of nodes for mesh");
818 mNclFileDataStart = mNclFile.tellg();
819 mNclItemWidth = mMaxContainingElements *
sizeof(
unsigned);
825 if (mCableElementsFile.is_open())
827 GetNextLineFromStream(mCableElementsFile, buffer);
828 std::stringstream cable_header_line(buffer);
829 unsigned num_nodes_per_cable_element;
830 cable_header_line >> mNumCableElements >> num_nodes_per_cable_element >> mNumCableElementAttributes;
831 assert(num_nodes_per_cable_element == 2u);
832 mCableElementsRead = 0u;
836 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
840 mElementsFile.close();
843 mCableElementsFile.close();
846 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
850 mEofException =
false;
853 getline(rFileStream, rRawLine,
'\n');
854 if (rFileStream.eof())
856 mEofException =
true;
857 EXCEPTION(
"File contains incomplete data: unexpected end of file.");
861 rRawLine = rRawLine.substr(0, rRawLine.find(
'#',0));
863 line_is_blank = (rRawLine.find_first_not_of(
" \t",0) == std::string::npos);
865 while (line_is_blank);
868 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
869 template<
class T_DATA>
871 std::vector<T_DATA>& rDataPacket,
const unsigned& rNumAttributes, std::vector<double>& rAttributes)
875 if (!rDataPacket.empty())
877 rFileStream.read((
char*)&rDataPacket[0], rDataPacket.size()*
sizeof(T_DATA));
879 if (rNumAttributes > 0)
881 for (
unsigned i = 0; i < rNumAttributes; i++)
884 rFileStream.read((
char*) &attribute,
sizeof(
double));
885 rAttributes.push_back(attribute);
892 GetNextLineFromStream(rFileStream, buffer);
893 std::stringstream buffer_stream(buffer);
896 buffer_stream >> item_index;
899 expectedItemNumber += mIndexFromZero ? 0 : 1;
901 if (item_index != expectedItemNumber)
906 expectedItemNumber--;
908 EXCEPTION(
"Data for item " << expectedItemNumber <<
" missing");
911 for (
unsigned i=0; i<rDataPacket.size(); i++)
913 buffer_stream >> rDataPacket[i];
916 if (rNumAttributes > 0)
918 for (
unsigned i = 0; i < rNumAttributes; i++)
921 buffer_stream >> attribute;
922 if (buffer_stream.fail())
924 EXCEPTION(
"Error in reading attribute index " << i <<
" (out of " << rNumAttributes <<
") in one of the files in " << mFilesBaseName);
926 rAttributes.push_back(attribute);
932 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
935 return mFilesBaseName;
938 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
941 assert(ELEMENT_DIM == 1);
942 mNumFaceAttributes = 0;
943 if (!mOneDimBoundary.empty())
948 std::vector<unsigned> node_indices(2);
949 std::vector<double> dummy_attribute;
952 std::vector<unsigned> node_count(mNumNodes);
953 for (
unsigned element_index=0; element_index<mNumElements;element_index++)
955 GetNextItemFromStream(mElementsFile, element_index, node_indices, mNumElementAttributes, dummy_attribute);
962 node_count[node_indices[0]]++;
963 node_count[node_indices[1]]++;
967 for (
unsigned node_index=0; node_index<mNumNodes;node_index++)
969 if (node_count[node_index] == 1u)
971 mOneDimBoundary.push_back(node_index);
976 mElementsFile.close();
977 mElementsFile.clear();
980 GetNextLineFromStream(mElementsFile, buffer);
983 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
988 for (
unsigned i=0; i<rNodeIndices.size(); i++)
995 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
998 return mFilesAreBinary;
1001 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1004 return mNclFileAvailable;
1007 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1010 mNodeFileReadBuffer =
new char[bufferSize];
1011 mElementFileReadBuffer =
new char[bufferSize];
1012 mFaceFileReadBuffer =
new char[bufferSize];
1014 mNodesFile.rdbuf()->pubsetbuf(mNodeFileReadBuffer, bufferSize);
1015 mElementsFile.rdbuf()->pubsetbuf(mElementFileReadBuffer, bufferSize);
1016 mFacesFile.rdbuf()->pubsetbuf(mFaceFileReadBuffer, bufferSize);
1019 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1022 if ( !mFilesAreBinary )
1025 EXCEPTION(
"Permuted read can only be used with binary files since it requires random access to the node file.");
1028 mNodePermutationDefined =
true;
1029 mPermutationVector = rPermutationVector;
1030 mInversePermutationVector.resize(mPermutationVector.size());
1031 for (
unsigned index=0; index<mPermutationVector.size(); index++)
1033 mInversePermutationVector[mPermutationVector[index]]=index;
1036 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1039 return(mNodePermutationDefined);
1047 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1050 return mPermutationVector;
ElementData GetNextCableElementData()
unsigned GetNumFaceAttributes() const
unsigned GetNumNodes() const
bool mReadContainingElementOfBoundaryElement
unsigned ContainingElement
void GetNextLineFromStream(std::ifstream &rFileStream, std::string &rRawLine)
#define EXCEPTION(message)
TrianglesMeshReader(std::string pathBaseName, unsigned orderOfElements=1, unsigned orderOfBoundaryElements=1, bool readContainingElementsForBoundaryElements=false)
std::vector< unsigned > GetContainingElementIndices(unsigned index)
unsigned GetNumElementAttributes() const
unsigned GetNumCableElementAttributes() const
unsigned GetNumCableElements() const
unsigned mNodesPerElement
unsigned GetNumElements() const
std::vector< unsigned > NodeIndices
bool IsFileFormatBinary()
ElementData GetNextElementData()
void SetNodePermutation(std::vector< unsigned > &rPermutationVector)
void SetReadBufferSize(unsigned bufferSize)
unsigned mOrderOfBoundaryElements
std::vector< double > GetNextNode()
void EnsureIndexingFromZero(std::vector< unsigned > &rNodeIndices)
void OpenCableElementsFile()
unsigned mOrderOfElements
bool HasNodePermutation()
ElementData GetFaceData(unsigned index)
unsigned GetNumFaces() const
ElementData GetNextFaceData()
const std::vector< unsigned > & rGetNodePermutation()
unsigned mNodesPerBoundaryElement
std::string GetMeshFileBaseName()
std::vector< double > GetNodeAttributes()
void GetNextItemFromStream(std::ifstream &rFileStream, unsigned expectedItemNumber, std::vector< T_DATA > &rDataPacket, const unsigned &rNumAttributes, std::vector< double > &rAttributes)
std::vector< double > GetNode(unsigned index)
ElementData GetElementData(unsigned index)