1 /*****************************************************************************/ 2 /* XDMF */ 3 /* eXtensible Data Model and Format */ 4 /* */ 5 /* Id : XdmfHeavyDataWriter.hpp */ 6 /* */ 7 /* Author: */ 8 /* Kenneth Leiter */ 9 /* kenneth.leiter@arl.army.mil */ 10 /* US Army Research Laboratory */ 11 /* Aberdeen Proving Ground, MD */ 12 /* */ 13 /* Copyright @ 2011 US Army Research Laboratory */ 14 /* All Rights Reserved */ 15 /* See Copyright.txt for details */ 16 /* */ 17 /* This software is distributed WITHOUT ANY WARRANTY; without */ 18 /* even the implied warranty of MERCHANTABILITY or FITNESS */ 19 /* FOR A PARTICULAR PURPOSE. See the above copyright notice */ 20 /* for more information. */ 21 /* */ 22 /*****************************************************************************/ 23 24 #ifndef XDMFHEAVYDATAWRITER_HPP_ 25 #define XDMFHEAVYDATAWRITER_HPP_ 26 27 #include "XdmfCore.hpp" 28 #include "XdmfArrayType.hpp" 29 #include "XdmfHeavyDataController.hpp" 30 #include "XdmfVisitor.hpp" 31 32 #ifdef __cplusplus 33 34 // Forward Declarations 35 class XdmfArray; 36 37 // Includes 38 #include <string> 39 #include <list> 40 41 /** 42 * @brief Traverses the Xdmf graph and writes heavy data stored in 43 * XdmfArrays to heavy data files on disk. 44 * 45 * This is an abstract base class to support the writing of different 46 * heavy data formats. 47 * 48 * XdmfHeavyDataWriter traverses an Xdmf graph structure and writes 49 * data stored in XdmfArrays to heavy data files on disk. Writing 50 * begins by calling the accept() operation on any XdmfItem and 51 * supplying this writer as the parameter. The writer will write all 52 * XdmfArrays under the XdmfItem to a heavy data file on disk. It will 53 * also attach an XdmfHeavyDataController to all XdmfArrays that it 54 * writes to disk. 55 * 56 * There are three modes of operation for this writer: 57 * Default - All initialized XdmfArrays are written to new heavy datasets 58 * regardless of whether they are attached to another heavy 59 * dataset on disk via an XdmfHeavyDataController. 60 * Overwrite - If an initialized XdmfArray is attached to an heavy dataset 61 * via an XdmfHeavyDataController the writer will write values 62 * to that location, overwriting all previous written values. 63 * The dataset on disk will be resized appropriately. 64 * Append - If an initialized XdmfArray is attached to an heavy dataset via 65 * an XdmfHeavyDataController the writer will append the values to 66 * the end of the dataset on disk. 67 * Hyperslab - If an initialized XdmfArray is attached to a heavy dataset 68 * via an XdmfHeavyDataController the writer will write to a 69 * hyperslab in the dataset based on the start, stride, and 70 * dimensions of the XdmfHeavyDataController. 71 */ 72 class XDMFCORE_EXPORT XdmfHeavyDataWriter : public XdmfVisitor, 73 public Loki::Visitor<XdmfArray> { 74 75 public: 76 77 enum Mode { 78 Default, 79 Overwrite, 80 Append, 81 Hyperslab 82 }; 83 84 virtual ~XdmfHeavyDataWriter() = 0; 85 86 /** 87 * Close file. This is only needed when the file is opened manually 88 * through openFile(). 89 * 90 * Example of use: 91 * 92 * C++ 93 * 94 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 95 * @skipline //#initialization 96 * @until //#initialization 97 * @skipline //#closeFile 98 * @until //#closeFile 99 * 100 * Python 101 * 102 * @dontinclude XdmfExampleHeavyDataWriter.py 103 * @skipline #//initialization 104 * @until #//initialization 105 * @skipline #//closeFile 106 * @until #//closeFile 107 */ 108 virtual void closeFile() = 0; 109 110 /** 111 * Gets whether the HDF5 Writer is allowed to split data sets when writing to hdf5. 112 * Splitting should only occur for massive data sets. 113 * Setting to false assures compatibility with previous editions. 114 * Default setting is false. 115 * 116 * Example of use: 117 * 118 * C++ 119 * 120 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 121 * @skipline //#initialization 122 * @until //#initialization 123 * @skipline //#getAllowSetSplitting 124 * @until //#getAllowSetSplitting 125 * 126 * Python 127 * 128 * @dontinclude XdmfExampleHeavyDataWriter.py 129 * @skipline #//initialization 130 * @until #//initialization 131 * @skipline #//getAllowSetSplitting 132 * @until #//getAllowSetSplitting 133 * 134 * @return Whether to allow data sets to be split across hdf5 files 135 */ 136 int getAllowSetSplitting(); 137 138 /** 139 * Gets the file index. Used when file splitting and incremented whent he current file is full. 140 * 141 * C++ 142 * 143 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 144 * @skipline //#initialization 145 * @until //#initialization 146 * @skipline //#getFileIndex 147 * @until //#getFileIndex 148 * 149 * Python 150 * 151 * @dontinclude XdmfExampleHeavyDataWriter.py 152 * @skipline #//initialization 153 * @until #//initialization 154 * @skipline #//getFileIndex 155 * @until #//getFileIndex 156 * 157 * @return The current file index. 158 */ 159 int getFileIndex(); 160 161 /** 162 * Gets the amount of bytes that the heavy data writer uses as overhead for the data type. 163 * 164 * Example of use: 165 * 166 * C++ 167 * 168 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 169 * @skipline //#initialization 170 * @until //#initialization 171 * @skipline //#getFileOverhead 172 * @until //#getFileOverhead 173 * 174 * Python 175 * 176 * @dontinclude XdmfExampleHeavyDataWriter.py 177 * @skipline #//initialization 178 * @until #//initialization 179 * @skipline #//getFileOverhead 180 * @until #//getFileOverhead 181 * 182 * @return Amount of bytes used as overhead 183 */ 184 unsigned int getFileOverhead(); 185 186 /** 187 * Get the path to the heavy data file on disk this writer is writing to. 188 * 189 * Example of use: 190 * 191 * C++ 192 * 193 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 194 * @skipline //#initialization 195 * @until //#initialization 196 * @skipline //#getFilePath 197 * @until //#getFilePath 198 * 199 * Python 200 * 201 * @dontinclude XdmfExampleHeavyDataWriter.py 202 * @skipline #//initialization 203 * @until #//initialization 204 * @skipline #//getFilePath 205 * @until #//getFilePath 206 * 207 * @return A std::string containing the path to the heavy file on disk this 208 * writer is writing to. 209 */ 210 std::string getFilePath() const; 211 212 /** 213 * Gets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file. 214 * 215 * Example of use: 216 * 217 * C++ 218 * 219 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 220 * @skipline //#initialization 221 * @until //#initialization 222 * @skipline //#getFileSizeLimit 223 * @until //#getFileSizeLimit 224 * 225 * Python 226 * 227 * @dontinclude XdmfExampleHeavyDataWriter.py 228 * @skipline #//initialization 229 * @until #//initialization 230 * @skipline #//getFileSizeLimit 231 * @until #//getFileSizeLimit 232 * 233 * @return The size limit in MB 234 */ 235 int getFileSizeLimit(); 236 237 /** 238 * Get the Mode of operation for this writer. 239 * 240 * Example of use: 241 * 242 * C++ 243 * 244 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 245 * @skipline //#initialization 246 * @until //#initialization 247 * @skipline //#getMode 248 * @until //#getMode 249 * 250 * Python 251 * 252 * @dontinclude XdmfExampleHeavyDataWriter.py 253 * @skipline #//initialization 254 * @until #//initialization 255 * @skipline #//getMode 256 * @until #//getMode 257 * 258 * @return The Mode of operation for this writer. 259 */ 260 Mode getMode() const; 261 262 /** 263 * Get whether to release data from memory after writing to disk. 264 * 265 * Example of use: 266 * 267 * C++ 268 * 269 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 270 * @skipline //#initialization 271 * @until //#initialization 272 * @skipline //#getReleaseData 273 * @until //#getReleaseData 274 * 275 * Python 276 * 277 * @dontinclude XdmfExampleHeavyDataWriter.py 278 * @skipline #//initialization 279 * @until #//initialization 280 * @skipline #//getReleaseData 281 * @until #//getReleaseData 282 * 283 * @return True if data is freed after writing 284 */ 285 bool getReleaseData() const; 286 287 /** 288 * Open file for writing. This is an optional command that can 289 * improve performance for some writers when writing many datasets 290 * to a single file. User must call closeFile() after completing 291 * output. 292 * 293 * By default, heavy data files are open and closed before and after 294 * writing each dataset to ensure that other writers have access to 295 * the file (we never know whether we will be writing to the file 296 * again). This is expensive in some cases, but is always 297 * safe. Opening the file once and writing many datasets may result 298 * in improved performance, but the user must tell the writer when 299 * to open and close the file. 300 * 301 * Example of use: 302 * 303 * C++ 304 * 305 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 306 * @skipline //#initialization 307 * @until //#initialization 308 * @skipline //#openFile 309 * @until //#openFile 310 * 311 * Python 312 * 313 * @dontinclude XdmfExampleHeavyDataWriter.py 314 * @skipline #//initialization 315 * @until #//initialization 316 * @skipline #//openFile 317 * @until #//openFile 318 */ 319 virtual void openFile() = 0; 320 321 /** 322 * Sets whether to allow the HDF5 writer to split data sets when writing to hdf5. 323 * Splitting should only occur for massive data sets. 324 * Setting to false assures compatibility with previous editions. 325 * Default setting is false 326 * 327 * Example of use: 328 * 329 * C++ 330 * 331 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 332 * @skipline //#initialization 333 * @until //#initialization 334 * @skipline //#setAllowSetSplitting 335 * @until //#setAllowSetSplitting 336 * 337 * Python 338 * 339 * @dontinclude XdmfExampleHeavyDataWriter.py 340 * @skipline #//initialization 341 * @until #//initialization 342 * @skipline #//setAllowSetSplitting 343 * @until #//setAllowSetSplitting 344 * 345 * @param newAllow Whether to allow data sets to be split across hdf5 files 346 */ 347 void setAllowSetSplitting(bool newAllow); 348 349 /** 350 * Sets the file index. Used when file splitting and incremented when the current file is full. Set to 0 before using hyperslab or overwrite. 351 * 352 * C++ 353 * 354 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 355 * @skipline //#initialization 356 * @until //#initialization 357 * @skipline //#getFileIndex 358 * @until //#getFileIndex 359 * 360 * Python 361 * 362 * @dontinclude XdmfExampleHeavyDataWriter.py 363 * @skipline #//initialization 364 * @until #//initialization 365 * @skipline #//getFileIndex 366 * @until #//getFileIndex 367 * 368 * @param newIndex The index that the writer will append to the file name when incorperating file splitting 369 */ 370 void setFileIndex(int newIndex); 371 372 /** 373 * Sets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file. 374 * Using with arrays of string type may reduce performance. 375 * 376 * Example of use: 377 * 378 * C++ 379 * 380 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 381 * @skipline //#initialization 382 * @until //#initialization 383 * @skipline //#setFileSizeLimit 384 * @until //#setFileSizeLimit 385 * 386 * Python 387 * 388 * @dontinclude XdmfExampleHeavyDataWriter.py 389 * @skipline #//initialization 390 * @until #//initialization 391 * @skipline #//setFileSizeLimit 392 * @until #//setFileSizeLimit 393 * 394 * @param newSize The size limit in MB 395 */ 396 void setFileSizeLimit(int newSize); 397 398 /** 399 * Set the mode of operation for this writer. 400 * 401 * Example of use: 402 * 403 * C++ 404 * 405 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 406 * @skipline //#initialization 407 * @until //#initialization 408 * @skipline //#setMode 409 * @until //#setMode 410 * 411 * Python 412 * 413 * @dontinclude XdmfExampleHeavyDataWriter.py 414 * @skipline #//initialization 415 * @until #//initialization 416 * @skipline #//setMode 417 * @until #//setMode 418 * 419 * @param mode The Mode of operation for this writer. 420 */ 421 void setMode(const Mode mode); 422 423 /** 424 * Set whether to release data from memory after writing to disk. 425 * 426 * Example of use: 427 * 428 * C++ 429 * 430 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 431 * @skipline //#initialization 432 * @until //#initialization 433 * @skipline //#setReleaseData 434 * @until //#setReleaseData 435 * 436 * Python 437 * 438 * @dontinclude XdmfExampleHeavyDataWriter.py 439 * @skipline #//initialization 440 * @until #//initialization 441 * @skipline #//setReleaseData 442 * @until #//setReleaseData 443 * 444 * @param releaseData True if data should be freed after writing 445 */ 446 void setReleaseData(const bool releaseData = true); 447 448 /** 449 * Write an XdmfArray to heavy data file on disk. 450 * 451 * Example of use: 452 * 453 * C++ 454 * 455 * @dontinclude ExampleXdmfHeavyDataWriter.cpp 456 * @skipline //#initialization 457 * @until //#initialization 458 * @skipline //#visit 459 * @until //#visit 460 * 461 * Python 462 * 463 * @dontinclude XdmfExampleHeavyDataWriter.py 464 * @skipline #//initialization 465 * @until #//initialization 466 * @skipline #//visit 467 * @until #//visit 468 * 469 * @param array An XdmfArray to write to heavy data. 470 * @param visitor A smart pointer to this visitor --- aids in grid traversal. 471 */ 472 using XdmfVisitor::visit; 473 virtual void visit(XdmfArray & array, 474 const shared_ptr<XdmfBaseVisitor> visitor) = 0; 475 476 protected: 477 478 XdmfHeavyDataWriter(const double compression = 1, const unsigned int overhead = 0); 479 XdmfHeavyDataWriter(const std::string & filePath, const double compression = 1, const unsigned int overhead = 0); 480 481 virtual shared_ptr<XdmfHeavyDataController> 482 createController(const std::string & filePath, 483 const std::string & descriptor, 484 const shared_ptr<const XdmfArrayType> type, 485 const std::vector<unsigned int> & start, 486 const std::vector<unsigned int> & stride, 487 const std::vector<unsigned int> & dimensions, 488 const std::vector<unsigned int> & dataspaceDimensions) = 0; 489 490 virtual int getDataSetSize(shared_ptr<XdmfHeavyDataController> descriptionController) = 0; 491 492 bool mAllowSplitDataSets; 493 int mDataSetId; 494 int mFileIndex; 495 std::string mFilePath; 496 unsigned int mFileSizeLimit; 497 Mode mMode; 498 bool mReleaseData; 499 double mCompressionRatio; 500 unsigned int mFileOverhead; 501 502 private: 503 504 XdmfHeavyDataWriter(const XdmfHeavyDataWriter &); // Not implemented. 505 void operator=(const XdmfHeavyDataWriter &); // Not implemented. 506 507 }; 508 509 #endif 510 511 #ifdef __cplusplus 512 extern "C" { 513 #endif 514 515 struct XDMFHEAVYDATAWRITER; // Simply as a typedef to ensure correct typing 516 typedef struct XDMFHEAVYDATAWRITER XDMFHEAVYDATAWRITER; 517 518 #define XDMF_HEAVY_WRITER_MODE_DEFAULT 20 519 #define XDMF_HEAVY_WRITER_MODE_OVERWRITE 21 520 #define XDMF_HEAVY_WRITER_MODE_APPEND 22 521 #define XDMF_HEAVY_WRITER_MODE_HYPERSLAB 23 522 523 // C wrappers go here 524 525 XDMFCORE_EXPORT void XdmfHeavyDataWriterFree(XDMFHEAVYDATAWRITER * item); 526 527 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetAllowSetSplitting(XDMFHEAVYDATAWRITER * writer); 528 529 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetFileIndex(XDMFHEAVYDATAWRITER * writer); 530 531 XDMFCORE_EXPORT unsigned int XdmfHeavyDataWriterGetFileOverhead(XDMFHEAVYDATAWRITER * writer); 532 533 XDMFCORE_EXPORT char * XdmfHeavyDataWriterGetFilePath(XDMFHEAVYDATAWRITER * writer); 534 535 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetFileSizeLimit(XDMFHEAVYDATAWRITER * writer); 536 537 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetMode(XDMFHEAVYDATAWRITER * writer); 538 539 XDMFCORE_EXPORT int XdmfHeavyDataWriterGetReleaseData(XDMFHEAVYDATAWRITER * writer); 540 541 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetAllowSetSplitting(XDMFHEAVYDATAWRITER * writer, int newAllow); 542 543 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetFileIndex(XDMFHEAVYDATAWRITER * writer, int newIndex); 544 545 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetFileSizeLimit(XDMFHEAVYDATAWRITER * writer, int newSize); 546 547 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetMode(XDMFHEAVYDATAWRITER * writer, int mode, int * status); 548 549 XDMFCORE_EXPORT void XdmfHeavyDataWriterSetReleaseData(XDMFHEAVYDATAWRITER * writer, int releaseData); 550 551 #define XDMF_HEAVYWRITER_C_CHILD_DECLARE(ClassName, CClassName, Level) \ 552 \ 553 Level##_EXPORT void ClassName##Free( CClassName * item); \ 554 Level##_EXPORT int ClassName##GetAllowSetSplitting( CClassName * writer); \ 555 Level##_EXPORT int ClassName##GetFileIndex( CClassName * writer); \ 556 Level##_EXPORT unsigned int ClassName##GetFileOverhead( CClassName * writer); \ 557 Level##_EXPORT char * ClassName##GetFilePath( CClassName * writer); \ 558 Level##_EXPORT int ClassName##GetFileSizeLimit( CClassName * writer); \ 559 Level##_EXPORT int ClassName##GetMode( CClassName * writer); \ 560 Level##_EXPORT int ClassName##GetReleaseData( CClassName * writer); \ 561 Level##_EXPORT void ClassName##SetAllowSetSplitting( CClassName * writer, int newAllow); \ 562 Level##_EXPORT void ClassName##SetFileIndex( CClassName * writer, int newIndex); \ 563 Level##_EXPORT void ClassName##SetFileSizeLimit( CClassName * writer, int newSize); \ 564 Level##_EXPORT void ClassName##SetMode( CClassName * writer, int mode, int * status); \ 565 Level##_EXPORT void ClassName##SetReleaseData( CClassName * writer, int releaseData); 566 567 568 569 #define XDMF_HEAVYWRITER_C_CHILD_WRAPPER(ClassName, CClassName) \ 570 \ 571 void ClassName##Free( CClassName * item) \ 572 { \ 573 XdmfHeavyDataWriterFree((XDMFHEAVYDATAWRITER *)((void *)item)); \ 574 } \ 575 \ 576 int ClassName##GetAllowSetSplitting( CClassName * writer) \ 577 { \ 578 return XdmfHeavyDataWriterGetAllowSetSplitting((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 579 } \ 580 \ 581 int ClassName##GetFileIndex( CClassName * writer) \ 582 { \ 583 return XdmfHeavyDataWriterGetFileIndex((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 584 } \ 585 \ 586 unsigned int ClassName##GetFileOverhead( CClassName * writer) \ 587 { \ 588 return XdmfHeavyDataWriterGetFileOverhead((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 589 } \ 590 \ 591 char * ClassName##GetFilePath( CClassName * writer) \ 592 { \ 593 return XdmfHeavyDataWriterGetFilePath((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 594 } \ 595 \ 596 int ClassName##GetFileSizeLimit( CClassName * writer) \ 597 { \ 598 return XdmfHeavyDataWriterGetFileSizeLimit((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 599 } \ 600 \ 601 int ClassName##GetMode( CClassName * writer) \ 602 { \ 603 return XdmfHeavyDataWriterGetMode((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 604 } \ 605 \ 606 int ClassName##GetReleaseData( CClassName * writer) \ 607 { \ 608 return XdmfHeavyDataWriterGetReleaseData((XDMFHEAVYDATAWRITER *)((void *)writer)); \ 609 } \ 610 \ 611 void ClassName##SetAllowSetSplitting( CClassName * writer, int newAllow) \ 612 { \ 613 XdmfHeavyDataWriterSetAllowSetSplitting((XDMFHEAVYDATAWRITER *)((void *)writer), newAllow); \ 614 } \ 615 \ 616 void ClassName##SetFileIndex( CClassName * writer, int newIndex) \ 617 { \ 618 XdmfHeavyDataWriterSetFileIndex((XDMFHEAVYDATAWRITER *)((void *)writer), newIndex); \ 619 } \ 620 \ 621 void ClassName##SetFileSizeLimit( CClassName * writer, int newSize) \ 622 { \ 623 XdmfHeavyDataWriterSetFileSizeLimit((XDMFHEAVYDATAWRITER *)((void *)writer), newSize); \ 624 } \ 625 \ 626 void ClassName##SetMode( CClassName * writer, int mode, int * status) \ 627 { \ 628 XdmfHeavyDataWriterSetMode((XDMFHEAVYDATAWRITER *)((void *)writer), mode, status); \ 629 } \ 630 \ 631 void ClassName##SetReleaseData( CClassName * writer, int releaseData) \ 632 { \ 633 XdmfHeavyDataWriterSetReleaseData((XDMFHEAVYDATAWRITER *)((void *)writer), releaseData); \ 634 } 635 636 #ifdef __cplusplus 637 } 638 #endif 639 640 #endif /* XDMFHEAVYDATAWRITER_HPP_ */ 641