XdmfArray.cpp 35.6 KB
Newer Older
Kenneth Leiter's avatar
Kenneth Leiter committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*****************************************************************************/
/*                                    XDMF                                   */
/*                       eXtensible Data Model and Format                    */
/*                                                                           */
/*  Id : XdmfArray.cpp                                                       */
/*                                                                           */
/*  Author:                                                                  */
/*     Kenneth Leiter                                                        */
/*     kenneth.leiter@arl.army.mil                                           */
/*     US Army Research Laboratory                                           */
/*     Aberdeen Proving Ground, MD                                           */
/*                                                                           */
/*     Copyright @ 2011 US Army Research Laboratory                          */
/*     All Rights Reserved                                                   */
/*     See Copyright.txt 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.                                                 */
/*                                                                           */
/*****************************************************************************/
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
23

24
#include <boost/tokenizer.hpp>
25
#include <boost/assign.hpp>
26
#include <limits>
27
#include <sstream>
28
#include <utility>
29 30
#include <stack>
#include <math.h>
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
31
#include "XdmfArray.hpp"
32
#include "XdmfArrayType.hpp"
33
#include "XdmfArrayReference.hpp"
34
#include "XdmfHDF5Controller.hpp"
35
#include "XdmfHeavyDataController.hpp"
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
36
#include "XdmfVisitor.hpp"
37
#include "XdmfError.hpp"
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
38

39

40 41 42 43 44
XDMF_CHILDREN_IMPLEMENTATION(XdmfArray,
                             XdmfHeavyDataController,
                             HeavyDataController,
                             Name)

45
class XdmfArray::Clear : public boost::static_visitor<void> {
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
46
public:
47

48 49 50 51 52 53
  Clear(XdmfArray * const array) :
    mArray(array)
  {
  }

  void
54
  operator()(const boost::blank & array) const
55
  {
56
    return;
57 58 59 60
  }

  template<typename T>
  void
61
  operator()(const shared_ptr<std::vector<T> > & array) const
62
  {
63
    array->clear();
64
  }
65 66 67 68 69 70 71 72 73 74

  template<typename T>
  void
  operator()(const boost::shared_array<const T> & array) const
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

75
private: 
76
  XdmfArray * const mArray;
77 78
};

79
class XdmfArray::Erase : public boost::static_visitor<void> {
80 81
public:

82 83 84
  Erase(XdmfArray * const array,
        const unsigned int index) :
    mArray(array),
85 86 87
    mIndex(index)
  {
  }
88

89
  void
90
  operator()(const boost::blank & array) const
91 92 93 94
  {
    return;
  }

95 96
  template<typename T>
  void
97
  operator()(const shared_ptr<std::vector<T> > & array) const
98 99 100
  {
    array->erase(array->begin() + mIndex);
  }
101

102 103
  template<typename T>
  void
104
  operator()(const boost::shared_array<const T> & array) const
105 106 107 108 109 110
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

111 112
private:

113
  XdmfArray * const mArray;
114
  const unsigned int mIndex;
115 116
};

