c++ - VTK 和 MPI : plot distributed data

标签 c++ animation mpi vtk

经过一些研究,我无法弄清楚将 VTK 与 MPI 结合使用以可视化分布式数据的最佳方式是什么。

我要绘制的数据是立方体中的一组移动点(如果这有帮助,我们知道边界)。这组点会在每次迭代时更新,而且可能会很大。目前我们真的不知道我们的实现将如何扩展,但目标是能够处理尽可能多的点。

以下是我在研究中发现的并行绘图的 2 种方法:

  1. 使用 vtkMultiProcessController .这种方法似乎相当复杂,我找到的唯一“文档”是类文档和 an example .这可能足以使用这个类(class),但我认为这会占用我太多时间。

  2. 使用 VTK 并行格式,如 link .这个选项似乎更容易使用,并不是真正的干扰,而且可能(?)比前一个更快。

我的问题是:

  • 是否有任何其他方法可用于有效地绘制分布式点集?
  • 哪种方法最适合绘制我的数据集?
  • (附带问题)VTK(用于创建文件)和 Paraview(用于查看动画)支持绘制此类动画的最佳格式是什么?

非常感谢您的宝贵时间!

最佳答案

我认为第一种方法更可靠,因为我花了很多时间使用第二种方法,但无法从中得到正确的结果。正如您所说,VTK 类没有很好的文档,尤其是像 vtkXMLPStructuredGridWriter 这样的并行类。

对了,我建议你使用第一种方法。但是,而不是使用 vtkMultiProcessController , 使用 vtkMPIController它派生自 vtkMultiProcessController 类。最近,我为 Structured Grid 写了一个示例,通过做一些更改,您可以将它用于您自己的应用程序:

// MPI Library
#include <mpi.h>

//VTK Library
#include <vtkXMLPStructuredGridWriter.h>
#include <vtkStructuredGrid.h>
#include <vtkSmartPointer.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkMPIController.h>
#include <vtkProgrammableFilter.h>
#include <vtkInformation.h>

struct Args {
  vtkProgrammableFilter* pf;
  int local_extent[6];
};

// function to operate on the point attribute data
void execute (void* arg) {
  Args* args = reinterpret_cast<Args*>(arg);
  auto info = args->pf->GetOutputInformation(0);
  auto output_tmp = args->pf->GetOutput();  // this is a vtkDataObject*
  auto input_tmp  = args->pf->GetInput();   // this is a vtkDataObject*
  vtkStructuredGrid* output = dynamic_cast<vtkStructuredGrid*>(output_tmp);
  vtkStructuredGrid* input  = dynamic_cast<vtkStructuredGrid*>(input_tmp);
  output->ShallowCopy(input);
  output->SetExtent(args->local_extent);
}

int main (int argc, char *argv[]) {
  MPI_Init (&argc, &argv);
  int myrank;
  MPI_Comm_rank (MPI_COMM_WORLD, &myrank);

  int lx {10}, ly{10}, lz{10};        //local dimensions of the process's grid
  int dims[3] = {lx+1, ly+1, lz+1};
  int global_extent[6] = {0, 2*lx, 0, ly, 0, lz};
  int local_extent[6] = {myrank*lx, (myrank+1)*lx, 0, ly, 0, lz};

  // Create and Initialize vtkMPIController
  auto contr = vtkSmartPointer<vtkMPIController>::New();
  contr->Initialize(&argc, &argv, 1);
  int nranks = contr->GetNumberOfProcesses();
  int rank   = contr->GetLocalProcessId();

  // Create grid points, allocate memory and Insert them
  auto points = vtkSmartPointer<vtkPoints>::New();
  points->Allocate(dims[0]*dims[1]*dims[2]);
  for (int k=0; k<dims[2]; ++k)
    for (int j=0; j<dims[1]; ++j)
      for (int i=0; i<dims[0]; ++i)
        points->InsertPoint(i + j*dims[0] + k*dims[0]*dims[1],
                            i+rank*(dims[0]-1), j, k);

  // Create a density field. Note that the number of cells is always less than
  // number of grid points by an amount of one so we use dims[i]-1
  auto density = vtkSmartPointer<vtkFloatArray>::New();
  density->SetNumberOfComponents(1);
  density->SetNumberOfTuples((dims[0]-1)*(dims[1]-1)*(dims[2]-1));
  density->SetName ("density");
  int index;
  for (int k=0; k<lz; ++k)
    for (int j=0; j<ly; ++j)
      for (int i=0; i<lx; ++i) {
        index = i + j*(dims[0]-1) + k*(dims[0]-1)*(dims[1]-1);
        density->SetValue(index, i+j+k);
      }

  // Create a vtkProgrammableFilter
  auto pf = vtkSmartPointer<vtkProgrammableFilter>::New();

  // Initialize an instance of Args
  Args args;
  args.pf = pf;
  for(int i=0; i<6; ++i) args.local_extent[i] = local_extent[i];

  pf->SetExecuteMethod(execute, &args);

  // Create a structured grid and assign point data and cell data to it
  auto structuredGrid = vtkSmartPointer<vtkStructuredGrid>::New();
  structuredGrid->SetExtent(global_extent);
  pf->SetInputData(structuredGrid);
  structuredGrid->SetPoints(points);
  structuredGrid->GetCellData()->AddArray(density);

  // Create the parallel writer and call some functions
  auto parallel_writer = vtkSmartPointer<vtkXMLPStructuredGridWriter>::New();
  parallel_writer->SetInputConnection(pf->GetOutputPort());
  parallel_writer->SetController(contr);
  parallel_writer->SetFileName("data/test.pvts");
  parallel_writer->SetNumberOfPieces(nranks);
  parallel_writer->SetStartPiece(rank);
  parallel_writer->SetEndPiece(rank);
  parallel_writer->SetDataModeToBinary();
  parallel_writer->Update();
  parallel_writer->Write();

  contr->Finalize();

  // WARNING: it seems that MPI_Finalize is not necessary since we are using
  // Finalize() function from vtkMPIController class. Uncomment the following
  // line and see what happens.
//   MPI_Finalize ();
  return 0;
}

关于你的最后一个问题,如果你使用 VTK 库,你可以选择 Ascii 和二进制格式。二进制格式通常在大小方面更小。您可以通过调用 SetDataModeToBinary() 函数轻松设置此二进制格式。我在上面的代码中使用了这个函数。

另请阅读此 question这与您正在寻找的内容相关。

关于c++ - VTK 和 MPI : plot distributed data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48130423/

相关文章:

c - 使用 MPI Send/Recv 实现自己的矩阵乘法

c++ - 为什么编译器不能为非静态成员函数的无效使用生成解决方法

c++ - NO 带有字符串数组的存储类或类型说明符

c++ - 序列返回 49 但应该返回 36

javascript - $animate.addClass 类型错误 : Cannot read property 'parentNode' of undefined

c - PETSc - MatLUFactor - 不支持此对象类型的此操作

c++ - 多个连接更新同一个表

javascript - 我有一个适用于我的侧边导航的动画,但需要点击两次才能触发动画

java - 单击时按钮旋转

apache - 无法使用 mpirun 使 apache mod_perl 工作