vtkLSDynaPartCollection.cxx 31 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkLSDynaReader.cxx

  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.
=========================================================================*/

#include "vtkLSDynaPartCollection.h"
16
#include "vtkLSDynaPart.h"
17 18
#include "LSDynaMetaData.h"

19

20
#include "vtkCellArray.h"
21 22
#include "vtkCellData.h"
#include "vtkDataArray.h"
23
#include "vtkDoubleArray.h"
24
#include "vtkIdTypeArray.h"
25
#include "vtkFloatArray.h"
26
#include "vtkObjectFactory.h"
27
#include "vtkPoints.h"
28
#include "vtkPointData.h"
29
#include "vtkStringArray.h"
30
#include "vtkUnsignedCharArray.h"
31 32
#include "vtkUnstructuredGrid.h"

33
#include <algorithm>
34
#include <vector>
35
#include <list>
36

37
//-----------------------------------------------------------------------------
38 39 40 41
class vtkLSDynaPartCollection::LSDynaPartStorage
{
protected:
  //---------------------------------------------------------------------------
42 43 44 45
  //stores the number of cells for a given part
  //this struct is meant to resemble a run length encoding style of storage
  //of mapping cell ids to the part that holds those cells
  struct PartInfo
46
  {
47
    PartInfo(vtkLSDynaPart *p, const int& type, const vtkIdType& pId,
48 49
             const vtkIdType& start, const vtkIdType& npts):
      numCells(1), //we are inserting the first cell when we create this so start with 1
50
      startId(start),
51 52 53 54 55
      cellStructureSize(npts), //start with number of points in first cell
      partId(pId)
    {
      //we store the part id our selves because we can have null parts
      //if the user has disabled reading that part
56
      this->part = p;
57
      if(this->part)
58
      {
59
        this->part->SetPartType(type);
60
      }
61 62
    }

Kyle Lutz's avatar
Kyle Lutz committed
63
    vtkIdType numCells; //number of cells in this continuous block
64 65
    vtkIdType startId; //the global index to start of this block
    vtkIdType cellStructureSize; //stores the size of the cell array for this section
66
    vtkIdType partId; //id of the part this block represents, because the part can be nullptr
67
    vtkLSDynaPart *part;
68
  };
69

70
  //---------------------------------------------------------------------------
71
  struct PartInsertion
72
  {
73 74 75
    PartInsertion():numCellsInserted(0){}

    PartInsertion(std::vector<PartInfo> *pInfo):numCellsInserted(0)
76
    {
77 78 79 80 81 82 83 84
      this->pIt = pInfo->begin();
    }

    //increments the numCells, and when needed increments to the next part
    void inc()
    {
      ++numCellsInserted;
      if ( (*pIt).numCells == numCellsInserted)
85
      {
86 87
        ++pIt;
        numCellsInserted=0;
88
      }
89 90 91 92
    }

    std::vector<PartInfo>::iterator pIt;
    vtkIdType numCellsInserted;
93
  };
94 95
  //---------------------------------------------------------------------------

96 97 98
public:
  LSDynaPartStorage(const vtkIdType& numMaterials):
    NumParts(numMaterials),PartIteratorLoc(0)
99
  {
100 101 102 103 104
    //a part represents a single material. A part type is
    this->Info = new std::vector<PartInfo>[LSDynaMetaData::NUM_CELL_TYPES];
    this->CellInsertionIterators = new PartInsertion[LSDynaMetaData::NUM_CELL_TYPES];
    this->Parts = new vtkLSDynaPart*[numMaterials];
    for(vtkIdType i=0; i<numMaterials; ++i)
105
    {
106
      this->Parts[i]=nullptr;
107
    }
108
  }
109
  ~LSDynaPartStorage()
110
  {
111
    for(vtkIdType i=0; i < this->NumParts; ++i)
112
    {
113
      if(this->Parts[i])
114
      {
115
        this->Parts[i]->Delete();
116
        this->Parts[i]=nullptr;
117
      }
118
    }
119 120 121
    delete[] this->Parts;
    delete[] this->CellInsertionIterators;
    delete[] this->Info;
122
  }
123

124 125
  //---------------------------------------------------------------------------
  vtkIdType GetNumParts() const { return NumParts; }
126

127 128 129 130
  //---------------------------------------------------------------------------
  void RegisterCell(const int& partType,const vtkIdType &matId,
                    const vtkIdType &npts)
  {
131
    if(!this->Info[partType].empty())
132
    {
133 134
      PartInfo *info = &this->Info[partType].back();
      if(info->partId == matId)
135
      {
136 137 138
        //append to this item
        ++info->numCells;
        info->cellStructureSize += npts;
139
      }
140
      else
141
      {
142
        //add a new item
143 144
        //PartInfo sets the part type!
        PartInfo newInfo(this->Parts[matId],partType,matId,
145 146 147
          (info->startId + info->numCells), npts);
        this->Info[partType].push_back(newInfo);
      }
148
    }
149
    else
150
    {
151 152
      //PartInfo sets the part type!
      PartInfo newInfo(this->Parts[matId],partType,matId,0,npts);
153
      this->Info[partType].push_back(newInfo);
154
    }
155
  }
156

157 158 159 160 161 162 163 164 165
  //---------------------------------------------------------------------------
  void ConstructPart(const vtkIdType &index,
                     const std::string &name,
                     const int &materialId,
                     const int &numGlobalNodes,
                     const int &wordSize
                     )
  {
    vtkLSDynaPart *p = vtkLSDynaPart::New();
166
    p->InitPart(name,index,materialId,
167 168 169
                numGlobalNodes,wordSize);
    this->Parts[index] = p;
  }
170

171 172 173 174 175 176
  //---------------------------------------------------------------------------
  void InitCellInsertion()
  {
    //we build up an array of cell insertion iterators
    //that point to the first element of each part type info
    for(int i=0; i < LSDynaMetaData::NUM_CELL_TYPES; ++i)
177
    {
178
      if(!this->Info[i].empty())
179
      {
180 181 182
        PartInsertion partIt(&this->Info[i]);
        this->CellInsertionIterators[i] = partIt;
      }
183
    }
184 185
  }

186 187 188
  //---------------------------------------------------------------------------
  void InsertCell(const int& partType, const int& cellType,
                  const vtkIdType& npts, vtkIdType conn[8])
189
  {
190 191
    //get the correct iterator from the array of iterations
    if(this->CellInsertionIterators[partType].pIt->part)
192
    {
193 194 195
      //only insert the cell if the part is turned on
      this->CellInsertionIterators[partType].pIt->part->AddCell(
            cellType,npts,conn);
196
    }
197 198 199 200 201 202 203
    this->CellInsertionIterators[partType].inc();
  }