117
class XdmfArray::GetArrayType :
118
  public boost::static_visitor<shared_ptr<const XdmfArrayType> > {
119 120
public:

121 122
  GetArrayType(const shared_ptr<XdmfHeavyDataController> & heavyDataController) :
    mHeavyDataController(heavyDataController)
123 124 125
  {
  }

126
  shared_ptr<const XdmfArrayType>
127 128 129 130 131
  getArrayType(const char * const) const
  {
    return XdmfArrayType::Int8();
  }

132
  shared_ptr<const XdmfArrayType>
133 134 135 136 137
  getArrayType(const short * const) const
  {
    return XdmfArrayType::Int16();
  }

138
  shared_ptr<const XdmfArrayType>
139 140 141 142 143
  getArrayType(const int * const) const
  {
    return XdmfArrayType::Int32();
  }

144
  shared_ptr<const XdmfArrayType>
145 146 147 148 149
  getArrayType(const long * const) const
  {
    return XdmfArrayType::Int64();
  }

150
  shared_ptr<const XdmfArrayType>
151 152 153 154 155
  getArrayType(const float * const) const
  {
    return XdmfArrayType::Float32();
  }

156
  shared_ptr<const XdmfArrayType>
157 158 159 160 161
  getArrayType(const double * const) const
  {
    return XdmfArrayType::Float64();
  }

162
  shared_ptr<const XdmfArrayType>
163 164 165 166 167
  getArrayType(const unsigned char * const) const
  {
    return XdmfArrayType::UInt8();
  }

168
  shared_ptr<const XdmfArrayType>
169 170 171 172 173
  getArrayType(const unsigned short * const) const
  {
    return XdmfArrayType::UInt16();
  }

174
  shared_ptr<const XdmfArrayType>
175 176 177 178 179
  getArrayType(const unsigned int * const) const
  {
    return XdmfArrayType::UInt32();
  }

Kenneth Leiter's avatar
Kenneth Leiter committed
180 181 182 183 184 185
  shared_ptr<const XdmfArrayType>
  getArrayType(const std::string * const) const
  {
    return XdmfArrayType::String();
  }

186
  shared_ptr<const XdmfArrayType>
187
  operator()(const boost::blank & array) const
188
  {
189 190
    if(mHeavyDataController) {
      return mHeavyDataController->getType();
191 192 193 194
    }
    return XdmfArrayType::Uninitialized();
  }

195
  template<typename T>
196 197
  shared_ptr<const XdmfArrayType>
  operator()(const shared_ptr<std::vector<T> > & array) const
198 199 200 201 202
  {
    return this->getArrayType(&(array.get()->operator[](0)));
  }

  template<typename T>
203
  shared_ptr<const XdmfArrayType>
204 205 206 207
  operator()(const boost::shared_array<const T> & array) const
  {
    return this->getArrayType(array.get());
  }
208 209 210 211

private:

  const shared_ptr<XdmfHeavyDataController> mHeavyDataController;
212 213 214 215 216
};

class XdmfArray::GetCapacity : public boost::static_visitor<unsigned int> {
public:

217 218 219
  GetCapacity()
  {
  }
220

221
  unsigned int
222
  operator()(const boost::blank & array) const
223 224 225 226
  {
    return 0;
  }

227 228
  template<typename T>
  unsigned int
229
  operator()(const shared_ptr<std::vector<T> > & array) const
230 231 232
  {
    return array->capacity();
  }
233 234 235

  template<typename T>
  unsigned int
236
  operator()(const boost::shared_array<const T> & array) const
237 238 239
  {
    return 0;
  }
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
240 241
};

242
class XdmfArray::GetValuesPointer :
243
  public boost::static_visitor<const void *> {
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
244 245
public:

246 247 248 249
  GetValuesPointer()
  {
  }

250
  const void *
251
  operator()(const boost::blank & array) const
252 253 254 255
  {
    return NULL;
  }

256
  template<typename T>
257
  const void *
258
  operator()(const shared_ptr<std::vector<T> > & array) const
259 260 261 262 263
  {
    return &array->operator[](0);
  }

  template<typename T>
264
  const void *
265 266 267 268
  operator()(const boost::shared_array<const T> & array) const
  {
    return array.get();
  }
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
269 270
};

271
class XdmfArray::GetValuesString : public boost::static_visitor<std::string> {
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
272 273
public:

274 275 276 277 278
  GetValuesString(const int arrayPointerNumValues) :
    mArrayPointerNumValues(arrayPointerNumValues)
  {
  }

279
  template<typename T, typename U>
280
  std::string
281
  getValuesString(const T * const array,
282 283
                  const int numValues) const
  {
284
    const int lastIndex = numValues - 1;
285 286 287 288 289

    if(lastIndex < 0) {
      return "";
    }

290
    std::stringstream toReturn;
291
    toReturn.precision(std::numeric_limits<U>::digits10 + 2);
292
    for(int i=0; i<lastIndex; ++i) {
293
      toReturn << (U)array[i] << " ";
294
    }
295
    toReturn << (U)array[lastIndex];
296 297 298
    return toReturn.str();
  }

299 300 301 302 303 304 305
  std::string
  getValuesString(const char * const array,
                  const int numValues) const
  {
    return getValuesString<char, int>(array, numValues);
  }

306 307 308 309
  std::string
  getValuesString(const unsigned char * const array,
                  const int numValues) const
  {
310
    return getValuesString<unsigned char, int>(array, numValues);
311 312 313 314 315 316 317
  }

  template<typename T>
  std::string
  getValuesString(const T * const array,
                  const int numValues) const
  {
318
    return getValuesString<T, T>(array, numValues);
319 320
  }

321
  std::string
322
  operator()(const boost::blank & array) const
323 324 325 326
  {
    return "";
  }

327 328
  template<typename T>
  std::string
329
  operator()(const shared_ptr<std::vector<T> > & array) const
330 331 332 333 334 335 336 337 338 339
  {
    return getValuesString(&(array->operator[](0)), array->size());
  }

