I am currently using VTK to write simulation data on the subdomains of a structured grid to .vts files with the vtkXMLStructuredGridWriter in C++. So far, this works great for me. Now I also want to write the parallel file, which contains the information on all the pieces and this part is painfully undocumented.
My target is to collect all consecutive files of a single process in a dedicated folder, named after the rank of the process, e.g '0/mydata_<timestep>.vts'. The parallel file then should be located in the parent folder and be named something like 'mydata_<timestep>.pvts'. In principle, I could write a parallel file with any xml utility to do that job. But I would prefer to use the vtk library for consistency. I found this and this example to get some idea how that is supposed to work, with not a lot of success. The first example is also mentioned on Stackoverflow.
It does write a parallel file with the information which contains:
- number of pieces
- data sets in the pieces
- the location of the pieces in the folders
But it also does:
- create additional '*.vts' files in the same folder as the 'test_<timestep>.pvts' file
- sets the extent of the whole domain and of each piece to the extent of the root subdomain (process with rank 0)
I am also confused by how this parallel writer is supposed to work. If it is only called on the root process as in the examples, how would it know about the extent of the total subdomain? Or if I should call it on each process in parallel, how would it avoid concurrent access to the file?
So finally: Does anyone know, how this parallel XML writer is supposed to be used? Or maybe knows a good example to learn from?
I use following code to write the files:
#include <vtkNew.h>
#include <vtkStructuredGrid.h>
#include <vtkXMLStructuredGridWriter.h>
#include <vtkXMLPStructuredGridWriter.h>
class MyPwriter : public vtkXMLPStructuredGridWriter {
public:
static MyPwriter* New();
void WritePPieceAttributes(int index) {
std::string filename = std::to_string(index);
filename += "/test.vts";
this->WriteStringAttribute("Source", filename.c_str());
}
};
vtkStandardNewMacro(MyPwriter);
int main(int argc, char* argv[]) {
MPI_Init(&argc, &argv);
int myrank, nproc;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
vtkNew<vtkStructuredGrid> grid;
... //populating the grid with values
vtkNew<vtkXMLStructuredGridWriter> writer;
writer->SetInputData(grid);
std::string fname = std::to_string(myrank);
fname += "/test_1." + writer->GetDefaultFileExtension();
writer->SetFileName(fname.c_str());
writer->Write();
// Until here, everything works as expected
// Now I want to write the parallel file
if(myrank == 0) {
vtkNew<MyPwriter> pwriter;
std::string pfname = "test_1.";
pfname += pwriter->GetDefaultFileExtension();
pwriter->SetFileName(pfname.c_str());
pwriter->SetNumberOfPieces(nproc);
pwriter->SetStartPiece(0);
pwriter->SetEndPiece(nproc-1);
pwriter->SetInputData(grid);
pwriter->Update();
}
MPI_Finalize();
return 0;
}
I found following post Composing VTK file from multiple MPI outputs concerning using VTK's parallel xml writer for structured grids. However, this post does not deal yet with halo and/or ghost cells.
To make sure that those are excluded properly when loading the parallel file, I took this approach to override the attributes of the displayed pieces. This has the advantage, that the ghost/halo cells of each piece are still there, if required.
An example with two parallel process then looks like this: Example
Note: I also included the option to save the separate pieces in a subfolder
The code: