ParallelIso.cxx 7.73 KB
Newer Older
1
2
3
4
5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    ParallelIso.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7
8
9
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

10
11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
13
14
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
15
16
17
18
19
20
// This example demonstrates the use of data parallelism in VTK. The
// pipeline ( vtkImageReader -> vtkContourFilter -> vtkElevationFilter )
// is created in parallel and each process is assigned 1 piece to process.
// All satellite processes send the result to the first process which
// collects and renders them.

Berk Geveci's avatar
Berk Geveci committed
21
#include "vtkActor.h"
22
23
#include "vtkAppendPolyData.h"
#include "vtkCamera.h"
24
#include "vtkConeSource.h"
25
#include "vtkContourFilter.h"
26
#include "vtkDataSet.h"
Berk Geveci's avatar
Berk Geveci committed
27
#include "vtkElevationFilter.h"
28
#include "vtkImageReader.h"
Berk Geveci's avatar
Berk Geveci committed
29
#include "vtkMath.h"
30
#include "vtkMPIController.h"
31
#include "vtkPolyData.h"
32
#include "vtkPolyDataMapper.h"
33
34
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
35
36
37
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
38
39
40
41
42
43
44
45
#include "vtkWindowToImageFilter.h"
#include "vtkImageData.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkInformation.h"

#include "vtkDebugLeaks.h"

#include <mpi.h>
Berk Geveci's avatar
Berk Geveci committed
46
47
48
49
50

static const float ISO_START=4250.0;
static const float ISO_STEP=-1250.0;
static const int ISO_NUM=3;
// Just pick a tag which is available
51
static const int ISO_VALUE_RMI_TAG=300;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
static const int ISO_OUTPUT_TAG=301;

struct ParallelIsoArgs_tmp
{
  int* retVal;
  int argc;
  char** argv;
};

struct ParallelIsoRMIArgs_tmp
{
  vtkContourFilter* ContourFilter;
  vtkMultiProcessController* Controller;
  vtkElevationFilter* Elevation;
};
Berk Geveci's avatar
Berk Geveci committed
67
68

// call back to set the iso surface value.
69
void SetIsoValueRMI(void *localArg, void* vtkNotUsed(remoteArg),
70
                    int vtkNotUsed(remoteArgLen), int vtkNotUsed(id))
71
{
72
73
  ParallelIsoRMIArgs_tmp* args = (ParallelIsoRMIArgs_tmp*)localArg;

Berk Geveci's avatar
Berk Geveci committed
74
75
  float val;

76
77
78
79
  vtkMultiProcessController* contrl = args->Controller;
  int myid = contrl->GetLocalProcessId();
  int numProcs = contrl->GetNumberOfProcesses();

80
  vtkContourFilter *iso = args->ContourFilter;
Berk Geveci's avatar
Berk Geveci committed
81
82
  val = iso->GetValue(0);
  iso->SetValue(0, val + ISO_STEP);
83
  args->Elevation->UpdatePiece(myid, numProcs, 0);
84
85

  contrl->Send(args->Elevation->GetOutput(), 0, ISO_OUTPUT_TAG);
Berk Geveci's avatar
Berk Geveci committed
86
87
88
89
90
91
92
93
94
95
96
}


