You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
329 lines
10 KiB
C++
329 lines
10 KiB
C++
/*=========================================================================
|
|
|
|
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 <fcntl.h>
|
|
#include <iostream>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <vector>
|
|
|
|
// this is needs to be moved over to fseekpos and ftellpos
|
|
// in the future
|
|
#ifndef _WIN32
|
|
#include <unistd.h>
|
|
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 <errno.h>
|
|
#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 <typename T>
|
|
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<std::string> 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<vtkIdType> FileSizes;
|
|
/// The adaptation level associated with each file.
|
|
std::vector<int> 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<int> 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<double> 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<LSDynaFamilyAdaptLevel> AdaptationsMarkers;
|
|
/// An array of bookmarks pointing to the start of state information for
|
|
/// each timestep.
|
|
std::vector<LSDynaFamilySectionMark> TimeStepMarks;
|
|
/// The adaptation level associated with each time step.
|
|
std::vector<int> 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 <typename T>
|
|
inline T* LSDynaFamily::GetBufferAs()
|
|
{
|
|
return reinterpret_cast<T*>(this->Chunk);
|
|
}
|
|
|
|
#endif // __LSDynaFamily_h
|