diff --git a/IO/IOSS/vtkIOSSModel.cxx b/IO/IOSS/vtkIOSSModel.cxx index 528a8a76f1122902665b23a0b02f3fbd38d81cad..fa1af080a8b0f084928a7e319a8c46545fba2b8a 100644 --- a/IO/IOSS/vtkIOSSModel.cxx +++ b/IO/IOSS/vtkIOSSModel.cxx @@ -153,7 +153,7 @@ bool HandleGlobalIds(vtkPartitionedDataSetCollection* pdc, int association, } //============================================================================= -std::set<unsigned int> GetDatasetIndices(vtkDataAssembly* assembly, std::vector<std::string> paths) +std::set<unsigned int> GetDatasetIndices(vtkDataAssembly* assembly, std::set<std::string> paths) { if (assembly && assembly->GetRootNodeName()) { @@ -246,7 +246,8 @@ std::map<unsigned char, int64_t> GetElementCounts( vtkSMPTools::For(0, ds->GetNumberOfCells(), [&](vtkIdType start, vtkIdType end) { for (vtkIdType cc = start; cc < end; ++cc) { - // memory_order_relaxed is safe here, since we're not using the atomics for synchronization. + // memory_order_relaxed is safe here, since we're not using the atomics for + // synchronization. elementCounts[ds->GetCellType(cc)].fetch_add(1, std::memory_order_relaxed); } }); @@ -411,7 +412,7 @@ struct PutFieldWorker array->GetTypedTuple((*this->SourceIds)[cc], tuple.data()); for (size_t comp = 0; comp < this->Data.size(); ++comp) { - this->Data[comp][this->Offset + cc] = tuple[comp]; + this->Data[comp][this->Offset + cc] = static_cast<T>(tuple[comp]); } } }); @@ -430,7 +431,7 @@ struct PutFieldWorker ds->GetPoint((*this->SourceIds)[cc], tuple.data()); for (size_t comp = 0; comp < this->Data.size(); ++comp) { - this->Data[comp][this->Offset + cc] = tuple[comp]; + this->Data[comp][this->Offset + cc] = static_cast<T>(tuple[comp]); } } }); @@ -482,7 +483,21 @@ struct vtkGroupingEntity { } virtual ~vtkGroupingEntity() = default; - virtual Ioss::EntityType GetEntityType() const = 0; + virtual Ioss::EntityType GetIOSSEntityType() const + { + try + { + return vtkIOSSUtilities::GetIOSSEntityType(this->GetEntityType()); + } + catch (std::runtime_error&) + { + return Ioss::EntityType::INVALID_TYPE; + } + } + virtual vtkIOSSWriter::EntityType GetEntityType() const + { + return vtkIOSSWriter::EntityType::NUMBER_OF_ENTITY_TYPES; + } virtual void DefineModel(Ioss::Region& region) const = 0; virtual void Model(Ioss::Region& region) const = 0; virtual void DefineTransient(Ioss::Region& region) const = 0; @@ -636,11 +651,14 @@ struct vtkNodeBlock : vtkGroupingEntity } assert(this->DataSets.size() == this->IdsRaw.size()); - this->Fields = ::GetFields(vtkDataObject::POINT, writer->GetNodeBlockFieldSelection(), + this->Fields = ::GetFields(vtkDataObject::POINT, writer->GetChooseFieldsToWrite(), writer->GetNodeBlockFieldSelection(), pdc, controller); } - Ioss::EntityType GetEntityType() const override { return Ioss::EntityType::NODEBLOCK; } + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::NODEBLOCK; + } void AppendMD5(vtksysMD5* md5) const override { @@ -727,27 +745,27 @@ struct vtkNodeBlock : vtkGroupingEntity }; /** - * Builds a Ioss::ElementBlock from a vtkPartitionedDataSet. The differences + * Builds an Ioss::(*)Block from a vtkPartitionedDataSet. The differences * between the Ioss and VTK data model for the two are handled as follows: * * * We only support vtkPartitionedDataSet comprising of one or more vtkDataSets. * All other dataset types are simply ignored. * - * * An ElementBlock cannot have multiple "pieces" in the same file. So if a + * * A Block cannot have multiple "pieces" in the same file. So if a * vtkPartitionedDataSet has multiple datasets, we need to "combine" them into * one. * - * * An ElementBlock cannot have elements of different types. However, + * * A Block cannot have elements of different types. However, * vtkDataSet supports heterogeneous cells. So if all * vtkDataSets in the vtkPartitionedDataSet have more than 1 cell type, - * we create multiple element blocks. Each ElementBlock is uniquely named by + * we create multiple blocks. Each Block is uniquely named by * using the given block name and the element type as a suffix. * * In MPI world, the cell types are gathered across all ranks to ensure each * ranks creates identical blocks / block names. * */ -struct vtkElementBlock : public vtkGroupingEntity +struct vtkEntityBlock : public vtkGroupingEntity { const std::vector<vtkDataSet*> DataSets; std::string RootName; @@ -757,8 +775,9 @@ struct vtkElementBlock : public vtkGroupingEntity std::map<unsigned char, int64_t> ElementCounts; std::vector<std::tuple<std::string, Ioss::Field::BasicType, int>> Fields; - vtkElementBlock(vtkPartitionedDataSet* pds, const std::string& name, const int blockId, - int startSplitElementBlockId, vtkMultiProcessController* controller, vtkIOSSWriter* writer) + vtkEntityBlock(vtkPartitionedDataSet* pds, vtkIOSSWriter::EntityType entityType, + const std::string& name, const int blockId, int startSplitElementBlockId, + vtkMultiProcessController* controller, vtkIOSSWriter* writer) : vtkGroupingEntity(writer) , DataSets(vtkCompositeDataSet::GetDataSets<vtkDataSet>(pds)) , RootName(name) @@ -776,12 +795,10 @@ struct vtkElementBlock : public vtkGroupingEntity } this->ElementCounts = ::GetElementCounts(pds, controller); - this->Fields = ::GetFields(vtkDataObject::CELL, writer->GetChooseElementBlockFieldsToWrite(), - writer->GetElementBlockFieldSelection(), pds, controller); + this->Fields = ::GetFields(vtkDataObject::CELL, writer->GetChooseFieldsToWrite(), + writer->GetFieldSelection(entityType), pds, controller); } - Ioss::EntityType GetEntityType() const override { return Ioss::EntityType::ELEMENTBLOCK; } - void AppendMD5(vtksysMD5* md5) const override { vtksysMD5_Append(md5, reinterpret_cast<const unsigned char*>(this->RootName.c_str()), -1); @@ -814,6 +831,14 @@ struct vtkElementBlock : public vtkGroupingEntity } } + virtual Ioss::EntityBlock* CreateEntity(Ioss::DatabaseIO* db, const std::string& blockName, + const std::string& elementType, int64_t elementCount) const = 0; + + virtual void AddEntity(Ioss::Region& region, Ioss::EntityBlock* entityBlock) const = 0; + + virtual Ioss::EntityBlock* GetEntity( + Ioss::Region& region, const std::string& blockName) const = 0; + void DefineModel(Ioss::Region& region) const override { for (const auto& element : this->ElementCounts) @@ -825,15 +850,15 @@ struct vtkElementBlock : public vtkGroupingEntity const auto& elementType = elementTopology->name(); const auto blockInfo = this->GetSubElementBlockInfo(vtk_cell_type, elementType); - auto* elementBlock = - new Ioss::ElementBlock(region.get_database(), blockInfo.second, elementType, elementCount); - elementBlock->property_add(Ioss::Property("id", blockInfo.first)); + auto entityBlock = + this->CreateEntity(region.get_database(), blockInfo.second, elementType, elementCount); + entityBlock->property_add(Ioss::Property("id", blockInfo.first)); if (this->Writer->GetPreserveOriginalIds()) { - elementBlock->property_add( + entityBlock->property_add( Ioss::Property("original_id", this->BlockId, Ioss::Property::ATTRIBUTE)); } - region.add(elementBlock); + this->AddEntity(region, entityBlock); } } @@ -848,8 +873,8 @@ struct vtkElementBlock : public vtkGroupingEntity const auto& elementType = elementTopology->name(); const auto blockName = this->GetSubElementBlockInfo(vtk_cell_type, elementType).second; - auto* elementBlock = region.get_element_block(blockName); - this->DefineFields(elementBlock, this->Fields, Ioss::Field::TRANSIENT, elementCount); + auto* entityBlock = this->GetEntity(region, blockName); + this->DefineFields(entityBlock, this->Fields, Ioss::Field::TRANSIENT, elementCount); } } @@ -865,7 +890,7 @@ struct vtkElementBlock : public vtkGroupingEntity const int nodeCount = elementTopology->number_nodes(); const auto blockName = this->GetSubElementBlockInfo(vtk_cell_type, elementType).second; - auto* elementBlock = region.get_element_block(blockName); + auto* entityBlock = this->GetEntity(region, blockName); // populate ids. std::vector<int32_t> elementIds; // these are global ids. @@ -903,8 +928,8 @@ struct vtkElementBlock : public vtkGroupingEntity } assert(elementIds.size() == static_cast<size_t>(elementCount)); assert(connectivity.size() == static_cast<size_t>(elementCount * nodeCount)); - elementBlock->put_field_data("ids", elementIds); - elementBlock->put_field_data("connectivity", connectivity); + entityBlock->put_field_data("ids", elementIds); + entityBlock->put_field_data("connectivity", connectivity); } } @@ -918,7 +943,7 @@ struct vtkElementBlock : public vtkGroupingEntity const auto& elementType = elementTopology->name(); const auto blockName = this->GetSubElementBlockInfo(vtk_cell_type, elementType).second; - auto* elementBlock = region.get_element_block(blockName); + auto* entityBlock = this->GetEntity(region, blockName); // populate ids. std::vector<std::vector<vtkIdType>> lIds; // these are local ids. @@ -939,11 +964,108 @@ struct vtkElementBlock : public vtkGroupingEntity } // add fields. - this->PutFields(elementBlock, this->Fields, lIds, this->DataSets, vtkDataObject::CELL); + this->PutFields(entityBlock, this->Fields, lIds, this->DataSets, vtkDataObject::CELL); } } }; +//============================================================================= +struct vtkEdgeBlock : public vtkEntityBlock +{ + vtkEdgeBlock(vtkPartitionedDataSet* pds, const std::string& name, const int blockId, + int startSplitElementBlockId, vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntityBlock( + pds, this->GetEntityType(), name, blockId, startSplitElementBlockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::EDGEBLOCK; + } + + Ioss::EntityBlock* CreateEntity(Ioss::DatabaseIO* db, const std::string& blockName, + const std::string& elementType, const int64_t elementCount) const override + { + return new Ioss::EdgeBlock(db, blockName, elementType, elementCount); + } + + void AddEntity(Ioss::Region& region, Ioss::EntityBlock* entityBlock) const override + { + region.add(dynamic_cast<Ioss::EdgeBlock*>(entityBlock)); + } + + Ioss::EntityBlock* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_edge_block(blockName); + } +}; + +//============================================================================= +struct vtkFaceBlock : public vtkEntityBlock +{ + vtkFaceBlock(vtkPartitionedDataSet* pds, const std::string& name, const int blockId, + int startSplitElementBlockId, vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntityBlock( + pds, this->GetEntityType(), name, blockId, startSplitElementBlockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::FACEBLOCK; + } + + Ioss::EntityBlock* CreateEntity(Ioss::DatabaseIO* db, const std::string& blockName, + const std::string& elementType, const int64_t elementCount) const override + { + return new Ioss::FaceBlock(db, blockName, elementType, elementCount); + } + + void AddEntity(Ioss::Region& region, Ioss::EntityBlock* entityBlock) const override + { + region.add(dynamic_cast<Ioss::FaceBlock*>(entityBlock)); + } + + Ioss::EntityBlock* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_face_block(blockName); + } +}; + +//============================================================================= +struct vtkElementBlock : public vtkEntityBlock +{ + vtkElementBlock(vtkPartitionedDataSet* pds, const std::string& name, const int blockId, + int startSplitElementBlockId, vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntityBlock( + pds, this->GetEntityType(), name, blockId, startSplitElementBlockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::ELEMENTBLOCK; + } + + Ioss::EntityBlock* CreateEntity(Ioss::DatabaseIO* db, const std::string& blockName, + const std::string& elementType, const int64_t elementCount) const override + { + return new Ioss::ElementBlock(db, blockName, elementType, elementCount); + } + + void AddEntity(Ioss::Region& region, Ioss::EntityBlock* entityBlock) const override + { + region.add(dynamic_cast<Ioss::ElementBlock*>(entityBlock)); + } + + Ioss::EntityBlock* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_element_block(blockName); + } +}; + +//============================================================================= struct vtkNodeSet : public vtkGroupingEntity { const std::vector<vtkDataSet*> DataSets; @@ -974,11 +1096,14 @@ struct vtkNodeSet : public vtkGroupingEntity } // in a nodeSet, number of points == number of cells, because cells are vertices - this->Fields = ::GetFields(vtkDataObject::CELL, writer->GetChooseNodeSetFieldsToWrite(), + this->Fields = ::GetFields(vtkDataObject::CELL, writer->GetChooseFieldsToWrite(), writer->GetNodeSetFieldSelection(), pds, controller); } - Ioss::EntityType GetEntityType() const override { return Ioss::EntityType::NODESET; } + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::NODESET; + } void AppendMD5(vtksysMD5* md5) const override { @@ -1037,7 +1162,8 @@ struct vtkNodeSet : public vtkGroupingEntity } }; -struct vtkSideSet : public vtkGroupingEntity +//============================================================================= +struct vtkEntitySet : public vtkGroupingEntity { const std::vector<vtkDataSet*> DataSets; std::string Name; @@ -1046,8 +1172,9 @@ struct vtkSideSet : public vtkGroupingEntity std::vector<std::tuple<std::string, Ioss::Field::BasicType, int>> Fields; - vtkSideSet(vtkPartitionedDataSet* pds, const std::string& name, int blockId, - vtkMultiProcessController* controller, vtkIOSSWriter* writer) + vtkEntitySet(vtkPartitionedDataSet* pds, vtkIOSSWriter::EntityType entityType, + const std::string& name, int blockId, vtkMultiProcessController* controller, + vtkIOSSWriter* writer) : vtkGroupingEntity(writer) , DataSets(vtkCompositeDataSet::GetDataSets<vtkDataSet>(pds)) , Name(name) @@ -1056,25 +1183,18 @@ struct vtkSideSet : public vtkGroupingEntity { for (auto& ds : this->DataSets) { - auto* cd = ds->GetCellData(); - if (vtkIdTypeArray::SafeDownCast(cd->GetGlobalIds()) != nullptr) - { - throw std::runtime_error("cell global ids present, must not be a sideset."); - } - - if (vtkIntArray::SafeDownCast(cd->GetArray("element_side")) == nullptr) + // no need to check for global ids + if (vtkIntArray::SafeDownCast(ds->GetCellData()->GetArray("element_side")) == nullptr) { throw std::runtime_error("missing 'element_side' cell array."); } this->Count += ds->GetNumberOfCells(); } - this->Fields = ::GetFields(vtkDataObject::CELL, writer->GetChooseSideSetFieldsToWrite(), - writer->GetSideSetFieldSelection(), pds, controller); + this->Fields = ::GetFields(vtkDataObject::CELL, writer->GetChooseFieldsToWrite(), + writer->GetFieldSelection(entityType), pds, controller); } - Ioss::EntityType GetEntityType() const override { return Ioss::EntityType::SIDESET; } - void AppendMD5(vtksysMD5* md5) const override { vtksysMD5_Append(md5, reinterpret_cast<const unsigned char*>(this->Name.c_str()), -1); @@ -1082,31 +1202,30 @@ struct vtkSideSet : public vtkGroupingEntity static_cast<int>(sizeof(this->Count))); } + virtual Ioss::GroupingEntity* CreateEntity( + Ioss::DatabaseIO* db, const std::string& blockName, int64_t elementCount) const = 0; + + virtual void AddEntity(Ioss::Region& region, Ioss::GroupingEntity* entitySet) const = 0; + + virtual Ioss::GroupingEntity* GetEntity( + Ioss::Region& region, const std::string& blockName) const = 0; + void DefineModel(Ioss::Region& region) const override { - // for mixed topology blocks, IOSS uses "unknown" - const auto* mixed_topo = Ioss::ElementTopology::factory("unknown"); - const auto& elementType = mixed_topo->name(); - auto* sideBlock = new Ioss::SideBlock( - region.get_database(), "sideblock_0", elementType, elementType, this->Count); - - auto* sideSet = new Ioss::SideSet(region.get_database(), this->Name); - sideSet->property_add(Ioss::Property("id", this->BlockId)); - sideSet->add(sideBlock); - region.add(sideSet); + auto entitySet = this->CreateEntity(region.get_database(), this->Name, this->Count); + entitySet->property_add(Ioss::Property("id", this->BlockId)); + this->AddEntity(region, entitySet); } void DefineTransient(Ioss::Region& region) const override { - auto* sideSet = region.get_sideset(this->Name); - auto* sideBlock = sideSet->get_side_block("sideblock_0"); - this->DefineFields(sideBlock, this->Fields, Ioss::Field::TRANSIENT, this->Count); + auto entity = this->GetEntity(region, this->Name); + this->DefineFields(entity, this->Fields, Ioss::Field::TRANSIENT, this->Count); } void Model(Ioss::Region& region) const override { - auto* sideSet = region.get_sideset(this->Name); - auto* sideBlock = sideSet->get_side_block("sideblock_0"); + auto entity = this->GetEntity(region, this->Name); std::vector<int32_t> elementSide; elementSide.reserve(this->Count * 2); @@ -1135,13 +1254,12 @@ struct vtkSideSet : public vtkGroupingEntity } assert(elementSide.size() == static_cast<size_t>(this->Count * 2)); - sideBlock->put_field_data("element_side", elementSide); + entity->put_field_data("element_side", elementSide); } void Transient(Ioss::Region& region) const override { - auto* sideSet = region.get_sideset(this->Name); - auto* sideBlock = sideSet->get_side_block("sideblock_0"); + auto entity = this->GetEntity(region, this->Name); // populate ids. std::vector<std::vector<vtkIdType>> lIds; // these are local ids. @@ -1162,7 +1280,138 @@ struct vtkSideSet : public vtkGroupingEntity } // add fields. - this->PutFields(sideBlock, this->Fields, lIds, this->DataSets, vtkDataObject::CELL); + this->PutFields(entity, this->Fields, lIds, this->DataSets, vtkDataObject::CELL); + } +}; + +//============================================================================= +struct vtkEdgeSet : public vtkEntitySet +{ + vtkEdgeSet(vtkPartitionedDataSet* pds, const std::string& name, int blockId, + vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntitySet(pds, this->GetEntityType(), name, blockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::EDGESET; + } + + Ioss::GroupingEntity* CreateEntity( + Ioss::DatabaseIO* db, const std::string& blockName, const int64_t elementCount) const override + { + return new Ioss::EdgeSet(db, blockName, elementCount); + } + + void AddEntity(Ioss::Region& region, Ioss::GroupingEntity* entitySet) const override + { + region.add(dynamic_cast<Ioss::EdgeSet*>(entitySet)); + } + + Ioss::GroupingEntity* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_edgeset(blockName); + } +}; + +//============================================================================= +struct vtkFaceSet : public vtkEntitySet +{ + vtkFaceSet(vtkPartitionedDataSet* pds, const std::string& name, int blockId, + vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntitySet(pds, this->GetEntityType(), name, blockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::FACESET; + } + + Ioss::GroupingEntity* CreateEntity( + Ioss::DatabaseIO* db, const std::string& blockName, const int64_t elementCount) const override + { + return new Ioss::FaceSet(db, blockName, elementCount); + } + + void AddEntity(Ioss::Region& region, Ioss::GroupingEntity* entitySet) const override + { + region.add(dynamic_cast<Ioss::FaceSet*>(entitySet)); + } + + Ioss::GroupingEntity* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_faceset(blockName); + } +}; + +//============================================================================= +struct vtkElementSet : public vtkEntitySet +{ + vtkElementSet(vtkPartitionedDataSet* pds, const std::string& name, int blockId, + vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntitySet(pds, this->GetEntityType(), name, blockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::ELEMENTSET; + } + + Ioss::GroupingEntity* CreateEntity( + Ioss::DatabaseIO* db, const std::string& blockName, const int64_t elementCount) const override + { + return new Ioss::ElementSet(db, blockName, elementCount); + } + + void AddEntity(Ioss::Region& region, Ioss::GroupingEntity* entitySet) const override + { + region.add(dynamic_cast<Ioss::ElementSet*>(entitySet)); + } + + Ioss::GroupingEntity* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_elementset(blockName); + } +}; + +//============================================================================= +struct vtkSideSet : public vtkEntitySet +{ + vtkSideSet(vtkPartitionedDataSet* pds, const std::string& name, int blockId, + vtkMultiProcessController* controller, vtkIOSSWriter* writer) + : vtkEntitySet(pds, this->GetEntityType(), name, blockId, controller, writer) + { + } + + vtkIOSSWriter::EntityType GetEntityType() const override + { + return vtkIOSSWriter::EntityType::SIDESET; + } + + Ioss::GroupingEntity* CreateEntity( + Ioss::DatabaseIO* db, const std::string& blockName, const int64_t elementCount) const override + { + // for mixed topology blocks, IOSS uses "unknown" + const auto* mixed_topo = Ioss::ElementTopology::factory("unknown"); + const auto& elementType = mixed_topo->name(); + auto* sideBlock = + new Ioss::SideBlock(db, "sideblock_0", elementType, elementType, elementCount); + auto* sideSet = new Ioss::SideSet(db, blockName); + sideSet->add(sideBlock); + return sideSet; + } + + void AddEntity(Ioss::Region& region, Ioss::GroupingEntity* entitySet) const override + { + region.add(dynamic_cast<Ioss::SideSet*>(entitySet)); + } + + Ioss::GroupingEntity* GetEntity(Ioss::Region& region, const std::string& blockName) const override + { + return region.get_sideset(blockName)->get_side_block("sideblock_0"); } }; @@ -1209,26 +1458,18 @@ vtkIOSSModel::vtkIOSSModel(vtkPartitionedDataSetCollection* pdc, vtkIOSSWriter* return; } } - std::vector<std::string> elementBlockSelectors(writer->GetNumberOfElementBlockSelectors()); - for (size_t idx = 0; idx < elementBlockSelectors.size(); ++idx) - { - elementBlockSelectors[idx] = writer->GetElementBlockSelector(idx); - } - std::vector<std::string> nodeSetSelectors(writer->GetNumberOfNodeSetSelectors()); - for (size_t idx = 0; idx < nodeSetSelectors.size(); ++idx) - { - nodeSetSelectors[idx] = writer->GetNodeSetSelector(idx); - } - std::vector<std::string> sideSetSelectors(writer->GetNumberOfSideSetSelectors()); - for (size_t idx = 0; idx < sideSetSelectors.size(); ++idx) + using EntityType = vtkIOSSWriter::EntityType; + std::map<EntityType, std::set<unsigned int>> entityIndices; + for (int i = EntityType::EDGEBLOCK; i < EntityType::NUMBER_OF_ENTITY_TYPES; ++i) { - sideSetSelectors[idx] = writer->GetSideSetSelector(idx); + const auto entityType = static_cast<EntityType>(i); + entityIndices[entityType] = ::GetDatasetIndices(assembly, writer->GetSelectors(entityType)); } - auto elementBlockIndices = ::GetDatasetIndices(assembly, elementBlockSelectors); - auto nodeSetIndices = ::GetDatasetIndices(assembly, nodeSetSelectors); - auto sideSetIndices = ::GetDatasetIndices(assembly, sideSetSelectors); - bool indicesEmpty = - elementBlockIndices.empty() && nodeSetIndices.empty() && sideSetIndices.empty(); + // write the above for loop with one line + const bool indicesEmpty = std::all_of(entityIndices.begin(), entityIndices.end(), + [](const std::pair<EntityType, std::set<unsigned int>>& indices) { + return indices.second.empty(); + }); if (indicesEmpty) { // if no indices are specified, then all blocks will be processed as element blocks @@ -1238,18 +1479,28 @@ vtkIOSSModel::vtkIOSSModel(vtkPartitionedDataSetCollection* pdc, vtkIOSSWriter* strcmp(dataAssembly->GetRootNodeName(), "IOSS") == 0); if (isIOSS) { - elementBlockIndices = ::GetDatasetIndices(dataAssembly, { "/IOSS/element_blocks" }); - nodeSetIndices = ::GetDatasetIndices(dataAssembly, { "/IOSS/node_sets" }); - sideSetIndices = ::GetDatasetIndices(dataAssembly, { "/IOSS/side_sets" }); - indicesEmpty = - elementBlockIndices.empty() && nodeSetIndices.empty() && sideSetIndices.empty(); + for (int i = EntityType::EDGEBLOCK; i < EntityType::NUMBER_OF_ENTITY_TYPES; ++i) + { + const auto entityType = static_cast<EntityType>(i); + const auto iossEntitySelector = + std::string("/IOSS/") + vtkIOSSReader::GetDataAssemblyNodeNameForEntityType(i); + entityIndices[entityType] = ::GetDatasetIndices(dataAssembly, { iossEntitySelector }); + } + } + else + { + // all blocks are element blocks + entityIndices[EntityType::ELEMENTBLOCK] = ::GetDatasetIndices(assembly, { "/" }); } } - // merge node sets and side sets indices into a single set of indices. + // merge sets indices into a single set of indices. std::set<unsigned int> indicesToIgnore; - indicesToIgnore.insert(nodeSetIndices.begin(), nodeSetIndices.end()); - indicesToIgnore.insert(sideSetIndices.begin(), sideSetIndices.end()); + for (int i = EntityType::SET_START; i < EntityType::SET_END; ++i) + { + const auto entityType = static_cast<EntityType>(i); + indicesToIgnore.insert(entityIndices[entityType].begin(), entityIndices[entityType].end()); + } internals.GlobalIdsCreated = false; // create global point ids if needed @@ -1278,27 +1529,24 @@ vtkIOSSModel::vtkIOSSModel(vtkPartitionedDataSetCollection* pdc, vtkIOSSWriter* } } } - // this will be used as a start id for split element blocks to ensure uniqueness. - int startSplitElementBlockId = *std::max_element(blockIds.begin(), blockIds.end()) + 1; - // ensure that all processes have the same startSplitElementBlockId. + // this will be used as a start id for split blocks to ensure uniqueness. + int startSplitEBlockId = *std::max_element(blockIds.begin(), blockIds.end()) + 1; + // ensure that all processes have the same startSplitEBlockId. if (controller && controller->GetNumberOfProcesses() > 1) { - int globalStartSplitElementBlockId; + int globalStartSplitBlockId; controller->AllReduce( - &startSplitElementBlockId, &globalStartSplitElementBlockId, 1, vtkCommunicator::MAX_OP); - startSplitElementBlockId = globalStartSplitElementBlockId; + &startSplitEBlockId, &globalStartSplitBlockId, 1, vtkCommunicator::MAX_OP); + startSplitEBlockId = globalStartSplitBlockId; } - // first things first, determine all information necessary about nodes. + // first things first, determine all information necessary about node block. // there's just 1 node block for exodus, build that. auto nodeBlock = std::make_shared<vtkNodeBlock>(dataset, "nodeblock_1", controller, writer); - entityGroups.emplace(nodeBlock->GetEntityType(), nodeBlock); + entityGroups.emplace(nodeBlock->GetIOSSEntityType(), nodeBlock); - // process element blocks. - // now, if input is not coming for IOSS reader, then all blocks are simply - // treated as element blocks, there's no way for us to deduce otherwise. - // let's start by simply doing that. - int elementBlockCounter = 0; + // process group entities. + int blockCounter = 0; for (unsigned int pidx = 0; pidx < dataset->GetNumberOfPartitionedDataSets(); ++pidx) { const std::string& blockName = blockNames[pidx]; @@ -1307,20 +1555,21 @@ vtkIOSSModel::vtkIOSSModel(vtkPartitionedDataSetCollection* pdc, vtkIOSSWriter* // now create each type of GroupingEntity. - // if indices are empty, all blocks will be processed as element blocks. - if (indicesEmpty || elementBlockIndices.find(pidx) != elementBlockIndices.end()) + // edge block + const bool edgeBlockFound = + entityIndices[EntityType::EDGEBLOCK].find(pidx) != entityIndices[EntityType::EDGEBLOCK].end(); + if (edgeBlockFound) { try { - if (elementBlockCounter != 0) + if (blockCounter++ != 0) { // add the number of cell types to the block id to ensure uniqueness. - startSplitElementBlockId += VTK_NUMBER_OF_CELL_TYPES; + startSplitEBlockId += VTK_NUMBER_OF_CELL_TYPES; } - auto elementBlock = std::make_shared<vtkElementBlock>( - pds, blockName, blockId, startSplitElementBlockId, controller, writer); - entityGroups.emplace(elementBlock->GetEntityType(), elementBlock); - ++elementBlockCounter; + auto edgeBlock = std::make_shared<vtkEdgeBlock>( + pds, blockName, blockId, startSplitEBlockId, controller, writer); + entityGroups.emplace(edgeBlock->GetIOSSEntityType(), edgeBlock); continue; } catch (std::runtime_error&) @@ -1329,12 +1578,44 @@ vtkIOSSModel::vtkIOSSModel(vtkPartitionedDataSetCollection* pdc, vtkIOSSWriter* } } - if (sideSetIndices.find(pidx) != sideSetIndices.end()) + // face block + const bool faceBlockFound = + entityIndices[EntityType::FACEBLOCK].find(pidx) != entityIndices[EntityType::FACEBLOCK].end(); + if (faceBlockFound) { try { - auto sideSet = std::make_shared<vtkSideSet>(pds, blockName, blockId, controller, writer); - entityGroups.emplace(sideSet->GetEntityType(), sideSet); + if (blockCounter++ != 0) + { + // add the number of cell types to the block id to ensure uniqueness. + startSplitEBlockId += VTK_NUMBER_OF_CELL_TYPES; + } + auto faceBlock = std::make_shared<vtkFaceBlock>( + pds, blockName, blockId, startSplitEBlockId, controller, writer); + entityGroups.emplace(faceBlock->GetIOSSEntityType(), faceBlock); + continue; + } + catch (std::runtime_error&) + { + break; + } + } + + // element block + const bool elementBlockFound = entityIndices[EntityType::ELEMENTBLOCK].find(pidx) != + entityIndices[EntityType::ELEMENTBLOCK].end(); + if (elementBlockFound) + { + try + { + if (blockCounter++ != 0) + { + // add the number of cell types to the block id to ensure uniqueness. + startSplitEBlockId += VTK_NUMBER_OF_CELL_TYPES; + } + auto elementBlock = std::make_shared<vtkElementBlock>( + pds, blockName, blockId, startSplitEBlockId, controller, writer); + entityGroups.emplace(elementBlock->GetIOSSEntityType(), elementBlock); continue; } catch (std::runtime_error&) @@ -1343,13 +1624,84 @@ vtkIOSSModel::vtkIOSSModel(vtkPartitionedDataSetCollection* pdc, vtkIOSSWriter* } } - // nodesets are the most forgiving kind, so let's do them last. - if (nodeSetIndices.find(pidx) != nodeSetIndices.end()) + // node set + const bool nodeSetFound = + entityIndices[EntityType::NODESET].find(pidx) != entityIndices[EntityType::NODESET].end(); + if (nodeSetFound) { try { auto nodeSet = std::make_shared<vtkNodeSet>(pds, blockName, blockId, controller, writer); - entityGroups.emplace(nodeSet->GetEntityType(), nodeSet); + entityGroups.emplace(nodeSet->GetIOSSEntityType(), nodeSet); + continue; + } + catch (std::runtime_error&) + { + break; + } + } + + // edge set + const bool edgeSetFound = + entityIndices[EntityType::EDGESET].find(pidx) != entityIndices[EntityType::EDGESET].end(); + if (edgeSetFound) + { + try + { + auto edgeSet = std::make_shared<vtkEdgeSet>(pds, blockName, blockId, controller, writer); + entityGroups.emplace(edgeSet->GetIOSSEntityType(), edgeSet); + continue; + } + catch (std::runtime_error&) + { + break; + } + } + + // face set + const bool faceSetFound = + entityIndices[EntityType::FACESET].find(pidx) != entityIndices[EntityType::FACESET].end(); + if (faceSetFound) + { + try + { + auto faceSet = std::make_shared<vtkFaceSet>(pds, blockName, blockId, controller, writer); + entityGroups.emplace(faceSet->GetIOSSEntityType(), faceSet); + continue; + } + catch (std::runtime_error&) + { + break; + } + } + + // element set + const bool elementSetFound = entityIndices[EntityType::ELEMENTSET].find(pidx) != + entityIndices[EntityType::ELEMENTSET].end(); + if (elementSetFound) + { + try + { + auto elementSet = + std::make_shared<vtkElementSet>(pds, blockName, blockId, controller, writer); + entityGroups.emplace(elementSet->GetIOSSEntityType(), elementSet); + continue; + } + catch (std::runtime_error&) + { + break; + } + } + + // side set + const bool sideSetFound = + entityIndices[EntityType::SIDESET].find(pidx) != entityIndices[EntityType::SIDESET].end(); + if (sideSetFound) + { + try + { + auto sideSet = std::make_shared<vtkSideSet>(pds, blockName, blockId, controller, writer); + entityGroups.emplace(sideSet->GetIOSSEntityType(), sideSet); continue; } catch (std::runtime_error&) diff --git a/IO/IOSS/vtkIOSSWriter.cxx b/IO/IOSS/vtkIOSSWriter.cxx index 739f7946281802d8152f29ffdd57280e0bbc00b4..d2b25dd6fe7266243c2e13d1e8e972a204306604 100644 --- a/IO/IOSS/vtkIOSSWriter.cxx +++ b/IO/IOSS/vtkIOSSWriter.cxx @@ -71,9 +71,6 @@ public: int CurrentTimeStepIndex{ 0 }; int RestartIndex{ 0 }; std::string LastMD5; - std::set<std::string> ElementBlockSelectors; - std::set<std::string> NodeSetSelectors; - std::set<std::string> SideSetSelectors; vtkInternals() = default; ~vtkInternals() = default; @@ -87,6 +84,7 @@ vtkIOSSWriter::vtkIOSSWriter() , Controller(nullptr) , FileName(nullptr) , AssemblyName(nullptr) + , ChooseFieldsToWrite(false) , RemoveGhosts(true) , OffsetGlobalIds(false) , PreserveOriginalIds(false) @@ -97,11 +95,9 @@ vtkIOSSWriter::vtkIOSSWriter() { this->SetController(vtkMultiProcessController::GetGlobalController()); this->SetAssemblyName(vtkDataAssemblyUtilities::HierarchyName()); - std::fill_n(this->ChooseEntityFieldsToWrite, EntityType::NUMBER_OF_ENTITY_TYPES, false); for (int i = 0; i < EntityType::NUMBER_OF_ENTITY_TYPES; ++i) { - this->EntityFieldSelection[i]->AddObserver( - vtkCommand::ModifiedEvent, this, &vtkIOSSWriter::Modified); + this->FieldSelection[i]->AddObserver(vtkCommand::ModifiedEvent, this, &vtkIOSSWriter::Modified); } } @@ -114,39 +110,11 @@ vtkIOSSWriter::~vtkIOSSWriter() } //---------------------------------------------------------------------------- -void vtkIOSSWriter::SetChooseEntityFieldsToWrite(EntityType type, bool val) +vtkDataArraySelection* vtkIOSSWriter::GetFieldSelection(EntityType type) { if (type < EntityType::NUMBER_OF_ENTITY_TYPES) { - this->ChooseEntityFieldsToWrite[type] = val; - this->Modified(); - } - else - { - vtkErrorMacro("Invalid entity type: " << type); - } -} - -//---------------------------------------------------------------------------- -bool vtkIOSSWriter::GetChooseEntityFieldsToWrite(vtkIOSSWriter::EntityType type) const -{ - if (type < EntityType::NUMBER_OF_ENTITY_TYPES) - { - return this->ChooseEntityFieldsToWrite[type]; - } - else - { - vtkErrorMacro("Invalid entity type: " << type); - return false; - } -} - -//---------------------------------------------------------------------------- -vtkDataArraySelection* vtkIOSSWriter::GetEntityFieldSelection(vtkIOSSWriter::EntityType type) -{ - if (type < EntityType::NUMBER_OF_ENTITY_TYPES) - { - return this->EntityFieldSelection[type]; + return this->FieldSelection[type]; } else { @@ -156,12 +124,11 @@ vtkDataArraySelection* vtkIOSSWriter::GetEntityFieldSelection(vtkIOSSWriter::Ent } //------------------------------------------------------------------------------ -bool vtkIOSSWriter::AddElementBlockSelector(const char* selector) +bool vtkIOSSWriter::AddSelector(vtkIOSSWriter::EntityType entityType, const char* selector) { if (selector) { - auto& internals = *this->Internals; - if (internals.ElementBlockSelectors.insert(selector).second) + if (this->Selectors[entityType].insert(selector).second) { this->Modified(); return true; @@ -171,178 +138,61 @@ bool vtkIOSSWriter::AddElementBlockSelector(const char* selector) } //------------------------------------------------------------------------------ -void vtkIOSSWriter::ClearElementBlockSelectors() +void vtkIOSSWriter::ClearSelectors(vtkIOSSWriter::EntityType entityType) { - auto& internals = *this->Internals; - if (!internals.ElementBlockSelectors.empty()) + if (!this->Selectors[entityType].empty()) { - internals.ElementBlockSelectors.clear(); + this->Selectors[entityType].clear(); this->Modified(); } } //------------------------------------------------------------------------------ -void vtkIOSSWriter::SetElementBlockSelector(const char* selector) +void vtkIOSSWriter::SetSelector(vtkIOSSWriter::EntityType entity, const char* selector) { if (selector) { - auto& internals = *this->Internals; - if (internals.ElementBlockSelectors.size() == 1 && - *internals.ElementBlockSelectors.begin() == selector) + if (this->Selectors[entity].size() == 1 && *this->Selectors[entity].begin() == selector) { return; } - internals.ElementBlockSelectors.clear(); - internals.ElementBlockSelectors.insert(selector); + this->Selectors[entity].clear(); + this->Selectors[entity].insert(selector); this->Modified(); } } //------------------------------------------------------------------------------ -int vtkIOSSWriter::GetNumberOfElementBlockSelectors() const +int vtkIOSSWriter::GetNumberOfSelectors(vtkIOSSWriter::EntityType entity) const { - auto& internals = *this->Internals; - return static_cast<int>(internals.ElementBlockSelectors.size()); -} - -//------------------------------------------------------------------------------ -const char* vtkIOSSWriter::GetElementBlockSelector(int index) const -{ - const auto& internals = *this->Internals; - if (index >= 0 && index < static_cast<int>(internals.ElementBlockSelectors.size())) + if (entity < EntityType::NUMBER_OF_ENTITY_TYPES) { - auto iter = std::next(internals.ElementBlockSelectors.begin(), index); - return iter->c_str(); + return static_cast<int>(this->Selectors[entity].size()); } - - vtkErrorMacro("Invalid index '" << index << "'."); - return nullptr; + return 0; } //------------------------------------------------------------------------------ -bool vtkIOSSWriter::AddNodeSetSelector(const char* selector) +const char* vtkIOSSWriter::GetSelector(vtkIOSSWriter::EntityType entityType, int index) const { - if (selector) - { - auto& internals = *this->Internals; - if (internals.NodeSetSelectors.insert(selector).second) - { - this->Modified(); - return true; - } - } - return false; -} - -//------------------------------------------------------------------------------ -void vtkIOSSWriter::ClearNodeSetSelectors() -{ - auto& internals = *this->Internals; - if (!internals.NodeSetSelectors.empty()) - { - internals.NodeSetSelectors.clear(); - this->Modified(); - } -} - -//------------------------------------------------------------------------------ -void vtkIOSSWriter::SetNodeSetSelector(const char* selector) -{ - if (selector) + if (index >= 0 && index < this->GetNumberOfSelectors(entityType)) { - auto& internals = *this->Internals; - if (internals.NodeSetSelectors.size() == 1 && *internals.NodeSetSelectors.begin() == selector) - { - return; - } - internals.NodeSetSelectors.clear(); - internals.NodeSetSelectors.insert(selector); - this->Modified(); + auto& selectors = this->Selectors[entityType]; + auto it = selectors.begin(); + std::advance(it, index); + return it->c_str(); } -} - -//------------------------------------------------------------------------------ -int vtkIOSSWriter::GetNumberOfNodeSetSelectors() const -{ - auto& internals = *this->Internals; - return static_cast<int>(internals.NodeSetSelectors.size()); -} - -//------------------------------------------------------------------------------ -const char* vtkIOSSWriter::GetNodeSetSelector(int index) const -{ - const auto& internals = *this->Internals; - if (index >= 0 && index < static_cast<int>(internals.NodeSetSelectors.size())) - { - auto iter = std::next(internals.NodeSetSelectors.begin(), index); - return iter->c_str(); - } - - vtkErrorMacro("Invalid index '" << index << "'."); return nullptr; } //------------------------------------------------------------------------------ -bool vtkIOSSWriter::AddSideSetSelector(const char* selector) -{ - if (selector) - { - auto& internals = *this->Internals; - if (internals.SideSetSelectors.insert(selector).second) - { - this->Modified(); - return true; - } - } - return false; -} - -//------------------------------------------------------------------------------ -void vtkIOSSWriter::ClearSideSetSelectors() -{ - auto& internals = *this->Internals; - if (!internals.SideSetSelectors.empty()) - { - internals.SideSetSelectors.clear(); - this->Modified(); - } -} - -//------------------------------------------------------------------------------ -void vtkIOSSWriter::SetSideSetSelector(const char* selector) -{ - if (selector) - { - auto& internals = *this->Internals; - if (internals.SideSetSelectors.size() == 1 && *internals.SideSetSelectors.begin() == selector) - { - return; - } - internals.SideSetSelectors.clear(); - internals.SideSetSelectors.insert(selector); - this->Modified(); - } -} - -//------------------------------------------------------------------------------ -int vtkIOSSWriter::GetNumberOfSideSetSelectors() const +std::set<std::string> vtkIOSSWriter::GetSelectors(vtkIOSSWriter::EntityType entityType) const { - auto& internals = *this->Internals; - return static_cast<int>(internals.SideSetSelectors.size()); -} - -//------------------------------------------------------------------------------ -const char* vtkIOSSWriter::GetSideSetSelector(int index) const -{ - const auto& internals = *this->Internals; - if (index >= 0 && index < static_cast<int>(internals.SideSetSelectors.size())) + if (entityType < EntityType::NUMBER_OF_ENTITY_TYPES) { - auto iter = std::next(internals.SideSetSelectors.begin(), index); - return iter->c_str(); + return this->Selectors[entityType]; } - - vtkErrorMacro("Invalid index '" << index << "'."); - return nullptr; + return std::set<std::string>(); } //------------------------------------------------------------------------------ @@ -599,39 +449,29 @@ void vtkIOSSWriter::PrintSelf(ostream& os, vtkIndent indent) os << indent << "FileName: " << (this->FileName ? this->FileName : "(nullptr)") << endl; os << indent << "AssemblyName: " << (this->AssemblyName ? this->AssemblyName : "(nullptr)") << endl; - os << indent - << "ChooseNodeBlockFieldsToWrite: " << (this->GetChooseNodeBlockFieldsToWrite() ? "On" : "Off") - << endl; - this->GetNodeSetFieldSelection()->PrintSelf(os, indent.GetNextIndent()); - os << indent << "ElementBlockSelectors: " << endl; - for (const auto& selector : this->Internals->ElementBlockSelectors) - { - os << indent << selector << " "; - } - os << endl; - os << indent << "ChooseElementBlockFieldsToWrite: " - << (this->GetChooseElementBlockFieldsToWrite() ? "On" : "Off") << endl; - this->GetElementBlockFieldSelection()->PrintSelf(os, indent.GetNextIndent()); - os << indent << "NodeSetSelectors: " << endl; - for (const auto& selector : this->Internals->NodeSetSelectors) + + os << indent << "ChooseFieldsToWrite: " << (this->ChooseFieldsToWrite ? "On" : "Off") << endl; + // Skip NodeBlock for selectors + for (int i = EntityType::EDGEBLOCK; i < EntityType::NUMBER_OF_ENTITY_TYPES; ++i) { - os << indent << selector << " "; + os << indent << vtkIOSSReader::GetDataAssemblyNodeNameForEntityType(i) + << " selectors: " << endl; + for (const auto& selector : this->Selectors[i]) + { + os << indent << selector << " "; + } + os << endl; } - os << endl; - os << indent - << "ChooseNodeSetFieldsToWrite: " << (this->GetChooseNodeSetFieldsToWrite() ? "On" : "Off") - << endl; - this->GetNodeSetFieldSelection()->PrintSelf(os, indent.GetNextIndent()); - os << indent << "SideSetSelectors: " << endl; - for (const auto& selector : this->Internals->SideSetSelectors) + if (this->ChooseFieldsToWrite) { - os << indent << selector << " "; + for (int i = EntityType::NODEBLOCK; i < EntityType::NUMBER_OF_ENTITY_TYPES; ++i) + { + os << indent << vtkIOSSReader::GetDataAssemblyNodeNameForEntityType(i) + << " fields to write: " << endl; + this->FieldSelection[i]->PrintSelf(os, indent.GetNextIndent()); + os << endl; + } } - os << endl; - os << indent - << "ChooseSideSetFieldsToWrite: " << (this->GetChooseSideSetFieldsToWrite() ? "On" : "Off") - << endl; - this->GetSideSetFieldSelection()->PrintSelf(os, indent.GetNextIndent()); os << indent << "RemoveGhosts: " << (this->RemoveGhosts ? "On" : "Off") << endl; os << indent << "Controller: " << this->Controller << endl; os << indent << "OffsetGlobalIds: " << OffsetGlobalIds << endl; diff --git a/IO/IOSS/vtkIOSSWriter.h b/IO/IOSS/vtkIOSSWriter.h index 15f7697a2c46515c74fbd18c8c081da995971e3b..19285b0894e82b1614ed72a8d588502a6eb63ac8 100644 --- a/IO/IOSS/vtkIOSSWriter.h +++ b/IO/IOSS/vtkIOSSWriter.h @@ -32,6 +32,8 @@ #include "vtkWriter.h" #include <memory> // for std::unique_ptr +#include <set> // for std::set +#include <string> // for std::string VTK_ABI_NAMESPACE_BEGIN class vtkDataArraySelection; @@ -67,146 +69,216 @@ public: using EntityType = vtkIOSSReader::EntityType; - ///////////////////////////////////////////////////////////////////////////////////////// - // Node Block API // - ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * Choose which node block fields to write. If this is true, then only the + * Choose which fields to write. If this is true, then only the * arrays selected will be written. If this is false, then all arrays will be * written. * * The default is false. */ - void SetChooseNodeBlockFieldsToWrite(bool value) - { - this->SetChooseEntityFieldsToWrite(EntityType::NODEBLOCK, value); - } - bool GetChooseNodeBlockFieldsToWrite() const - { - return this->GetChooseEntityFieldsToWrite(EntityType::NODEBLOCK); - } - vtkBooleanMacro(ChooseNodeBlockFieldsToWrite, bool); + vtkSetMacro(ChooseFieldsToWrite, bool); + vtkGetMacro(ChooseFieldsToWrite, bool); + vtkBooleanMacro(ChooseFieldsToWrite, bool); ///@} - /** - * Returns the field selection object for the element block arrays. - */ - vtkDataArraySelection* GetNodeBlockFieldSelection() - { - return this->GetEntityFieldSelection(EntityType::NODEBLOCK); - } - ///////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// - // Element Block API // + // Generic Entity API // ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * API to set element block selectors. Multiple selectors can be added using - * `AddElementBlockSelector`. The order in which selectors are specified is not preserved + * API to set entity selectors. Multiple selectors can be added using + * `AddSelector`. The order in which selectors are specified is not preserved * and has no impact on the result. * - * `AddElementBlockSelector` returns true if the selector was added, false if the selector + * `AddSelector` returns true if the selector was added, false if the selector * was already specified and hence not added. * * @sa vtkDataAssembly::SelectNodes */ - bool AddElementBlockSelector(const char* selector); - void ClearElementBlockSelectors(); + bool AddSelector(EntityType entity, const char* selector); + void ClearSelectors(EntityType entity); ///@} /** - * Convenience method to set a single element block selector. + * Convenience method to set a single entity selector. * This clears any other existing selectors. */ - void SetElementBlockSelector(const char* selector); + void SetSelector(EntityType entity, const char* selector); ///@{ /** - * API to access element block selectors. + * API to access entity selectors. */ - int GetNumberOfElementBlockSelectors() const; - const char* GetElementBlockSelector(int index) const; + int GetNumberOfSelectors(EntityType entity) const; + const char* GetSelector(EntityType entity, int index) const; + std::set<std::string> GetSelectors(EntityType entity) const; ///@} + /** + * Get the selection object for the given entity type. This can be used to + * select which fields to write. + */ + vtkDataArraySelection* GetFieldSelection(EntityType type); + ///////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////// + // Node Block API // + ///////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns the field selection object for the element block arrays. + */ + vtkDataArraySelection* GetNodeBlockFieldSelection() + { + return this->GetFieldSelection(EntityType::NODEBLOCK); + } + ///////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////// + // Edge Block API // + ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * Choose which element block fields to write. If this is true, then only the - * arrays selected will be written. If this is false, then all arrays will be - * written. - * - * The default is false. + * Add/Clear/Set/Get edge block selectors */ - void SetChooseElementBlockFieldsToWrite(bool value) + bool AddEdgeBlockSelector(const char* selector) { - this->SetChooseEntityFieldsToWrite(EntityType::ELEMENTBLOCK, value); + return this->AddSelector(EntityType::EDGEBLOCK, selector); } - bool GetChooseElementBlockFieldsToWrite() const + void ClearEdgeBlockSelectors() { this->ClearSelectors(EntityType::EDGEBLOCK); } + void SetEdgeBlockSelector(const char* selector) { - return this->GetChooseEntityFieldsToWrite(EntityType::ELEMENTBLOCK); + this->SetSelector(EntityType::EDGEBLOCK, selector); + } + int GetNumberOfEdgeBlockSelectors() const + { + return this->GetNumberOfSelectors(EntityType::EDGEBLOCK); + } + const char* GetEdgeBlockSelector(int index) const + { + return this->GetSelector(EntityType::EDGEBLOCK, index); + } + std::set<std::string> GetEdgeBlockSelectors() const + { + return this->GetSelectors(EntityType::EDGEBLOCK); } - vtkBooleanMacro(ChooseElementBlockFieldsToWrite, bool); ///@} /** - * Returns the field selection object for the element block arrays. + * Returns the field selection object for the edge block arrays. */ - vtkDataArraySelection* GetElementBlockFieldSelection() + vtkDataArraySelection* GetEdgeBlockFieldSelection() { - return this->GetEntityFieldSelection(EntityType::ELEMENTBLOCK); + return this->GetFieldSelection(EntityType::EDGEBLOCK); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// - // Node Set API // + // Face Block API // ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * API to set node set selectors. Multiple selectors can be added using - * `AddNodeSetSelector`. The order in which selectors are specified is not preserved - * and has no impact on the result. - * - * `AddNodeSetSelector` returns true if the selector was added, false if the selector - * was already specified and hence not added. - * - * @sa vtkDataAssembly::SelectNodes + * Add/Clear/Set/Get face block selectors */ - bool AddNodeSetSelector(const char* selector); - void ClearNodeSetSelectors(); + bool AddFaceBlockSelector(const char* selector) + { + return this->AddSelector(EntityType::FACEBLOCK, selector); + } + void ClearFaceBlockSelectors() { this->ClearSelectors(EntityType::FACEBLOCK); } + void SetFaceBlockSelector(const char* selector) + { + this->SetSelector(EntityType::FACEBLOCK, selector); + } + int GetNumberOfFaceBlockSelectors() const + { + return this->GetNumberOfSelectors(EntityType::FACEBLOCK); + } + const char* GetFaceBlockSelector(int index) const + { + return this->GetSelector(EntityType::FACEBLOCK, index); + } + std::set<std::string> GetFaceBlockSelectors() const + { + return this->GetSelectors(EntityType::FACEBLOCK); + } ///@} /** - * Convenience method to set a single node set selector. - * This clears any other existing selectors. + * Returns the field selection object for the face block arrays. */ - void SetNodeSetSelector(const char* selector); + vtkDataArraySelection* GetFaceBlockFieldSelection() + { + return this->GetFieldSelection(EntityType::FACEBLOCK); + } + ///////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////// + // Element Block API // + ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * API to access node set selectors. + * Add/Clear/Set/Get element block selectors */ - int GetNumberOfNodeSetSelectors() const; - const char* GetNodeSetSelector(int index) const; + bool AddElementBlockSelector(const char* selector) + { + return this->AddSelector(EntityType::ELEMENTBLOCK, selector); + } + void ClearElementBlockSelectors() { this->ClearSelectors(EntityType::ELEMENTBLOCK); } + void SetElementBlockSelector(const char* selector) + { + this->SetSelector(EntityType::ELEMENTBLOCK, selector); + } + int GetNumberOfElementBlockSelectors() const + { + return this->GetNumberOfSelectors(EntityType::ELEMENTBLOCK); + } + const char* GetElementBlockSelector(int index) const + { + return this->GetSelector(EntityType::ELEMENTBLOCK, index); + } + std::set<std::string> GetElementBlockSelectors() const + { + return this->GetSelectors(EntityType::ELEMENTBLOCK); + } ///@} + /** + * Returns the field selection object for the element block arrays. + */ + vtkDataArraySelection* GetElementBlockFieldSelection() + { + return this->GetFieldSelection(EntityType::ELEMENTBLOCK); + } + ///////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////// + // Node Set API // + ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * Choose which node set fields to write. If this is true, then only the - * arrays selected will be written. If this is false, then all arrays will be - * written. - * - * The default is false. + * Add/Clear/Set/Get node set selectors */ - void SetChooseNodeSetFieldsToWrite(bool value) + bool AddNodeSetSelector(const char* selector) + { + return this->AddSelector(EntityType::NODESET, selector); + } + void ClearNodeSetSelectors() { this->ClearSelectors(EntityType::NODESET); } + void SetNodeSetSelector(const char* selector) { - this->SetChooseEntityFieldsToWrite(EntityType::NODESET, value); + this->SetSelector(EntityType::NODESET, selector); } - bool GetChooseNodeSetFieldsToWrite() const + int GetNumberOfNodeSetSelectors() const { - return this->GetChooseEntityFieldsToWrite(EntityType::NODESET); + return this->GetNumberOfSelectors(EntityType::NODESET); + } + const char* GetNodeSetSelector(int index) const + { + return this->GetSelector(EntityType::NODESET, index); + } + std::set<std::string> GetNodeSetSelectors() const + { + return this->GetSelectors(EntityType::NODESET); } - vtkBooleanMacro(ChooseNodeSetFieldsToWrite, bool); ///@} /** @@ -214,61 +286,155 @@ public: */ vtkDataArraySelection* GetNodeSetFieldSelection() { - return this->GetEntityFieldSelection(EntityType::NODESET); + return this->GetFieldSelection(EntityType::NODESET); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// - // Side Set API // + // Edge Set API // ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * API to set side set selectors. Multiple selectors can be added using - * `AddSideSetSelector`. The order in which selectors are specified is not preserved - * and has no impact on the result. - * - * `AddSideSetSelector` returns true if the selector was added, false if the selector - * was already specified and hence not added. - * - * @sa vtkDataAssembly::SelectNodes - * - * Default: /IOSS/side_sets + * Add/Clear/Set/Get edge set selectors */ - bool AddSideSetSelector(const char* selector); - void ClearSideSetSelectors(); + bool AddEdgeSetSelector(const char* selector) + { + return this->AddSelector(EntityType::SIDESET, selector); + } + void ClearEdgeSetSelectors() { this->ClearSelectors(EntityType::SIDESET); } + void SetEdgeSetSelector(const char* selector) + { + this->SetSelector(EntityType::SIDESET, selector); + } + int GetNumberOfEdgeSetSelectors() const + { + return this->GetNumberOfSelectors(EntityType::SIDESET); + } + const char* GetEdgeSetSelector(int index) const + { + return this->GetSelector(EntityType::SIDESET, index); + } + std::set<std::string> GetEdgeSetSelectors() const + { + return this->GetSelectors(EntityType::SIDESET); + } ///@} /** - * Convenience method to set a single side set selector. - * This clears any other existing selectors. + * Returns the field selection object for the edge set arrays. + */ + vtkDataArraySelection* GetEdgeSetFieldSelection() + { + return this->GetFieldSelection(EntityType::SIDESET); + } + ///////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////// + // Face Set API // + ///////////////////////////////////////////////////////////////////////////////////////// + ///@{ + /** + * Add/Clear/Set/Get edge set selectors + */ + bool AddFaceSetSelector(const char* selector) + { + return this->AddSelector(EntityType::SIDESET, selector); + } + void ClearFaceSetSelectors() { this->ClearSelectors(EntityType::SIDESET); } + void SetFaceSetSelector(const char* selector) + { + this->SetSelector(EntityType::SIDESET, selector); + } + int GetNumberOfFaceSetSelectors() const + { + return this->GetNumberOfSelectors(EntityType::SIDESET); + } + const char* GetFaceSetSelector(int index) const + { + return this->GetSelector(EntityType::SIDESET, index); + } + std::set<std::string> GetFaceSetSelectors() const + { + return this->GetSelectors(EntityType::SIDESET); + } + ///@} + + /** + * Returns the field selection object for the edge set arrays. */ - void SetSideSetSelector(const char* selector); + vtkDataArraySelection* GetFaceSetFieldSelection() + { + return this->GetFieldSelection(EntityType::SIDESET); + } + ///////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////// + // Element Set API // + ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * API to access side set selectors. + * Add/Clear/Set/Get element set selectors */ - int GetNumberOfSideSetSelectors() const; - const char* GetSideSetSelector(int index) const; + bool AddElementSetSelector(const char* selector) + { + return this->AddSelector(EntityType::SIDESET, selector); + } + void ClearElementSetSelectors() { this->ClearSelectors(EntityType::SIDESET); } + void SetElementSetSelector(const char* selector) + { + this->SetSelector(EntityType::SIDESET, selector); + } + int GetNumberOfElementSetSelectors() const + { + return this->GetNumberOfSelectors(EntityType::SIDESET); + } + const char* GetElementSetSelector(int index) const + { + return this->GetSelector(EntityType::SIDESET, index); + } + std::set<std::string> GetElementSetSelectors() const + { + return this->GetSelectors(EntityType::SIDESET); + } ///@} + /** + * Returns the field selection object for the element set arrays. + */ + vtkDataArraySelection* GetElementSetFieldSelection() + { + return this->GetFieldSelection(EntityType::SIDESET); + } + ///////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////////////////////// + // Side Set API // + ///////////////////////////////////////////////////////////////////////////////////////// ///@{ /** - * Choose which side set fields to write. If this is true, then only the - * arrays selected will be written. If this is false, then all arrays will be - * written. - * - * The default is false. + * Add/Clear/Set/Get side set selectors */ - void SetChooseSideSetFieldsToWrite(bool value) + bool AddSideSetSelector(const char* selector) + { + return this->AddSelector(EntityType::SIDESET, selector); + } + void ClearSideSetSelectors() { this->ClearSelectors(EntityType::SIDESET); } + void SetSideSetSelector(const char* selector) + { + this->SetSelector(EntityType::SIDESET, selector); + } + int GetNumberOfSideSetSelectors() const { - this->SetChooseEntityFieldsToWrite(EntityType::SIDESET, value); + return this->GetNumberOfSelectors(EntityType::SIDESET); } - bool GetChooseSideSetFieldsToWrite() const + const char* GetSideSetSelector(int index) const { - return this->GetChooseEntityFieldsToWrite(EntityType::SIDESET); + return this->GetSelector(EntityType::SIDESET, index); + } + std::set<std::string> GetSideSetSelectors() const + { + return this->GetSelectors(EntityType::SIDESET); } - vtkBooleanMacro(ChooseSideSetFieldsToWrite, bool); ///@} /** @@ -276,7 +442,7 @@ public: */ vtkDataArraySelection* GetSideSetFieldSelection() { - return this->GetEntityFieldSelection(EntityType::SIDESET); + return this->GetFieldSelection(EntityType::SIDESET); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -430,14 +596,10 @@ private: class vtkInternals; std::unique_ptr<vtkInternals> Internals; - void SetChooseEntityFieldsToWrite(EntityType type, bool val); - bool GetChooseEntityFieldsToWrite(EntityType type) const; - - vtkDataArraySelection* GetEntityFieldSelection(EntityType type); - vtkMultiProcessController* Controller; char* FileName; char* AssemblyName; + bool ChooseFieldsToWrite; bool RemoveGhosts; bool OffsetGlobalIds; bool PreserveOriginalIds; @@ -445,8 +607,9 @@ private: double DisplacementMagnitude; int TimeStepRange[2]; int TimeStepStride; - bool ChooseEntityFieldsToWrite[EntityType::NUMBER_OF_ENTITY_TYPES]; - vtkNew<vtkDataArraySelection> EntityFieldSelection[EntityType::NUMBER_OF_ENTITY_TYPES]; + + std::set<std::string> Selectors[EntityType::NUMBER_OF_ENTITY_TYPES]; + vtkNew<vtkDataArraySelection> FieldSelection[EntityType::NUMBER_OF_ENTITY_TYPES]; }; VTK_ABI_NAMESPACE_END