  //---------------------------------------------------------------------------
  bool PartExists(const vtkIdType &index) const
  {
    if(index<0||index>this->NumParts)
204
    {
205
      return false;
206
    }
207
    return (this->Parts[index]!=nullptr && this->Parts[index]->HasCells());
208
  }
209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
  //---------------------------------------------------------------------------
  vtkLSDynaPart* GetPart(const vtkIdType &index)
  {
    return this->Parts[index];
  }

  //---------------------------------------------------------------------------
  vtkUnstructuredGrid* GetPartGrid(const vtkIdType &index)
  {
    return this->Parts[index]->GenerateGrid();
  }

  //---------------------------------------------------------------------------
  void InitPartIteration(const int &partType)
  {
    for(vtkIdType i=0; i < this->NumParts; ++i)
226
    {
227
      if(this->Parts[i] && this->Parts[i]->PartType() == partType)
228
      {
229 230 231
        PartIteratorLoc = i;
        this->PartIterator = this->Parts[i];
        return;
232
      }
233
    }
234 235
    //failed to find a part that matches the type
    PartIteratorLoc = -1;
236
    this->PartIterator = nullptr;
237
  }
238

239 240 241 242
  //---------------------------------------------------------------------------
  bool GetNextPart(vtkLSDynaPart *&part)
  {
    if(!this->PartIterator)
243
    {
244
      part = nullptr;
245
      return false;
246
    }
247
    part=this->PartIterator;
248

249 250
    //clear iterator before we search for the next part
    vtkIdType pos = this->PartIteratorLoc + 1;
251
    this->PartIterator = nullptr;
252
    this->PartIteratorLoc = -1;
253

254 255
    //find the next part
    for(vtkIdType i=pos; i<this->NumParts;i++)
256
    {
257
      if(this->Parts[i] && this->Parts[i]->PartType() == part->PartType())
258
      {
259 260 261 262
        this->PartIteratorLoc = i;
        this->PartIterator = this->Parts[i];
        break;
      }
263
    }
264 265
    return true;
  }
266

267 268 269 270 271
  //---------------------------------------------------------------------------
  void AllocateParts()
  {
    vtkIdType numCells=0,cellLength=0;
    for (vtkIdType i=0; i < this->NumParts; ++i)
272
    {
273
      vtkLSDynaPart* part = this->Parts[i];
274 275

      if(part)
276
      {
277 278
        bool canBeAllocated = this->GetInfoForPart(part, numCells,cellLength);
        if(canBeAllocated)
279
        {
280
          part->AllocateCellMemory(numCells,cellLength);
281
        }
282
        else
283
        {
284 285
          //this part has no cells allocated to it, so remove it now.
          part->Delete();
286
          this->Parts[i] = nullptr;
287 288
        }
      }
289
    }
290 291
    //Only needed when debugging
    //this->DumpPartInfo();
292
  }
293

294
  //---------------------------------------------------------------------------
295 296
  bool GetInfoForPart(vtkLSDynaPart *part, vtkIdType &numCells,
                      vtkIdType &cellArrayLength) const
297 298