  template<typename T>
  std::string
  operator()(const boost::shared_array<const T> & array) const
  {
    return getValuesString(array.get(), mArrayPointerNumValues);
  }
340 341 342

private:

343
  const unsigned int mArrayPointerNumValues;
344 345
};

346 347 348
class XdmfArray::InsertArray : public boost::static_visitor<void> {
public:

349 350
  InsertArray(XdmfArray * const array,
              const unsigned int startIndex,
351 352 353
              const unsigned int valuesStartIndex,
              const unsigned int numValues,
              const unsigned int arrayStride,
354
              const unsigned int valuesStride,
355 356 357
              std::vector<unsigned int> & dimensions,
              const shared_ptr<const XdmfArray> & arrayToCopy) :
    mArray(array),
358 359 360 361
    mStartIndex(startIndex),
    mValuesStartIndex(valuesStartIndex),
    mNumValues(numValues),
    mArrayStride(arrayStride),
362
    mValuesStride(valuesStride),
363 364
    mDimensions(dimensions),
    mArrayToCopy(arrayToCopy)
365 366 367 368
  {
  }

  void
369
  operator()(const boost::blank & array) const
370 371 372 373 374 375 376 377 378
  {
    mArray->initialize(mArrayToCopy->getArrayType());
    boost::apply_visitor(*this,
                         mArray->mArray);
  }

  template<typename T>
  void
  operator()(const shared_ptr<std::vector<T> > & array) const
379
  {
380
    unsigned int size = mStartIndex + (mNumValues - 1) * mArrayStride + 1;
381 382
    if(array->size() < size) {
      array->resize(size);
383
      mDimensions.clear();
384
    }
385 386 387 388 389 390 391 392 393 394 395 396 397 398
    mArrayToCopy->getValues(mValuesStartIndex,
                            &(array->operator[](mStartIndex)),
                            mNumValues,
                            mValuesStride,
                            mArrayStride);
  }

  template<typename T>
  void
  operator()(const boost::shared_array<const T> & array) const
  {
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
399
  }
400 401 402

private:

403
  XdmfArray * const mArray;
404 405 406 407 408
  const unsigned int mStartIndex;
  const unsigned int mValuesStartIndex;
  const unsigned int mNumValues;
  const unsigned int mArrayStride;
  const unsigned int mValuesStride;
409
  std::vector<unsigned int> & mDimensions;
410
  const shared_ptr<const XdmfArray> mArrayToCopy;
411 412
};

413
class XdmfArray::InternalizeArrayPointer : public boost::static_visitor<void> {
414 415
public:

416 417 418 419 420
  InternalizeArrayPointer(XdmfArray * const array) :
    mArray(array)
  {
  }

421
  void
422
  operator()(const boost::blank & array) const
423 424 425 426 427 428
  {
    return;
  }

  template<typename T>
  void
429
  operator()(const shared_ptr<std::vector<T> > & array) const
430 431 432 433
  {
    return;
  }

434 435 436 437
  template<typename T>
  void
  operator()(const boost::shared_array<const T> & array) const
  {
438 439 440 441
    const T * const pointer = array.get();
    shared_ptr<std::vector<T> > newArray(new std::vector<T>(pointer,
                                                            pointer + mArray->mArrayPointerNumValues));
    mArray->mArray = newArray;
442 443
    mArray->mArrayPointerNumValues = 0;
  }
444 445 446

private:

447
  XdmfArray * const mArray;
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
448 449
};

450 451 452 453 454 455 456 457
class XdmfArray::IsInitialized : public boost::static_visitor<bool> {
public:

  IsInitialized()
  {
  }

  bool
458
  operator()(const boost::blank &) const
459 460 461 462 463 464
  {
    return false;
  }

  template<typename T>
  bool
465
  operator()(const shared_ptr<std::vector<T> > &) const
466 467 468 469 470 471
  {
    return true;
  }

  template<typename T>
  bool
472
  operator()(const T &) const
473 474 475 476 477
  {
    return true;
  }
};

478
class XdmfArray::Reserve : public boost::static_visitor<void> {
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
479 480
public:

481 482 483 484
  Reserve(XdmfArray * const array,
          const unsigned int size):
    mArray(array),
    mSize(size)
485 486 487 488
  {
  }

