// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkPartitionedDataSetCollectionSource.h" #include "vtkAssume.h" #include "vtkDataArrayRange.h" #include "vtkDataAssembly.h" #include "vtkDoubleArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkIntArray.h" #include "vtkLogger.h" #include "vtkNew.h" #include "vtkObjectFactory.h" #include "vtkParametricBoy.h" #include "vtkParametricConicSpiral.h" #include "vtkParametricCrossCap.h" #include "vtkParametricDini.h" #include "vtkParametricEllipsoid.h" #include "vtkParametricEnneper.h" #include "vtkParametricFigure8Klein.h" #include "vtkParametricFunctionSource.h" #include "vtkParametricKlein.h" #include "vtkParametricMobius.h" #include "vtkParametricRoman.h" #include "vtkParametricSuperToroid.h" #include "vtkParametricTorus.h" #include "vtkPartitionedDataSetCollection.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkSMPTools.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkVector.h" #include #include #include #include VTK_ABI_NAMESPACE_BEGIN namespace { std::vector GenerateAssignments(int numRanks, int& count) { std::vector partsPerRank(numRanks); std::iota(partsPerRank.begin(), partsPerRank.end(), 1); count = std::accumulate(partsPerRank.begin(), partsPerRank.end(), 0); return partsPerRank; } // returns [start, end]. std::pair GetRange(int rank, const std::vector& counts) { std::pair result(0, counts[0]); if (rank == 0) { return result; } for (int cc = 1; cc <= rank; ++cc) { result.first = result.second; result.second += counts[cc]; } return result; } template void OffsetPoints(ArrayType* array, const vtkVector3d& delta) { VTK_ASSUME(array->GetNumberOfComponents() == 3); using ValueType = vtk::GetAPIType; vtkSMPTools::For(0, array->GetNumberOfTuples(), [&](vtkIdType start, vtkIdType end) { ValueType tuple[3]; for (vtkIdType tidx = start; tidx < end; ++tidx) { array->GetTypedTuple(tidx, tuple); tuple[0] += delta[0]; tuple[1] += delta[1]; tuple[2] += delta[2]; array->SetTypedTuple(tidx, tuple); } }); } } vtkStandardNewMacro(vtkPartitionedDataSetCollectionSource); //---------------------------------------------------------------------------- vtkPartitionedDataSetCollectionSource::vtkPartitionedDataSetCollectionSource() : NumberOfShapes(7) { this->SetNumberOfInputPorts(0); this->SetNumberOfOutputPorts(1); } //---------------------------------------------------------------------------- vtkPartitionedDataSetCollectionSource::~vtkPartitionedDataSetCollectionSource() = default; //------------------------------------------------------------------------------ int vtkPartitionedDataSetCollectionSource::RequestInformation(vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector) { auto outInfo = outputVector->GetInformationObject(0); outInfo->Set(CAN_HANDLE_PIECE_REQUEST(), 1); return 1; } //---------------------------------------------------------------------------- int vtkPartitionedDataSetCollectionSource::RequestData( vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) { auto outInfo = outputVector->GetInformationObject(0); auto output = vtkPartitionedDataSetCollection::GetData(outInfo); const int piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); const int numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); vtkNew source; source->SetOutputPointsPrecision(vtkAlgorithm::DOUBLE_PRECISION); std::vector> functions; functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); const auto firstOrientableSurface = static_cast(functions.size()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); functions.emplace_back(vtkSmartPointer::New()); vtkNew assembly; assembly->SetRootNodeName("Assembly"); output->SetDataAssembly(assembly); auto nonOrientableSurfaces = assembly->AddNode("NonOrientableSurfaces"); auto orientableSurfaces = assembly->AddNode("OrientableSurfaces"); for (int idx = 0; idx < this->NumberOfShapes; ++idx) { auto& function = functions.at(idx); function->JoinVOff(); function->JoinUOff(); source->SetParametricFunction(function); source->SetScalarModeToV(); const double maxV = function->GetMaximumV(); int totalParts; std::vector counts = ::GenerateAssignments(numPieces, totalParts); const double deltaV = maxV / totalParts; const auto range = ::GetRange(piece, counts); for (int partition = range.first; partition < range.second; ++partition) { function->SetMinimumV(partition * deltaV); function->SetMaximumV((partition + 1) * deltaV); vtkLogF(TRACE, "min=%f max=%f", function->GetMinimumV(), function->GetMaximumV()); source->Update(); vtkNew clone; clone->ShallowCopy(source->GetOutputDataObject(0)); vtkNew partId; partId->SetName("PartitionId"); partId->SetNumberOfTuples(clone->GetNumberOfPoints()); partId->FillValue(partition); clone->GetPointData()->AddArray(partId); vtkNew objectId; objectId->SetName("ObjectId"); objectId->SetNumberOfTuples(clone->GetNumberOfPoints()); objectId->FillValue(idx); clone->GetPointData()->AddArray(objectId); ::OffsetPoints( vtkDoubleArray::SafeDownCast(clone->GetPoints()->GetData()), vtkVector3d(2.5 * idx, 0, 0)); output->SetPartition(idx, output->GetNumberOfPartitions(idx), clone); } output->GetMetaData(idx)->Set(vtkCompositeDataSet::NAME(), // offset to remove vtkParametric prefix from the class name. vtksys::SystemTools::AddSpaceBetweenCapitalizedWords( function->GetClassName() + strlen("vtkParametric")) .c_str()); if (idx < firstOrientableSurface) { assembly->AddDataSetIndex(nonOrientableSurfaces, idx); } else { assembly->AddDataSetIndex(orientableSurfaces, idx); } } return 1; } //---------------------------------------------------------------------------- void vtkPartitionedDataSetCollectionSource::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "NumberOfShapes: " << this->NumberOfShapes << endl; } VTK_ABI_NAMESPACE_END