// This will be called by all processes
void MyMain( vtkMultiProcessController *controller, void *arg )
{
  vtkImageReader *reader;
  vtkContourFilter *iso;
  vtkElevationFilter *elev;
  int myid, numProcs;
  float val;
97
  ParallelIsoArgs_tmp* args = reinterpret_cast<ParallelIsoArgs_tmp*>(arg);
98

Berk Geveci's avatar
Berk Geveci committed
99
100
101
102
  // Obtain the id of the running process and the total
  // number of processes
  myid = controller->GetLocalProcessId();
  numProcs = controller->GetNumberOfProcesses();
103

Berk Geveci's avatar
Berk Geveci committed
104
105
  // Create the reader, the data file name might have
  // to be changed depending on where the data files are.
106
  char* fname = vtkTestUtilities::ExpandDataFileName(args->argc, args->argv,
107
                                                     "Data/headsq/quarter");
Berk Geveci's avatar
Berk Geveci committed
108
109
  reader = vtkImageReader::New();
  reader->SetDataByteOrderToLittleEndian();
110
111
112
  reader->SetDataExtent(0, 63, 0, 63, 1, 93);
  reader->SetFilePrefix(fname);
  reader->SetDataSpacing(3.2, 3.2, 1.5);
113
  delete[] fname;
Berk Geveci's avatar
Berk Geveci committed
114
115
116

  // Iso-surface.
  iso = vtkContourFilter::New();
117
  iso->SetInputConnection(reader->GetOutputPort());
Berk Geveci's avatar
Berk Geveci committed
118
119
120
  iso->SetValue(0, ISO_START);
  iso->ComputeScalarsOff();
  iso->ComputeGradientsOff();
121

Berk Geveci's avatar
Berk Geveci committed
122
123
  // Compute a different color for each process.
  elev = vtkElevationFilter::New();
124
  elev->SetInputConnection(iso->GetOutputPort());
125
  val = (myid+1) / static_cast<float>(numProcs);
Berk Geveci's avatar
Berk Geveci committed
126
127
128
129
130
  elev->SetScalarRange(val, val+0.001);

  if (myid != 0)
    {
    // If I am not the root process
131
132
133
134
    ParallelIsoRMIArgs_tmp args2;
    args2.ContourFilter = iso;
    args2.Controller = controller;
    args2.Elevation = elev;
Berk Geveci's avatar
Berk Geveci committed
135
136
137
138

    // Last, set up a RMI call back to change the iso surface value.
    // This is done so that the root process can let this process
    // know that it wants the contour value to change.
139
    controller->AddRMI(SetIsoValueRMI, (void *)&args2, ISO_VALUE_RMI_TAG);
140
    controller->ProcessRMIs();
Berk Geveci's avatar
Berk Geveci committed
141
142
143
    }
  else
    {
144
    // Create the rendering part of the pipeline
Berk Geveci's avatar
Berk Geveci committed
145
146
147
148
149
150
151
152
153
154
155
    vtkAppendPolyData *app = vtkAppendPolyData::New();
    vtkRenderer *ren = vtkRenderer::New();
    vtkRenderWindow *renWindow = vtkRenderWindow::New();
    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
    vtkActor *actor = vtkActor::New();
    vtkCamera *cam = vtkCamera::New();
    renWindow->AddRenderer(ren);
    iren->SetRenderWindow(renWindow);
    ren->SetBackground(0.9, 0.9, 0.9);
    renWindow->SetSize( 400, 400);
156
    mapper->SetInputConnection(app->GetOutputPort());
Berk Geveci's avatar
Berk Geveci committed
157
158
159
160
161
162
163
164
    actor->SetMapper(mapper);
    ren->AddActor(actor);
    cam->SetFocalPoint(100, 100, 65);
    cam->SetPosition(100, 450, 65);
    cam->SetViewUp(0, 0, -1);
    cam->SetViewAngle(30);
    cam->SetClippingRange(177.0, 536.0);
    ren->SetActiveCamera(cam);
165

Berk Geveci's avatar
Berk Geveci committed
166
    // loop through some iso surface values.
167
    for (int j = 0; j < ISO_NUM; ++j)
Berk Geveci's avatar
Berk Geveci committed
168
169
      {
      // set the local value
170
      iso->SetValue(0, iso->GetValue(0) + ISO_STEP);
171
      elev->UpdatePiece(myid, numProcs, 0);
172
173

      for (int i = 1; i < numProcs; ++i)
Brad King's avatar
Brad King committed
174
175
        {
        // trigger the RMI to change the iso surface value.
176
        controller->TriggerRMI(i, ISO_VALUE_RMI_TAG);
Brad King's avatar
Brad King committed
177
        }
178
179
180
181
182
183
      for (int i = 1; i < numProcs; ++i)
        {
        vtkPolyData* pd = vtkPolyData::New();
        controller->Receive(pd, i, ISO_OUTPUT_TAG);
        if (j == ISO_NUM - 1)
          {
184
          app->AddInputData(pd);
185
186
187
          }
        pd->Delete();
        }
Berk Geveci's avatar
Berk Geveci committed
188
189
190
      }

    // Tell the other processors to stop processing RMIs.
191
    for (int i = 1; i < numProcs; ++i)
Berk Geveci's avatar
Berk Geveci committed
192
      {
193
      controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG);
Berk Geveci's avatar
Berk Geveci committed
194
      }
195
196
197

    vtkPolyData* outputCopy = vtkPolyData::New();
    outputCopy->ShallowCopy(elev->GetOutput());
198
    app->AddInputData(outputCopy);
199
200
201
202
    outputCopy->Delete();
    app->Update();
    renWindow->Render();

203
    *(args->retVal) =
204
205
206
207
208
209
210
      vtkRegressionTester::Test(args->argc, args->argv, renWindow, 10);

    if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR)
      {
      iren->Start();
      }

Berk Geveci's avatar
Berk Geveci committed
211
212
213
214
215
216
217
    // Clean up
    app->Delete();
    ren->Delete();
    renWindow->Delete();
    iren->Delete();
    mapper->Delete();
    actor->Delete();
218
    cam->Delete();
Berk Geveci's avatar
Berk Geveci committed
219
    }
220

Berk Geveci's avatar
Berk Geveci committed
221
222
223
224
225
226
227
  // clean up objects in all processes.
  reader->Delete();
  iso->Delete();
  elev->Delete();
}


228
int main( int argc, char* argv[] )
Berk Geveci's avatar
Berk Geveci committed
229
{
230
231
232
233
234
235
  // This is here to avoid false leak messages from vtkDebugLeaks when
  // using mpich. It appears that the root process which spawns all the
  // main processes waits in MPI_Init() and calls exit() when
  // the others are done, causing apparent memory leaks for any objects
  // created before MPI_Init().
  MPI_Init(&argc, &argv);
Berk Geveci's avatar
Berk Geveci committed
236
237
238

  // Note that this will create a vtkMPIController if MPI
  // is configured, vtkThreadedController otherwise.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  vtkMPIController* controller = vtkMPIController::New();

  controller->Initialize(&argc, &argv, 1);

  // Added for regression test.
  // ----------------------------------------------
  int retVal = 1;
  ParallelIsoArgs_tmp args;
  args.retVal = &retVal;
  args.argc = argc;
  args.argv = argv;
  // ----------------------------------------------

  controller->SetSingleMethod(MyMain, &args);
Berk Geveci's avatar
Berk Geveci committed
253
  controller->SingleMethodExecute();
254

Berk Geveci's avatar
Berk Geveci committed
255
256
  controller->Finalize();
  controller->Delete();
257

258
  return !retVal;
Berk Geveci's avatar
Berk Geveci committed
259
260
261
262
263
264
}