1 // -*- c++ -*- 2 /*========================================================================= 3 4 Program: Visualization Toolkit 5 Module: vtkSLACReader.h 6 7 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 8 All rights reserved. 9 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 10 11 This software is distributed WITHOUT ANY WARRANTY; without even 12 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 PURPOSE. See the above copyright notice for more information. 14 15 =========================================================================*/ 16 17 /*------------------------------------------------------------------------- 18 Copyright 2008 Sandia Corporation. 19 Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 20 the U.S. Government retains certain rights in this software. 21 -------------------------------------------------------------------------*/ 22 23 /** 24 * @class vtkSLACReader 25 * 26 * 27 * 28 * A reader for a data format used by Omega3p, Tau3p, and several other tools 29 * used at the Standford Linear Accelerator Center (SLAC). The underlying 30 * format uses netCDF to store arrays, but also imposes several conventions 31 * to form an unstructured grid of elements. 32 * 33 */ 34 35 #ifndef vtkSLACReader_h 36 #define vtkSLACReader_h 37 38 #include "vtkIONetCDFModule.h" // For export macro 39 #include "vtkMultiBlockDataSetAlgorithm.h" 40 41 #include "vtkSmartPointer.h" // For internal method. 42 43 class vtkDataArraySelection; 44 class vtkDoubleArray; 45 class vtkIdTypeArray; 46 class vtkInformationIntegerKey; 47 class vtkInformationObjectBaseKey; 48 49 class VTKIONETCDF_EXPORT vtkSLACReader : public vtkMultiBlockDataSetAlgorithm 50 { 51 public: 52 vtkTypeMacro(vtkSLACReader, vtkMultiBlockDataSetAlgorithm); 53 static vtkSLACReader* New(); 54 void PrintSelf(ostream& os, vtkIndent indent) override; 55 56 vtkGetFilePathMacro(MeshFileName); 57 vtkSetFilePathMacro(MeshFileName); 58 59 ///@{ 60 /** 61 * There may be one mode file (usually for actual modes) or multiple mode 62 * files (which usually actually represent time series). These methods 63 * set and clear the list of mode files (which can be a single mode file). 64 */ 65 virtual void AddModeFileName(VTK_FILEPATH const char* fname); 66 virtual void RemoveAllModeFileNames(); 67 virtual unsigned int GetNumberOfModeFileNames(); 68 virtual VTK_FILEPATH const char* GetModeFileName(unsigned int idx); 69 ///@} 70 71 ///@{ 72 /** 73 * If on, reads the internal volume of the data set. Set to off by default. 74 */ 75 vtkGetMacro(ReadInternalVolume, vtkTypeBool); 76 vtkSetMacro(ReadInternalVolume, vtkTypeBool); 77 vtkBooleanMacro(ReadInternalVolume, vtkTypeBool); 78 ///@} 79 80 ///@{ 81 /** 82 * If on, reads the external surfaces of the data set. Set to on by default. 83 */ 84 vtkGetMacro(ReadExternalSurface, vtkTypeBool); 85 vtkSetMacro(ReadExternalSurface, vtkTypeBool); 86 vtkBooleanMacro(ReadExternalSurface, vtkTypeBool); 87 ///@} 88 89 ///@{ 90 /** 91 * If on, reads midpoint information for external surfaces and builds 92 * quadratic surface triangles. Set to on by default. 93 */ 94 vtkGetMacro(ReadMidpoints, vtkTypeBool); 95 vtkSetMacro(ReadMidpoints, vtkTypeBool); 96 vtkBooleanMacro(ReadMidpoints, vtkTypeBool); 97 ///@} 98 99 ///@{ 100 /** 101 * Variable array selection. 102 */ 103 virtual int GetNumberOfVariableArrays(); 104 virtual const char* GetVariableArrayName(int index); 105 virtual int GetVariableArrayStatus(const char* name); 106 virtual void SetVariableArrayStatus(const char* name, int status); 107 ///@} 108 109 ///@{ 110 /** 111 * Sets the scale factor for each mode. Each scale factor is reset to 1. 112 */ 113 virtual void ResetFrequencyScales(); 114 virtual void SetFrequencyScale(int index, double scale); 115 ///@} 116 117 ///@{ 118 /** 119 * Sets the phase offset for each mode. Each shift is reset to 0. 120 */ 121 virtual void ResetPhaseShifts(); 122 virtual void SetPhaseShift(int index, double shift); 123 ///@} 124 125 ///@{ 126 /** 127 * NOTE: This is not thread-safe. 128 */ 129 virtual vtkDoubleArray* GetFrequencyScales(); 130 virtual vtkDoubleArray* GetPhaseShifts(); 131 ///@} 132 133 /** 134 * Returns true if the given file can be read by this reader. 135 */ 136 static int CanReadFile(VTK_FILEPATH const char* filename); 137 138 /** 139 * This key is attached to the metadata information of all data sets in the 140 * output that are part of the internal volume. 141 */ 142 static vtkInformationIntegerKey* IS_INTERNAL_VOLUME(); 143 144 /** 145 * This key is attached to the metadata information of all data sets in the 146 * output that are part of the external surface. 147 */ 148 static vtkInformationIntegerKey* IS_EXTERNAL_SURFACE(); 149 150 ///@{ 151 /** 152 * All the data sets stored in the multiblock output share the same point 153 * data. For convenience, the point coordinates (vtkPoints) and point data 154 * (vtkPointData) are saved under these keys in the vtkInformation of the 155 * output data set. 156 */ 157 static vtkInformationObjectBaseKey* POINTS(); 158 static vtkInformationObjectBaseKey* POINT_DATA(); 159 ///@} 160 161 ///@{ 162 /** 163 * Simple class used internally to define an edge based on the endpoints. The 164 * endpoints are canonically identified by the lower and higher values. 165 */ 166 class VTKIONETCDF_EXPORT EdgeEndpoints 167 { 168 public: EdgeEndpoints()169 EdgeEndpoints() 170 : MinEndPoint(-1) 171 , MaxEndPoint(-1) 172 { 173 } EdgeEndpoints(vtkIdType endpointA,vtkIdType endpointB)174 EdgeEndpoints(vtkIdType endpointA, vtkIdType endpointB) 175 { 176 if (endpointA < endpointB) 177 { 178 this->MinEndPoint = endpointA; 179 this->MaxEndPoint = endpointB; 180 } 181 else 182 { 183 this->MinEndPoint = endpointB; 184 this->MaxEndPoint = endpointA; 185 } 186 } GetMinEndPoint()187 inline vtkIdType GetMinEndPoint() const { return this->MinEndPoint; } GetMaxEndPoint()188 inline vtkIdType GetMaxEndPoint() const { return this->MaxEndPoint; } 189 inline bool operator==(const EdgeEndpoints& other) const 190 { 191 return ((this->GetMinEndPoint() == other.GetMinEndPoint()) && 192 (this->GetMaxEndPoint() == other.GetMaxEndPoint())); 193 } 194 195 protected: 196 vtkIdType MinEndPoint; 197 vtkIdType MaxEndPoint; 198 }; 199 ///@} 200 201 ///@{ 202 /** 203 * Simple class used internally for holding midpoint information. 204 */ 205 class VTKIONETCDF_EXPORT MidpointCoordinates 206 { 207 public: 208 MidpointCoordinates() = default; MidpointCoordinates(const double coord[3],vtkIdType id)209 MidpointCoordinates(const double coord[3], vtkIdType id) 210 { 211 this->Coordinate[0] = coord[0]; 212 this->Coordinate[1] = coord[1]; 213 this->Coordinate[2] = coord[2]; 214 this->ID = id; 215 } 216 double Coordinate[3]; 217 vtkIdType ID; 218 }; 219 ///@} 220 221 enum 222 { 223 SURFACE_OUTPUT = 0, 224 VOLUME_OUTPUT = 1, 225 NUM_OUTPUTS = 2 226 }; 227 228 protected: 229 vtkSLACReader(); 230 ~vtkSLACReader() override; 231 232 class vtkInternal; 233 vtkInternal* Internal; 234 235 // Friend so vtkInternal can access MidpointIdMap 236 // (so Sun CC compiler doesn't complain). 237 friend class vtkInternal; 238 239 char* MeshFileName; 240 241 vtkTypeBool ReadInternalVolume; 242 vtkTypeBool ReadExternalSurface; 243 vtkTypeBool ReadMidpoints; 244 245 /** 246 * True if reading from a proper mode file. Set in RequestInformation. 247 */ 248 bool ReadModeData; 249 250 /** 251 * True if "mode" files are a sequence of time steps. 252 */ 253 bool TimeStepModes; 254 255 /** 256 * True if mode files describe vibrating fields. 257 */ 258 bool FrequencyModes; 259 260 int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector, 261 vtkInformationVector* outputVector) override; 262 263 int RequestData(vtkInformation* request, vtkInformationVector** inputVector, 264 vtkInformationVector* outputVector) override; 265 266 /** 267 * Callback registered with the VariableArraySelection. 268 */ 269 static void SelectionModifiedCallback( 270 vtkObject* caller, unsigned long eid, void* clientdata, void* calldata); 271 272 /** 273 * Convenience function that checks the dimensions of a 2D netCDF array that 274 * is supposed to be a set of tuples. It makes sure that the number of 275 * dimensions is expected and that the number of components in each tuple 276 * agree with what is expected. It then returns the number of tuples. An 277 * error is emitted and 0 is returned if the checks fail. 278 */ 279 virtual vtkIdType GetNumTuplesInVariable(int ncFD, int varId, int expectedNumComponents); 280 281 /** 282 * Checks the winding of the tetrahedra in the mesh file. Returns 1 if 283 * the winding conforms to VTK, 0 if the winding needs to be corrected. 284 */ 285 virtual int CheckTetrahedraWinding(int meshFD); 286 287 /** 288 * Read the connectivity information from the mesh file. Returns 1 on 289 * success, 0 on failure. 290 */ 291 virtual int ReadConnectivity( 292 int meshFD, vtkMultiBlockDataSet* surfaceOutput, vtkMultiBlockDataSet* volumeOutput); 293 294 ///@{ 295 /** 296 * Reads tetrahedron connectivity arrays. Called by ReadConnectivity. 297 */ 298 virtual int ReadTetrahedronInteriorArray(int meshFD, vtkIdTypeArray* connectivity); 299 virtual int ReadTetrahedronExteriorArray(int meshFD, vtkIdTypeArray* connectivity); 300 ///@} 301 302 /** 303 * Reads point data arrays. Called by ReadCoordinates and ReadFieldData. 304 */ 305 virtual vtkSmartPointer<vtkDataArray> ReadPointDataArray(int ncFD, int varId); 306 307 /** 308 * Helpful constants equal to the amount of identifiers per tet. 309 */ 310 enum 311 { 312 NumPerTetInt = 5, 313 NumPerTetExt = 9 314 }; 315 316 ///@{ 317 /** 318 * Manages a map from edges to midpoint coordinates. 319 */ 320 class VTKIONETCDF_EXPORT MidpointCoordinateMap 321 { 322 public: 323 MidpointCoordinateMap(); 324 ~MidpointCoordinateMap(); 325 ///@} 326 327 void AddMidpoint(const EdgeEndpoints& edge, const MidpointCoordinates& midpoint); 328 void RemoveMidpoint(const EdgeEndpoints& edge); 329 void RemoveAllMidpoints(); 330 vtkIdType GetNumberOfMidpoints() const; 331 332 /** 333 * Finds the coordinates for the given edge or returns nullptr if it 334 * does not exist. 335 */ 336 MidpointCoordinates* FindMidpoint(const EdgeEndpoints& edge); 337 338 protected: 339 class vtkInternal; 340 vtkInternal* Internal; 341 342 private: 343 // Too lazy to implement these. 344 MidpointCoordinateMap(const MidpointCoordinateMap&) = delete; 345 void operator=(const MidpointCoordinateMap&) = delete; 346 }; 347 348 ///@{ 349 /** 350 * Manages a map from edges to the point id of the midpoint. 351 */ 352 class VTKIONETCDF_EXPORT MidpointIdMap 353 { 354 public: 355 MidpointIdMap(); 356 ~MidpointIdMap(); 357 ///@} 358 359 void AddMidpoint(const EdgeEndpoints& edge, vtkIdType midpoint); 360 void RemoveMidpoint(const EdgeEndpoints& edge); 361 void RemoveAllMidpoints(); 362 vtkIdType GetNumberOfMidpoints() const; 363 364 /** 365 * Finds the id for the given edge or returns nullptr if it does not exist. 366 */ 367 vtkIdType* FindMidpoint(const EdgeEndpoints& edge); 368 369 /** 370 * Initialize iteration. The iteration can occur in any order. 371 */ 372 void InitTraversal(); 373 /** 374 * Get the next midpoint in the iteration. Return 0 if the end is reached. 375 */ 376 bool GetNextMidpoint(EdgeEndpoints& edge, vtkIdType& midpoint); 377 378 protected: 379 class vtkInternal; 380 vtkInternal* Internal; 381 382 private: 383 // Too lazy to implement these. 384 MidpointIdMap(const MidpointIdMap&) = delete; 385 void operator=(const MidpointIdMap&) = delete; 386 }; 387 388 /** 389 * Read in the point coordinate data from the mesh file. Returns 1 on 390 * success, 0 on failure. 391 */ 392 virtual int ReadCoordinates(int meshFD, vtkMultiBlockDataSet* output); 393 394 /** 395 * Reads in the midpoint coordinate data from the mesh file and returns a map 396 * from edges to midpoints. This method is called by ReadMidpointData. 397 * Returns 1 on success, 0 on failure. 398 */ 399 virtual int ReadMidpointCoordinates( 400 int meshFD, vtkMultiBlockDataSet* output, MidpointCoordinateMap& map); 401 402 /** 403 * Read in the midpoint data from the mesh file. Returns 1 on success, 404 * 0 on failure. Also fills a midpoint id map that will be passed into 405 * InterpolateMidpointFieldData. 406 */ 407 virtual int ReadMidpointData( 408 int meshFD, vtkMultiBlockDataSet* output, MidpointIdMap& midpointIds); 409 410 /** 411 * Instead of reading data from the mesh file, restore the data from the 412 * previous mesh file read. 413 */ 414 virtual int RestoreMeshCache(vtkMultiBlockDataSet* surfaceOutput, 415 vtkMultiBlockDataSet* volumeOutput, vtkMultiBlockDataSet* compositeOutput); 416 417 /** 418 * Read in the field data from the mode file. Returns 1 on success, 0 419 * on failure. 420 */ 421 virtual int ReadFieldData(const int* modeFDArray, int numModeFDs, vtkMultiBlockDataSet* output); 422 423 /** 424 * Takes the data read on the fields and interpolates data for the midpoints. 425 * map is the same map that was created in ReadMidpointData. 426 */ 427 virtual int InterpolateMidpointData(vtkMultiBlockDataSet* output, MidpointIdMap& map); 428 429 /** 430 * A time stamp for the last time the mesh file was read. This is used to 431 * determine whether the mesh needs to be read in again or if we just need 432 * to read the mode data. 433 */ 434 vtkTimeStamp MeshReadTime; 435 436 /** 437 * Returns 1 if the mesh is up to date, 0 if the mesh needs to be read from 438 * disk. 439 */ 440 virtual int MeshUpToDate(); 441 442 private: 443 vtkSLACReader(const vtkSLACReader&) = delete; 444 void operator=(const vtkSLACReader&) = delete; 445 }; 446 447 #endif // vtkSLACReader_h 448