1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: GenericCommunicator.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 #include <vtk_mpi.h>
16
17 #include "vtkActor.h"
18 #include "vtkCallbackCommand.h"
19 #include "vtkCharArray.h"
20 #include "vtkContourFilter.h"
21 #include "vtkDebugLeaks.h"
22 #include "vtkDoubleArray.h"
23 #include "vtkFloatArray.h"
24 #include "vtkIdTypeArray.h"
25 #include "vtkImageData.h"
26 #include "vtkIntArray.h"
27 #include "vtkMPIController.h"
28 #include "vtkNew.h"
29 #include "vtkPolyData.h"
30 #include "vtkPolyDataMapper.h"
31 #include "vtkRTAnalyticSource.h"
32 #include "vtkRenderWindow.h"
33 #include "vtkRenderWindowInteractor.h"
34 #include "vtkRenderer.h"
35 #include "vtkSphereSource.h"
36 #include "vtkUnsignedLongArray.h"
37
38 #include "vtkDebugLeaks.h"
39 #include "vtkRegressionTestImage.h"
40
41 static const int scMsgLength = 10;
42
43 struct GenericCommunicatorArgs_tmp
44 {
45 int* retVal;
46 int argc;
47 char** argv;
48 };
49
Process2(vtkMultiProcessController * contr,void * vtkNotUsed (arg))50 void Process2(vtkMultiProcessController* contr, void* vtkNotUsed(arg))
51 {
52 vtkCommunicator* comm = contr->GetCommunicator();
53
54 int i, retVal = 1;
55
56 // Test receiving all supported types of arrays
57 vtkIntArray* ia = vtkIntArray::New();
58 if (!comm->Receive(ia, 0, 11))
59 {
60 cerr << "Server error: Error receiving data." << endl;
61 retVal = 0;
62 }
63 for (i = 0; i < ia->GetNumberOfTuples(); i++)
64 {
65 if (ia->GetValue(i) != i)
66 {
67 cerr << "Server error: Corrupt integer array." << endl;
68 retVal = 0;
69 break;
70 }
71 }
72 ia->Delete();
73
74 vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New();
75 if (!comm->Receive(ula, 0, 22))
76 {
77 cerr << "Server error: Error receiving data." << endl;
78 retVal = 0;
79 }
80 for (i = 0; i < ula->GetNumberOfTuples(); i++)
81 {
82 if (ula->GetValue(i) != static_cast<unsigned long>(i))
83 {
84 cerr << "Server error: Corrupt unsigned long array." << endl;
85 retVal = 0;
86 break;
87 }
88 }
89 ula->Delete();
90
91 vtkCharArray* ca = vtkCharArray::New();
92 if (!comm->Receive(ca, 0, 33))
93 {
94 cerr << "Server error: Error receiving data." << endl;
95 retVal = 0;
96 }
97 for (i = 0; i < ca->GetNumberOfTuples(); i++)
98 {
99 if (ca->GetValue(i) != static_cast<char>(i))
100 {
101 cerr << "Server error: Corrupt char array." << endl;
102 retVal = 0;
103 break;
104 }
105 }
106 ca->Delete();
107
108 vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New();
109 if (!comm->Receive(uca, 0, 44))
110 {
111 cerr << "Server error: Error receiving data." << endl;
112 retVal = 0;
113 }
114 for (i = 0; i < uca->GetNumberOfTuples(); i++)
115 {
116 if (uca->GetValue(i) != static_cast<unsigned char>(i))
117 {
118 cerr << "Server error: Corrupt unsigned char array." << endl;
119 retVal = 0;
120 break;
121 }
122 }
123 uca->Delete();
124
125 vtkFloatArray* fa = vtkFloatArray::New();
126 if (!comm->Receive(fa, 0, 7))
127 {
128 cerr << "Server error: Error receiving data." << endl;
129 retVal = 0;
130 }
131 for (i = 0; i < fa->GetNumberOfTuples(); i++)
132 {
133 if (fa->GetValue(i) != static_cast<float>(i))
134 {
135 cerr << "Server error: Corrupt float array." << endl;
136 retVal = 0;
137 break;
138 }
139 }
140 fa->Delete();
141
142 vtkDoubleArray* da = vtkDoubleArray::New();
143 if (!comm->Receive(da, 0, 7))
144 {
145 cerr << "Server error: Error receiving data." << endl;
146 retVal = 0;
147 }
148 for (i = 0; i < da->GetNumberOfTuples(); i++)
149 {
150 if (da->GetValue(i) != static_cast<double>(i))
151 {
152 cerr << "Server error: Corrupt double array." << endl;
153 retVal = 0;
154 break;
155 }
156 }
157 da->Delete();
158
159 vtkIdTypeArray* ita = vtkIdTypeArray::New();
160 if (!comm->Receive(ita, 0, 7))
161 {
162 cerr << "Server error: Error receiving data." << endl;
163 retVal = 0;
164 }
165 for (i = 0; i < ita->GetNumberOfTuples(); i++)
166 {
167 if (ita->GetValue(i) != static_cast<vtkIdType>(i))
168 {
169 cerr << "Server error: Corrupt vtkIdType array." << endl;
170 retVal = 0;
171 break;
172 }
173 }
174 ita->Delete();
175
176 vtkNew<vtkSphereSource> sphereSource;
177 sphereSource->Update();
178 std::vector<vtkSmartPointer<vtkDataObject>> rdata;
179 if (!comm->Gather(sphereSource->GetOutputDataObject(0), rdata, 0))
180 {
181 cerr << "Server error: Error gathering data." << endl;
182 retVal = 0;
183 }
184 rdata.clear();
185 if (!comm->Gather(sphereSource->GetOutputDataObject(0), rdata, 0))
186 {
187 cerr << "Server error: Error gathering data." << endl;
188 retVal = 0;
189 }
190
191 comm->Send(&retVal, 1, 0, 11);
192 }
193
Process1(vtkMultiProcessController * contr,void * arg)194 void Process1(vtkMultiProcessController* contr, void* arg)
195 {
196 GenericCommunicatorArgs_tmp* args = reinterpret_cast<GenericCommunicatorArgs_tmp*>(arg);
197
198 vtkCommunicator* comm = contr->GetCommunicator();
199
200 int i;
201
202 // Test sending all supported types of arrays
203 int datai[scMsgLength];
204 for (i = 0; i < scMsgLength; i++)
205 {
206 datai[i] = i;
207 }
208 vtkIntArray* ia = vtkIntArray::New();
209 ia->SetArray(datai, 10, 1);
210 if (!comm->Send(ia, 1, 11))
211 {
212 cerr << "Client error: Error sending data." << endl;
213 *(args->retVal) = 0;
214 }
215 ia->Delete();
216
217 unsigned long dataul[scMsgLength];
218 for (i = 0; i < scMsgLength; i++)
219 {
220 dataul[i] = static_cast<unsigned long>(i);
221 }
222 vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New();
223 ula->SetArray(dataul, 10, 1);
224 if (!comm->Send(ula, 1, 22))
225 {
226 cerr << "Client error: Error sending data." << endl;
227 *(args->retVal) = 0;
228 }
229 ula->Delete();
230
231 char datac[scMsgLength];
232 for (i = 0; i < scMsgLength; i++)
233 {
234 datac[i] = static_cast<char>(i);
235 }
236 vtkCharArray* ca = vtkCharArray::New();
237 ca->SetArray(datac, 10, 1);
238 if (!comm->Send(ca, 1, 33))
239 {
240 cerr << "Client error: Error sending data." << endl;
241 *(args->retVal) = 0;
242 }
243 ca->Delete();
244
245 unsigned char datauc[scMsgLength];
246 for (i = 0; i < scMsgLength; i++)
247 {
248 datauc[i] = static_cast<unsigned char>(i);
249 }
250 vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New();
251 uca->SetArray(datauc, 10, 1);
252 if (!comm->Send(uca, 1, 44))
253 {
254 cerr << "Client error: Error sending data." << endl;
255 *(args->retVal) = 0;
256 }
257 uca->Delete();
258
259 float dataf[scMsgLength];
260 for (i = 0; i < scMsgLength; i++)
261 {
262 dataf[i] = static_cast<float>(i);
263 }
264 vtkFloatArray* fa = vtkFloatArray::New();
265 fa->SetArray(dataf, 10, 1);
266 if (!comm->Send(fa, 1, 7))
267 {
268 cerr << "Client error: Error sending data." << endl;
269 *(args->retVal) = 0;
270 }
271 fa->Delete();
272
273 double datad[scMsgLength];
274 for (i = 0; i < scMsgLength; i++)
275 {
276 datad[i] = static_cast<double>(i);
277 }
278 vtkDoubleArray* da = vtkDoubleArray::New();
279 da->SetArray(datad, 10, 1);
280 if (!comm->Send(da, 1, 7))
281 {
282 cerr << "Client error: Error sending data." << endl;
283 *(args->retVal) = 0;
284 }
285 da->Delete();
286
287 vtkIdType datait[scMsgLength];
288 for (i = 0; i < scMsgLength; i++)
289 {
290 datait[i] = static_cast<vtkIdType>(i);
291 }
292 vtkIdTypeArray* ita = vtkIdTypeArray::New();
293 ita->SetArray(datait, 10, 1);
294 if (!comm->Send(ita, 1, 7))
295 {
296 cerr << "Client error: Error sending data." << endl;
297 *(args->retVal) = 0;
298 }
299 ita->Delete();
300
301 vtkNew<vtkSphereSource> sphereSource;
302 sphereSource->Update();
303 std::vector<vtkSmartPointer<vtkDataObject>> rdata;
304 if (!comm->Gather(sphereSource->GetOutputDataObject(0), rdata, 0))
305 {
306 cerr << "Client error: Error gathering data." << endl;
307 *(args->retVal) = 0;
308 }
309 if (rdata.size() == 2 && vtkPolyData::SafeDownCast(rdata[0]) &&
310 vtkPolyData::SafeDownCast(rdata[1]))
311 {
312 }
313 else
314 {
315 cerr << "Client error: Error gathering data (invalid data received)." << endl;
316 *(args->retVal) = 0;
317 }
318 rdata.clear();
319 if (!comm->Gather(nullptr, rdata, 0))
320 {
321 cerr << "Client error: Error gathering data." << endl;
322 *(args->retVal) = 0;
323 }
324 if (rdata.size() == 2 && rdata[0] == nullptr && vtkPolyData::SafeDownCast(rdata[1]))
325 {
326 }
327 else
328 {
329 cerr << "Client error: Error gathering data (invalid data received)." << endl;
330 *(args->retVal) = 0;
331 }
332
333 int remoteRetVal;
334 comm->Receive(&remoteRetVal, 1, 1, 11);
335 if (!remoteRetVal)
336 {
337 *(args->retVal) = 0;
338 }
339 }
340
GenericCommunicator(int argc,char * argv[])341 int GenericCommunicator(int argc, char* argv[])
342 {
343 // This is here to avoid false leak messages from vtkDebugLeaks when
344 // using mpich. It appears that the root process which spawns all the
345 // main processes waits in MPI_Init() and calls exit() when
346 // the others are done, causing apparent memory leaks for any objects
347 // created before MPI_Init().
348 MPI_Init(&argc, &argv);
349
350 vtkMPIController* contr = vtkMPIController::New();
351 contr->Initialize(&argc, &argv, 1);
352 contr->CreateOutputWindow();
353
354 // Added for regression test.
355 // ----------------------------------------------
356 int retVal = 1;
357 GenericCommunicatorArgs_tmp args;
358 args.retVal = &retVal;
359 args.argc = argc;
360 args.argv = argv;
361 // ----------------------------------------------
362
363 contr->SetMultipleMethod(0, Process1, &args);
364 contr->SetMultipleMethod(1, Process2, nullptr);
365 contr->MultipleMethodExecute();
366
367 contr->Finalize();
368 contr->Delete();
369
370 return !retVal;
371 }
372