diff --git a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C index 8c9ee4e2f7..69224c565a 100644 --- a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C @@ -8,6 +8,7 @@ #include #include "Ioss_CommSet.h" // for CommSet +#include "Ioss_CodeTypes.h" // for IOSS_SCALAR() #include "Ioss_DBUsage.h" // for DatabaseUsage, etc #include "Ioss_DatabaseIO.h" // for DatabaseIO #include "Ioss_EdgeBlock.h" // for EdgeBlock @@ -141,6 +142,8 @@ namespace Iocatalyst { inline static const std::string RANGEEND = "m_rangeEnd"; inline static const std::string FACE = "m_face"; + inline static const std::string SURFACESPLITTYPE = "surface_split_type"; + std::string getValuePath(const std::string &prop) { return detail::PROPERTIES + detail::FS + prop + detail::FS + detail::VALUE; @@ -305,12 +308,17 @@ namespace Iocatalyst { bool defineModel(Ioss::Region *region) { - assert(region->model_defined()); + if(!region->model_defined()) { + std::ostringstream errmsg; + errmsg << "Catalyst Write in defineModel(): model isn't defined in region"<<"\n"; + IOSS_ERROR(errmsg); + } auto &node = this->DBNode; node = conduit_cpp::Node(); node[detail::getAPISizePath()].set_int8(region->get_database()->int_byte_size_api()); + node[detail::SURFACESPLITTYPE].set_int8(region->get_database()->get_surface_split_type()); RegionContainer rc; rc.push_back(region); this->defineEntityGroup(node[detail::REGION], rc); @@ -810,6 +818,24 @@ namespace Iocatalyst { template bool readFields(const conduit_cpp::Node &&parent, GroupingEntityT *block) const { + //Assumption: count = entity_count (in block) + Ioss::DatabaseIO *dbase = block->get_database(); + Ioss::EntityType b_t = block->type(); + bool is_entity_block = false; + if(b_t == Ioss::EntityType::ELEMENTBLOCK || + b_t == Ioss::EntityType::EDGEBLOCK || + b_t == Ioss::EntityType::FACEBLOCK || + b_t == Ioss::EntityType::NODEBLOCK || + b_t == Ioss::EntityType::SIDEBLOCK || + b_t == Ioss::EntityType::STRUCTUREDBLOCK) { + is_entity_block = true; + } + const int FNAME_MAX_LENGTH = 255; + size_t field_count = 0; + char **field_names = + Ioss::Utils::get_name_array(parent.number_of_children(), FNAME_MAX_LENGTH); + size_t entity_count = 0; + for (conduit_index_t idx = 0, max = parent.number_of_children(); idx < max; ++idx) { auto &&child = parent[idx]; const auto name = child.name(); @@ -819,17 +845,43 @@ namespace Iocatalyst { const auto index = child[detail::INDEX].as_int64(); const auto storage = child[detail::STORAGE].as_string(); if (!block->field_exists(name)) { - block->field_add( + if(storage == IOSS_SCALAR() && role==Ioss::Field::TRANSIENT && is_entity_block) { + //Add to get_fields() call + char field_name[FNAME_MAX_LENGTH + 1]; + Ioss::Utils::copy_string(field_name, name, FNAME_MAX_LENGTH + 1); + Ioss::Utils::copy_string(field_names[field_count++], field_name, FNAME_MAX_LENGTH + 1); + if(entity_count == 0) + entity_count = count; + } + else { + block->field_add( Ioss::Field(name, type, storage, role, count, index).set_zero_copy_enabled()); + } } else { - // TODO verify field details. - auto field = block->get_fieldref(name); - if (!field.has_transform()) { + // Verify field details. + auto field_block = block->get_fieldref(name); + if (!field_block.has_transform()) { block->get_fieldref(name).set_zero_copy_enabled(); } - assert(field.get_type() == type); - auto f = block->get_fieldref(name); + auto field_conduit = Ioss::Field(name, type, storage, role, count, index).set_zero_copy_enabled(); + if(field_block != field_conduit) { + std::ostringstream errmsg; + errmsg << "Catalyst Read: Field '"<name().c_str()<< + "' of type '"<type_string()<<"' and differs from it\n"; + IOSS_ERROR(errmsg); + } + } + } + + //Apply Exodus Properties to Scalar Fields in Entity Blocks + if(field_count > 0) { + std::vector fields; + Ioss::Utils::get_fields(entity_count, field_names, field_count, Ioss::Field::TRANSIENT, + dbase, nullptr, fields); + for (const auto &field : fields) { + block->field_add(field.set_zero_copy_enabled()); } } @@ -1039,6 +1091,12 @@ namespace Iocatalyst { auto &node = this->DBNode; region->get_database()->set_int_byte_size_api( static_cast(node[detail::getAPISizePath()].as_int8())); + const auto write_split_type = + static_cast(node[detail::SURFACESPLITTYPE].as_int8()); + if(write_split_type != region->get_database()->get_surface_split_type()) { + static_cast(region->get_database())->set_split_type_changed(true); + } + auto tpath = detail::REGION + detail::FS + detail::TIME; if (node.has_path(tpath)) { region->add_state(node[tpath].to_float64()); @@ -1048,8 +1106,14 @@ namespace Iocatalyst { this->readEntityGroup(node[detail::ELEMENTBLOCKS], region); this->readEntityGroup(node[detail::EDGEBLOCKS], region); this->readEntityGroup(node[detail::FACEBLOCKS], region); - this->readEntityGroup(node[detail::SIDEBLOCKS], region); - this->readEntityGroup(node[detail::SIDESETS], region); + + bool surface_split_changed = + static_cast(region->get_database())->split_type_changed(); + if(!surface_split_changed) { + this->readEntityGroup(node[detail::SIDEBLOCKS], region); + this->readEntityGroup(node[detail::SIDESETS], region); + } + this->readEntityGroup(node[detail::NODESETS], region); this->readEntityGroup(node[detail::EDGESETS], region); this->readEntityGroup(node[detail::FACESETS], region); @@ -1116,11 +1180,19 @@ namespace Iocatalyst { bool DatabaseIO::end_nl(Ioss::State state) { - assert(this->dbState == state); + if(this->dbState != state) { + std::ostringstream errmsg; + errmsg << "Catalyst: dbState != state in end_nl"<<"\n"; + IOSS_ERROR(errmsg); + } if (!is_input()) { auto region = this->get_region(); - assert(region != nullptr); + if(region == nullptr) { + std::ostringstream errmsg; + errmsg << "Catalyst: region is nullptr in end_nl"<<"\n"; + IOSS_ERROR(errmsg); + } auto &impl = (*this->Impl.get()); switch (state) { @@ -1180,7 +1252,11 @@ namespace Iocatalyst { void DatabaseIO::read_meta_data_nl() { auto region = this->get_region(); - assert(region != nullptr); + if(region == nullptr) { + std::ostringstream errmsg; + errmsg << "Catalyst: region is nullptr in read_meta_data_nl()"<<"\n"; + IOSS_ERROR(errmsg); + } auto &impl = (*this->Impl.get()); impl.readModel(region); @@ -1189,7 +1265,11 @@ namespace Iocatalyst { void DatabaseIO::get_step_times_nl() { auto region = this->get_region(); - assert(region != nullptr); + if(region == nullptr) { + std::ostringstream errmsg; + errmsg << "Catalyst: region is nullptr in get_step_times_nl()"<<"\n"; + IOSS_ERROR(errmsg); + } auto &impl = (*this->Impl.get()); impl.readTime(region); @@ -1420,6 +1500,7 @@ namespace Iocatalyst { int64_t DatabaseIO::get_field_internal(const Ioss::SideBlock *sb, const Ioss::Field &field, void *data, size_t data_size) const { + if(split_type_changed()) { return -1; } auto &impl = (*this->Impl.get()); return impl.getField(detail::SIDEBLOCKS, sb, field, data, data_size); } @@ -1450,6 +1531,7 @@ namespace Iocatalyst { int64_t DatabaseIO::get_field_internal(const Ioss::SideSet *ss, const Ioss::Field &field, void *data, size_t data_size) const { + if(split_type_changed()) { return -1; } auto &impl = (*this->Impl.get()); return impl.getField(detail::SIDESETS, ss, field, data, data_size); } @@ -1531,6 +1613,7 @@ namespace Iocatalyst { int64_t DatabaseIO::get_zc_field_internal(const Ioss::SideBlock *sb, const Ioss::Field &field, void **data, size_t *data_size) const { + if(split_type_changed()) { return -1; } auto &impl = (*this->Impl.get()); return impl.getFieldZeroCopy(detail::SIDEBLOCKS, sb, field, data, data_size); } @@ -1561,6 +1644,7 @@ namespace Iocatalyst { int64_t DatabaseIO::get_zc_field_internal(const Ioss::SideSet *ss, const Ioss::Field &field, void **data, size_t *data_size) const { + if(split_type_changed()) { return -1; } auto &impl = (*this->Impl.get()); return impl.getFieldZeroCopy(detail::SIDESETS, ss, field, data, data_size); } diff --git a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.h b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.h index c9602e7a5b..743cebe6fa 100644 --- a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.h @@ -85,6 +85,9 @@ namespace Iocatalyst { std::string get_catalyst_dump_dir() const; + void set_split_type_changed(bool split_type_changed) { split_type_c = split_type_changed; } + IOSS_NODISCARD bool split_type_changed() const { return split_type_c; } + private: bool open_group_nl(const std::string & /* group_name */) override { return false; } bool create_subgroup_nl(const std::string & /* group_name */) override { return false; } @@ -202,5 +205,6 @@ namespace Iocatalyst { class ImplementationT; std::unique_ptr Impl; bool useDeepCopy; + bool split_type_c{false}; }; } // namespace Iocatalyst diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.C b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.C index 745b9cf91f..b5c5ab8bbb 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.C +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.C @@ -291,4 +291,24 @@ namespace Iocatalyst { return (extents.i + offset) * (extents.j + offset) * (extents.k + offset); } + std::map* BlockMesh::getTransientCellFieldMap() + { + return &(this->transientCellFields); + } + + std::map* BlockMesh::getTransientPointFieldMap() + { + return &(this->transientPointFields); + } + + void BlockMesh::addTransientCellField(std::string f_name, double f_value) + { + this->transientCellFields.insert({ f_name, f_value }); + } + + void BlockMesh::addTransientPointField(std::string f_name, double f_value) + { + this->transientPointFields.insert({ f_name, f_value }); + } + } // namespace Iocatalyst diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.h b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.h index 2732c6d60e..ba5c4caa21 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.h +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMesh.h @@ -82,6 +82,12 @@ namespace Iocatalyst { static Extent getCoordsForID(ID id, Extent bounds); static ID getIDfromCoords(Extent coords, Extent bounds); + void addTransientCellField(std::string f_name, double f_value); + void addTransientPointField(std::string f_name, double f_value); + + std::map* getTransientCellFieldMap(); + std::map* getTransientPointFieldMap(); + private: Partition partition; Extent origin; @@ -98,6 +104,9 @@ namespace Iocatalyst { int getNumInBlockMesh(unsigned int offset) const; ID id; static ID _id; + + std::map transientCellFields; + std::map transientPointFields; }; } // namespace Iocatalyst diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.C b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.C index a94edd44af..10fa7f5721 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.C +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.C @@ -40,18 +40,20 @@ namespace Iocatalyst { { CatalystManager::getInstance().reset(); iop.isCatalyst = true; + + //Cat Writes writeIOSSFile(iop); - Ioss::PropertyManager cdbProps; + Ioss::PropertyManager cdbProps = Ioss::PropertyManager(iop.dbProps); cdbProps.add(Ioss::Property("CATALYST_CONDUIT_NODE", iop.getCatalystConduitNode())); + //Cat Reads here Ioss::DatabaseIO *cdbi = Ioss::IOFactory::create(CATALYST_DATABASE_TYPE, CATALYST_DUMMY_DATABASE, Ioss::READ_RESTART, Ioss::ParallelUtils::comm_world(), cdbProps); if (cdbi == nullptr || !cdbi->ok(true)) { return; } - - Ioss::PropertyManager properties; + Ioss::PropertyManager properties = Ioss::PropertyManager(iop.dbProps); Ioss::DatabaseIO *cdbo = Ioss::IOFactory::create(iop.dbType, iop.fileName, Ioss::WRITE_RESULTS, Ioss::ParallelUtils::comm_world(), properties); @@ -68,6 +70,30 @@ namespace Iocatalyst { Ioss::copy_database(cir, cor, options); } + Ioss::DatabaseIO* BlockMeshSet::getCatalystDatabase(IOSSparams &iop) + { + CatalystManager::getInstance().reset(); + iop.isCatalyst = true; + + //Write to Cat database + writeIOSSFile(iop); + + Ioss::PropertyManager cdbProps = Ioss::PropertyManager(iop.dbProps); + + //Get Conduit + cdbProps.add(Ioss::Property("CATALYST_CONDUIT_NODE", iop.getCatalystConduitNode())); + + //Read to Cat Database + Ioss::DatabaseIO *cdbi = + Ioss::IOFactory::create(CATALYST_DATABASE_TYPE, CATALYST_DUMMY_DATABASE, Ioss::READ_RESTART, + Ioss::ParallelUtils::comm_world(), cdbProps); + if (cdbi == nullptr || !cdbi->ok(true)) { + return nullptr; + } + + return cdbi; + } + void BlockMeshSet::writeIOSSFile(IOSSparams &iop) { openIOSSDatabase(iop); @@ -80,7 +106,7 @@ namespace Iocatalyst { void BlockMeshSet::openIOSSDatabase(IOSSparams &iop) { - Ioss::PropertyManager properties; + Ioss::PropertyManager properties = Ioss::PropertyManager(iop.dbProps); std::string dbType = iop.dbType; if (iop.isCatalyst) { dbType = CATALYST_DATABASE_TYPE; @@ -162,7 +188,8 @@ namespace Iocatalyst { { auto c_node = reinterpret_cast( ((Iocatalyst::DatabaseIO *)iop.databaseIO)->get_catalyst_conduit_node()); - conduit_node_set_node(conduit_cpp::c_node(&iop.conduitNode), c_node); + auto cpp_node = conduit_cpp::cpp_node(c_node); + iop.conduitNode.set(cpp_node); } void BlockMeshSet::writeStructuredBlockDefinitions(IOSSparams &iop) @@ -231,6 +258,7 @@ namespace Iocatalyst { void BlockMeshSet::writeStructuredTransientFieldDefinitions(IOSSparams &iop) { for (auto bm : bms) { + //Modify this to access field dict in "bm" and populate ioss block with those fields (as well). auto iossBlock = iop.region->get_structured_block(getStructuredBlockName(bm.getID())); iossBlock->field_add(Ioss::Field(IOSS_CELL_FIELD, Ioss::Field::REAL, IOSS_SCALAR_STORAGE, Ioss::Field::TRANSIENT)); @@ -331,9 +359,39 @@ namespace Iocatalyst { auto nodeBlock = iop.region->get_node_block("nodeblock"); nodeBlock->field_add(Ioss::Field(IOSS_POINT_FIELD, Ioss::Field::REAL, IOSS_SCALAR_STORAGE, Ioss::Field::TRANSIENT)); + + writeUnstructuredAddedTransientFields(bm, iop); } } + void BlockMeshSet::writeUnstructuredAddedTransientFields(BlockMesh bm, IOSSparams &iop) + { + writeUnstructuredAddedCellTransientFields(bm, iop); + writeUnstructuredAddedPointTransientFields(bm, iop); + } + + void BlockMeshSet::writeUnstructuredAddedCellTransientFields(BlockMesh bm, IOSSparams &iop) + { + auto cell_fields = bm.getTransientCellFieldMap(); + auto elemBlock = iop.region->get_element_block(getUnstructuredBlockName(bm.getID())); + for (auto itr = cell_fields->begin(); itr != cell_fields->end(); ++itr) + { + elemBlock->field_add(Ioss::Field(itr->first, Ioss::Field::REAL, IOSS_SCALAR_STORAGE, + Ioss::Field::TRANSIENT)); + } + } + + void BlockMeshSet::writeUnstructuredAddedPointTransientFields(BlockMesh bm, IOSSparams &iop) + { + auto point_fields = bm.getTransientPointFieldMap(); + auto nodeBlock = iop.region->get_node_block("nodeblock"); + for (auto itr = point_fields->begin(); itr != point_fields->end(); ++itr) + { + nodeBlock->field_add(Ioss::Field(itr->first, Ioss::Field::REAL, IOSS_SCALAR_STORAGE, + Ioss::Field::TRANSIENT)); + } + } + void BlockMeshSet::writeUnstructuredTransientBulkData(IOSSparams &iop) { std::vector values; @@ -353,9 +411,47 @@ namespace Iocatalyst { values.push_back(bm.getPartition().id); } nodeBlock->put_field_data(IOSS_POINT_FIELD, values); + + writeUnstructuredAddedTransientFieldsBulkData(bm, iop); } } + void BlockMeshSet::writeUnstructuredAddedTransientFieldsBulkData(BlockMesh bm, IOSSparams &iop) + { + writeUnstructuredAddedCellTransientFieldsBulkData(bm, iop); + writeUnstructuredAddedPointTransientFieldsBulkData(bm, iop); + } + + void BlockMeshSet::writeUnstructuredAddedCellTransientFieldsBulkData(BlockMesh bm, IOSSparams &iop) + { + auto cell_fields = bm.getTransientCellFieldMap(); + auto elemBlock = iop.region->get_element_block(getUnstructuredBlockName(bm.getID())); + std::vector values; + for (auto itr = cell_fields->begin(); itr != cell_fields->end(); ++itr) + { + int num_elements = elemBlock->get_field(itr->first).raw_count(); + for (int j = 0; j < num_elements; j++) { + values.push_back(itr->second + j*0.1); + } + elemBlock->put_field_data(itr->first, values); + } + } + + void BlockMeshSet::writeUnstructuredAddedPointTransientFieldsBulkData(BlockMesh bm, IOSSparams &iop) + { + auto point_fields = bm.getTransientPointFieldMap(); + auto nodeBlock = iop.region->get_node_block("nodeblock"); + std::vector values; + for (auto itr = point_fields->begin(); itr != point_fields->end(); ++itr) + { + int num_nodes = nodeBlock->get_field(itr->first).raw_count(); + for (int j = 0; j < num_nodes; j++) { + values.push_back(itr->second + j*0.1); + } + nodeBlock->put_field_data(itr->first, values); + } + } + std::string BlockMeshSet::getStructuredBlockName(int index) { return "StructuredBlock" + std::to_string(index); diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.h b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.h index 3041e92158..bc98721fe3 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.h +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSet.h @@ -26,8 +26,8 @@ namespace Iocatalyst { class IOSSparams { public: - IOSSparams(const std::string &fileName, const std::string &dbType) - : fileName(fileName), dbType(dbType), databaseIO(nullptr), isCatalyst(false) + IOSSparams(const std::string &fileName, const std::string &dbType, Ioss::PropertyManager dbProps = {}) + : fileName(fileName), dbType(dbType), databaseIO(nullptr), isCatalyst(false), dbProps(dbProps) { } bool isStructured() { return dbType == CGNS_DATABASE_TYPE; } @@ -39,6 +39,7 @@ namespace Iocatalyst { bool isCatalyst; std::unique_ptr region; conduit_cpp::Node conduitNode; + Ioss::PropertyManager dbProps; private: IOSSparams(); @@ -47,8 +48,15 @@ namespace Iocatalyst { void addBlockMesh(const BlockMesh &blockMesh); void writeIOSSFile(IOSSparams &iop); void writeCatalystIOSSFile(IOSSparams &iop); + Ioss::DatabaseIO* getCatalystDatabase(IOSSparams &iop); + int getNumLocalPointsInMeshSet(); + std::string getStructuredBlockName(int index); + std::string getStructuredNodeBlockName(int index); + + std::string getUnstructuredBlockName(int index); + private: std::vector bms; @@ -68,15 +76,16 @@ namespace Iocatalyst { void writeUnstructuredBlockDefinitions(IOSSparams &iop); void writeUnstructuredBlockBulkData(IOSSparams &iop); void writeUnstructuredTransientFieldDefinitions(IOSSparams &iop); + void writeUnstructuredAddedTransientFields(BlockMesh bm, IOSSparams &iop); + void writeUnstructuredAddedCellTransientFields(BlockMesh bm, IOSSparams &iop); + void writeUnstructuredAddedPointTransientFields(BlockMesh bm, IOSSparams &iop); void writeUnstructuredTransientBulkData(IOSSparams &iop); + void writeUnstructuredAddedTransientFieldsBulkData(BlockMesh bm, IOSSparams &iop); + void writeUnstructuredAddedCellTransientFieldsBulkData(BlockMesh bm, IOSSparams &iop); + void writeUnstructuredAddedPointTransientFieldsBulkData(BlockMesh bm, IOSSparams &iop); void saveConduitNode(IOSSparams &iop); - std::string getStructuredBlockName(int index); - std::string getStructuredNodeBlockName(int index); - - std::string getUnstructuredBlockName(int index); - inline static const std::string CGNS_DATABASE_TYPE = "cgns"; inline static const std::string EXODUS_DATABASE_TYPE = "exodus"; inline static const std::string IOSS_CELL_FIELD = "cell"; diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSetTest.C b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSetTest.C index b5a0094539..98b155b038 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSetTest.C +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshSetTest.C @@ -31,4 +31,20 @@ TEST_F(Iocatalyst_DatabaseIOTest, GetNumLocalPointsInMeshSet) setOrigin(5, 0, 0); addBlockMesh(bmFour); EXPECT_EQ(bmSet.getNumLocalPointsInMeshSet(), 189); +} + +TEST_F(Iocatalyst_DatabaseIOTest, AddTransientFieldToBlockMesh) +{ + Iocatalyst::BlockMesh bmOne; + setBlockMeshSize(2, 2, 2); + + bmOne.addTransientCellField("foo_x", 2); + bmOne.addTransientPointField("bar_x", 3); + + addBlockMesh(bmOne); + + std::string exodusFileName = + "AddTransientFieldToBlockMesh" + CATALYST_TEST_FILE_NP + std::to_string(part.size) + EXODUS_FILE_EXTENSION; + Iocatalyst::BlockMeshSet::IOSSparams iop(exodusFileName, EXODUS_DATABASE_TYPE); + bmSet.writeIOSSFile(iop); } \ No newline at end of file diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshTest.C b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshTest.C index 1f9d43dfa0..12a7985c3d 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshTest.C +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_BlockMeshTest.C @@ -504,3 +504,21 @@ TEST_F(BlockMeshTest, GetGlobalIDForPointID) id = bmOne.getIDfromCoords(coords, bmOne.getGlobalPointExtents()); EXPECT_EQ(bmOne.getGlobalIDForPointID(27), id); } + +TEST_F(BlockMeshTest, AddTransientField) +{ + part.id = 0; + part.size = 1; + numBlocks.i = 2; + numBlocks.j = 2; + numBlocks.k = 2; + bmOne.init(part, numBlocks, origin); + + bmOne.addTransientCellField("foo_x", 2); + bmOne.addTransientPointField("bar_x", 3); + + auto cell_fields = bmOne.getTransientCellFieldMap(); + EXPECT_EQ((*cell_fields)["foo_x"], 2); + auto point_fields = bmOne.getTransientPointFieldMap(); + EXPECT_EQ((*point_fields)["bar_x"], 3); +} diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_DatabaseIOTest.C b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_DatabaseIOTest.C index e203091c0c..bdf3d43227 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_DatabaseIOTest.C +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_DatabaseIOTest.C @@ -5,6 +5,7 @@ // See packages/seacas/LICENSE for details #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include Iocatalyst_DatabaseIOTest::Iocatalyst_DatabaseIOTest() { @@ -90,6 +92,130 @@ void Iocatalyst_DatabaseIOTest::runUnstructuredTest(const std::string &testName) EXPECT_TRUE(regionsAreEqual(exodusFileName, catalystFileName, EXODUS_DATABASE_TYPE)); } +Ioss::DatabaseIO* Iocatalyst_DatabaseIOTest::writeAndGetExodusDatabaseOnRead(const std::string &testName, + Ioss::PropertyManager dbProps) +{ + std::string exodusFileName = + testName + CATALYST_TEST_FILE_NP + std::to_string(part.size) + EXODUS_FILE_EXTENSION; + Iocatalyst::BlockMeshSet::IOSSparams iop(exodusFileName, EXODUS_DATABASE_TYPE); + bmSet.writeIOSSFile(iop); + Ioss::DatabaseIO* exo_db = getDatabaseOnReadFromFileName(exodusFileName, EXODUS_DATABASE_TYPE, dbProps); + if(exo_db == nullptr) + { + EXPECT_TRUE(false) << "Exodus db unable to initialize on read"; + } + return exo_db; +} + +Ioss::DatabaseIO* Iocatalyst_DatabaseIOTest::getExodusDatabaseFromFile(std::string &filename, + Ioss::PropertyManager dbProps) { + Ioss::PropertyManager edbProps(dbProps); + + std::string inputFileName = filename; + + Ioss::DatabaseIO *edbi = + Ioss::IOFactory::create(EXODUS_DATABASE_TYPE, inputFileName, Ioss::READ_RESTART, + Ioss::ParallelUtils::comm_self(), edbProps); + if (edbi == nullptr || !edbi->ok(true)) { + return nullptr; + } + + return edbi; +} + +conduit_cpp::Node Iocatalyst_DatabaseIOTest::getConduitFromExodusFile(std::string &filename, + Ioss::PropertyManager dbProps) +{ + Iocatalyst::CatalystManager::getInstance().reset(); + + Ioss::PropertyManager edbProps; + edbProps.add(Ioss::Property("SURFACE_SPLIT_TYPE", "TOPOLOGY")); + Ioss::DatabaseIO *edbi = getExodusDatabaseFromFile(filename, edbProps); + + //Create Cat Db on write + Ioss::PropertyManager cdbwProps(edbi->get_property_manager()); + Ioss::DatabaseIO *cdb_on_write = + Ioss::IOFactory::create(CATALYST_DATABASE_TYPE, CATALYST_DUMMY_DATABASE, Ioss::WRITE_RESULTS, + Ioss::ParallelUtils::comm_world(), cdbwProps); + if (cdb_on_write == nullptr || !cdb_on_write->ok(true)) { + return conduit_cpp::Node(); + } + + Ioss::Region cor(edbi); + Ioss::Region cir(cdb_on_write); + Ioss::MeshCopyOptions options; + options.data_storage_type = 1; + Ioss::copy_database(cor, cir, options); + + auto c_node = reinterpret_cast( + ((Iocatalyst::DatabaseIO *)cdb_on_write)->get_catalyst_conduit_node()); + conduit_cpp::Node conduitNode; + auto cpp_node = conduit_cpp::cpp_node(c_node); + conduitNode.set(cpp_node); + return conduitNode; + +} + +Ioss::DatabaseIO* Iocatalyst_DatabaseIOTest::getCatalystDatabaseFromConduit(conduit_cpp::Node &conduitNode, + Ioss::PropertyManager dbProps) +{ + + Ioss::PropertyManager cdbrProps = Ioss::PropertyManager(dbProps); + cdbrProps.add(Ioss::Property("CATALYST_CONDUIT_NODE", conduit_cpp::c_node(&conduitNode))); + + //Give to Cat Db on read + Ioss::DatabaseIO *cdb_on_read = + Ioss::IOFactory::create(CATALYST_DATABASE_TYPE, CATALYST_DUMMY_DATABASE, Ioss::READ_RESTART, + Ioss::ParallelUtils::comm_world(), cdbrProps); + if (cdb_on_read == nullptr || !cdb_on_read->ok(true)) { + return nullptr; + } + + return cdb_on_read; +} + +Ioss::DatabaseIO* Iocatalyst_DatabaseIOTest::getDatabaseOnReadFromFileName(const std::string &fileName, + const std::string &iossDatabaseType, + Ioss::PropertyManager dbProps) +{ + Ioss::PropertyManager dbaseProps = Ioss::PropertyManager(dbProps); + //dbProps.add(Ioss::Property("ENABLE_FIELD_RECOGNITION", "OFF")); + auto inputFileName = fileName; + Ioss::ParallelUtils pu; + int numRanks = pu.parallel_size(); + int rank = pu.parallel_rank(); + if (iossDatabaseType == EXODUS_DATABASE_TYPE && numRanks > 1) { + inputFileName += "." + std::to_string(numRanks) + "." + std::to_string(rank); + } + Ioss::DatabaseIO *dbi = + Ioss::IOFactory::create(iossDatabaseType, inputFileName, Ioss::READ_RESTART, + Ioss::ParallelUtils::comm_self(), dbaseProps); + if (dbi == nullptr || !dbi->ok(true)) { + return nullptr; + } + return dbi; +} + +/*Ioss::DatabaseIO* Iocatalyst_DatabaseIOTest::writeAndGetCatalystDatabaseOnRead(Ioss::PropertyManager dbProps) +{ + std::string exodusFileName = + "test_eb_1_enable_field_recog" + CATALYST_TEST_FILE_NP + std::to_string(part.size) + EXODUS_FILE_EXTENSION; + Iocatalyst::BlockMeshSet::IOSSparams iop(exodusFileName, EXODUS_DATABASE_TYPE); + + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + //Ioss::Region cir(cat_d); + //std::cout<<"Done Region!"< @@ -63,4 +81,6 @@ class IOCATALYST_EXPORT Iocatalyst_DatabaseIOTest : public ::testing::Test const std::string EXODUS_FILE_EXTENSION = ".ex2"; const std::string CATALYST_TEST_FILE_PREFIX = "catalyst_"; const std::string CATALYST_TEST_FILE_NP = "_np_"; + inline static const std::string CATALYST_DATABASE_TYPE = "catalyst"; + inline static const std::string CATALYST_DUMMY_DATABASE = "dummy.db"; }; diff --git a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_ElementBlockTest.C b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_ElementBlockTest.C index 1541359134..afcbaa9141 100644 --- a/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_ElementBlockTest.C +++ b/packages/seacas/libraries/ioss/src/catalyst_tests/Iocatalyst_ElementBlockTest.C @@ -5,6 +5,10 @@ // See packages/seacas/LICENSE for details #include +#include + +#include + TEST_F(Iocatalyst_DatabaseIOTest, WriteThreeElementBlocksWith24Cells) { @@ -58,4 +62,282 @@ TEST_F(Iocatalyst_DatabaseIOTest, WriteThreeElementBlocksWith835Cells) addBlockMesh(bmThree); runUnstructuredTest("test_eb_3_cells_835"); -} \ No newline at end of file +} + +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_ENABLE_FIELD_RECOGNITION_ON) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + bm.addTransientCellField("foo_x", 2); + bm.addTransientCellField("foo_y", 3); + bm.addTransientCellField("foo_z", 4); + + + addBlockMesh(bm); + + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("ENABLE_FIELD_RECOGNITION", "ON")); + Ioss::DatabaseIO *exo_d = writeAndGetExodusDatabaseOnRead("test_eb_1_enable_field_recog", iossProp); + + Iocatalyst::BlockMeshSet::IOSSparams iop("cat", EXODUS_DATABASE_TYPE, iossProp); + + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize on read"; } + Ioss::Region cat_reg(cat_d); + + Ioss::Region exo_reg(exo_d); + + auto cat_elemBlock = cat_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + auto exo_elemBlock = exo_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + + bool exo_foo_exists = exo_elemBlock->field_exists("foo"); + bool cat_foo_exists = cat_elemBlock->field_exists("foo"); + EXPECT_TRUE(exo_foo_exists); + EXPECT_TRUE(cat_foo_exists); + if(exo_foo_exists && cat_foo_exists) + EXPECT_TRUE(exo_elemBlock->get_field("foo") == cat_elemBlock->get_field("foo")); + + //Check foo_x doesn't exist + bool exo_foo_x_exists = exo_elemBlock->field_exists("foo_x"); + bool cat_foo_x_exists = cat_elemBlock->field_exists("foo_x"); + EXPECT_FALSE(exo_foo_x_exists); + EXPECT_FALSE(cat_foo_x_exists); +} + +//Sanity Test +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_ENABLE_FIELD_RECOGNITION_OFF) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + bm.addTransientCellField("foo_x", 2); + bm.addTransientCellField("foo_y", 3); + bm.addTransientCellField("foo_z", 4); + + + addBlockMesh(bm); + + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("ENABLE_FIELD_RECOGNITION", "OFF")); + Ioss::DatabaseIO *exo_d = writeAndGetExodusDatabaseOnRead("test_eb_1_enable_field_recog", iossProp); + + Iocatalyst::BlockMeshSet::IOSSparams iop("cat", EXODUS_DATABASE_TYPE, iossProp); + + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize on read"; } + Ioss::Region cat_reg(cat_d); + + Ioss::Region exo_reg(exo_d); + + auto cat_elemBlock = cat_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + auto exo_elemBlock = exo_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + + bool exo_foo_x_exists = exo_elemBlock->field_exists("foo_x"); + bool cat_foo_x_exists = cat_elemBlock->field_exists("foo_x"); + EXPECT_TRUE(exo_foo_x_exists); + EXPECT_TRUE(cat_foo_x_exists); + if(exo_foo_x_exists && cat_foo_x_exists) + EXPECT_TRUE(exo_elemBlock->get_field("foo_x") == cat_elemBlock->get_field("foo_x")); + +} + + +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_IGNORE_REALN_FIELDS_ON) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + bm.addTransientCellField("foo_1", 2); + bm.addTransientCellField("foo_2", 3); + bm.addTransientCellField("foo_3", 4); + + + addBlockMesh(bm); + + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("IGNORE_REALN_FIELDS", "ON")); + Ioss::DatabaseIO *exo_d = writeAndGetExodusDatabaseOnRead("test_eb_1_ignore_realn_fields", iossProp); + + Iocatalyst::BlockMeshSet::IOSSparams iop("cat", EXODUS_DATABASE_TYPE, iossProp); + + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize on read"; } + Ioss::Region cat_reg(cat_d); + + Ioss::Region exo_reg(exo_d); + + auto cat_elemBlock = cat_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + auto exo_elemBlock = exo_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + + bool exo_foo_1_exists = exo_elemBlock->field_exists("foo_1"); + bool cat_foo_1_exists = cat_elemBlock->field_exists("foo_1"); + EXPECT_TRUE(exo_foo_1_exists); + EXPECT_TRUE(cat_foo_1_exists); + if(exo_foo_1_exists && cat_foo_1_exists) + EXPECT_TRUE(exo_elemBlock->get_field("foo_1") == cat_elemBlock->get_field("foo_1")); +} + +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_IGNORE_REALN_FIELDS_OFF) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + bm.addTransientCellField("foo_1", 2); + bm.addTransientCellField("foo_2", 3); + bm.addTransientCellField("foo_3", 4); + + + addBlockMesh(bm); + + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("IGNORE_REALN_FIELDS", "OFF")); + Ioss::DatabaseIO *exo_d = writeAndGetExodusDatabaseOnRead("test_eb_1_ignore_realn_fields_off", iossProp); + + Iocatalyst::BlockMeshSet::IOSSparams iop("cat", EXODUS_DATABASE_TYPE, iossProp); + + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize on read"; } + Ioss::Region cat_reg(cat_d); + + Ioss::Region exo_reg(exo_d); + + auto cat_elemBlock = cat_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + auto exo_elemBlock = exo_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + + bool exo_foo_exists = exo_elemBlock->field_exists("foo"); + bool cat_foo_exists = cat_elemBlock->field_exists("foo"); + EXPECT_TRUE(exo_foo_exists); + EXPECT_TRUE(cat_foo_exists); + if(exo_foo_exists && cat_foo_exists) + EXPECT_TRUE(exo_elemBlock->get_field("foo") == cat_elemBlock->get_field("foo")); +} + +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_FIELD_SUFFIX_SEPARATOR) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + bm.addTransientCellField("foo_x", 2); + bm.addTransientCellField("foo_y", 3); + bm.addTransientCellField("foo_z", 4); + bm.addTransientCellField("bar:x", 5); + bm.addTransientCellField("bar:y", 6); + bm.addTransientCellField("bar:z", 7); + + + addBlockMesh(bm); + + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("FIELD_SUFFIX_SEPARATOR", ":")); + + Ioss::DatabaseIO *exo_d = writeAndGetExodusDatabaseOnRead("test_eb_1_field_suf_sep", iossProp); + + Iocatalyst::BlockMeshSet::IOSSparams iop("cat", EXODUS_DATABASE_TYPE, iossProp); + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize on read"; } + Ioss::Region cat_reg(cat_d); + + Ioss::Region exo_reg(exo_d); + + auto cat_elemBlock = cat_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + auto exo_elemBlock = exo_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + + bool exo_foo_x_exists = exo_elemBlock->field_exists("foo_x"); + bool cat_foo_x_exists = cat_elemBlock->field_exists("foo_x"); + EXPECT_TRUE(exo_foo_x_exists); + EXPECT_TRUE(cat_foo_x_exists); + if(exo_foo_x_exists && cat_foo_x_exists) + EXPECT_TRUE(exo_elemBlock->get_field("foo_x") == cat_elemBlock->get_field("foo_x")); + + bool exo_bar_exists = exo_elemBlock->field_exists("bar"); + bool cat_bar_exists = cat_elemBlock->field_exists("bar"); + EXPECT_TRUE(exo_bar_exists); + EXPECT_TRUE(cat_bar_exists); + if(exo_bar_exists && cat_bar_exists) + EXPECT_TRUE(exo_elemBlock->get_field("bar") == cat_elemBlock->get_field("bar")); + +} + +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_FIELD_STRIP_TRAILING_UNDERSCORE) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + bm.addTransientCellField("foo_x", 2); + bm.addTransientCellField("foo_y", 3); + bm.addTransientCellField("foo_z", 4); + + addBlockMesh(bm); + + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("FIELD_STRIP_TRAILING_UNDERSCORE", "ON")); + iossProp.add(Ioss::Property("FIELD_SUFFIX_SEPARATOR", "")); + + Ioss::DatabaseIO *exo_d = writeAndGetExodusDatabaseOnRead("test_eb_1_field_strip_tr_unders", iossProp); + + Iocatalyst::BlockMeshSet::IOSSparams iop("cat", EXODUS_DATABASE_TYPE, iossProp); + + Ioss::DatabaseIO *cat_d = bmSet.getCatalystDatabase(iop); + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize on read"; } + Ioss::Region cat_reg(cat_d); + + Ioss::Region exo_reg(exo_d); + + auto cat_elemBlock = cat_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + auto exo_elemBlock = exo_reg.get_element_block(bmSet.getUnstructuredBlockName(bm.getID())); + + bool exo_foo_exists = exo_elemBlock->field_exists("foo"); + bool cat_foo_exists = cat_elemBlock->field_exists("foo"); + EXPECT_TRUE(exo_foo_exists); + EXPECT_TRUE(cat_foo_exists); + if(exo_foo_exists && cat_foo_exists) + EXPECT_TRUE(exo_elemBlock->get_field("foo") == cat_elemBlock->get_field("foo")); + +} + +//Read from file. Can. Or available exodus file in test suite. +TEST_F(Iocatalyst_DatabaseIOTest, Exodus_Prop_SURFACE_SPLIT_TYPE) +{ + Iocatalyst::BlockMesh bm; + setBlockMeshSize(2, 2, 2); + + addBlockMesh(bm); + + //If write and read have same split type, we can handle. Else no. + Ioss::PropertyManager iossProp; + iossProp.add(Ioss::Property("SURFACE_SPLIT_TYPE", "BLOCK")); + + std::string exoFile = "can.ex2"; + + conduit_cpp::Node c_node = getConduitFromExodusFile(exoFile, iossProp); + + Ioss::DatabaseIO *cat_d = getCatalystDatabaseFromConduit(c_node, iossProp); + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize"; } + + Ioss::Region cat_reg(cat_d); + + Ioss::SideSetContainer cat_sideSets = cat_reg.get_sidesets(); + + EXPECT_TRUE(cat_sideSets.empty())<<"Cat sidesets not empty when different SURFACE_SPLIT_TYPE"; + + Ioss::PropertyManager iossProp_s; + iossProp_s.add(Ioss::Property("SURFACE_SPLIT_TYPE", "TOPOLOGY")); + cat_d = getCatalystDatabaseFromConduit(c_node, iossProp_s); + + if(cat_d == nullptr){ EXPECT_TRUE(false) << "Catalyst db unable to initialize"; } + + Ioss::Region cat_reg_same(cat_d); + + cat_sideSets = cat_reg_same.get_sidesets(); + + EXPECT_TRUE(!cat_sideSets.empty())<<"Cat sidesets empty when identical SURFACE_SPLIT_TYPE"; + +}