Skip to content

Commit

Permalink
Fix silo global node ids for point meshes (#19302) (#19315)
Browse files Browse the repository at this point in the history
  • Loading branch information
markcmiller86 committed Feb 14, 2024
1 parent 57dcf45 commit 0efcefa
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 153 deletions.
231 changes: 81 additions & 150 deletions src/databases/Silo/avtSiloFileFormat.C
Original file line number Diff line number Diff line change
Expand Up @@ -14017,12 +14017,12 @@ avtSiloFileFormat::GetAuxiliaryData(const char *var, int domain,
}
else if (strcmp(type, AUXILIARY_DATA_GLOBAL_NODE_IDS) == 0)
{
rv = (void *) GetGlobalNodeIds(domain, var);
rv = (void *) GetGlobalIds(domain, var, "node");
df = avtVariableCache::DestructVTKObject;
}
else if (strcmp(type, AUXILIARY_DATA_GLOBAL_ZONE_IDS) == 0)
{
rv = (void *) GetGlobalZoneIds(domain, var);
rv = (void *) GetGlobalIds(domain, var, "zone");
df = avtVariableCache::DestructVTKObject;
}
else if (strcmp(type, AUXILIARY_DATA_SPATIAL_EXTENTS) == 0)
Expand Down Expand Up @@ -14303,15 +14303,15 @@ avtSiloFileFormat::GetSpecies(int dom, const char *spec)


// ****************************************************************************
// Method: avtSiloFileFormat::AllocAndDetermineMeshnameForUcdmesh
// Method: avtSiloFileFormat::DetermineMeshnameForMeshType
//
// Purpose:
// Allocate space for and determine the real mesh name for a ucd mesh,
// which may be a multimesh
// Determine the real mesh name for a multiblock mesh of a specific type.
//
// Arguments:
// dom The domain of the mesh.
// mesh The mesh we want the real name for
// mesh The mesh we want the real name for .
// mtype The Silo type for the mesh.
//
// Returns: The real mesh name
//
Expand All @@ -14323,68 +14323,65 @@ avtSiloFileFormat::GetSpecies(int dom, const char *spec)
// Limited support for Silo nameschemes, use new multi block cache data
// structures.
//
// Mark C. Miller, Tue Feb 13 09:23:13 PST 2024
// Switch from char * to string return value.
// ****************************************************************************

char *
avtSiloFileFormat::AllocAndDetermineMeshnameForUcdmesh(int dom, const char *mesh)
string
avtSiloFileFormat::DetermineMeshnameForMeshType(int dom, const char *mesh, int mtype)
{
//
// Get the file handle, throw an exception if it hasn't already been opened
//
string mb_meshname = "";
DBfile *dbfile = GetFile(tocIndex);

//
// Silo can't accept consts, so cast it away.
//
char *m = const_cast< char * >(mesh);
VisitMutexLock("avtSiloFileFormat");
int type = DBInqVarType(dbfile, m);
int type = DBInqVarType(dbfile, mesh);
VisitMutexUnlock("avtSiloFileFormat");

if (type != DB_MULTIMESH && type != DB_UCDMESH)
if (type != DB_MULTIMESH && type != mtype)
{
//
// This is not a ucd mesh or a multi-mesh, so it does not have a
// facelist.
// This is not the desired mesh type or a multi-mesh.
//
return NULL;
return mb_meshname;
}

DBmultimesh *mm = NULL;
avtSiloMultiMeshCacheEntry *mm_ent = NULL;
string mb_meshname = "";
char *meshname = NULL;

if (type == DB_MULTIMESH)
{
GetMultiMesh("", m, &mm_ent);
GetMultiMesh("", mesh, &mm_ent);
if(mm_ent != NULL)
mm = mm_ent->DataObject();
if (mm == NULL)
{
EXCEPTION1(InvalidFilesException, m);
EXCEPTION1(InvalidFilesException, mesh);
}
if (dom >= mm->nblocks || dom < 0 )
{
EXCEPTION2(BadDomainException, dom, mm->nblocks);
}
if (mm_ent->MeshType(dom) != DB_UCDMESH)
if (mm_ent->MeshType(dom) != mtype)
{
return NULL;
return mb_meshname;
}
mb_meshname = mm_ent->GenerateName(dom);
meshname = CXX_strdup(mb_meshname.c_str());
}
else // (type == DB_UCDMESH)
else // (type == mtype)
{
if (dom != 0)
{
EXCEPTION2(BadDomainException, dom, 1);
}
meshname = CXX_strdup(mesh);
}

return meshname;
return mb_meshname;
}


Expand Down Expand Up @@ -14433,8 +14430,8 @@ avtSiloFileFormat::GetExternalFacelist(int dom, const char *mesh)

DBfile *dbfile = GetFile(tocIndex);

char *meshname = AllocAndDetermineMeshnameForUcdmesh(dom, mesh);
if (meshname == NULL || string(meshname) == "EMPTY")
string meshname = DetermineMeshnameForMeshType(dom, mesh, DB_UCDMESH);
if (meshname == "" || meshname == "EMPTY")
return NULL;

//
Expand All @@ -14443,25 +14440,18 @@ avtSiloFileFormat::GetExternalFacelist(int dom, const char *mesh)
//
DBfile *domain_file = dbfile;
string directory_mesh;
DetermineFileAndDirectory(meshname, "", domain_file, directory_mesh);
DetermineFileAndDirectory(meshname.c_str(), "", domain_file, directory_mesh);

avtFacelist *rv = CalcExternalFacelist(domain_file, directory_mesh.c_str());

if (meshname != NULL)
{
delete [] meshname;
meshname = NULL;
}

return rv;
}