  {
299
    //verify that the part is valid
300 301
    numCells = 0;
    cellArrayLength = 0;
302 303
    bool validPart = part->hasValidType();
    if(!validPart)
304
    {
305 306 307
      //we return early because an invalid type would
      //cause the Info array to be accessed out of bounds
      return validPart;
308
    }
309

310 311
    //give a part type and a material id
    //walk the run length encoding to determe the total size
312
    std::vector<PartInfo>::const_iterator it;
313 314
    for(it = this->Info[part->PartType()].begin();
        it != this->Info[part->PartType()].end(); ++it)
315
    {
316
      const PartInfo *info = &(*it);
317
      if(info->partId== part->GetPartId())
318
      {
319
        validPart = true;
320 321
        numCells += info->numCells;
        cellArrayLength += info->cellStructureSize;
322
      }
323
    }
324 325 326 327 328 329 330 331

    return validPart;
  }

  //---------------------------------------------------------------------------
  void DumpPartInfo()
  {
  for(int i=0; i < LSDynaMetaData::NUM_CELL_TYPES;++i)
332
  {
333 334 335 336 337 338 339 340
    //now lets dump all the part info

    std::cout << "For Info index: " << i << std::endl;
    std::cout << "We have " << this->Info[i].size() << " info entries" <<std::endl;

    std::vector<PartInfo>::const_iterator it;
    for(it = this->Info[i].begin();
      it != this->Info[i].end(); ++it)
341
    {
342
      const PartInfo *info = &(*it);
343
      if(info->part != nullptr)
344
      {
345 346 347 348 349 350 351 352 353
        std::cout << "The material id is: " << info->partId << std::endl;
        std::cout << "The numCells is:    " << info->numCells << std::endl;
        std::cout << std::endl;
        std::cout << "The Part is :" << std::endl;
        info->part->PrintSelf(cout,vtkIndent().GetNextIndent());
        std::cout << std::endl;
        std::cout << std::endl;
      }
    }
354
  }
355
  }
356

357

358 359 360 361
  //---------------------------------------------------------------------------
  void InitCellIteration(const int &partType, int pos=0)
  {
    this->CellIteratorEnd = this->Info[partType].end();
362
    if(!this->Info[partType].empty())
363
    {
364
      this->CellIterator = this->Info[partType].begin();
365
    }
366
    else
367
    {
368
      this->CellIterator = this->Info[partType].end();
369
    }
370

371
    while(pos>0 && this->CellIterator != this->CellIteratorEnd)
372
    {
373 374
      pos -= (*this->CellIterator).numCells;
      if(pos>0)
375
      {
376 377
        ++this->CellIterator;
      }
378
    }
379
  }
380

381 382 383 384 385
  //---------------------------------------------------------------------------
  bool GetNextCellPart(vtkIdType& startId, vtkIdType &numCells,
                       vtkLSDynaPart *&part)
  {
    if(this->CellIterator == this->CellIteratorEnd)
386
    {
387
      return false;
388
    }
389

390 391 392 393 394 395
    startId = (*this->CellIterator).startId;
    numCells = (*this->CellIterator).numCells;
    part = (*this->CellIterator).part;
    ++this->CellIterator;
    return true;
  }
396

397 398 399 400
  //---------------------------------------------------------------------------
  void FinalizeTopology()
  {
    for (vtkIdType i=0; i < this->NumParts; ++i)
401
    {
402 403
      vtkLSDynaPart* part = this->Parts[i];
      if (part && part->HasCells())
404
      {
405
        part->BuildToplogy();
406
      }
407
      else if(part)
408
      {
409
        part->Delete();
410
        this->Parts[i]=nullptr;
411
      }
412
    }
413
  }
414

415 416 417 418
  //---------------------------------------------------------------------------
  void DisableDeadCells()
  {
    for (vtkIdType i=0; i < this->NumParts; ++i)
419
    {
420 421
      vtkLSDynaPart* part = this->Parts[i];
      if (part && part->HasCells())
422
      {
423 424
        part->DisableDeadCells();
      }
425
    }
426
  }
427

428 429 430 431
  //---------------------------------------------------------------------------
  void PrintSelf(ostream &os, vtkIndent indent)
  {
    for (vtkIdType i=0; i < this->NumParts; ++i)
432
    {
433 434
      os << indent << "Part Number " << i << std::endl;
      if(this->PartExists(i))
435
      {
436 437
        vtkLSDynaPart* part = this->Parts[i];
        part->PrintSelf(os,indent.GetNextIndent());
438
      }
439
      else
440
      {
441 442 443
        os << indent.GetNextIndent() << "Does not exist." << std::endl;
      }
    }
444
  }
445

446 447
protected:
  vtkIdType NumParts;
448

449 450
  //stores all the parts for this collection.
  vtkLSDynaPart **Parts;
451

452 453 454 455
  //maps cell indexes which are tracked by output type to the part
  //Since cells are ordered the same between the cell connectivity data block
  //and the state block in the d3plot format we only need to know which part
  //the cell is part of.
456 457 458
  //This info is constant for each time step
  std::vector<PartInfo> *Info;
  PartInsertion *CellInsertionIterators;
459

460 461 462
  std::vector<PartInfo>::const_iterator CellIterator,CellIteratorEnd;
  vtkLSDynaPart *PartIterator;
  vtkIdType PartIteratorLoc;
463 464 465
};

