1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    ParallelResampling.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 // Tests ParallelResampling.
17 
18 /*
19 ** This test only builds if MPI is in use
20 */
21 #include "vtkDataArray.h"
22 #include "vtkDataObject.h"
23 #include "vtkPolyDataMapper.h"
24 #include "vtkDebugLeaks.h"
25 #include "vtkFloatArray.h"
26 #include "vtkImageData.h"
27 #include "vtkMPICommunicator.h"
28 #include "vtkMPIController.h"
29 #include "vtkNew.h"
30 #include "vtkObjectFactory.h"
31 #include "vtkPResampleFilter.h"
32 #include "vtkPointData.h"
33 #include "vtkProcess.h"
34 #include "vtkRTAnalyticSource.h"
35 #include "vtkTestUtilities.h"
36 #include "vtkDataSetSurfaceFilter.h"
37 #include <mpi.h>
38 
39 namespace
40 {
41 
42 class MyProcess : public vtkProcess
43 {
44 public:
45   static MyProcess *New();
46   vtkTypeMacro(MyProcess, vtkProcess);
47 
48   virtual void Execute();
49 
50   void SetArgs(int anArgc,
51                char *anArgv[]);
52 
53 protected:
54   MyProcess();
55 
56   int Argc;
57   char **Argv;
58 };
59 
60 vtkStandardNewMacro(MyProcess);
61 
MyProcess()62 MyProcess::MyProcess()
63 {
64   this->Argc=0;
65   this->Argv=0;
66 }
67 
SetArgs(int anArgc,char * anArgv[])68 void MyProcess::SetArgs(int anArgc,
69                         char *anArgv[])
70 {
71   this->Argc=anArgc;
72   this->Argv=anArgv;
73 }
74 
Execute()75 void MyProcess::Execute()
76 {
77   this->ReturnValue=1;
78   int numProcs=this->Controller->GetNumberOfProcesses();
79   int me=this->Controller->GetLocalProcessId();
80   cout << "Nb process found: " << numProcs << endl;
81 
82   // Create and execute pipeline
83   vtkNew<vtkRTAnalyticSource> wavelet;
84   vtkNew<vtkPResampleFilter> sampler;
85   vtkNew<vtkDataSetSurfaceFilter> toPolyData;
86   vtkNew<vtkPolyDataMapper> mapper;
87 
88   sampler->SetInputConnection(wavelet->GetOutputPort());
89   sampler->SetSamplingDimension(21,21,21); // 21 for perfect match with wavelet default extent
90   //sampler->SetUseInputBounds(0);
91   //sampler->SetCustomSamplingBounds(-10, 10, -10, 10, -10, 10);
92 
93   toPolyData->SetInputConnection(sampler->GetOutputPort());
94 
95   mapper->SetInputConnection(toPolyData->GetOutputPort());
96   mapper->SetScalarRange(0, numProcs);
97   mapper->SetPiece(me);
98   mapper->SetNumberOfPieces(numProcs);
99   mapper->Update();
100 
101   cout << "Got for Wavelet " << wavelet->GetOutput()->GetNumberOfPoints() << " points on process " << me << endl;
102   cout << "Got for Surface " << toPolyData->GetOutput()->GetNumberOfPoints() << " points on process " << me << endl;
103 
104   if (me == 0)
105     {
106     // Only root node compare the standard Wavelet data with the probed one
107     vtkNew<vtkRTAnalyticSource> waveletBase1Piece;
108     waveletBase1Piece->Update();
109     vtkImageData *reference = waveletBase1Piece->GetOutput();
110     vtkImageData *result = sampler->GetOutput();
111 
112     // Compare RTData Array
113     vtkFloatArray* rtDataRef = vtkFloatArray::SafeDownCast(reference->GetPointData()->GetArray("RTData"));
114     vtkFloatArray* rtDataTest = vtkFloatArray::SafeDownCast(result->GetPointData()->GetArray("RTData"));
115     vtkIdType sizeRef = rtDataRef->GetNumberOfTuples();
116     if(sizeRef == rtDataTest->GetNumberOfTuples() && rtDataRef->GetNumberOfComponents() == 1)
117       {
118       for(vtkIdType idx = 0; idx < sizeRef; ++idx)
119         {
120         if(rtDataRef->GetValue(idx) != rtDataTest->GetValue(idx))
121           {
122           this->ReturnValue = 0;
123           return;
124           }
125         }
126       return; // OK
127       }
128 
129     this->ReturnValue = 0;
130     }
131   else
132     {
133     if(sampler->GetOutput()->GetNumberOfPoints() != 0 || wavelet->GetOutput()->GetNumberOfPoints() == 0)
134       {
135       this->ReturnValue = 0;
136       }
137     }
138 }
139 
140 }
141 
ParallelResampling(int argc,char * argv[])142 int ParallelResampling(int argc, char *argv[])
143 {
144   // This is here to avoid false leak messages from vtkDebugLeaks when
145   // using mpich. It appears that the root process which spawns all the
146   // main processes waits in MPI_Init() and calls exit() when
147   // the others are done, causing apparent memory leaks for any objects
148   // created before MPI_Init().
149   MPI_Init(&argc, &argv);
150 
151   // Note that this will create a vtkMPIController if MPI
152   // is configured, vtkThreadedController otherwise.
153   vtkMPIController *contr = vtkMPIController::New();
154   contr->Initialize(&argc, &argv, 1);
155 
156   int retVal = 1;
157 
158   vtkMultiProcessController::SetGlobalController(contr);
159 
160   int me = contr->GetLocalProcessId();
161 
162   if (!contr->IsA("vtkMPIController"))
163     {
164     if (me == 0)
165       {
166       cout << "DistributedData test requires MPI" << endl;
167       }
168     contr->Delete();
169     return retVal;   // is this the right error val?   TODO
170     }
171 
172   MyProcess *p=MyProcess::New();
173   p->SetArgs(argc,argv);
174   contr->SetSingleProcessObject(p);
175   contr->SingleMethodExecute();
176 
177   retVal=p->GetReturnValue();
178   p->Delete();
179 
180   contr->Finalize();
181   contr->Delete();
182 
183   return !retVal;
184 }
185