  void
489
  operator()(const boost::blank & array) const
490
  {
491
    mArray->mTmpReserveSize = mSize;
492
  }
493

494 495 496
  template<typename T>
  void
  operator()(shared_ptr<std::vector<T> > & array) const
497
  {
498
    array->reserve(mSize);
499
  }
500

501 502
  template<typename T>
  void
503
  operator()(const boost::shared_array<const T> & array) const
504
  {
505 506 507
    mArray->internalizeArrayPointer();
    boost::apply_visitor(*this,
                         mArray->mArray);
508
  }
509 510 511

private:

512
  XdmfArray * const mArray;
513
  const unsigned int mSize;
514 515
};

516 517 518
class XdmfArray::Size : public boost::static_visitor<unsigned int> {
public:

519 520 521 522 523 524
  Size(const XdmfArray * const array) :
    mArray(array)
  {
  }

  unsigned int
525
  operator()(const boost::blank & array) const
526
  {
527
    if(mArray->mHeavyDataControllers.size()>0) {
528
      int total = 0;
529
      for (unsigned int i = 0; i < mArray->mHeavyDataControllers.size(); ++i) {
530 531
        total += mArray->mHeavyDataControllers[i]->getSize();
      }
532
      return total;
533 534
    }
    return 0;
535
  }
536

537 538
  template<typename T>
  unsigned int
539
  operator()(const shared_ptr<std::vector<T> > & array) const
540 541 542
  {
    return array->size();
  }
543 544 545

  template<typename T>
  unsigned int
546
  operator()(const boost::shared_array<const T> & array) const
547 548 549 550 551 552
  {
    return mArray->mArrayPointerNumValues;
  }

private:

553
  const XdmfArray * const mArray; 
554 555
};

556
shared_ptr<XdmfArray>
557
XdmfArray::New()
558
{
559
  shared_ptr<XdmfArray> p(new XdmfArray());
560
  return p;
561 562
}

Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
563
XdmfArray::XdmfArray() :
564 565
  mArrayPointerNumValues(0),
  mName(""),
566
  mTmpReserveSize(0),
567
  mReadMode(XdmfArray::Controller)
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
568 569 570 571 572 573 574
{
}

XdmfArray::~XdmfArray()
{
}

575
const std::string XdmfArray::ItemTag = "DataItem";
576

577 578
void
XdmfArray::clear()
579
{
580
  boost::apply_visitor(Clear(this), 
581 582
                       mArray);
  mDimensions.clear();
583 584
}

585 586
void
XdmfArray::erase(const unsigned int index)
587
{
588 589 590 591
  boost::apply_visitor(Erase(this,
                             index),
                       mArray);
  mDimensions.clear();
592 593
}

594 595
shared_ptr<const XdmfArrayType>
XdmfArray::getArrayType() const
596
{
597 598 599
  if (mHeavyDataControllers.size()>0) {
    return boost::apply_visitor(GetArrayType(mHeavyDataControllers[0]), 
                                mArray);
600
  }
601 602 603
  else {
    return boost::apply_visitor(GetArrayType(shared_ptr<XdmfHDF5Controller>()),
                                mArray);
604
  }
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
}

unsigned int
XdmfArray::getCapacity() const
{
  return boost::apply_visitor(GetCapacity(), 
                              mArray);
}

std::vector<unsigned int>
XdmfArray::getDimensions() const
{
  if(mDimensions.size() == 0) {
    if(!this->isInitialized() && mHeavyDataControllers.size() > 0) {
      std::vector<unsigned int> returnDimensions;
      std::vector<unsigned int> tempDimensions;
621
      // Find the controller with the most dimensions
622 623 624 625 626 627 628 629 630 631
      int dimControllerIndex = 0;
      unsigned int dimSizeMax = 0;
      unsigned int dimTotal = 0;
      for (unsigned int i = 0; i < mHeavyDataControllers.size(); ++i) {
        dimTotal += mHeavyDataControllers[i]->getSize();
        if (mHeavyDataControllers[i]->getSize() > dimSizeMax) {
          dimSizeMax = mHeavyDataControllers[i]->getSize();
          dimControllerIndex = i;
        }
      }
632
      // Total up the size of the lower dimensions
633
      int controllerDimensionSubtotal = 1;
634 635 636
      for (unsigned int i = 0;
           i < mHeavyDataControllers[dimControllerIndex]->getDimensions().size() - 1;
           ++i) {
637 638 639
        returnDimensions.push_back(mHeavyDataControllers[dimControllerIndex]->getDimensions()[i]);
        controllerDimensionSubtotal *= mHeavyDataControllers[dimControllerIndex]->getDimensions()[i];
      }
640
      // Divide the total contained by the dimensions by the size of the lower dimensions
641 642
      returnDimensions.push_back(dimTotal/controllerDimensionSubtotal);
      return returnDimensions;
643
    }
644 645
    const unsigned int size = this->getSize();
    return std::vector<unsigned int>(1, size);
646
  }
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
  return mDimensions;
}

