/*========================================================================= Program: Visualization Toolkit Module: LSDynaFamily.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /*---------------------------------------------------------------------------- Copyright (c) Sandia Corporation See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. ----------------------------------------------------------------------------*/ // .NAME LSDynaFamily // .SECTION Description // A class to abstract away I/O from families of output files. // This performs the actual reads and writes plus any required byte swapping. // Also contains a subclass, LSDynaFamilyAdaptLevel, used to store // file+offset // information for each mesh adaptation's state info. #ifndef __LSDynaFamily_h #define __LSDynaFamily_h #include "vtkType.h" #include #include #include #include #include #include #include #include // this is needs to be moved over to fseekpos and ftellpos // in the future #ifndef _WIN32 #include typedef off_t vtkLSDynaOff_t; // sanity typedef int vtkLSDynaFile_t; #define VTK_LSDYNA_BADFILE -1 #define VTK_LSDYNA_TELL(fid) lseek(fid, 0, SEEK_CUR) #define VTK_LSDYNA_SEEK(fid, off, whence) lseek(fid, off, whence) #define VTK_LSDYNA_SEEKTELL(fid, off, whence) lseek(fid, off, whence) #define VTK_LSDYNA_READ(fid, ptr, cnt) read(fid, ptr, cnt) #define VTK_LSDYNA_ISBADFILE(fid) (fid < 0) #define VTK_LSDYNA_CLOSEFILE(fid) close(fid) #else // _WIN32 typedef long vtkLSDynaOff_t; // insanity typedef FILE* vtkLSDynaFile_t; #define VTK_LSDYNA_BADFILE 0 #define VTK_LSDYNA_TELL(fid) ftell(fid) #define VTK_LSDYNA_SEEK(fid, off, whence) fseek(fid, off, whence) #define VTK_LSDYNA_SEEKTELL(fid, off, whence) fseek(fid, off, whence), ftell(fid) #define VTK_LSDYNA_READ(fid, ptr, cnt) fread(ptr, 1, cnt, fid) #define VTK_LSDYNA_ISBADFILE(fid) (fid == 0) #define VTK_LSDYNA_CLOSEFILE(fid) fclose(fid) #endif #ifdef VTKSNL_HAVE_ERRNO_H #include #endif class LSDynaFamily { public: LSDynaFamily(); ~LSDynaFamily(); struct LSDynaFamilySectionMark { vtkIdType FileNumber; vtkIdType Offset; }; void SetDatabaseDirectory(const std::string& dd); std::string GetDatabaseDirectory(); void SetDatabaseBaseName(const std::string& bn); std::string GetDatabaseBaseName(); int ScanDatabaseDirectory(); enum SectionType { // These are the "section" marks: // They are absolute (independent of current timestep). ControlSection = 0, StaticSection, TimeStepSection, // These are the "subsection" marks: // == ControlSection has no subsections // == StaticSection has these "absolute" marks: MaterialTypeData, FluidMaterialIdData, SPHElementData, GeometryData, UserIdData, AdaptedParentData, SPHNodeData, RigidSurfaceData, EndOfStaticSection, // == TimeStepSection has these marks, relative to timestep 0 (so they are // not valid for an arbitrary timestep, but may easily be used to compute // an offset for any time step by adding a multiple of the state size): ElementDeletionState, SPHNodeState, RigidSurfaceState, // THIS MUST BE LAST NumberOfSectionTypes }; class LSDynaFamilyAdaptLevel { public: LSDynaFamilySectionMark Marks[NumberOfSectionTypes]; LSDynaFamilyAdaptLevel() { LSDynaFamilySectionMark mark; mark.FileNumber = 0; mark.Offset = 0; for (int i = 0; i < LSDynaFamily::NumberOfSectionTypes; ++i) { this->Marks[i] = mark; } } }; static const char* SectionTypeNames[]; enum WordType { Char, Float, Int }; static const float EOFMarker; static const char* SectionTypeToString(SectionType s); int SkipToWord(SectionType sType, vtkIdType sId, vtkIdType wordNumber); int MarkTimeStep(); int SkipWords(vtkIdType numWords); int BufferChunk(WordType wType, vtkIdType chunkSizeInWords); int ClearBuffer(); // Description: // Setup reading of a number of words to be split across multiple // bufferChunk. This is used to read really large buffer sections // in more reasonable sizes. The parameters are used to specify the total buffer // size. The buffer size will always be evenly divisable by numComps and total // word size of all buffers will be numTuples*numComps vtkIdType InitPartialChunkBuffering(const vtkIdType& numTuples, const vtkIdType& numComps); vtkIdType GetNextChunk(const WordType& wType); inline char* GetNextWordAsChars(); inline double GetNextWordAsFloat(); inline vtkIdType GetNextWordAsInt(); // Get the raw chunk buffer as a buffer of type T template T* GetBufferAs(); // Not needed (yet): // void GetCurrentWord( SectionType& stype, vtkIdType& sId, vtkIdType& wN ); int AdvanceFile(); void MarkSectionStart(int adapteLevel, SectionType m); int JumpToMark(SectionType m); int DetermineStorageModel(); void SetStateSize(vtkIdType sz); vtkIdType GetStateSize() const; vtkIdType GetNumberOfFiles(); std::string GetFileName(int i); vtkIdType GetFileSize(int i); int GetCurrentAdaptLevel() const { return this->FAdapt; } int TimeAdaptLevel(int i) const { return this->TimeAdaptLevels[i]; } vtkIdType GetCurrentFWord() const { return this->FWord; } int GetWordSize() const; // Reset erases all information about the current database. // It does not free memory allocated for the current chunk. void Reset(); /// Print all adaptation and time step marker information. void DumpMarks(std::ostream& os); // Closes the current file descripter. This is called after // we are done reading in request data void CloseFileHandles(); void OpenFileHandles(); protected: /// The directory containing d3plot files std::string DatabaseDirectory; /// The name (title string) of the database. This is the first 10 words /// (40 or 80 bytes) of the first file. std::string DatabaseBaseName; /// The list of files that make up the database. std::vector Files; /// The size of each file in the database. Note that they can be padded, /// so this is >= the amount of data in each file. std::vector FileSizes; /// The adaptation level associated with each file. std::vector FileAdaptLevels; /// Which files mark the start of a new mesh adaptation. There is at /// least one entry and the first entry is always 0. std::vector Adaptations; /// The currently open file descriptor vtkLSDynaFile_t FD; /// The index of currently open file descriptor into list of files vtkIdType FNum; /// The current adaptation level. This is checked whenever a file is /// advanced so we can skip its control+geometry headers. int FAdapt; /// The offset of Chunk in currently open file vtkIdType FWord; /// A comprehensive list of all time values across all files (and mesh /// adaptations) // std::vector TimeValues; /// The current timestep vtkIdType TimeStep; /// Whether files are reverse endian-ness of architecture int SwapEndian; /// Whether words are 4 or 8 bytes int WordSize; /// How many words is a timestep on disk? vtkIdType StateSize; /// A vector of arrays of offsets to various header information sections /// (that do not vary with timestep), one for each mesh adaptation. std::vector AdaptationsMarkers; /// An array of bookmarks pointing to the start of state information for /// each timestep. std::vector TimeStepMarks; /// The adaptation level associated with each time step. std::vector TimeAdaptLevels; /// A buffer containing file contents of file FNum starting with word FWord. unsigned char* Chunk; /// A pointer to the next word in Chunk that will be returned when the /// reader requests a word. vtkIdType ChunkWord; // How much of the allocated space is filled with valid data (assert // ChunkValid <= ChunkAlloc). vtkIdType ChunkValid; /// The allocated size (in words) of Chunk. vtkIdType ChunkAlloc; bool FileHandlesClosed; struct BufferingInfo; BufferingInfo* BufferInfo; }; //----------------------------------------------------------------------------- inline char* LSDynaFamily::GetNextWordAsChars() { if (this->ChunkWord >= this->ChunkValid) fprintf(stderr, "Read char past end of buffer\n"); return (char*)(&this->Chunk[(this->ChunkWord++) * this->WordSize]); } //----------------------------------------------------------------------------- inline double LSDynaFamily::GetNextWordAsFloat() { if (this->ChunkWord >= this->ChunkValid) fprintf(stderr, "Read float past end of buffer\n"); switch (this->WordSize) { case 4: { vtkTypeFloat32 value; memcpy(&value, &this->Chunk[this->ChunkWord++ << 2], sizeof(value)); return value; } case 8: default: { vtkTypeFloat64 value; memcpy(&value, &this->Chunk[this->ChunkWord++ << 3], sizeof(value)); return value; } } } //----------------------------------------------------------------------------- inline vtkIdType LSDynaFamily::GetNextWordAsInt() { if (this->ChunkWord >= this->ChunkValid) { fprintf(stderr, "Read int past end of buffer\n"); } switch (this->WordSize) { case 4: { vtkTypeInt32 value; memcpy(&value, &this->Chunk[this->ChunkWord++ << 2], sizeof(value)); return value; } case 8: default: { vtkIdType value; memcpy(&value, &this->Chunk[this->ChunkWord++ << 3], sizeof(value)); return value; } } } //----------------------------------------------------------------------------- template inline T* LSDynaFamily::GetBufferAs() { return reinterpret_cast(this->Chunk); } #endif // __LSDynaFamily_h