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(nullptr),
83 mElementFileReadBuffer(nullptr),
84 mFaceFileReadBuffer(nullptr),
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 assert(SPACE_DIM==ELEMENT_DIM);
109 assert(SPACE_DIM==ELEMENT_DIM);
119 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
122 delete[] mNodeFileReadBuffer;
123 delete[] mElementFileReadBuffer;
124 delete[] mFaceFileReadBuffer;
127 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
133 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
139 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
145 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
148 return mNumCableElements;
151 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
154 return mNumElementAttributes;
157 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
160 return mNumFaceAttributes;
163 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
166 return mNumCableElementAttributes;
169 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
177 mBoundaryFacesRead = 0;
178 mCableElementsRead = 0;
180 mEofException =
false;
186 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
189 std::vector<double> ret_coords(SPACE_DIM);
191 mNodeAttributes.clear();
192 GetNextItemFromStream(mNodesFile, mNodesRead, ret_coords, mNumNodeAttributes, mNodeAttributes);
198 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
205 std::vector<double> element_attributes;
206 GetNextItemFromStream(mElementsFile, mElementsRead, element_data.
NodeIndices, mNumElementAttributes, element_attributes);
208 if (mNumElementAttributes > 0)
217 if (mNodePermutationDefined)
219 for (std::vector<unsigned>::iterator node_it = element_data.
NodeIndices.begin();
223 assert(*node_it < mPermutationVector.size());
224 *node_it = mPermutationVector[*node_it];
231 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
238 std::vector<double> cable_element_attributes;
239 GetNextItemFromStream(mCableElementsFile, mCableElementsRead, element_data.
NodeIndices, mNumCableElementAttributes, cable_element_attributes);
240 if (mNumCableElementAttributes > 0)
247 mCableElementsRead++;
264 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
268 std::vector<unsigned> ret_indices;
271 if (ELEMENT_DIM == 1)
273 ret_indices.push_back( mOneDimBoundary[mBoundaryFacesRead] );
277 ret_indices.resize(mNodesPerBoundaryElement);
279 assert(ELEMENT_DIM != 0);
284 std::vector<double> face_attributes;
285 if (mReadContainingElementOfBoundaryElement)
287 assert(mNumFaceAttributes == 0);
288 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, 1, face_attributes);
290 if (face_attributes.size() > 0)
298 GetNextItemFromStream(mFacesFile, mFacesRead, ret_indices, mNumFaceAttributes,
301 if (mNumFaceAttributes > 0)
307 EnsureIndexingFromZero(ret_indices);
314 mBoundaryFacesRead++;
316 if (mNodePermutationDefined)
318 for (std::vector<unsigned>::iterator node_it = ret_indices.begin();
319 node_it != ret_indices.end();
322 assert(*node_it < mPermutationVector.size());
323 *node_it = mPermutationVector[*node_it];
332 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
335 if (!mFilesAreBinary)
337 EXCEPTION(
"Random access is only implemented in mesh readers for binary mesh files.");
339 if (index >= mNumNodes)
341 EXCEPTION(
"Node does not exist - not enough nodes.");
344 if (mNodePermutationDefined)
346 assert(index<mInversePermutationVector.size());
347 index = mInversePermutationVector[index];
351 if (index > mNodesRead)
355 mNodesFile.seekg( mNodeItemWidth*(index-mNodesRead), std::ios_base::cur);
357 else if (mNodesRead != index)
359 mNodesFile.seekg(mNodeFileDataStart + mNodeItemWidth*index, std::ios_base::beg);
364 return GetNextNode();
367 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
370 if (!mFilesAreBinary)
372 EXCEPTION(
"Random access is only implemented in mesh readers for binary mesh files.");
374 if (index >= mNumElements)
376 EXCEPTION(
"Element " << index <<
" does not exist - not enough elements (only " << mNumElements <<
").");
380 if (index > mElementsRead)
384 mElementsFile.seekg( mElementItemWidth*(index-mElementsRead), std::ios_base::cur);
386 else if (mElementsRead != index)
388 mElementsFile.seekg(mElementFileDataStart + mElementItemWidth*index, std::ios_base::beg);
391 mElementsRead = index;
393 return GetNextElementData();
396 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
399 if (!mFilesAreBinary)
401 EXCEPTION(
"Random access is only implemented in mesh readers for binary mesh files.");
403 if (index >=mNumFaces)
405 EXCEPTION(
"Face does not exist - not enough faces.");
419 if (mFacesRead != index)
421 mFacesFile.seekg(mFaceFileDataStart + mFaceItemWidth*index, std::ios_base::beg);
426 return GetNextFaceData();
429 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
432 if (!mFilesAreBinary)
434 EXCEPTION(
"NCL file functionality is only implemented in mesh readers for binary mesh files.");
437 if (!mNclFileAvailable)
439 EXCEPTION(
"No NCL file available for this mesh.");
441 if (index >= mNumNodes)
443 EXCEPTION(
"Connectivity list does not exist - not enough nodes.");
446 if (mNodePermutationDefined)
448 assert(index < mInversePermutationVector.size());
449 index = mInversePermutationVector[index];
453 if (index > mNclItemsRead)
457 mNclFile.seekg( mNclItemWidth*(index-mNclItemsRead), std::ios_base::cur);
459 else if ( mNclItemsRead != index )
461 mNclFile.seekg(mNclFileDataStart + mNclItemWidth*index, std::ios_base::beg);
465 std::vector<unsigned> containing_element_indices;
466 containing_element_indices.resize(mMaxContainingElements);
468 std::vector<double> dummy;
469 GetNextItemFromStream(mNclFile, index, containing_element_indices, 0, dummy);
470 mNclItemsRead = index + 1;
472 EnsureIndexingFromZero(containing_element_indices);
474 unsigned num_containing_elements = mMaxContainingElements;
475 while ( containing_element_indices[num_containing_elements-1] == UINT_MAX )
477 num_containing_elements--;
480 containing_element_indices.resize(num_containing_elements);
482 return containing_element_indices;
485 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
492 OpenCableElementsFile();
495 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
499 std::string file_name = mFilesBaseName + NODES_FILE_EXTENSION;
500 mNodesFile.open(file_name.c_str(), std::ios::binary);
501 if (!mNodesFile.is_open())
503 EXCEPTION(
"Could not open data file: " + file_name);
507 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
511 std::string file_name;
512 if (ELEMENT_DIM == SPACE_DIM)
514 file_name = mFilesBaseName + ELEMENTS_FILE_EXTENSION;
518 if (ELEMENT_DIM == 1)
520 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
522 else if (ELEMENT_DIM == 2)
524 file_name = mFilesBaseName + FACES_FILE_EXTENSION;
528 EXCEPTION(
"Can't have a zero-dimensional mesh in a one-dimensional space");
532 mElementsFile.open(file_name.c_str(), std::ios::binary);
533 if (!mElementsFile.is_open())
535 EXCEPTION(
"Could not open data file: " + file_name);
539 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
543 std::string file_name;
544 if (ELEMENT_DIM == 3)
546 file_name = mFilesBaseName + FACES_FILE_EXTENSION;
548 else if (ELEMENT_DIM == 2)
550 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
558 mFacesFile.open(file_name.c_str(), std::ios::binary);
559 if (!mFacesFile.is_open())
561 EXCEPTION(
"Could not open data file: " + file_name);
565 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
568 std::string file_name = mFilesBaseName + NCL_FILE_EXTENSION;
569 mNclFile.open(file_name.c_str(), std::ios::binary);
571 mNclFileAvailable = mNclFile.is_open();
574 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
577 std::string file_name = mFilesBaseName + CABLE_FILE_EXTENSION;
578 mCableElementsFile.open(file_name.c_str(), std::ios::binary);
579 if (!mCableElementsFile.is_open())
581 mNumCableElements = 0u;
582 mNumCableElementAttributes = 0u;
586 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
589 return mNodeAttributes;
592 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
599 GetNextLineFromStream(mNodesFile, buffer);
600 std::stringstream node_header_line(buffer);
602 node_header_line >> mNumNodes >> dimension >> mNumNodeAttributes >> mMaxNodeBdyMarker;
603 if (SPACE_DIM != dimension)
605 EXCEPTION(
"SPACE_DIM != dimension read from file ");
610 node_header_line >> extras;
613 mFilesAreBinary =
true;
614 mNodeFileDataStart = mNodesFile.tellg();
615 mNodeItemWidth = SPACE_DIM *
sizeof(
double);
618 mIndexFromZero =
true;
623 assert(!mNclFileAvailable);
626 GetNextLineFromStream(mNodesFile, buffer);
627 std::stringstream node_first_line(buffer);
628 unsigned first_index;
629 node_first_line >> first_index;
630 assert(first_index == 0 || first_index == 1);
631 mIndexFromZero = (first_index == 0);
636 GetNextLineFromStream(mNodesFile, buffer);
642 GetNextLineFromStream(mElementsFile, buffer);
643 std::stringstream element_header_line(buffer);
645 unsigned extra_attributes = 0;
647 if (ELEMENT_DIM == SPACE_DIM)
649 element_header_line >> mNumElements >> mNumElementNodes >> mNumElementAttributes;
651 extra_attributes = mNumElementAttributes;
654 std::string element_extras;
655 element_header_line >> element_extras;
656 if (element_extras ==
"BIN")
659 assert (mFilesAreBinary);
661 else if (element_extras ==
"HEX")
663 mMeshIsHexahedral =
true;
664 if (ELEMENT_DIM == 2)
666 mNodesPerElement = 4;
667 mNodesPerBoundaryElement = 2;
669 if (ELEMENT_DIM == 3)
671 mNodesPerElement = 8;
672 mNodesPerBoundaryElement = 4;
677 assert (element_extras ==
"");
681 if (mNumElements != 0)
683 if (mNumElementNodes != mNodesPerElement)
685 EXCEPTION(
"Number of nodes per elem, " << mNumElementNodes <<
", does not match "
686 <<
"expected number, " << mNodesPerElement <<
" (which is calculated given "
687 <<
"the order of elements chosen, " << mOrderOfElements <<
" (1=linear, 2=quadratics)");
694 element_header_line >> mNumElements >> mNumFaceAttributes;
696 extra_attributes = mNumFaceAttributes;
698 if (ELEMENT_DIM == 1 || ELEMENT_DIM == 2)
700 mNumElementAttributes = mNumFaceAttributes;
704 std::string element_extras;
705 element_header_line >> element_extras;
706 if (element_extras ==
"BIN")
709 assert (mFilesAreBinary);
712 mNodesPerElement = ELEMENT_DIM+1;
717 mElementFileDataStart = mElementsFile.tellg();
718 mElementItemWidth = mNodesPerElement*
sizeof(
unsigned) + extra_attributes*
sizeof(
double);
725 if (mNumElements != 0)
727 if (ELEMENT_DIM == 1)
730 mNumFaces = mOneDimBoundary.size();
734 GetNextLineFromStream(mFacesFile, buffer);
735 std::stringstream face_header_line(buffer);
737 face_header_line >> mNumFaces >> mNumFaceAttributes;
738 assert(mNumFaceAttributes==0 || mNumFaceAttributes==1);
745 std::string face_extras;
746 face_header_line >> face_extras;
747 assert (mFilesAreBinary == (face_extras ==
"BIN"));
748 if (mNumFaceAttributes==1)
750 unsigned num_boundary_faces = 0;
751 bool end_of_file=
false;
757 num_boundary_faces++;
771 mNumFaces = num_boundary_faces;
784 GetNextLineFromStream(mFacesFile, buffer);
786 mBoundaryFacesRead = 0;
793 mFaceFileDataStart = mFacesFile.tellg();
794 mFaceItemWidth = ELEMENT_DIM*
sizeof(
unsigned) + mNumFaceAttributes*
sizeof(
double);
800 if (mNclFileAvailable)
802 GetNextLineFromStream(mNclFile, buffer);
803 std::stringstream ncl_header_line(buffer);
804 unsigned num_nodes_in_file;
805 ncl_header_line >> num_nodes_in_file >> mMaxContainingElements;
807 if (mNumNodes != num_nodes_in_file)
809 EXCEPTION(
"NCL file does not contain the correct number of nodes for mesh");
812 mNclFileDataStart = mNclFile.tellg();
813 mNclItemWidth = mMaxContainingElements *
sizeof(
unsigned);
819 if (mCableElementsFile.is_open())
821 GetNextLineFromStream(mCableElementsFile, buffer);
822 std::stringstream cable_header_line(buffer);
823 unsigned num_nodes_per_cable_element;
824 cable_header_line >> mNumCableElements >> num_nodes_per_cable_element >> mNumCableElementAttributes;
825 assert(num_nodes_per_cable_element == 2u);
826 mCableElementsRead = 0u;
830 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
834 mElementsFile.close();
837 mCableElementsFile.close();
840 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
844 mEofException =
false;
847 getline(rFileStream, rRawLine,
'\n');
848 if (rFileStream.eof())
850 mEofException =
true;
851 EXCEPTION(
"File contains incomplete data: unexpected end of file.");
855 rRawLine = rRawLine.substr(0, rRawLine.find(
'#',0));
857 line_is_blank = (rRawLine.find_first_not_of(
" \t",0) == std::string::npos);
859 while (line_is_blank);
862 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
863 template<
class T_DATA>
865 std::vector<T_DATA>& rDataPacket,
const unsigned& rNumAttributes, std::vector<double>& rAttributes)
869 if (!rDataPacket.empty())
871 rFileStream.read((
char*)&rDataPacket[0], rDataPacket.size()*
sizeof(T_DATA));
873 if (rNumAttributes > 0)
875 for (
unsigned i = 0; i < rNumAttributes; i++)
878 rFileStream.read((
char*) &attribute,
sizeof(
double));
879 rAttributes.push_back(attribute);
886 GetNextLineFromStream(rFileStream, buffer);
887 std::stringstream buffer_stream(buffer);
890 buffer_stream >> item_index;
893 expectedItemNumber += mIndexFromZero ? 0 : 1;
895 if (item_index != expectedItemNumber)
900 expectedItemNumber--;
902 EXCEPTION(
"Data for item " << expectedItemNumber <<
" missing");
905 for (
unsigned i=0; i<rDataPacket.size(); i++)
907 buffer_stream >> rDataPacket[i];
910 if (rNumAttributes > 0)
912 for (
unsigned i = 0; i < rNumAttributes; i++)
915 buffer_stream >> attribute;
916 if (buffer_stream.fail())
918 EXCEPTION(
"Error in reading attribute index " << i <<
" (out of " << rNumAttributes <<
") in one of the files in " << mFilesBaseName);
920 rAttributes.push_back(attribute);
926 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
929 return mFilesBaseName;
932 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
935 assert(ELEMENT_DIM == 1);
936 mNumFaceAttributes = 0;
937 if (!mOneDimBoundary.empty())
942 std::vector<unsigned> node_indices(2);
943 std::vector<double> dummy_attribute;
946 std::vector<unsigned> node_count(mNumNodes);
947 for (
unsigned element_index=0; element_index<mNumElements;element_index++)
949 GetNextItemFromStream(mElementsFile, element_index, node_indices, mNumElementAttributes, dummy_attribute);
956 node_count[node_indices[0]]++;
957 node_count[node_indices[1]]++;
961 for (
unsigned node_index=0; node_index<mNumNodes;node_index++)
963 if (node_count[node_index] == 1u)
965 mOneDimBoundary.push_back(node_index);
970 mElementsFile.close();
971 mElementsFile.clear();
974 GetNextLineFromStream(mElementsFile, buffer);
977 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
982 for (
unsigned i=0; i<rNodeIndices.size(); i++)
989 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
992 return mFilesAreBinary;
995 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
998 return mNclFileAvailable;
1001 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1004 mNodeFileReadBuffer =
new char[bufferSize];
1005 mElementFileReadBuffer =
new char[bufferSize];
1006 mFaceFileReadBuffer =
new char[bufferSize];
1008 mNodesFile.rdbuf()->pubsetbuf(mNodeFileReadBuffer, bufferSize);
1009 mElementsFile.rdbuf()->pubsetbuf(mElementFileReadBuffer, bufferSize);
1010 mFacesFile.rdbuf()->pubsetbuf(mFaceFileReadBuffer, bufferSize);
1013 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1016 if (!mFilesAreBinary)
1019 EXCEPTION(
"Permuted read can only be used with binary files since it requires random access to the node file.");
1022 mNodePermutationDefined =
true;
1023 mPermutationVector = rPermutationVector;
1024 mInversePermutationVector.resize(mPermutationVector.size());
1025 for (
unsigned index=0; index<mPermutationVector.size(); index++)
1027 mInversePermutationVector[mPermutationVector[index]]=index;
1031 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1034 return(mNodePermutationDefined);
1040 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1043 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)