1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkExodusIIWriter.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 /*---------------------------------------------------------------------------- 16 Copyright (c) Sandia Corporation 17 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. 18 ----------------------------------------------------------------------------*/ 19 20 /** 21 * @class vtkExodusIIWriter 22 * @brief Write Exodus II files 23 * 24 * This is a vtkWriter that writes it's vtkUnstructuredGrid 25 * input out to an Exodus II file. Go to http://endo.sandia.gov/SEACAS/ 26 * for more information about the Exodus II format. 27 * 28 * Exodus files contain much information that is not captured 29 * in a vtkUnstructuredGrid, such as time steps, information 30 * lines, node sets, and side sets. This information can be 31 * stored in a vtkModelMetadata object. 32 * 33 * The vtkExodusReader and vtkPExodusReader can create 34 * a vtkModelMetadata object and embed it in a vtkUnstructuredGrid 35 * in a series of field arrays. This writer searches for these 36 * field arrays and will use the metadata contained in them 37 * when creating the new Exodus II file. 38 * 39 * You can also explicitly give the vtkExodusIIWriter a 40 * vtkModelMetadata object to use when writing the file. 41 * 42 * In the absence of the information provided by vtkModelMetadata, 43 * if this writer is not part of a parallel application, we will use 44 * reasonable defaults for all the values in the output Exodus file. 45 * If you don't provide a block ID element array, we'll create a 46 * block for each cell type that appears in the unstructured grid. 47 * 48 * However if this writer is part of a parallel application (hence 49 * writing out a distributed Exodus file), then we need at the very 50 * least a list of all the block IDs that appear in the file. And 51 * we need the element array of block IDs for the input unstructured grid. 52 * 53 * In the absence of a vtkModelMetadata object, you can also provide 54 * time step information which we will include in the output Exodus 55 * file. 56 * 57 * @warning 58 * If the input floating point field arrays and point locations are all 59 * floats or all doubles, this class will operate more efficiently. 60 * Mixing floats and doubles will slow you down, because Exodus II 61 * requires that we write only floats or only doubles. 62 * 63 * @warning 64 * We use the terms "point" and "node" interchangeably. 65 * Also, we use the terms "element" and "cell" interchangeably. 66 */ 67 68 #ifndef vtkExodusIIWriter_h 69 #define vtkExodusIIWriter_h 70 71 #include "vtkIOExodusModule.h" // For export macro 72 #include "vtkSmartPointer.h" // For vtkSmartPointer 73 #include "vtkWriter.h" 74 75 #include <map> // STL Header 76 #include <string> // STL Header 77 #include <vector> // STL Header 78 79 class vtkModelMetadata; 80 class vtkDoubleArray; 81 class vtkIntArray; 82 class vtkUnstructuredGrid; 83 84 class VTKIOEXODUS_EXPORT vtkExodusIIWriter : public vtkWriter 85 { 86 public: 87 static vtkExodusIIWriter* New(); 88 vtkTypeMacro(vtkExodusIIWriter, vtkWriter); 89 void PrintSelf(ostream& os, vtkIndent indent) override; 90 91 /** 92 * Specify the vtkModelMetadata object which contains the Exodus file 93 * model information (metadata) absent in the vtkUnstructuredGrid. If you 94 * have this object, you don't need to set any other values before writing. 95 * (Just the FileName and the Input.) 96 * Note that the vtkExodusReader can create and attach a vtkModelMetadata 97 * object to it's output. If this has happened, the ExodusIIWriter will 98 * find it and use it. 99 */ 100 101 void SetModelMetadata(vtkModelMetadata*); 102 vtkGetObjectMacro(ModelMetadata, vtkModelMetadata); 103 104 /** 105 * Name for the output file. If writing in parallel, the number 106 * of processes and the process rank will be appended to the name, 107 * so each process is writing out a separate file. 108 * If not set, this class will make up a file name. 109 */ 110 111 vtkSetFilePathMacro(FileName); 112 vtkGetFilePathMacro(FileName); 113 114 /** 115 * If StoreDoubles is ON, the floating point fields in the Exodus file 116 * will be double precision fields. The default is determined by the 117 * max precision of the input. If the field data appears to be doubles, 118 * then StoreDoubles will be ON, otherwise StoreDoubles will be OFF. 119 */ 120 121 vtkSetMacro(StoreDoubles, int); 122 vtkGetMacro(StoreDoubles, int); 123 124 /** 125 * We never write out ghost cells. This variable is here to satisfy 126 * the behavior of ParaView on invoking a parallel writer. 127 */ 128 129 vtkSetMacro(GhostLevel, int); 130 vtkGetMacro(GhostLevel, int); 131 132 /** 133 * By default, the integer array containing the global Block Ids of the 134 * cells is not included when the new Exodus II file is written out. If 135 * you do want to include this array, set WriteOutBlockIdArray to ON. 136 */ 137 138 vtkSetMacro(WriteOutBlockIdArray, vtkTypeBool); 139 vtkGetMacro(WriteOutBlockIdArray, vtkTypeBool); 140 vtkBooleanMacro(WriteOutBlockIdArray, vtkTypeBool); 141 142 /** 143 * By default, the integer array containing the global Node Ids 144 * is not included when the new Exodus II file is written out. If 145 * you do want to include this array, set WriteOutGlobalNodeIdArray to ON. 146 */ 147 148 vtkSetMacro(WriteOutGlobalNodeIdArray, vtkTypeBool); 149 vtkGetMacro(WriteOutGlobalNodeIdArray, vtkTypeBool); 150 vtkBooleanMacro(WriteOutGlobalNodeIdArray, vtkTypeBool); 151 152 /** 153 * By default, the integer array containing the global Element Ids 154 * is not included when the new Exodus II file is written out. If you 155 * do want to include this array, set WriteOutGlobalElementIdArray to ON. 156 */ 157 158 vtkSetMacro(WriteOutGlobalElementIdArray, vtkTypeBool); 159 vtkGetMacro(WriteOutGlobalElementIdArray, vtkTypeBool); 160 vtkBooleanMacro(WriteOutGlobalElementIdArray, vtkTypeBool); 161 162 /** 163 * When WriteAllTimeSteps is turned ON, the writer is executed once for 164 * each timestep available from the reader. 165 */ 166 167 vtkSetMacro(WriteAllTimeSteps, vtkTypeBool); 168 vtkGetMacro(WriteAllTimeSteps, vtkTypeBool); 169 vtkBooleanMacro(WriteAllTimeSteps, vtkTypeBool); 170 171 vtkSetStringMacro(BlockIdArrayName); 172 vtkGetStringMacro(BlockIdArrayName); 173 174 /** 175 * In certain cases we know that metadata doesn't exist and 176 * we want to ignore that warning. 177 */ 178 179 vtkSetMacro(IgnoreMetaDataWarning, bool); 180 vtkGetMacro(IgnoreMetaDataWarning, bool); 181 vtkBooleanMacro(IgnoreMetaDataWarning, bool); 182 183 protected: 184 vtkExodusIIWriter(); 185 ~vtkExodusIIWriter() override; 186 187 vtkModelMetadata* ModelMetadata; 188 189 char* BlockIdArrayName; 190 191 char* FileName; 192 int fid; 193 194 int NumberOfProcesses; 195 int MyRank; 196 197 int PassDoubles; 198 199 int StoreDoubles; 200 int GhostLevel; 201 vtkTypeBool WriteOutBlockIdArray; 202 vtkTypeBool WriteOutGlobalNodeIdArray; 203 vtkTypeBool WriteOutGlobalElementIdArray; 204 vtkTypeBool WriteAllTimeSteps; 205 int NumberOfTimeSteps; 206 207 int CurrentTimeIndex; 208 int FileTimeOffset; 209 bool TopologyChanged; 210 bool IgnoreMetaDataWarning; 211 212 vtkDataObject* OriginalInput; 213 std::vector<vtkSmartPointer<vtkUnstructuredGrid>> FlattenedInput; 214 std::vector<vtkSmartPointer<vtkUnstructuredGrid>> NewFlattenedInput; 215 216 std::vector<vtkStdString> FlattenedNames; 217 std::vector<vtkStdString> NewFlattenedNames; 218 219 std::vector<vtkIntArray*> BlockIdList; 220 221 struct Block 222 { BlockBlock223 Block() 224 { 225 this->Name = nullptr; 226 this->Type = 0; 227 this->NumElements = 0; 228 this->ElementStartIndex = -1; 229 this->NodesPerElement = 0; 230 this->EntityCounts = std::vector<int>(); 231 this->EntityNodeOffsets = std::vector<int>(); 232 this->GridIndex = 0; 233 this->OutputIndex = -1; 234 this->NumAttributes = 0; 235 this->BlockAttributes = nullptr; 236 }; 237 const char* Name; 238 int Type; 239 int NumElements; 240 int ElementStartIndex; 241 int NodesPerElement; 242 std::vector<int> EntityCounts; 243 std::vector<int> EntityNodeOffsets; 244 size_t GridIndex; 245 // std::vector<int> CellIndex; 246 int OutputIndex; 247 int NumAttributes; 248 float* BlockAttributes; // Owned by metamodel or null. Don't delete. 249 }; 250 std::map<int, Block> BlockInfoMap; 251 int NumCells, NumPoints, MaxId; 252 253 std::vector<vtkIdType*> GlobalElementIdList; 254 std::vector<vtkIdType*> GlobalNodeIdList; 255 256 int AtLeastOneGlobalElementIdList; 257 int AtLeastOneGlobalNodeIdList; 258 259 struct VariableInfo 260 { 261 int NumComponents; 262 int InIndex; 263 int ScalarOutOffset; 264 std::vector<std::string> OutNames; 265 }; 266 std::map<std::string, VariableInfo> GlobalVariableMap; 267 std::map<std::string, VariableInfo> BlockVariableMap; 268 std::map<std::string, VariableInfo> NodeVariableMap; 269 int NumberOfScalarGlobalArrays; 270 int NumberOfScalarElementArrays; 271 int NumberOfScalarNodeArrays; 272 273 std::vector<std::vector<int>> CellToElementOffset; 274 275 // By BlockId, and within block ID by element variable, with variables 276 // appearing in the same order in which they appear in OutputElementArrayNames 277 278 int* BlockElementVariableTruthTable; 279 int AllVariablesDefinedInAllBlocks; 280 281 int BlockVariableTruthValue(int blockIdx, int varIdx); 282 283 char* StrDupWithNew(const char* s); 284 void StringUppercase(std::string& str); 285 286 vtkTypeBool ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, 287 vtkInformationVector* outputVector) override; 288 289 int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector, 290 vtkInformationVector* outputVector); 291 292 virtual int RequestUpdateExtent(vtkInformation* request, vtkInformationVector** inputVector, 293 vtkInformationVector* outputVector); 294 295 int FillInputPortInformation(int port, vtkInformation* info) override; 296 297 int RequestData(vtkInformation* request, vtkInformationVector** inputVector, 298 vtkInformationVector* outputVector) override; 299 300 void WriteData() override; 301 302 int FlattenHierarchy(vtkDataObject* input, const char* name, bool& changed); 303 304 int CreateNewExodusFile(); 305 void CloseExodusFile(); 306 307 int IsDouble(); 308 void RemoveGhostCells(); 309 int CheckParametersInternal(int numberOfProcesses, int myRank); 310 virtual int CheckParameters(); 311 // If writing in parallel multiple time steps exchange after each time step 312 // if we should continue the execution. Pass local continueExecution as a 313 // parameter and return the global continueExecution. 314 virtual int GlobalContinueExecuting(int localContinueExecution); 315 int CheckInputArrays(); 316 virtual void CheckBlockInfoMap(); 317 int ConstructBlockInfoMap(); 318 int ConstructVariableInfoMaps(); 319 int ParseMetadata(); 320 int CreateDefaultMetadata(); 321 char* GetCellTypeName(int t); 322 323 int CreateBlockIdMetadata(vtkModelMetadata* em); 324 int CreateBlockVariableMetadata(vtkModelMetadata* em); 325 int CreateSetsMetadata(vtkModelMetadata* em); 326 327 void ConvertVariableNames(std::map<std::string, VariableInfo>& variableMap); 328 char** FlattenOutVariableNames( 329 int nScalarArrays, const std::map<std::string, VariableInfo>& variableMap); 330 std::string CreateNameForScalarArray(const char* root, int component, int numComponents); 331 332 std::map<vtkIdType, vtkIdType>* LocalNodeIdMap; 333 std::map<vtkIdType, vtkIdType>* LocalElementIdMap; 334 335 vtkIdType GetNodeLocalId(vtkIdType id); 336 vtkIdType GetElementLocalId(vtkIdType id); 337 int GetElementType(vtkIdType id); 338 339 int WriteInitializationParameters(); 340 int WriteInformationRecords(); 341 int WritePoints(); 342 int WriteCoordinateNames(); 343 int WriteGlobalPointIds(); 344 int WriteBlockInformation(); 345 int WriteGlobalElementIds(); 346 int WriteVariableArrayNames(); 347 int WriteNodeSetInformation(); 348 int WriteSideSetInformation(); 349 int WriteProperties(); 350 int WriteNextTimeStep(); 351 vtkIntArray* GetBlockIdArray(const char* BlockIdArrayName, vtkUnstructuredGrid* input); 352 static bool SameTypeOfCells(vtkIntArray* cellToBlockId, vtkUnstructuredGrid* input); 353 354 double ExtractGlobalData(const char* name, int comp, int ts); 355 int WriteGlobalData(int timestep, vtkDataArray* buffer); 356 void ExtractCellData(const char* name, int comp, vtkDataArray* buffer); 357 int WriteCellData(int timestep, vtkDataArray* buffer); 358 void ExtractPointData(const char* name, int comp, vtkDataArray* buffer); 359 int WritePointData(int timestep, vtkDataArray* buffer); 360 361 /** 362 * Get the maximum length name in the input data set. If it is smaller 363 * than 32 characters long we just return the ExodusII default of 32. 364 */ 365 virtual unsigned int GetMaxNameLength(); 366 367 private: 368 vtkExodusIIWriter(const vtkExodusIIWriter&) = delete; 369 void operator=(const vtkExodusIIWriter&) = delete; 370 }; 371 372 #endif 373