vtkStandardNewMacro(vtkLSDynaPartCollection);
466
//-----------------------------------------------------------------------------
467
vtkLSDynaPartCollection::vtkLSDynaPartCollection()
468
{
469 470 471 472
  this->MetaData = nullptr;
  this->Storage = nullptr;
  this->MinIds = nullptr;
  this->MaxIds = nullptr;
473 474
}

475
//-----------------------------------------------------------------------------
476 477
vtkLSDynaPartCollection::~vtkLSDynaPartCollection()
{
478 479 480
  delete this->Storage;
  delete[] this->MinIds;
  delete[] this->MaxIds;
481
  this->MetaData = nullptr;
482 483
}

484
//-----------------------------------------------------------------------------
485 486
void vtkLSDynaPartCollection::PrintSelf(ostream &os, vtkIndent indent)
{
487 488 489 490 491
  //just needs to print all public accessible ivars
  this->Superclass::PrintSelf(os, indent);

  //number of parts
  os << indent << "Number of Parts: " << this->GetNumberOfParts() << std::endl;
492

493 494
  //print self for each part
  this->Storage->PrintSelf(os,indent.GetNextIndent());
495 496
}

497
//-----------------------------------------------------------------------------
498
void vtkLSDynaPartCollection::InitCollection(LSDynaMetaData *metaData,
499
                                             vtkIdType* mins, vtkIdType* maxs)
