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++

/*=========================================================================
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