Skip to content

HOWTO: Write a Multi domain Mesh

Arto Sandroos edited this page Jul 2, 2015 · 1 revision

Here is a checklist (for each domain):

  • Separate zones into locals and ghosts. Local zones are always written first, only mesh data needs ghost zones.
  • Figure out an order in which to write out zones.
  • At this point you have local IDs for all zones (=the order they are written to file).
  • Synchronize local IDs with neighbor processes.
  • Each process must know the domain (=MPI rank) where the ghost zone belongs to, and local ID of ghost zone in that domain.

Write Mesh Bounding Box

Write mesh bounding box to array MESH_BBOX (master process only):

long unsigned int bbox[6];
bbox[0] = <<number of blocks in x-direction>>;
bbox[1] = <<number of blocks in y-direction>>;
bbox[2] = <<number of blocks in z-direction>>;
bbox[3] = <<number of cells in x-direction in blocks>>;
bbox[4] = <<number of cells in y-direction in blocks>>;
bbox[5] = <<number of cells in z-direction in blocks>>;

// NOTE: If you are not using block-based mesh, use
//bbox[0] = <<number of zones in x-direction>>;
//bbox[1] = <<number of zones in y-direction>>;
//bbox[2] = <<number of zones in z-direction>>;
//bbox[3] = 1;
//bbox[4] = 1;
//bbox[5] = 1;

map<string,string> xmlAttributes;
xmlAttributes["mesh"] = <<name of your mesh>>;
bool success;
if (myRank == masterRank) success = vlsv.writeArray("MESH_BBOX",xmlAttributes,6,1,bbox);
else success = vlsv.writeArray("MESH_BBOX",xmlAttributes,0,1,bbox);

Following XML attributes are supported:

Attribute name Mandatory or optional? Accepted values Value datatype
mesh Mandatory Name of the mesh string

Rationale: Plugin needs to know how to compute zone (i,j,k) indices from global IDs using the formula given above. Nx is equal to bbox[0]*bbox[3] etc.

Write Bounding Box Node Coordinates

Write bounding box node (x,y,z) coordinates to arrays MESH_NODE_CRDS_X, MESH_NODE_CRDS_Y, and MESH_NODE_CRDS_Z (master process only). NOTE that a mesh always has more nodes than zones:

unsigned int xCells = <<number of zones in x-direction>>;
unsigned int yCells = <<number of zones in y-direction>>;
unsigned int zCells = <<number of zones in z-direction>>;

float* xNodeCrds = new float[xCells+1];
float* yNodeCrds = new float[yCells+1];
float* zNodeCrds = new float[zCells+1];
for (unsigned int i=0; i<xCells+1; ++i) xNodeCrds[i] = <<x-coordinate of node i>>;
for (unsigned int j=0; j<yCells+1; ++j) yNodeCrds[j] = <<y-coordinate of node j>>;
for (unsigned int k=0; k<zCells+1; ++k) zNodeCrds[k] = <<z-coordinate of node k>>;

map<string,string> xmlAttributes;
xmlAttributes["mesh"] = <<name of your mesh>>;
bool success = true;
if (myRank == masterRank) {
   if (vlsv.writeArray("MESH_NODE_CRDS_X",xmlAttributes,xCells+1,1,xNodeCrds) == false) success = false;
   if (vlsv.writeArray("MESH_NODE_CRDS_Y",xmlAttributes,yCells+1,1,yNodeCrds) == false) success = false;
   if (vlsv.writeArray("MESH_NODE_CRDS_Z",xmlAttributes,zCells+1,1,zNodeCrds) == false) success = false;
} else {
   if (vlsv.writeArray("MESH_NODE_CRDS_X",xmlAttributes,0,1,xNodeCrds) == false) success = false;
   if (vlsv.writeArray("MESH_NODE_CRDS_Y",xmlAttributes,0,1,yNodeCrds) == false) success = false;
   if (vlsv.writeArray("MESH_NODE_CRDS_Z",xmlAttributes,0,1,zNodeCrds) == false) success = false;
}