500
{
501 502 503
  delete this->Storage;
  delete[] this->MinIds;
  delete[] this->MaxIds;
504

505 506 507
  //reserve enough space for the grids. Each node
  //will have a part allocated, since we don't know yet
  //how the cells map to parts.
508
  this->Storage = new LSDynaPartStorage(static_cast<vtkIdType>(metaData->PartIds.size()));
509

510 511 512
  this->MinIds = new vtkIdType[LSDynaMetaData::NUM_CELL_TYPES];
  this->MaxIds = new vtkIdType[LSDynaMetaData::NUM_CELL_TYPES];

513
  //We only have to map the cell ids between min and max, so we
514 515
  //skip into the proper place
  for(int i=0; i < LSDynaMetaData::NUM_CELL_TYPES;++i)
516
  {
517 518
    this->MinIds[i]= (mins!=nullptr) ? mins[i] : 0;
    this->MaxIds[i]= (maxs!=nullptr) ? maxs[i] : metaData->NumberOfCells[i];
519
  }
520

521
  if(metaData)
522
  {
523
    this->MetaData = metaData;
524
    this->BuildPartInfo();
525
  }
526 527
}

528
//-----------------------------------------------------------------------------
529
void vtkLSDynaPartCollection::BuildPartInfo()
530
{
531
  //we iterate on part materials as those are those are from 1 to num Parts.
532 533
  //the part ids are the user material ids

534
  std::vector<int>::const_iterator partMIt;
535
  std::vector<int>::const_iterator materialIdIt = this->MetaData->PartIds.begin();
536
  std::vector<int>::const_iterator statusIt = this->MetaData->PartStatus.begin();
537 538
  std::vector<std::string>::const_iterator nameIt = this->MetaData->PartNames.begin();

539 540
  for (partMIt = this->MetaData->PartMaterials.begin();
       partMIt != this->MetaData->PartMaterials.end();
541
       ++partMIt,++statusIt,++nameIt,++materialIdIt)
542
  {
543
    if (*statusIt)
544
    {
545
      //make the index contain a part
546
      this->Storage->ConstructPart((*partMIt)-1,*nameIt,*materialIdIt,
547 548 549
                                   this->MetaData->NumberOfNodes,
                                   this->MetaData->Fam.GetWordSize());
    }
550
  }
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
}


//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::RegisterCellIndexToPart(const int& partType,
                                            const vtkIdType& matId,
                                            const vtkIdType&,
                                            const vtkIdType& npts)

{
  this->Storage->RegisterCell(partType,matId-1,npts);
}

//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::AllocateParts( )
{
  this->Storage->AllocateParts();
}

//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::InitCellInsertion()
{
  this->Storage->InitCellInsertion();
574 575
}

576
//-----------------------------------------------------------------------------
577
void vtkLSDynaPartCollection::InsertCell(const int& partType,
578
                                         const vtkIdType&,
579 580 581 582 583
                                         const int& cellType,
                                         const vtkIdType& npts,
                                         vtkIdType conn[8])
{

584
  this->Storage->InsertCell(partType,cellType,npts,conn);
585 586
}