// ****************************************************************************
// Method: avtSiloFileFormat::GetGlobalNodeIds
// Method: avtSiloFileFormat::GetGlobalIds
//
// Purpose:
// Gets the global node ids from the Silo file
// Gets global mesh entity (nodes or zones) ids from the Silo file
//
// Programmer: Mark C. Miller
// Creation: August 4, 2004
Expand Down Expand Up @@ -14491,19 +14481,46 @@ avtSiloFileFormat::GetExternalFacelist(int dom, const char *mesh)
// Moved debug5 output lines indicating that global node ids are being read
// down so that it appears in debug logs only when there is actually data
// being read and returned from the plugin.
// ****************************************************************************
//
// Mark C. Miller, Mon Feb 12 20:26:21 PST 2024
// Refactored away GetGlobalZoneIds and GetGlobalNodeIds into this one
// method that does both and does so for both UCD and POINT meshes.
// The main tricks are to a) set Silo's data read mask appropriately (and
// then also reset it when done) and then b) to allow VisIt's cache to take
// ownership of the resulting data. We do this by zeroing the Silo object's
// data member holding the global ids and keeping a separate local pointer
// to the data. For point meshes, nodes and zones are one in the same so the
// logic for both is the same. For UCD meshes, there is separate logic for
// global node ids and global zone ids embodied by a different set of args
// to the LOAD_GLOBAL_IDS macro'd logic.
// ****************************************************************************
#define LOAD_GLOBAL_IDS(DBTYP, GETFUNC, CKMEMBR, FREEFUNC, MASK, GIDTYP, NIDS, IDS) \
do { \
DBSetDataReadMask2(MASK); \
DBTYP *obj = GETFUNC(domain_file, directory_mesh.c_str()); \
if (obj && obj->CKMEMBR) \
{ \
gids = obj->IDS; \
ngids = obj->NIDS; \
gidtype = obj->GIDTYP; \
obj->IDS = 0; \
} \
FREEFUNC(obj); \
} while (0)