std::string
XdmfArray::getDimensionsString() const
{
  const std::vector<unsigned int> dimensions = this->getDimensions();
  return GetValuesString(dimensions.size()).getValuesString(&dimensions[0],
                                                            dimensions.size());
}

std::map<std::string, std::string>
XdmfArray::getItemProperties() const
{
  std::map<std::string, std::string> arrayProperties;
  if(mHeavyDataControllers.size()>0) {
    arrayProperties.insert(std::make_pair("Format",
                                          mHeavyDataControllers[0]->getName()));
665
  }
666 667
  else {
    arrayProperties.insert(std::make_pair("Format", "XML"));
668
  }
669 670 671 672
  arrayProperties.insert(std::make_pair("Dimensions", 
                                        this->getDimensionsString()));
  if(mName.compare("") != 0) {
    arrayProperties.insert(std::make_pair("Name", mName));
673
  }
674
  shared_ptr<const XdmfArrayType> type = this->getArrayType();
675 676
  type->getProperties(arrayProperties);
  return arrayProperties;
677 678
}

679 680
std::string
XdmfArray::getItemTag() const
681
{
682
  return ItemTag;
683 684
}

685 686
std::string
XdmfArray::getName() const
687
{
688
  return mName;
689 690
}

Andrew J. Burns (Cont's avatar
Andrew J. Burns (Cont committed
691 692 693 694 695 696
XdmfArray::ReadMode
XdmfArray::getReadMode() const
{
  return mReadMode;
}

697 698
unsigned int
XdmfArray::getSize() const
699
{
700
  return boost::apply_visitor(Size(this), 
701
                              mArray);
702 703
}

704 705
shared_ptr<XdmfArrayReference>
XdmfArray::getReference()
Andrew J. Burns (Cont's avatar
Andrew J. Burns (Cont committed
706
{
707
  return mReference;
Andrew J. Burns (Cont's avatar
Andrew J. Burns (Cont committed
708 709
}

710 711
void *
XdmfArray::getValuesInternal()
712
{
713 714
  return const_cast<void *>
    (static_cast<const XdmfArray &>(*this).getValuesInternal());
715 716
}

717 718
const void *
XdmfArray::getValuesInternal() const
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
719
{
720
  return boost::apply_visitor(GetValuesPointer(), 
721
                              mArray);
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
722 723
}

724 725
std::string
XdmfArray::getValuesString() const
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
726
{
727
  return boost::apply_visitor(GetValuesString(mArrayPointerNumValues), 
728
                              mArray);
729 730
}

731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
shared_ptr<XdmfHeavyDataController>
XdmfArray::getHeavyDataController()
{
  return boost::const_pointer_cast<XdmfHeavyDataController>
    (static_cast<const XdmfArray &>(*this).getHeavyDataController(0));
}

shared_ptr<const XdmfHeavyDataController>
XdmfArray::getHeavyDataController() const
{
  if (mHeavyDataControllers.size()>0) {
    return mHeavyDataControllers[0];
  }
  else {
    return shared_ptr<XdmfHeavyDataController>();
  }
}

749
void
750
XdmfArray::initialize(const shared_ptr<const XdmfArrayType> arrayType,
751
                      const unsigned int size)
752
{
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
  if(arrayType == XdmfArrayType::Int8()) {
    this->initialize<char>(size);
  }
  else if(arrayType == XdmfArrayType::Int16()) {
    this->initialize<short>(size);
  }
  else if(arrayType == XdmfArrayType::Int32()) {
    this->initialize<int>(size);
  }
  else if(arrayType == XdmfArrayType::Int64()) {
    this->initialize<long>(size);
  }
  else if(arrayType == XdmfArrayType::Float32()) {
    this->initialize<float>(size);
  }
  else if(arrayType == XdmfArrayType::Float64()) {
    this->initialize<double>(size);
  }
  else if(arrayType == XdmfArrayType::UInt8()) {
    this->initialize<unsigned char>(size);
  }
  else if(arrayType == XdmfArrayType::UInt16()) {
    this->initialize<unsigned short>(size);
  }
  else if(arrayType == XdmfArrayType::UInt32()) {
    this->initialize<unsigned int>(size);
  }
Kenneth Leiter's avatar
Kenneth Leiter committed
780 781 782
  else if(arrayType == XdmfArrayType::String()) {
    this->initialize<std::string>(size);
  }
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
  else if(arrayType == XdmfArrayType::Uninitialized()) {
    this->release();
  }
  else {
    try {
      XdmfError::message(XdmfError::FATAL, 
                         "Array of unsupported type in XdmfArray::initialize");
    }
    catch (XdmfError e) {
      throw e;
    }
  }
}

void
XdmfArray::initialize(const shared_ptr<const XdmfArrayType> arrayType,
                      const std::vector<unsigned int> & dimensions)
{
  mDimensions = dimensions;
  const unsigned int size = std::accumulate(dimensions.begin(),
                                            dimensions.end(),
                                            1,
                                            std::multiplies<unsigned int>());
  return this->initialize(arrayType, size);
}

void
XdmfArray::insert(const unsigned int startIndex,
                  const shared_ptr<const XdmfArray> values,
                  const unsigned int valuesStartIndex,
                  const unsigned int numValues,
                  const unsigned int arrayStride,
                  const unsigned int valuesStride)
{
  boost::apply_visitor(InsertArray(this,
                                   startIndex,
                                   valuesStartIndex,
                                   numValues,
                                   arrayStride,
                                   valuesStride,
                                   mDimensions,
                                   values),
                       mArray);
}


void
XdmfArray::insert(const std::vector<unsigned int> startIndex,
                  const shared_ptr<const XdmfArray> values,
                  const std::vector<unsigned int> valuesStartIndex,
                  const std::vector<unsigned int> numValues,
                  const std::vector<unsigned int> numInserted,
                  const std::vector<unsigned int> arrayStride,
                  const std::vector<unsigned int> valuesStride)
{
838 839 840 841 842
  // Ensuring dimensions match up when pulling data
  if ((values->getDimensions().size() == valuesStartIndex.size()
      && valuesStartIndex.size() == numValues.size()
      && numValues.size() == valuesStride.size())
      && (numInserted.size() == startIndex.size()
Andrew J. Burns (Cont's avatar
Andrew J. Burns (Cont committed
843 844
      && startIndex.size() == this->getDimensions().size()
      && this->getDimensions().size() == arrayStride.size())) {
845
    // Pull data from values
846 847 848 849 850 851 852 853 854 855 856 857
    std::vector<unsigned int > dimTotalVector;
    unsigned int dimTotal = 1;
    for (unsigned int i = 0; i < values->getDimensions().size(); ++i) {
      dimTotalVector.push_back(dimTotal);
      dimTotal *= values->getDimensions()[i];
    }
    std::vector<unsigned int> indexVector;
    for (unsigned int i = 0; i < values->getDimensions().size(); ++i) {
      indexVector.push_back(0);
    }
    shared_ptr<XdmfArray> holderArray = XdmfArray::New();
    unsigned int holderoffset = 0;
858
    // End when the last index is incremented
859
    while (indexVector[indexVector.size()-1] < 1) {
860
      // Initialize the section of the array you're pulling from
861 862 863
      unsigned int startTotal = 0;
      dimTotal = 1;
      for (unsigned int i = 0; i < values->getDimensions().size(); ++i) {
864 865
        // Stride doesn't factor in to the first dimension
        // Since it's being used with the insert call
866 867 868 869
        if (i == 0) {
          startTotal += valuesStartIndex[i] * dimTotal;
        }
        else {
870 871
          startTotal += valuesStartIndex[i] * dimTotal
                        + valuesStride[i] * dimTotal * indexVector[i-1];
872 873 874
        }
        dimTotal *= values->getDimensions()[i];
      }
875 876 877 878 879 880 881
      // Insert the subsection
      holderArray->insert(holderoffset,
                          values,
                          startTotal,
                          numValues[0],
                          1,
                          valuesStride[0]);
882
      holderoffset+=numValues[0];
883
      // Increment up the vector
884 885 886
      bool increment = true;
      for (unsigned int i = 0; i < indexVector.size() && increment; ++i) {
        indexVector[i]++;
887
        // To keep the loop from breaking at the end
888 889 890 891 892 893 894 895 896 897
        if (i+1 < numValues.size()) {
          if (indexVector[i] >= numValues[i+1]) {
            indexVector[i] = indexVector[i] % numValues[i+1];
          }
          else {
            increment = false;
          }
        }
      }
    }
898 899
    // Values being inserted retrieved
    // Use an variation of the last loop to insert into this array
900 901 902 903 904 905

    indexVector.clear();
    for (unsigned int i = 0; i < this->getDimensions().size(); ++i) {
      indexVector.push_back(0);
    }
    holderoffset = 0;
906
    // End when the last index is incremented
907
    while (indexVector[indexVector.size()-1] < 1) {
908
      // Initialize the section of the array you're pulling from
909 910 911
      unsigned int startTotal = 0;
      dimTotal = 1;
      for (unsigned int i = 0; i < this->getDimensions().size(); ++i) {
912 913 914
        if (i == 0) {
          // Stride doesn't factor in to the first dimension
          // Since it's being used with the insert call
915 916 917 918 919 920 921
          startTotal += startIndex[i] * dimTotal;
        }
        else {
          startTotal += startIndex[i] * dimTotal + arrayStride[i] * dimTotal * indexVector[i-1];
        }
        dimTotal *= this->getDimensions()[i];
      }
922
      // Insert the subsection
923 924
      this->insert(startTotal, holderArray, holderoffset, numInserted[0], arrayStride[0], 1);
      holderoffset+=numInserted[0];
925
      // Increment up the vector
926 927 928
      bool increment = true;
      for (unsigned int i = 0; i < indexVector.size() && increment; ++i) {
        indexVector[i]++;
929 930
        if (i+1 < numInserted.size()) {
          // To keep the loop from breaking at the end
931 932 933 934 935 936 937 938 939 940 941
          if (indexVector[i] >= numInserted[i+1]) {
            indexVector[i] = indexVector[i] % numInserted[i+1];
          }
          else {
            increment = false;
          }
        }
      }
    }
  }
  else {
942 943 944 945
    // Throw an error
    if (!(values->getDimensions().size() == valuesStartIndex.size()
          && valuesStartIndex.size() == numValues.size()
          && numValues.size() == valuesStride.size())) {
946 947
      try {
        XdmfError::message(XdmfError::FATAL,
948 949 950
                           "Error: Number of starts, strides, and/or values "
                           "retrieved does not match up with the dimensions "
                           "of the array being retrieved from");
951 952 953 954 955
      }
      catch (XdmfError e) {
        throw e;
      }
    }
956
    else if (!(numInserted.size() == startIndex.size()
Andrew J. Burns (Cont's avatar
Andrew J. Burns (Cont committed
957 958
               && startIndex.size() == this->getDimensions().size()
               && this->getDimensions().size() == arrayStride.size())) {
959 960
      try {
        XdmfError::message(XdmfError::FATAL,
961 962 963
                           "Error: Number of starts, strides, and/or values "
                           "written does not match up with the dimensions "
                           "of the array being inserted into");
964 965 966 967 968 969 970 971
      }
      catch (XdmfError e) {
        throw e;
      }
    }
  }
}

972 973
bool
XdmfArray::isInitialized() const
974
{
975
  return boost::apply_visitor(IsInitialized(),
976
                                mArray);
977 978
}

979 980
void
XdmfArray::internalizeArrayPointer()
981
{
982
  boost::apply_visitor(InternalizeArrayPointer(this), 
983
                       mArray);
Ken Leiter (Civ ARL/CISD) kleiter's avatar
ENH:  
Ken Leiter (Civ ARL/CISD) kleiter committed
984 985
}

986 987
void
XdmfArray::populateItem(const std::map<std::string, std::string> & itemProperties,
988
                        const std::vector<shared_ptr<XdmfItem> > & childItems,
989
                        const XdmfCoreReader * const reader)
990
{
991
  // This inserts any XdmfInformation in childItems into the object.
992 993
  XdmfItem::populateItem(itemProperties, childItems, reader);

994
  const shared_ptr<const XdmfArrayType> arrayType = 
995 996
    XdmfArrayType::New(itemProperties);

997 998
 std::map<std::string, std::string>::const_iterator content =
    itemProperties.find("Content");
999
  if(content == itemProperties.end()) {
1000
    try {
1001
      XdmfError::message(XdmfError::FATAL,
1002 1003 1004 1005 1006 1007
                         "'Content' not found in itemProperties in "
                         "XdmfArray::populateItem");
    }
    catch (XdmfError e) {
      throw e;
    }
1008
  }
1009

Andrew J. Burns (Cont's avatar
Andrew J. Burns (Cont committed
1010
  unsigned int contentIndex;
1011

1012
  const std::string & contentVal = content->second;
1013

1014
  std::vector<std::string> contentVals;
1015

1016 1017 1018 1019 1020 1021 1022 1023 1024
  // Split the content based on "|" characters
  size_t barSplit = 0;
  std::string splitString(contentVal);
  std::string subcontent;
  while (barSplit != std::string::npos) {
    barSplit = 0;
    barSplit = splitString.find_first_of("|", barSplit);
    if (barSplit == std::string::npos) {
      subcontent = splitString;
1025 1026
    }
    else {
1027 1028 1029
      subcontent = splitString.substr(0, barSplit);
      splitString = splitString.substr(barSplit+1);
      barSplit++;
1030
    }
1031
    contentVals.push_back(subcontent);
1032
  }
1033

1034
  std::map<std::string, std::string>::const_iterator dimensions =
1035
    itemProperties.find("Dimensions");
1036
  if(dimensions == itemProperties.end()) {
1037 1038 1039 1040 1041 1042 1043 1044
    try {
      XdmfError::message(XdmfError::FATAL, 
                         "'Dimensions' not found in itemProperties in "
                         "XdmfArray::populateItem");
    }
    catch (XdmfError e) {
      throw e;
    }
1045
  }
1046
   
1047 1048 1049 1050 1051 1052
  boost::tokenizer<> tokens(dimensions->second);
  for(boost::tokenizer<>::const_iterator iter = tokens.begin();
      iter != tokens.end();
      ++iter) {
    mDimensions.push_back(atoi((*iter).c_str()));
  }
1053 1054 1055

  std::map<std::string, std::string>::const_iterator format =
    itemProperties.find("Format");
1056
  if(format == itemProperties.end()) {
1057 1058 1059 1060 1061 1062 1063 1064
    try {
      XdmfError::message(XdmfError::FATAL, 
                         "'Format' not found in itemProperties in "
                         "XdmfArray::populateItem");
    }
    catch (XdmfError e) {
      throw e;
    }
1065 1066 1067
  }
  const std::string & formatVal = format->second;

1068

1069
  if(formatVal.compare("HDF") == 0) {
1070 1071 1072 1073 1074
    contentIndex = 0;
    int contentStep = 2;
    while (contentIndex < contentVals.size()) {
      size_t colonLocation = contentVals[contentIndex].find(":");
      if(colonLocation == std::string::npos) {
1075 1076 1077 1078 1079 1080 1081 1082 1083
        try {
          XdmfError::message(XdmfError::FATAL, 
                             "':' not found in content in "
                             "XdmfArray::populateItem -- double check an HDF5 "
                             "data set is specified for the file");
        }
        catch (XdmfError e) {
          throw e;
        }
1084 1085
      }

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
      std::string hdf5Path = 
        contentVals[contentIndex].substr(0, colonLocation);
      std::string dataSetPath = 
        contentVals[contentIndex].substr(colonLocation+1);

      // FIXME: for other OS (e.g. windows)
      if(hdf5Path.size() > 0 && hdf5Path[0] != '/') {
        // Dealing with a relative path for hdf5 location
        std::map<std::string, std::string>::const_iterator xmlDir =
          itemProperties.find("XMLDir");
        if(xmlDir == itemProperties.end()) {
          XdmfError::message(XdmfError::FATAL,
                             "'XMLDir' not found in itemProperties in "
                             "XdmfArray::populateItem");
        }
        std::stringstream newHDF5Path;
        newHDF5Path << xmlDir->second << hdf5Path;
        hdf5Path = newHDF5Path.str();
      }
1105

1106
      // Parse dimensions from the content
1107
      std::vector<unsigned int> contentDims;
1108
      if (contentVals.size() > contentIndex+1) {
1109
        // This is the string that contains the dimensions
1110 1111 1112 1113 1114 1115
        boost::tokenizer<> dimtokens(contentVals[contentIndex+1]);
        for(boost::tokenizer<>::const_iterator iter = dimtokens.begin();
            iter != dimtokens.end();
            ++iter) {
          contentDims.push_back(atoi((*iter).c_str()));
        }
1116
	contentStep = 2;
1117
        // If this works then the dimension content should be skipped over
1118
      }
1119
      else {
1120
        // If it fails then it means that the next content is not a dimension string
1121 1122
        // In this case it is assumed that the controller will have
        // dimensions equal to the array
1123
        for (unsigned int j = 0; j < mDimensions.size(); ++j) {
1124 1125 1126
          contentDims.push_back(mDimensions[j]);
        }
        contentStep = 1;
1127
      }
1128

1129

1130