File: vtkPExtractDataArraysOverTime.cxx

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-6
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 205,984 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: 181; javascript: 165; objc: 153; tcl: 59
file content (207 lines) | stat: -rw-r--r-- 6,526 bytes parent folder | download | duplicates (5)
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-FileCopyrightText: Copyright (c) Kitware, Inc.
// SPDX-License-Identifier: BSD-3-Clause
#include "vtkPExtractDataArraysOverTime.h"

#include "vtkDataSetAttributes.h"
#include "vtkInformation.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkMultiProcessController.h"
#include "vtkMultiProcessStream.h"
#include "vtkObjectFactory.h"
#include "vtkTable.h"
#include "vtkUnsignedCharArray.h"

#include <cassert>
#include <map>
#include <sstream>
#include <string>

VTK_ABI_NAMESPACE_BEGIN
namespace
{
vtkSmartPointer<vtkTable> vtkMergeTable(vtkTable* dest, vtkTable* src)
{
  if (dest == nullptr)
  {
    return src;
  }

  const auto numRows = dest->GetNumberOfRows();
  if (numRows != src->GetNumberOfRows())
  {
    return dest;
  }

  auto srcRowData = src->GetRowData();
  auto destRowData = dest->GetRowData();
  auto srcMask = vtkUnsignedCharArray::SafeDownCast(srcRowData->GetArray("vtkValidPointMask"));
  for (vtkIdType cc = 0; srcMask != nullptr && cc < numRows; ++cc)
  {
    if (srcMask->GetTypedComponent(cc, 0) == 0)
    {
      continue;
    }

    // Copy arrays from remote to current
    const int numArray = srcRowData->GetNumberOfArrays();
    for (int aidx = 0; aidx < numArray; aidx++)
    {
      auto srcArray = srcRowData->GetAbstractArray(aidx);
      if (const char* name = srcArray ? srcArray->GetName() : nullptr)
      {
        auto destArray = destRowData->GetAbstractArray(name);
        if (destArray == nullptr)
        {
          // add new array array if necessary
          destRowData->AddArray(destArray);
        }
        else
        {
          destArray->InsertTuple(cc, cc, srcArray);
        }
      }
    }
  }
  return dest;
}
}

vtkStandardNewMacro(vtkPExtractDataArraysOverTime);
vtkCxxSetObjectMacro(vtkPExtractDataArraysOverTime, Controller, vtkMultiProcessController);
//------------------------------------------------------------------------------
vtkPExtractDataArraysOverTime::vtkPExtractDataArraysOverTime()
{
  this->Controller = nullptr;
  this->SetController(vtkMultiProcessController::GetGlobalController());
}

//------------------------------------------------------------------------------
vtkPExtractDataArraysOverTime::~vtkPExtractDataArraysOverTime()
{
  this->SetController(nullptr);
}

//------------------------------------------------------------------------------
void vtkPExtractDataArraysOverTime::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Controller: " << this->Controller << endl;
}

//------------------------------------------------------------------------------
void vtkPExtractDataArraysOverTime::PostExecute(
  vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
{
  this->Superclass::PostExecute(request, inputVector, outputVector);
  if (!this->Controller || this->Controller->GetNumberOfProcesses() < 2)
  {
    return;
  }

  vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::GetData(outputVector, 0);
  assert(output);
  this->ReorganizeData(output);
}

//------------------------------------------------------------------------------
void vtkPExtractDataArraysOverTime::ReorganizeData(vtkMultiBlockDataSet* dataset)
{
  // 1. Send all blocks to 0.
  // 2. Rank 0 then reorganizes blocks. This is done as follows:
  //    i. If blocks form different ranks have same names, then we check if they
  //       are referring to the same global-id. If so, the tables are merged
  //       into one. If not, we the tables separately, with their names
  //       uniquified with rank number.
  // 3. Rank 0 send info about number blocks and their names to everyone
  // 4. Satellites, then, simply initialize their output to and make it match
  //    the structure reported by rank 0.

  const int myRank = this->Controller->GetLocalProcessId();
  const int numRanks = this->Controller->GetNumberOfProcesses();
  if (myRank != 0)
  {
    std::vector<vtkSmartPointer<vtkDataObject>> recvBuffer;
    this->Controller->Gather(dataset, recvBuffer, 0);

    vtkMultiProcessStream stream;
    this->Controller->Broadcast(stream, 0);

    dataset->Initialize();
    while (!stream.Empty())
    {
      std::string name;
      stream >> name;

      auto idx = dataset->GetNumberOfBlocks();
      dataset->SetBlock(idx, nullptr);
      dataset->GetMetaData(idx)->Set(vtkCompositeDataSet::NAME(), name.c_str());
    }
  }
  else
  {
    std::vector<vtkSmartPointer<vtkDataObject>> recvBuffer;
    this->Controller->Gather(dataset, recvBuffer, 0);

    assert(static_cast<int>(recvBuffer.size()) == numRanks);

    recvBuffer[myRank] = dataset;

    std::map<std::string, std::map<int, vtkSmartPointer<vtkTable>>> collection;
    for (int rank = 0; rank < numRanks; ++rank)
    {
      if (auto mb = vtkMultiBlockDataSet::SafeDownCast(recvBuffer[rank]))
      {
        for (unsigned int cc = 0, max = mb->GetNumberOfBlocks(); cc < max; ++cc)
        {
          const char* name = mb->GetMetaData(cc)->Get(vtkCompositeDataSet::NAME());
          vtkTable* subblock = vtkTable::SafeDownCast(mb->GetBlock(cc));
          if (name && subblock)
          {
            collection[name][rank] = subblock;
          }
        }
      }
    }

    vtkMultiProcessStream stream;
    vtkNew<vtkMultiBlockDataSet> mb;
    for (auto& item : collection)
    {
      const std::string& name = item.first;

      // as we using global ids, if so merge the tables.
      if (strncmp(name.c_str(), "gid=", 4) == 0)
      {
        vtkSmartPointer<vtkTable> mergedTable;
        for (auto& sitem : item.second)
        {
          mergedTable = vtkMergeTable(mergedTable, sitem.second);
        }

        auto idx = mb->GetNumberOfBlocks();
        mb->SetBlock(idx, mergedTable);
        mb->GetMetaData(idx)->Set(vtkCompositeDataSet::NAME(), name.c_str());
        stream << name;
      }
      else
      {
        // if not gids, then add each table separately with rank info.
        for (auto& sitem : item.second)
        {
          auto idx = mb->GetNumberOfBlocks();
          mb->SetBlock(idx, sitem.second);

          std::ostringstream str;
          str << name << " rank=" << sitem.first;
          mb->GetMetaData(idx)->Set(vtkCompositeDataSet::NAME(), str.str().c_str());
          stream << str.str();
        }
      }
    }

    this->Controller->Broadcast(stream, 0);
    dataset->CompositeShallowCopy(mb);
  } // end rank 0
}
VTK_ABI_NAMESPACE_END