587
//-----------------------------------------------------------------------------
588 589 590
void vtkLSDynaPartCollection::SetCellDeadFlags(const int& partType,
                                          vtkUnsignedCharArray *death,
                                          const int& deadCellsAsGhostArray)
591
{
592 593 594
  //go through and flag each part cell as deleted or not.
  //this means breaking up this array into an array for each part
  if (!death)
595
  {
596
    return;
597
  }
598 599 600 601

  //The array that passed in from the reader only contains the subset
  //of the full data that we are interested in so we don't have to adjust
  //any indices
602 603 604 605 606
  this->Storage->InitCellIteration(partType);
  vtkIdType numCells, startId;
  vtkLSDynaPart *part;
  unsigned char* dead = static_cast<unsigned char*>(death->GetVoidPointer(0));
  while(this->Storage->GetNextCellPart(startId,numCells,part))
607
  {
608
    //perfectly valid to have a nullptr part being returned
609 610
    //just skip it as the user doesn't want it loaded.
    if(part)
611
    {
612
      part->EnableDeadCells(deadCellsAsGhostArray);
613
      part->SetCellsDeadState(dead,numCells);
614
    }
615 616
    dead += numCells;
  }
617 618
}

619 620 621 622 623
//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::AddProperty(
                    const LSDynaMetaData::LSDYNA_TYPES& type, const char* name,
                    const int& offset, const int& numComps)
{
624

625
  vtkLSDynaPart* part = nullptr;
626 627
  this->Storage->InitPartIteration(type);
  while(this->Storage->GetNextPart(part))
628
  {
629
    if(part)
630
    {
631
      part->AddCellProperty(name,offset,numComps);
632
    }
633
  }
634 635 636
}

//-----------------------------------------------------------------------------
637
void vtkLSDynaPartCollection::FillCellProperties(float *buffer,
638
  const LSDynaMetaData::LSDYNA_TYPES& type, const vtkIdType& startId,
639
  const vtkIdType& numCells, const int& numPropertiesInCell)
640
{
641
  this->FillCellArray(buffer,type,startId,numCells,numPropertiesInCell);
642
}
643

644 645
//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::FillCellProperties(double *buffer,
646
  const LSDynaMetaData::LSDYNA_TYPES& type, const vtkIdType& startId,
647
  const vtkIdType& numCells, const int& numPropertiesInCell)
648
{
649
  this->FillCellArray(buffer,type,startId,numCells,numPropertiesInCell);
650 651 652 653
}

//-----------------------------------------------------------------------------
template<typename T>
654
void vtkLSDynaPartCollection::FillCellArray(T *buffer,
655
  const LSDynaMetaData::LSDYNA_TYPES& type, const vtkIdType& startId,
656
  vtkIdType numCells, const int& numPropertiesInCell)
657
{
658
  //we only need to iterate the array for the subsection we need
659 660 661 662 663
  T* loc = buffer;
  vtkIdType size, globalStartId;
  vtkLSDynaPart *part;
  this->Storage->InitCellIteration(type,startId);
  while(this->Storage->GetNextCellPart(globalStartId,size,part))
664
  {
665 666 667
    vtkIdType start = std::max(globalStartId,startId);
    vtkIdType end = std::min(globalStartId+size,startId+numCells);
    if(end<start)
668
    {
669
      break;
670
    }
671 672
    vtkIdType is = end - start;
    if(part)
673
    {
674
      part->ReadCellProperties(loc,is,numPropertiesInCell);
675
    }
676 677
    loc += is * numPropertiesInCell;
  }
678 679
}