vtkDataArray *
avtSiloFileFormat::GetGlobalNodeIds(int dom, const char *mesh)
avtSiloFileFormat::GetGlobalIds(int dom, char const *mesh, char const *idtype)
{
DBfile *dbfile = GetFile(tocIndex);

char *meshname = AllocAndDetermineMeshnameForUcdmesh(dom, mesh);
if (meshname == NULL || string(meshname) == "EMPTY")
int mtype = DB_UCDMESH;
string meshname = DetermineMeshnameForMeshType(dom, mesh, mtype);
if (meshname == "" || meshname == "EMPTY")
{
if (meshname != NULL)
delete [] meshname;
return NULL;
mtype = DB_POINTMESH;
meshname = DetermineMeshnameForMeshType(dom, mesh, mtype);
if (meshname == "" || meshname == "EMPTY")
return NULL;
}

//
Expand All @@ -14512,43 +14529,41 @@ avtSiloFileFormat::GetGlobalNodeIds(int dom, const char *mesh)
//
DBfile *domain_file = dbfile;
string directory_mesh;
DetermineFileAndDirectory(meshname, "", domain_file, directory_mesh);
DetermineFileAndDirectory(meshname.c_str(), "", domain_file, directory_mesh);

// We want to get just the global node ids. So we need to get the ReadMask,
// set it to read global node ids, then set it back.
unsigned long long mask = DBGetDataReadMask2();
DBSetDataReadMask2(DBUMGlobNodeNo);
DBucdmesh *um = DBGetUcdmesh(domain_file, directory_mesh.c_str());
DBSetDataReadMask2(mask);
if (um == NULL)
// Save whatever current data read mask is
unsigned long long saved_mask = DBGetDataReadMask2();

int ngids, gidtype;
void *gids = 0;
if (mtype == DB_UCDMESH)
{
if (!ignoreMissingBlocks)
{
EXCEPTION1(InvalidVariableException, mesh);
}
return 0;
if (string(idtype) == "node")
LOAD_GLOBAL_IDS(DBucdmesh, DBGetUcdmesh, gnodeno, DBFreeUcdmesh, DBUMGlobNodeNo, gnznodtype, nnodes, gnodeno);
else
LOAD_GLOBAL_IDS(DBucdmesh, DBGetUcdmesh, zones && obj->zones->gzoneno, DBFreeUcdmesh,
DBUMZonelist|DBZonelistGlobZoneNo|DBZonelistInfo,
zones->gnznodtype, zones->nzones, zones->gzoneno);
}
else if (mtype == DB_POINTMESH)
{
LOAD_GLOBAL_IDS(DBpointmesh, DBGetPointmesh, gnodeno, DBFreePointmesh, DBPMGlobNodeNo, gnznodtype, nels, gnodeno);
}
DBSetDataReadMask2(saved_mask);

vtkDataArray *rv = NULL;
if (um->gnodeno != NULL)
if (gids)
{

debug5 << "Reading in domain " << dom << ", global node ids for " << mesh << endl;
debug5 << "Reading in domain " << dom << ", global " << idtype << " ids for " << mesh << endl;
debug5 << "Reading in from toc " << filenames[tocIndex] << endl;

rv = CreateDataArray(um->gnznodtype, um->gnodeno, um->nnodes);
um->gnodeno = 0; // vtkDataArray owns the data now.

rv = CreateDataArray(gidtype, gids, ngids);
}

DBFreeUcdmesh(um);

delete [] meshname;

return rv;
}


// ****************************************************************************
// Method: avtSiloFileFormat::GetLocalDomainBoundaryInfo
//
Expand Down Expand Up @@ -14632,90 +14647,6 @@ avtSiloFileFormat::GetLocalDomainBoundaryInfo(int domain, const char *var)
return res;
}

// ****************************************************************************
// Method: avtSiloFileFormat::GetGlobalZoneIds
//
// Purpose:
// Gets the global zone ids from the Silo file
//
// Programmer: Mark C. Miller
// Creation: August 9, 2004
//
// Modifications:
// Mark C. Miller, Thu Oct 14 15:18:31 PDT 2004
// Uncommented the data read mask
//
// Mark C. Miller, Tue Jun 28 17:28:56 PDT 2005
// Made it handle the new "EMPTY" domain convention
//
// Mark C. Miller, Sun Dec 3 12:20:11 PST 2006
// Moved code to set data read mask back to its original value to *before*
// throwing of exeption.
//
// Mark C. Miller, Thu Oct 15 21:31:07 PDT 2009
// Add DBZonelistInfo to data read mask to work around a bug in Silo
// library where attempt to DBGetUcdmesh causes call to DBGetZonelist
// and a subsequent segv down in the bowels of Silo due to invalid
// assumptions regarding the existence of certain zonelist strutures.
//
// Mark C. Miller, Tue Jan 12 17:55:54 PST 2010
// Use CreateDataArray for global zone numbers, handling long long too.
//
// Cyrus Harrison, Wed Dec 21 15:22:21 PST 2011
// Limited support for Silo nameschemes, use new multi block cache data
// structures.
//
// ****************************************************************************

