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