Following XML attributes are supported:

| Attribute name | Mandatory or optional? | Accepted values | Value datatype | | mesh | mandatory | Name of the mesh | string |

Rationale: Plugin calculates zone's (i,j,k) indices from its global ID using the formula given above. Each zone has eight nodes: (i,j,k), (i+1,j,k), (i+1,j+1,k), ..., (i+1,j+1,k+1). Node (x,y,z) coordinates are obtained by indexing the arrays written above.

Write Zone Global ID numbers

Write global IDs of local zones, followed by global IDs of ghost zones, to an array MESH.

unsigned int localID=0;
vector<unsigned int> globalIDs;
for all local zones z {
   // Current value of localID is the local ID of zone z
   unsigned int gID = <<global ID of z>>;
   globalIDs.push_back(gID);
   ++localID;
}
for all ghost zones g {
   // Current value of localID is the local ID of zone g
   unsigned int gID = <<global ID of g>>;
   globalIDs.push_back(gID);
   ++localID;
}
unsigned int N_zones = globalIDs.size();

map<string,string> xmlAttributes;
attributes["name"] = <<name of your mesh>>;
attributes["type"] = "multi_ucd";
bool success = vlsv.writeArray("MESH",xmlAttributes,N_zones,1,&(globalIDs[0]));

The example above also shows how local ID values are obtaines -- it is simply zone's order in vector globalIDs. Local IDs need to be syncronized between neighboring MPI processes, they are needed in writing array MESH_GHOST_LOCALIDS below. Important: the order of zones in vector globalIDs defines the order in which a process writes out its variable data.

Following XML attributes are supported:

| Attribute name | Mandatory or optional? | Accepted values | value datatype | | domains | optional | number of domains | integer |

Rationale: In order for VisIt to visualize data in parallel it must be able to compute each domain independently, including ghost zones. Plugin uses global IDs to compute node coordinates of each zone.

Write Domain Sizes

Write a vector of size two containing (total number of zones, number of ghosts) in the domain to an array MESH_DOMAIN_SIZES:

int domainSize[2];
domainSize[0] = <<total number or zones in this domain>>;
domainSize[1] = <<number of ghost zones in this domain>>;

map<string,string> xmlAttributes;
attributes["mesh"] = <<name of mesh>>;bool success = vlsv.writeArray("MESH_DOMAIN_SIZES",xmlAttributes,1,2,domainSize);

Following XML attributes are supported:

| Attribute name | Mandatory or optional? | Accepted values | Value datatype | | mesh | mandatory | Name of the mesh | string |

Rationale: Plugin needs to know the number of local and ghost zones in each domain -- ghost zones need to be flagged so that VisIt does not draw them. Number of ghost zones given here also tells how to index the two arrays written below.

Write Ghost Zone Domain and Local ID Numbers

Write ghost zone domain IDs to array MESH_GHOST_DOMAINS, and local IDs to array MESH_GHOST_LOCALIDS:

unsigned int N_ghosts = 0;
vector<unsigned int> ghostDomainIDs;
vector<unsigned int> ghostLocalIDs;
for all ghost zones g {
   int domainID = <<MPI process rank owning ghost zone g>>;
   int localID = <<local ID of ghost zone g in domain domainID>>;
   ghostDomainIDs.push_back(domainID);
   ghostLocalIDs.push_back(localID);
   ++N_ghosts;
}

map<string,string> xmlAttributes;
attributes["mesh"] = <name of mesh>;
bool success1 = vlsv.writeArray("MESH_GHOST_DOMAINS",xmlAttributes,N_ghosts,1,&(ghostDomainIDs[0]));
bool success2 = vlsv.writeArray("MESH_GHOST_LOCALIDS",xmlAttributes,N_ghosts,1,&(ghostLocalIDs[0]));

Following XML attributes are supported:

| Attribute name | Mandatory or optional? | Accepted values | Value datatype | | mesh | mandatory | Name of the mesh | string |