// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkXMLUniformGridAMRWriter.h" #include "vtkAMRBox.h" #include "vtkCartesianGrid.h" #include "vtkErrorCode.h" #include "vtkInformation.h" #include "vtkObjectFactory.h" #include "vtkOverlappingAMR.h" #include "vtkSmartPointer.h" #include "vtkXMLDataElement.h" #include VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkXMLUniformGridAMRWriter); //------------------------------------------------------------------------------ vtkXMLUniformGridAMRWriter::vtkXMLUniformGridAMRWriter() = default; //------------------------------------------------------------------------------ vtkXMLUniformGridAMRWriter::~vtkXMLUniformGridAMRWriter() = default; //------------------------------------------------------------------------------ int vtkXMLUniformGridAMRWriter::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAMRDataObject"); return 1; } //------------------------------------------------------------------------------ int vtkXMLUniformGridAMRWriter::WriteComposite( vtkCompositeDataSet* compositeData, vtkXMLDataElement* parent, int& writerIdx) { vtkAMRDataObject* amr = vtkAMRDataObject::SafeDownCast(compositeData); assert(amr != nullptr); vtkOverlappingAMR* oamr = vtkOverlappingAMR::SafeDownCast(amr); // For vtkOverlappingAMR, we need to add additional meta-data to the XML. if (oamr) { const double* origin = oamr->GetOrigin(); // I cannot decide what case to use. The other VTK-XML format used mixed // case for attributes, but the composite files are using all lower case // attributes. For consistency, I'm sticking with that. parent->SetVectorAttribute("origin", 3, origin); const char* gridDescription = ""; switch (oamr->GetGridDescription()) { case vtkStructuredData::VTK_STRUCTURED_XY_PLANE: gridDescription = "XY"; break; case vtkStructuredData::VTK_STRUCTURED_YZ_PLANE: gridDescription = "YZ"; break; case vtkStructuredData::VTK_STRUCTURED_XZ_PLANE: gridDescription = "XZ"; break; case vtkStructuredData::VTK_STRUCTURED_XYZ_GRID: default: gridDescription = "XYZ"; break; } parent->SetAttribute("grid_description", gridDescription); } unsigned int numLevels = amr->GetNumberOfLevels(); // Iterate over each level. for (unsigned int level = 0; level < numLevels; level++) { vtkSmartPointer block = vtkSmartPointer::New(); block->SetName("Block"); block->SetIntAttribute("level", level); if (oamr) { // save spacing for each level. double spacing[3]; oamr->GetSpacing(level, spacing); block->SetVectorAttribute("spacing", 3, spacing); // we no longer save the refinement ratios since those can be deduced from // the spacing very easily. } unsigned int numDS = amr->GetNumberOfBlocks(level); for (unsigned int cc = 0; cc < numDS; cc++) { vtkCartesianGrid* cg = amr->GetDataSetAsCartesianGrid(level, cc); vtkSmartPointer datasetXML = vtkSmartPointer::New(); datasetXML->SetName("DataSet"); datasetXML->SetIntAttribute("index", cc); if (oamr) { // AMRBox meta-data is available only for vtkOverlappingAMR. Also this // meta-data is expected to be consistent (and available) on all // processes so we don't have to worry about missing amr-box // information. const vtkAMRBox& amrBox = oamr->GetAMRBox(level, cc); int box_buffer[6]; box_buffer[0] = amrBox.GetLoCorner()[0]; box_buffer[1] = amrBox.GetHiCorner()[0]; box_buffer[2] = amrBox.GetLoCorner()[1]; box_buffer[3] = amrBox.GetHiCorner()[1]; box_buffer[4] = amrBox.GetLoCorner()[2]; box_buffer[5] = amrBox.GetHiCorner()[2]; // Don't use vtkAMRBox.Serialize() since it writes the box in a different // order than we wrote the box in traditionally. The expected order is // (xLo, xHi, yLo, yHi, zLo, zHi). datasetXML->SetVectorAttribute("amr_box", 6, box_buffer); } std::string fileName = this->CreatePieceFileName(writerIdx); if (!fileName.empty()) { // if fileName is empty, it implies that no file is written out for this // node, so don't add a filename attribute for it. datasetXML->SetAttribute("file", fileName.c_str()); } block->AddNestedElement(datasetXML); // if this->WriteNonCompositeData() returns 0, it doesn't meant it's an // error, it just means that it didn't write a file for the current node. this->WriteNonCompositeData(cg, datasetXML, writerIdx, fileName.c_str()); if (this->GetErrorCode() != vtkErrorCode::NoError) { return 0; } } parent->AddNestedElement(block); } return 1; } //------------------------------------------------------------------------------ void vtkXMLUniformGridAMRWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } VTK_ABI_NAMESPACE_END