680 681 682 683 684 685 686 687 688
//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::ReadCellUserIds(
    const LSDynaMetaData::LSDYNA_TYPES& type, const int& status)
{

  vtkIdType numCells,numSkipStart,numSkipEnd;
  this->GetPartReadInfo(type,numCells,numSkipStart,numSkipEnd);

  if(!status)
689
  {
690 691 692
    //skip this part type
    this->MetaData->Fam.SkipWords(numSkipStart + numCells + numSkipEnd);
    return;
693
  }
694 695 696 697 698

  this->MetaData->Fam.SkipWords(numSkipStart);
  vtkIdType numChunks = this->MetaData->Fam.InitPartialChunkBuffering(numCells,1);
  vtkIdType startId = 0;
  if(this->MetaData->Fam.GetWordSize() == 8 && numCells > 0)
699
  {
700
    for(vtkIdType i=0; i < numChunks; ++i)
701
    {
702 703
      vtkIdType chunkSize = this->MetaData->Fam.GetNextChunk( LSDynaFamily::Float);
      vtkIdType numCellsInChunk = chunkSize;
704
      vtkIdType *buf = this->MetaData->Fam.GetBufferAs<vtkIdType>();
705 706 707
      this->FillCellUserId(buf,type,startId,numCellsInChunk);
      startId += numCellsInChunk;
    }
708
  }
709
  else if (numCells > 0)
710
  {
711
    for(vtkIdType i=0; i < numChunks; ++i)
712
    {
713 714
      vtkIdType chunkSize = this->MetaData->Fam.GetNextChunk( LSDynaFamily::Float);
      vtkIdType numCellsInChunk = chunkSize;
715
      int *buf = this->MetaData->Fam.GetBufferAs<int>();
716 717 718
      this->FillCellUserId(buf,type,startId,numCellsInChunk);
      startId += numCellsInChunk;
    }
719
  }
720 721 722 723 724 725 726 727 728 729
  this->MetaData->Fam.SkipWords(numSkipEnd);

  //clear the buffer as it will be very large and not needed
  this->MetaData->Fam.ClearBuffer();
}

//-----------------------------------------------------------------------------
template<typename T>
void vtkLSDynaPartCollection::FillCellUserIdArray(T *buffer,
  const LSDynaMetaData::LSDYNA_TYPES& type, const vtkIdType& startId,
730
  vtkIdType numCells)
731
{
732
  const int numWordsPerIdType(this->MetaData->Fam.GetWordSize() / sizeof(T));
733 734 735 736 737 738
  //we only need to iterate the array for the subsection we need
  T* loc = buffer;
  vtkIdType size,globalStartId;
  vtkLSDynaPart *part;
  this->Storage->InitCellIteration(type,startId);
  while(this->Storage->GetNextCellPart(globalStartId,size,part))
739
  {
740 741 742
    vtkIdType start = std::max(globalStartId,startId);
    vtkIdType end = std::min(globalStartId+size,startId+numCells);
    if(end<start)
743
    {
744
      break;
745
    }
746
    vtkIdType is = (end - start)*numWordsPerIdType;
747
    if(part)
748
    {
749
      part->EnableCellUserIds();
750
      for(vtkIdType i=0; i<is; i+=numWordsPerIdType)
751
      {
752
        part->SetNextCellUserIds((vtkIdType)loc[i]);
753
      }
754
    }
755
    //perfectly valid to have a nullptr part being returned
756 757
    //just skip it as the user doesn't want it loaded.
    loc+=is;
758
  }
759 760
}

761
//-----------------------------------------------------------------------------
762
bool vtkLSDynaPartCollection::IsActivePart(const int& id) const
763
{
764
  return this->Storage->PartExists(id);
765 766
}

767
//-----------------------------------------------------------------------------
768
vtkUnstructuredGrid* vtkLSDynaPartCollection::GetGridForPart(
769 770 771
  const int& index) const
{
  return this->Storage->GetPartGrid(index);
772 773
}

774
//-----------------------------------------------------------------------------
775 776
int vtkLSDynaPartCollection::GetNumberOfParts() const
{
777 778 779 780 781 782
  return static_cast<int>(this->Storage->GetNumParts());
}
//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::DisbleDeadCells()
{
  this->Storage->DisableDeadCells();
783 784
}

785
//-----------------------------------------------------------------------------
786 787 788
void vtkLSDynaPartCollection::GetPartReadInfo(const int& partType,
  vtkIdType& numberOfCells, vtkIdType& numCellsToSkipStart,
  vtkIdType& numCellsToSkipEnd) const
