Commit f9af8ca2 authored by Greg Sjaardema's avatar Greg Sjaardema
Browse files

IOSS: Update db_zone property after reopening cgns database

The CGNS library will reorder (sort) zones based on their names,
so if an application defines zones to an output file; closes that
file and then reopens the file, the zones on the file will have
a different ordering or indexing than when they were originally
defined on the file.

This commit causes the IOSS library to update the `db_zone` property
on all StructuredBlocks and ElementBlocks when a CGNS database
is closed and then reopened.  It also verifies that all expected
zones (blocks) exist on the database.

Discovered by SPARC team. Verified that fix works for the issue
that they reported. Developing a test to make this continues to work.
parent ec7ddad2
......@@ -534,6 +534,9 @@ namespace Iocgns {
set_int_byte_size_api(Ioss::USE_INT64_API);
}
if (mode == CG_MODE_MODIFY) {
Utils::update_db_zone_property(m_cgnsFilePtr, get_region(), myProcessor, isParallel);
}
#if 0
// This isn't currently working since CGNS currently has chunking
// disabled for HDF5 files and compression requires chunking.
......
......@@ -284,6 +284,9 @@ namespace Iocgns {
set_int_byte_size_api(Ioss::USE_INT64_API);
}
if (mode == CG_MODE_MODIFY) {
Utils::update_db_zone_property(m_cgnsFilePtr, get_region(), myProcessor, false);
}
#if 0
// This isn't currently working since CGNS currently has chunking
// disabled for HDF5 files and compression requires chunking.
......
......@@ -57,6 +57,7 @@
#include <Ioss_Wedge18.h>
#include <Ioss_Wedge6.h>
#include <tokenize.h>
#include <numeric>
#include <set>
......@@ -77,6 +78,29 @@
}
namespace {
std::pair<std::string, int> decompose_name(const std::string &name, bool is_parallel)
{
int proc = 0;
std::string zname{name};
if (is_parallel) {
// Name should/might be of the form `basename_proc-#`. Strip
// off the `_proc-#` portion and return just the basename.
auto tokens = Ioss::tokenize(zname, "_");
zname = tokens[0];
if (tokens.size() >= 2) {
size_t idx = tokens.size() - 1;
if (tokens[idx].substr(0, 5) == "proc-") {
auto ptoken = Ioss::tokenize(tokens[idx], "-");
proc = std::stoi(ptoken[1]);
idx--;
zname = tokens[idx];
}
}
}
return std::make_pair(zname, proc);
}
int power_2(int count)
{
// Return the maximum power of two which is less than or equal to 'count'
......@@ -419,6 +443,64 @@ Ioss::MeshType Iocgns::Utils::check_mesh_type(int cgns_file_ptr)
}
}
void Iocgns::Utils::update_db_zone_property(int cgns_file_ptr, const Ioss::Region *region,
int myProcessor, bool is_parallel)
{
// If an output file is closed/opened, make sure that the zones in the Region
// match the zones on the database (file). CGNS likes to sort the zones, so they
// might be in a different order after reopening. Update the 'db_zone_id' property...
int num_zones = 0;
int base = 1;
CGCHECK(cg_nzones(cgns_file_ptr, base, &num_zones));
// Read each zone and put names in a map indexed by zone id.
// Then iterate all of the region's structured blocks and element blocks
// and make sure that the zone exists in the map and then update the 'db_zone'
std::map<std::string, int> zones;
for (int zone = 1; zone <= num_zones; zone++) {
cgsize_t size[9];
char zname[CGNS_MAX_NAME_LENGTH + 1];
CGCHECK(cg_zone_read(cgns_file_ptr, base, zone, zname, size));
auto name_proc = decompose_name(std::string(zname), is_parallel);
zones[name_proc.first] = zone;
}
const auto &sblocks = region->get_structured_blocks();
for (const auto &block : sblocks) {
if (block->is_active()) {
const std::string &name = block->name();
auto iter = zones.find(name);
if (iter != zones.end()) {
auto db_zone = (*iter).second;
block->property_update("db_zone", db_zone);
}
else {
std::ostringstream errmsg;
errmsg << "ERROR: CGNS: Structured Block " << name
<< " was not found on the CGNS database on processor " << myProcessor;
IOSS_ERROR(errmsg);
}
}
}
const auto &eblocks = region->get_element_blocks();
for (const auto &block : eblocks) {
const std::string &name = block->name();
auto iter = zones.find(name);
if (iter != zones.end()) {
auto db_zone = (*iter).second;
block->property_update("db_zone", db_zone);
}
else {
std::ostringstream errmsg;
errmsg << "ERROR: CGNS: Element Block " << name
<< " was not found on the CGNS database on processor " << myProcessor;
IOSS_ERROR(errmsg);
}
}
}
int Iocgns::Utils::get_db_zone(const Ioss::EntityBlock *block)
{
// Returns the zone of the entity as it appears on the cgns database.
......
......@@ -86,6 +86,8 @@ namespace Iocgns {
static void cgns_error(int cgnsid, const char *file, const char *function, int lineno,
int processor);
static void update_db_zone_property(int cgns_file_ptr, const Ioss::Region *region,
int myProcessor, bool is_parallel);
static int get_db_zone(const Ioss::EntityBlock *block);
static void set_field_index(const Ioss::Field &field, size_t index, CG_GridLocation_t location);
static bool is_cell_field(const Ioss::Field &field);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment