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
|
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#include "vtkXMLPStructuredDataWriter.h"
#include "vtkCommunicator.h"
#include "vtkDataSet.h"
#include "vtkErrorCode.h"
#include "vtkExecutive.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMultiProcessController.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkXMLStructuredDataWriter.h"
//------------------------------------------------------------------------------
VTK_ABI_NAMESPACE_BEGIN
vtkXMLPStructuredDataWriter::vtkXMLPStructuredDataWriter() = default;
//------------------------------------------------------------------------------
vtkXMLPStructuredDataWriter::~vtkXMLPStructuredDataWriter() = default;
//------------------------------------------------------------------------------
void vtkXMLPStructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//------------------------------------------------------------------------------
int vtkXMLPStructuredDataWriter::WriteInternal()
{
int retVal = this->Superclass::WriteInternal();
if (retVal == 0 || !this->GetContinuingExecution())
{
this->Extents.clear();
}
return retVal;
}
//------------------------------------------------------------------------------
void vtkXMLPStructuredDataWriter::WritePrimaryElementAttributes(ostream& os, vtkIndent indent)
{
int* wExt =
this->GetInputInformation(0, 0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
this->WriteVectorAttribute("WholeExtent", 6, wExt);
this->Superclass::WritePrimaryElementAttributes(os, indent);
}
//------------------------------------------------------------------------------
void vtkXMLPStructuredDataWriter::WritePPieceAttributes(int index)
{
if (this->Extents.find(index) != this->Extents.end())
{
this->WriteVectorAttribute("Extent", 6, this->Extents[index].data());
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
{
return;
}
}
this->Superclass::WritePPieceAttributes(index);
}
//------------------------------------------------------------------------------
vtkXMLWriter* vtkXMLPStructuredDataWriter::CreatePieceWriter(int index)
{
vtkXMLStructuredDataWriter* pWriter = this->CreateStructuredPieceWriter();
pWriter->SetNumberOfPieces(this->NumberOfPieces);
pWriter->SetWritePiece(index);
pWriter->SetGhostLevel(this->GhostLevel);
return pWriter;
}
//------------------------------------------------------------------------------
void vtkXMLPStructuredDataWriter::PrepareSummaryFile()
{
this->Superclass::PrepareSummaryFile();
// The code below gathers extens from all processes to write in the
// meta-file. Note that the extent of each piece was already stored by
// each writer in WritePiece(). This is gathering it all to root node.
if (this->Controller)
{
// Even though the logic is pretty straightforward, we need to
// do a fair amount of work to use GatherV. Each rank simply
// serializes its extents to 7 int blocks - piece number and 6
// extent values. Then we gather this all to root.
int rank = this->Controller->GetLocalProcessId();
int nRanks = this->Controller->GetNumberOfProcesses();
int nPiecesTotal = 0;
vtkIdType nPieces = static_cast<vtkIdType>(this->Extents.size());
vtkIdType* offsets = nullptr;
vtkIdType* nPiecesAll = nullptr;
vtkIdType* recvLengths = nullptr;
if (rank == 0)
{
nPiecesAll = new vtkIdType[nRanks];
recvLengths = new vtkIdType[nRanks];
offsets = new vtkIdType[nRanks];
}
this->Controller->Gather(&nPieces, nPiecesAll, 1, 0);
if (rank == 0)
{
for (int i = 0; i < nRanks; i++)
{
offsets[i] = nPiecesTotal * 7;
nPiecesTotal += nPiecesAll[i];
recvLengths[i] = nPiecesAll[i] * 7;
}
}
int* sendBuffer = nullptr;
int sendSize = nPieces * 7;
if (nPieces > 0)
{
sendBuffer = new int[sendSize];
ExtentsType::iterator iter = this->Extents.begin();
for (int count = 0; iter != this->Extents.end(); ++iter, ++count)
{
sendBuffer[count * 7] = iter->first;
memcpy(&sendBuffer[count * 7 + 1], iter->second.data(), 6 * sizeof(int));
}
}
int* recvBuffer = nullptr;
if (rank == 0)
{
recvBuffer = new int[nPiecesTotal * 7];
}
this->Controller->GatherV(sendBuffer, recvBuffer, sendSize, recvLengths, offsets, 0);
if (rank == 0)
{
// Add all received values to Extents.
// These are later written in WritePPieceAttributes()
for (int i = 1; i < nRanks; i++)
{
for (int j = 0; j < nPiecesAll[i]; j++)
{
int* buffer = recvBuffer + offsets[i] + j * 7;
this->Extents[*buffer] = std::vector<int>(buffer + 1, buffer + 7);
}
}
}
delete[] nPiecesAll;
delete[] recvBuffer;
delete[] offsets;
delete[] recvLengths;
delete[] sendBuffer;
}
}
//------------------------------------------------------------------------------
int vtkXMLPStructuredDataWriter::WritePiece(int index)
{
int result = this->Superclass::WritePiece(index);
if (result)
{
// Store the extent of this piece in Extents. This is later used
// in WritePPieceAttributes to write the summary file.
vtkDataSet* input = this->GetInputAsDataSet();
int* ext = input->GetInformation()->Get(vtkDataObject::DATA_EXTENT());
this->Extents[index] = std::vector<int>(ext, ext + 6);
}
return result;
}
VTK_ABI_NAMESPACE_END
|