789
{
790 791
  vtkIdType size = this->MaxIds[partType]-this->MinIds[partType];
  if(size<=0)
792
  {
793 794 795 796
    numberOfCells = 0;
    //skip everything
    numCellsToSkipStart = this->MetaData->NumberOfCells[partType];
    numCellsToSkipEnd = 0; //no reason to skip anything else
797
  }
798
  else
799
  {
800
    numberOfCells = size;
801 802 803
    numCellsToSkipStart = this->MinIds[partType];
    numCellsToSkipEnd = this->MetaData->NumberOfCells[partType] -
                                        (numberOfCells+numCellsToSkipStart);
804
  }
805 806
}

807 808 809
//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::FinalizeTopology()
{
810
  this->Storage->FinalizeTopology();
811 812
}

813 814 815 816 817 818 819
//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::ReadPointUserIds(const vtkIdType& numTuples,
                                        const char* name)
{
  this->SetupPointPropertyForReading(numTuples,1,name,true,true,false,false);
}

820
//-----------------------------------------------------------------------------
821 822 823 824 825 826 827
void vtkLSDynaPartCollection::ReadPointProperty(
                                        const vtkIdType& numTuples,
                                        const vtkIdType& numComps,
                                        const char* name,
                                        const bool &isProperty,
                                        const bool& isGeometryPoints,
                                        const bool& isRoadPoints)
828 829 830 831 832 833 834 835 836 837 838 839 840 841
{
  this->SetupPointPropertyForReading(numTuples,numComps,name,false,isProperty,
                                     isGeometryPoints,isRoadPoints);
}

//-----------------------------------------------------------------------------
void vtkLSDynaPartCollection::SetupPointPropertyForReading(
                                        const vtkIdType& numTuples,
                                        const vtkIdType& numComps,
                                        const char* name,
                                        const bool &isIdType,
                                        const bool &isProperty,
                                        const bool& isGeometryPoints,
                                        const bool& isRoadPoints)
842
{
843
  if ( !isProperty && !isGeometryPoints && !isRoadPoints)
844
  {
845 846 847
    // don't read arrays the user didn't request, just skip them
    this->MetaData->Fam.SkipWords(numTuples * numComps);
    return;
848
  }
849 850 851 852 853

  //If this is a geometeric point property it needs to apply
  //to the following
  //BEAM,SHELL,THICK_SHELL,SOLID,Particles
  //if it is road surface it only applies to RigidSurfaceData part types
854
  vtkLSDynaPart* part=nullptr;
855 856 857
  vtkLSDynaPart **validParts = new vtkLSDynaPart*[this->Storage->GetNumParts()];
  vtkIdType idx=0;
  if(!isRoadPoints)
858
  {
859 860 861 862 863 864 865 866
    enum LSDynaMetaData::LSDYNA_TYPES validCellTypes[5] = {
          LSDynaMetaData::PARTICLE,
          LSDynaMetaData::BEAM,
          LSDynaMetaData::SHELL,
          LSDynaMetaData::THICK_SHELL,
          LSDynaMetaData::SOLID
          };
    for(int i=0; i<5;++i)
867
    {
868 869
      this->Storage->InitPartIteration(validCellTypes[i]);
      while(this->Storage->GetNextPart(part))
870
      {
871 872
        part->AddPointProperty(name,numComps,isIdType,isProperty,
                              isGeometryPoints);
873
        validParts[idx++]=part;
874 875
      }
    }
876
  }
877
  else
878
  {
879 880 881
    //is a road point
    this->Storage->InitPartIteration(LSDynaMetaData::ROAD_SURFACE);
    while(this->Storage->GetNextPart(part))
882
    {
883 884
      part->AddPointProperty(name,numComps,isIdType,isProperty,
                            isGeometryPoints);
885
      validParts[idx++]=part;
Robert Maynard's avatar