1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPLSDynaReader.cxx
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 // NOTE TO DEVELOPERS: ========================================================
21 //
22 // This is a parallel version of the LSDynaReader.
23 // Its primary tasks are to determine which parts should be read on each process
24 // and to send the relevant information from the master node to all slave nodes
25
26 #include "vtkPLSDynaReader.h"
27 #include "LSDynaFamily.h"
28 #include "LSDynaMetaData.h"
29 #include "vtkLSDynaPartCollection.h"
30
31 #include "vtkInformation.h"
32 #include "vtkInformationVector.h"
33 #include "vtkIntArray.h"
34 #include "vtkMultiBlockDataSet.h"
35 #include "vtkMultiProcessController.h"
36 #include "vtkObjectFactory.h"
37 #include "vtkStreamingDemandDrivenPipeline.h"
38 #include "vtkUnstructuredGrid.h"
39
40 vtkStandardNewMacro(vtkPLSDynaReader);
41
42 struct vtkPLSDynaReader::vtkPLSDynaReaderInternal
43 {
44 unsigned int MinDataset;
45 unsigned int MaxDataset;
46 unsigned int UpdatePiece;
47 unsigned int UpdateNumPieces;
48
49 vtkIdType NumProcesses;
50 vtkIdType ProcessRank;
51
vtkPLSDynaReaderInternalvtkPLSDynaReader::vtkPLSDynaReaderInternal52 vtkPLSDynaReaderInternal()
53 : MinDataset(0)
54 , MaxDataset(0)
55 , UpdatePiece(0)
56 , UpdateNumPieces(0)
57 {
58 }
59 };
60
61 //------------------------------------------------------------------------------
vtkPLSDynaReader()62 vtkPLSDynaReader::vtkPLSDynaReader()
63 {
64 this->Controller = nullptr;
65
66 // need to construct the internal datastructure before call SetController
67 this->Internal = new vtkPLSDynaReader::vtkPLSDynaReaderInternal();
68 this->SetController(vtkMultiProcessController::GetGlobalController());
69 }
70
71 //------------------------------------------------------------------------------
~vtkPLSDynaReader()72 vtkPLSDynaReader::~vtkPLSDynaReader()
73 {
74 this->SetController(nullptr);
75
76 delete this->Internal;
77 }
78
PrintSelf(ostream & os,vtkIndent indent)79 void vtkPLSDynaReader::PrintSelf(ostream& os, vtkIndent indent)
80 {
81 os << indent << "Controller: " << this->Controller << endl;
82 this->Superclass::PrintSelf(os, indent);
83 }
84
85 //------------------------------------------------------------------------------
SetController(vtkMultiProcessController * c)86 void vtkPLSDynaReader::SetController(vtkMultiProcessController* c)
87 {
88 if ((c == nullptr) || (c->GetNumberOfProcesses() == 0))
89 {
90 this->Internal->NumProcesses = 1;
91 this->Internal->ProcessRank = 0;
92 }
93
94 if (this->Controller == c)
95 {
96 return;
97 }
98
99 this->Modified();
100
101 if (this->Controller)
102 {
103 this->Controller->UnRegister(this);
104 this->Controller = nullptr;
105 }
106
107 if (c == nullptr)
108 {
109 return;
110 }
111
112 this->Controller = c;
113
114 c->Register(this);
115 this->Internal->NumProcesses = c->GetNumberOfProcesses();
116 this->Internal->ProcessRank = c->GetLocalProcessId();
117 }
118
119 //------------------------------------------------------------------------------
CanReadFile(const char * fname)120 int vtkPLSDynaReader::CanReadFile(const char* fname)
121 {
122 return this->Superclass::CanReadFile(fname);
123 }
124
125 //------------------------------------------------------------------------------
RequestInformation(vtkInformation * request,vtkInformationVector ** iinfo,vtkInformationVector * outputVector)126 int vtkPLSDynaReader::RequestInformation(
127 vtkInformation* request, vtkInformationVector** iinfo, vtkInformationVector* outputVector)
128 {
129 vtkInformation* outInfo = outputVector->GetInformationObject(0);
130
131 // call the parents request information on all the nodes.
132 // This is not optimal, but sooo much information is stored in the
133 // metadata that is read during request information that sending it over the wire
134 // might not be faster than each node contending for the info. Plus it would
135 // be a massive chunk of code
136 this->Superclass::RequestInformation(request, iinfo, outputVector);
137
138 outInfo->Set(CAN_HANDLE_PIECE_REQUEST(), 1);
139 return 1;
140 }
141
142 //------------------------------------------------------------------------------
RequestData(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)143 int vtkPLSDynaReader::RequestData(
144 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
145 {
146 // get the information needed to determine which subsection of the full
147 // data set we need to load
148 vtkInformation* outInfo = outputVector->GetInformationObject(0);
149 this->Internal->UpdatePiece =
150 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
151 this->Internal->UpdateNumPieces =
152 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
153
154 return this->Superclass::RequestData(request, inputVector, outputVector);
155 }
156
157 //------------------------------------------------------------------------------
ReadTopology()158 int vtkPLSDynaReader::ReadTopology()
159 {
160 bool readTopology = false;
161 if (!this->Parts)
162 {
163 readTopology = true;
164 this->Parts = vtkLSDynaPartCollection::New();
165 vtkIdType* minCellIds = new vtkIdType[LSDynaMetaData::NUM_CELL_TYPES];
166 vtkIdType* maxCellIds = new vtkIdType[LSDynaMetaData::NUM_CELL_TYPES];
167 this->GetPartRanges(minCellIds, maxCellIds);
168
169 this->Parts->InitCollection(this->P, minCellIds, maxCellIds);
170 delete[] minCellIds;
171 delete[] maxCellIds;
172 }
173 if (!readTopology)
174 {
175 return 0;
176 }
177
178 if (this->ReadPartSizes())
179 {
180 vtkErrorMacro("Could not read cell sizes.");
181 return 1;
182 }
183
184 if (this->ReadConnectivityAndMaterial())
185 {
186 vtkErrorMacro("Could not read connectivity.");
187 return 1;
188 }
189
190 // finalize the topology on each process, each process will remove
191 // any part that it doesn't have a cell for.
192 this->Parts->FinalizeTopology();
193
194 if (this->ReadNodes())
195 {
196 vtkErrorMacro("Could not read static node values.");
197 return 1;
198 }
199
200 // we need to read the user ids after we have read the topology
201 // so we know how many cells are in each part
202 if (this->ReadUserIds())
203 {
204 vtkErrorMacro("Could not read user node/element IDs.");
205 return 1;
206 }
207
208 return 0;
209 }
210
211 //------------------------------------------------------------------------------
212 // determine which parts will be read by this processor
GetPartRanges(vtkIdType * mins,vtkIdType * maxs)213 void vtkPLSDynaReader::GetPartRanges(vtkIdType* mins, vtkIdType* maxs)
214 {
215 // 1 == load the whole data
216 // determine which domains in this mesh this processor is responsible for
217 if (this->Internal->UpdateNumPieces > 1)
218 {
219 double numCells;
220 for (int i = 0; i < LSDynaMetaData::NUM_CELL_TYPES; ++i)
221 {
222 numCells = static_cast<double>(this->P->NumberOfCells[i]);
223 if (numCells > 1000)
224 {
225 double percent = (1.0 / this->Internal->UpdateNumPieces) * numCells;
226 mins[i] = static_cast<vtkIdType>(percent * this->Internal->UpdatePiece);
227 maxs[i] = static_cast<vtkIdType>(percent * (this->Internal->UpdatePiece + 1));
228 }
229 else
230 {
231 // else not enough cells to worth dividing the reading
232 mins[i] = 0;
233 maxs[i] = static_cast<vtkIdType>((this->Internal->ProcessRank == 0) ? numCells : 0);
234 }
235 }
236 }
237 else
238 {
239 for (int i = 0; i < LSDynaMetaData::NUM_CELL_TYPES; ++i)
240 {
241 mins[i] = 0;
242 maxs[i] = this->P->NumberOfCells[i];
243 }
244 }
245 }
246