VTK和MPI:绘制分布式数据

时间:2018-01-06 18:18:06

标签: c++ animation mpi vtk

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

我想绘制的数据是一个立方体内的一组移动点(如果这可以帮助我们知道边界)。这组点将在每次迭代时更新,也可能很大。目前我们还不知道我们的实施将如何扩展,但目标是能够尽可能多地处理。

以下是我在平行绘图研究中找到的两种方法:

  1. 使用vtkMultiProcessController。这种方法似乎相当复杂,而且是唯一的"文档"我发现是课程文档和an example。这可能足以使用这个课程,但在我看来,这将花费我太多时间。

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

  3. 我的问题是:

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

    非常感谢你的时间!

1 个答案:

答案 0 :(得分:1)

我认为第一种方式更可靠,因为我花了很多时间来处理第二种方法而且我无法从中获得正确的结果。正如你所说,VTK类没有很好的文档,特别是像vtkXMLPStructuredGridWriter这样的并行类。

顺便说一句,我建议你使用第一种方法。但是,不使用vtkMultiProcessController,而是使用从vtkMultiProcessController类派生的vtkMPIController。最近,我为结构化网格编写了一个示例,通过进行一些更改,您可以将它用于您自己的应用程序:

// 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和Binary格式。二进制格式通常在大小方面较小。您可以通过调用SetDataModeToBinary()函数轻松设置此二进制格式。我在上面的代码中使用了这个函数。

另请阅读与您要查找的内容相关的question