File: TestDistributedPointCloudFilter.cxx

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 205,992 kB
  • sloc: cpp: 2,336,570; ansic: 327,116; python: 111,200; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; makefile: 185; javascript: 165; objc: 153; tcl: 59
file content (152 lines) | stat: -rw-r--r-- 5,072 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause

#include "vtkBoundingBox.h"
#include "vtkDistributedPointCloudFilter.h"
#include "vtkDoubleArray.h"
#include "vtkGenerateIds.h"
#include "vtkGenerateProcessIds.h"
#include "vtkMPICommunicator.h"
#include "vtkMPIController.h"
#include "vtkMinimalStandardRandomSequence.h"
#include "vtkNew.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkStringArray.h"

#ifdef DEBUG_ON
#include "vtkXMLPPolyDataWriter.h"
#endif

#include <sstream>

int TestDistributedPointCloudFilter(int argc, char* argv[])
{
  vtkNew<vtkMPIController> controller;
  controller->Initialize(&argc, &argv, 0);
  assert("pre: Controller should not be nullptr" && (controller != nullptr));
  vtkMultiProcessController::SetGlobalController(controller);

  const int rank = controller->GetLocalProcessId();
  const int numberOfProcessors = controller->GetNumberOfProcesses();
  assert("pre: NumberOfProcessors >= 1" && (numberOfProcessors >= 1));
  assert("pre: Rank is out-of-bounds" && (rank >= 0));

  const int finalNumberOfPointsPerRank = 40;
  const int totalNumberOfPoints = numberOfProcessors * finalNumberOfPointsPerRank;
  const int initialNumberOfPoints = totalNumberOfPoints / (numberOfProcessors > 1 ? 2 : 1);
  vtkNew<vtkPolyData> inputPoly;
  // Create random set of points on the two first ranks only
  if (rank == 0 || rank == 1)
  {
    vtkNew<vtkMinimalStandardRandomSequence> random;
    random->Initialize(rank);

    vtkNew<vtkPoints> points;
    points->SetNumberOfPoints(initialNumberOfPoints);
    inputPoly->SetPoints(points);

    vtkNew<vtkDoubleArray> data;
    data->SetNumberOfValues(initialNumberOfPoints);
    data->SetName("ReverseOrder");
    inputPoly->GetPointData()->AddArray(data);

    vtkNew<vtkStringArray> sdata;
    sdata->SetNumberOfValues(initialNumberOfPoints);
    sdata->SetName("RankString");
    inputPoly->GetPointData()->AddArray(sdata);

    std::stringstream ss;
    ss << "Rank_" << rank;

    for (vtkIdType i = 0; i < initialNumberOfPoints; i++)
    {
      double coords[3];
      coords[0] = random->GetValue();
      random->Next();
      coords[1] = random->GetValue();
      random->Next();
      coords[2] = random->GetValue();
      random->Next();
      points->SetPoint(i, coords);
      data->SetValue(i, totalNumberOfPoints - i - 1);
      sdata->SetValue(i, ss.str());
    }
  }

  // attach initial ids and process ids
  vtkNew<vtkGenerateIds> idFilter;
  idFilter->SetInputData(inputPoly);
  idFilter->SetPointIdsArrayName("OriginalId");
  idFilter->SetCellIdsArrayName("OriginalId");
  vtkNew<vtkGenerateProcessIds> procIdScalars;
  procIdScalars->SetInputConnection(idFilter->GetOutputPort());
  procIdScalars->Update();
  procIdScalars->GetPolyDataOutput()->GetPointData()->GetProcessIds()->SetName(
    "OriginalProcessIds");
  procIdScalars->GetPolyDataOutput()->GetPointData()->SetActiveAttribute(
    -1, vtkDataSetAttributes::PROCESSIDS);

  // distribute the points over the processors
  vtkNew<vtkDistributedPointCloudFilter> filter;
  filter->SetInputConnection(procIdScalars->GetOutputPort());

  // attach new process ids
  vtkNew<vtkGenerateProcessIds> outProcIdScalars;
  outProcIdScalars->SetInputConnection(filter->GetOutputPort());
  outProcIdScalars->Update();
  vtkPolyData* outputPoly = vtkPolyData::SafeDownCast(outProcIdScalars->GetOutput());

  bool error = false;
  int nbOfLocallyReceivedPoints = outputPoly->GetNumberOfPoints();
  if (nbOfLocallyReceivedPoints != finalNumberOfPointsPerRank)
  {
    cerr << "No point on the node " << rank << "\n";
    // do not exit here so MPI can end correctly
    error = true;
  }

  if (outputPoly->GetPointData()->GetNumberOfArrays() != 5)
  {
    cerr << "Incorrect number of point data arrays on rank " << rank << "\n";
    error = true;
  }

  double bounds[6];
  outputPoly->GetBounds(bounds);
  vtkBoundingBox bbox(bounds);
  if (!bbox.IsValid() || bbox.GetLength(0) == 0. || bbox.GetLength(1) == 0. ||
    bbox.GetLength(2) == 0.)
  {
    cerr << "Incorrect bounding box of output points on rank " << rank << "\n";
    error = true;
  }

  vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast(controller->GetCommunicator());
  std::vector<int> nbOfReceivedPoints(numberOfProcessors);
  com->AllGather(&nbOfLocallyReceivedPoints, nbOfReceivedPoints.data(), 1);

  int totalNumberOfReceivedPoints = 0;
  for (vtkIdType i = 0; i < numberOfProcessors; i++)
  {
    totalNumberOfReceivedPoints += nbOfReceivedPoints[i];
  }

  if (totalNumberOfReceivedPoints != totalNumberOfPoints)
  {
    cerr << "Wrong total of points: " << totalNumberOfReceivedPoints << " instead of "
         << totalNumberOfPoints << "\n";
    cerr << "Rank " << rank << ":";
    for (int i = 0; i < nbOfLocallyReceivedPoints; i++)
    {
      cout << " " << outputPoly->GetPoints()->GetPoint(i)[0];
    }
    cerr << endl;
    error = true;
  }

  controller->Finalize();

  return error ? EXIT_FAILURE : EXIT_SUCCESS;
}