vtkDataArray *
avtSiloFileFormat::GetGlobalZoneIds(int dom, const char *mesh)
{
debug5 << "Reading in domain " << dom << ", global zone ids for " << mesh << endl;
debug5 << "Reading in from toc " << filenames[tocIndex] << endl;

DBfile *dbfile = GetFile(tocIndex);

char *meshname = AllocAndDetermineMeshnameForUcdmesh(dom, mesh);
if (meshname == NULL || string(meshname) == "EMPTY")
return NULL;

//
// Some Silo objects are distributed across several files,
// so handle that here.
//
DBfile *domain_file = dbfile;
string directory_mesh;
DetermineFileAndDirectory(meshname, "", domain_file, directory_mesh);

// We want to get just the global node ids. So we need to get the ReadMask,
// set it to read global node ids, then set it back.
unsigned long long mask = DBGetDataReadMask2();
DBSetDataReadMask2(DBUMZonelist|DBZonelistGlobZoneNo|DBZonelistInfo);
DBucdmesh *um = DBGetUcdmesh(domain_file, directory_mesh.c_str());
DBSetDataReadMask2(mask);
if (um == NULL)
{
if (!ignoreMissingBlocks)
{
EXCEPTION1(InvalidVariableException, mesh);
}
return 0;
}

vtkDataArray *rv = NULL;
if (um->zones->gzoneno != NULL)
{
rv = CreateDataArray(um->zones->gnznodtype, um->zones->gzoneno, um->zones->nzones);
um->zones->gzoneno = 0; // vtkDataArray owns the data now.
}

DBFreeUcdmesh(um);

delete [] meshname;

return rv;
}

// ****************************************************************************
// Method: avtSiloFileFormat::GetSpatialExtents
//
Expand Down
9 changes: 6 additions & 3 deletions src/databases/Silo/avtSiloFileFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ typedef struct _GroupInfo
// Mark C. Miller, Wed Jun 15 09:16:56 PDT 2016
// Added support for loading the block decomposition as a variable
// under certain conditions.
//
// Mark C. Miller, Tue Feb 13 10:08:31 PST 2024
// Switch char * AllocAndDetermineMeshnameForUcdmesh to
// string AllocAndDetermineMeshnameForMeshType
// ****************************************************************************

class avtSiloFileFormat : public avtSTMDFileFormat
Expand Down Expand Up @@ -453,8 +457,7 @@ class avtSiloFileFormat : public avtSTMDFileFormat
avtFacelist *CalcExternalFacelist(DBfile *, const char *);
avtMaterial *CalcMaterial(DBfile *, const char *, const char *, int dom);
avtSpecies *CalcSpecies(DBfile *, const char *);
vtkDataArray *GetGlobalNodeIds(int, const char *);
vtkDataArray *GetGlobalZoneIds(int, const char *);
vtkDataArray *GetGlobalIds(int, char const *, char const *);

avtIntervalTree *GetSpatialExtents(const char *);
avtIntervalTree *GetDataExtents(const char *);
Expand Down Expand Up @@ -489,7 +492,7 @@ class avtSiloFileFormat : public avtSTMDFileFormat
std::string &location_out);

void GetRelativeVarName(const char *,const char *,char *);
char *AllocAndDetermineMeshnameForUcdmesh(int, const char *);
std::string DetermineMeshnameForMeshType(int, const char *, int);

std::string DetermineMultiMeshForSubVariable(DBfile *dbfile,
const char *name,
Expand Down

0 comments on commit 0efcefa

Please sign in to comment.