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.

447 lines
13 KiB
C++

// -*- c++ -*-
/*=========================================================================
Program: Visualization Toolkit
Module: vtkSLACReader.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 2008 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
/**
* @class vtkSLACReader
*
*
*
* A reader for a data format used by Omega3p, Tau3p, and several other tools
* used at the Standford Linear Accelerator Center (SLAC). The underlying
* format uses netCDF to store arrays, but also imposes several conventions
* to form an unstructured grid of elements.
*
*/
#ifndef vtkSLACReader_h
#define vtkSLACReader_h
#include "vtkIONetCDFModule.h" // For export macro
#include "vtkMultiBlockDataSetAlgorithm.h"
#include "vtkSmartPointer.h" // For internal method.
class vtkDataArraySelection;
class vtkDoubleArray;
class vtkIdTypeArray;
class vtkInformationIntegerKey;
class vtkInformationObjectBaseKey;
class VTKIONETCDF_EXPORT vtkSLACReader : public vtkMultiBlockDataSetAlgorithm
{
public:
vtkTypeMacro(vtkSLACReader, vtkMultiBlockDataSetAlgorithm);
static vtkSLACReader* New();
void PrintSelf(ostream& os, vtkIndent indent) override;
vtkGetStringMacro(MeshFileName);
vtkSetStringMacro(MeshFileName);
//@{
/**
* There may be one mode file (usually for actual modes) or multiple mode
* files (which usually actually represent time series). These methods
* set and clear the list of mode files (which can be a single mode file).
*/
virtual void AddModeFileName(const char* fname);
virtual void RemoveAllModeFileNames();
virtual unsigned int GetNumberOfModeFileNames();
virtual const char* GetModeFileName(unsigned int idx);
//@}
//@{
/**
* If on, reads the internal volume of the data set. Set to off by default.
*/
vtkGetMacro(ReadInternalVolume, vtkTypeBool);
vtkSetMacro(ReadInternalVolume, vtkTypeBool);
vtkBooleanMacro(ReadInternalVolume, vtkTypeBool);
//@}
//@{
/**
* If on, reads the external surfaces of the data set. Set to on by default.
*/
vtkGetMacro(ReadExternalSurface, vtkTypeBool);
vtkSetMacro(ReadExternalSurface, vtkTypeBool);
vtkBooleanMacro(ReadExternalSurface, vtkTypeBool);
//@}
//@{
/**
* If on, reads midpoint information for external surfaces and builds
* quadratic surface triangles. Set to on by default.
*/
vtkGetMacro(ReadMidpoints, vtkTypeBool);
vtkSetMacro(ReadMidpoints, vtkTypeBool);
vtkBooleanMacro(ReadMidpoints, vtkTypeBool);
//@}
//@{
/**
* Variable array selection.
*/
virtual int GetNumberOfVariableArrays();
virtual const char* GetVariableArrayName(int idx);
virtual int GetVariableArrayStatus(const char* name);
virtual void SetVariableArrayStatus(const char* name, int status);
//@}
//@{
/**
* Sets the scale factor for each mode. Each scale factor is reset to 1.
*/
virtual void ResetFrequencyScales();
virtual void SetFrequencyScale(int index, double scale);
//@}
//@{
/**
* Sets the phase offset for each mode. Each shift is reset to 0.
*/
virtual void ResetPhaseShifts();
virtual void SetPhaseShift(int index, double shift);
//@}
//@{
/**
* NOTE: This is not thread-safe.
*/
virtual vtkDoubleArray* GetFrequencyScales();
virtual vtkDoubleArray* GetPhaseShifts();
//@}
/**
* Returns true if the given file can be read by this reader.
*/
static int CanReadFile(const char* filename);
/**
* This key is attached to the metadata information of all data sets in the
* output that are part of the internal volume.
*/
static vtkInformationIntegerKey* IS_INTERNAL_VOLUME();
/**
* This key is attached to the metadata information of all data sets in the
* output that are part of the external surface.
*/
static vtkInformationIntegerKey* IS_EXTERNAL_SURFACE();
//@{
/**
* All the data sets stored in the multiblock output share the same point
* data. For convenience, the point coordinates (vtkPoints) and point data
* (vtkPointData) are saved under these keys in the vtkInformation of the
* output data set.
*/
static vtkInformationObjectBaseKey* POINTS();
static vtkInformationObjectBaseKey* POINT_DATA();
//@}
//@{
/**
* Simple class used internally to define an edge based on the endpoints. The
* endpoints are canonically identified by the lower and higher values.
*/
class VTKIONETCDF_EXPORT EdgeEndpoints
{
public:
EdgeEndpoints()
: MinEndPoint(-1)
, MaxEndPoint(-1)
{
}
EdgeEndpoints(vtkIdType endpointA, vtkIdType endpointB)
{
if (endpointA < endpointB)
{
this->MinEndPoint = endpointA;
this->MaxEndPoint = endpointB;
}
else
{
this->MinEndPoint = endpointB;
this->MaxEndPoint = endpointA;
}
}
inline vtkIdType GetMinEndPoint() const { return this->MinEndPoint; }
inline vtkIdType GetMaxEndPoint() const { return this->MaxEndPoint; }
inline bool operator==(const EdgeEndpoints& other) const
{
return ((this->GetMinEndPoint() == other.GetMinEndPoint()) &&
(this->GetMaxEndPoint() == other.GetMaxEndPoint()));
}
protected:
vtkIdType MinEndPoint;
vtkIdType MaxEndPoint;
};
//@}
//@{
/**
* Simple class used internally for holding midpoint information.
*/
class VTKIONETCDF_EXPORT MidpointCoordinates
{
public:
MidpointCoordinates() {}
MidpointCoordinates(const double coord[3], vtkIdType id)
{
this->Coordinate[0] = coord[0];
this->Coordinate[1] = coord[1];
this->Coordinate[2] = coord[2];
this->ID = id;
}
double Coordinate[3];
vtkIdType ID;
};
//@}
enum
{
SURFACE_OUTPUT = 0,
VOLUME_OUTPUT = 1,
NUM_OUTPUTS = 2
};
protected:
vtkSLACReader();
~vtkSLACReader() override;
class vtkInternal;
vtkInternal* Internal;
// Friend so vtkInternal can access MidpointIdMap
// (so Sun CC compiler doesn't complain).
friend class vtkInternal;
char* MeshFileName;
vtkTypeBool ReadInternalVolume;
vtkTypeBool ReadExternalSurface;
vtkTypeBool ReadMidpoints;
/**
* True if reading from a proper mode file. Set in RequestInformation.
*/
bool ReadModeData;
/**
* True if "mode" files are a sequence of time steps.
*/
bool TimeStepModes;
/**
* True if mode files describe vibrating fields.
*/
bool FrequencyModes;
int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
/**
* Callback registered with the VariableArraySelection.
*/
static void SelectionModifiedCallback(
vtkObject* caller, unsigned long eid, void* clientdata, void* calldata);
/**
* Convenience function that checks the dimensions of a 2D netCDF array that
* is supposed to be a set of tuples. It makes sure that the number of
* dimensions is expected and that the number of components in each tuple
* agree with what is expected. It then returns the number of tuples. An
* error is emitted and 0 is returned if the checks fail.
*/
virtual vtkIdType GetNumTuplesInVariable(int ncFD, int varId, int expectedNumComponents);
/**
* Checks the winding of the tetrahedra in the mesh file. Returns 1 if
* the winding conforms to VTK, 0 if the winding needs to be corrected.
*/
virtual int CheckTetrahedraWinding(int meshFD);
/**
* Read the connectivity information from the mesh file. Returns 1 on
* success, 0 on failure.
*/
virtual int ReadConnectivity(
int meshFD, vtkMultiBlockDataSet* surfaceOutput, vtkMultiBlockDataSet* volumeOutput);
//@{
/**
* Reads tetrahedron connectivity arrays. Called by ReadConnectivity.
*/
virtual int ReadTetrahedronInteriorArray(int meshFD, vtkIdTypeArray* connectivity);
virtual int ReadTetrahedronExteriorArray(int meshFD, vtkIdTypeArray* connectivity);
//@}
/**
* Reads point data arrays. Called by ReadCoordinates and ReadFieldData.
*/
virtual vtkSmartPointer<vtkDataArray> ReadPointDataArray(int ncFD, int varId);
/**
* Helpful constants equal to the amount of identifiers per tet.
*/
enum
{
NumPerTetInt = 5,
NumPerTetExt = 9
};
//@{
/**
* Manages a map from edges to midpoint coordinates.
*/
class VTKIONETCDF_EXPORT MidpointCoordinateMap
{
public:
MidpointCoordinateMap();
~MidpointCoordinateMap();
//@}
void AddMidpoint(const EdgeEndpoints& edge, const MidpointCoordinates& midpoint);
void RemoveMidpoint(const EdgeEndpoints& edge);
void RemoveAllMidpoints();
vtkIdType GetNumberOfMidpoints() const;
/**
* Finds the coordinates for the given edge or returns nullptr if it
* does not exist.
*/
MidpointCoordinates* FindMidpoint(const EdgeEndpoints& edge);
protected:
class vtkInternal;
vtkInternal* Internal;
private:
// Too lazy to implement these.
MidpointCoordinateMap(const MidpointCoordinateMap&);
void operator=(const MidpointCoordinateMap&);
};
//@{
/**
* Manages a map from edges to the point id of the midpoint.
*/
class VTKIONETCDF_EXPORT MidpointIdMap
{
public:
MidpointIdMap();
~MidpointIdMap();
//@}
void AddMidpoint(const EdgeEndpoints& edge, vtkIdType midpoint);
void RemoveMidpoint(const EdgeEndpoints& edge);
void RemoveAllMidpoints();
vtkIdType GetNumberOfMidpoints() const;
/**
* Finds the id for the given edge or returns nullptr if it does not exist.
*/
vtkIdType* FindMidpoint(const EdgeEndpoints& edge);
/**
* Initialize iteration. The iteration can occur in any order.
*/
void InitTraversal();
/**
* Get the next midpoint in the iteration. Return 0 if the end is reached.
*/
bool GetNextMidpoint(EdgeEndpoints& edge, vtkIdType& midpoint);
protected:
class vtkInternal;
vtkInternal* Internal;
private:
// Too lazy to implement these.
MidpointIdMap(const MidpointIdMap&);
void operator=(const MidpointIdMap&);
};
/**
* Read in the point coordinate data from the mesh file. Returns 1 on
* success, 0 on failure.
*/
virtual int ReadCoordinates(int meshFD, vtkMultiBlockDataSet* output);
/**
* Reads in the midpoint coordinate data from the mesh file and returns a map
* from edges to midpoints. This method is called by ReadMidpointData.
* Returns 1 on success, 0 on failure.
*/
virtual int ReadMidpointCoordinates(
int meshFD, vtkMultiBlockDataSet* output, MidpointCoordinateMap& map);
/**
* Read in the midpoint data from the mesh file. Returns 1 on success,
* 0 on failure. Also fills a midpoint id map that will be passed into
* InterpolateMidpointFieldData.
*/
virtual int ReadMidpointData(int meshFD, vtkMultiBlockDataSet* output, MidpointIdMap& map);
/**
* Instead of reading data from the mesh file, restore the data from the
* previous mesh file read.
*/
virtual int RestoreMeshCache(vtkMultiBlockDataSet* surfaceOutput,
vtkMultiBlockDataSet* volumeOutput, vtkMultiBlockDataSet* compositeOutput);
/**
* Read in the field data from the mode file. Returns 1 on success, 0
* on failure.
*/
virtual int ReadFieldData(const int* modeFDArray, int numModeFDs, vtkMultiBlockDataSet* output);
/**
* Takes the data read on the fields and interpolates data for the midpoints.
* map is the same map that was created in ReadMidpointData.
*/
virtual int InterpolateMidpointData(vtkMultiBlockDataSet* output, MidpointIdMap& map);
/**
* A time stamp for the last time the mesh file was read. This is used to
* determine whether the mesh needs to be read in again or if we just need
* to read the mode data.
*/
vtkTimeStamp MeshReadTime;
/**
* Returns 1 if the mesh is up to date, 0 if the mesh needs to be read from
* disk.
*/
virtual int MeshUpToDate();
private:
vtkSLACReader(const vtkSLACReader&) = delete;
void operator=(const vtkSLACReader&) = delete;
};
#endif // vtkSLACReader_h