/*******************************************************************/ /* XDMF */ /* eXtensible Data Model and Format */ /* */ /* Id : Id */ /* Date : $Date$ */ /* Version : $Revision$ */ /* */ /* Author: */ /* Kenneth Leiter */ /* kenneth.leiter@arl.army.mil */ /* US Army Research Laboratory */ /* Aberdeen Proving Ground, MD */ /* */ /* Copyright @ 2009 US Army Research Laboratory */ /* All Rights Reserved */ /* See Copyright.txt or http://www.arl.hpc.mil/ice for details */ /* */ /* This software is distributed WITHOUT ANY WARRANTY; without */ /* even the implied warranty of MERCHANTABILITY or FITNESS */ /* FOR A PARTICULAR PURPOSE. See the above copyright notice */ /* for more information. */ /* */ /*******************************************************************/ #include "XdmfExodusWriter.h" #include #include #include #include class XdmfExodusWriterNameHandler { public: // Helper function to construct attribute names for attributes with > 1 component since exodus // cannot store vectors. Also deals with MAX_STR_LENGTH limitation in exodus. void ConstructAttributeName(const char * attributeName, std::vector& names, int numComponents) { std::string name = attributeName; if(numComponents == 1) { if(name.length() > MAX_STR_LENGTH) { name = name.substr(0, MAX_STR_LENGTH); } names.push_back(name); } else if(numComponents > 1) { int numComponentDigits = int(numComponents / 10); if(name.length() + numComponentDigits > MAX_STR_LENGTH) { name = name.substr(0, MAX_STR_LENGTH - numComponentDigits); } for(int j=0; jGetName(); if(title.length() > MAX_STR_LENGTH) { title = title.substr(0, MAX_STR_LENGTH); } int num_dim; switch(gridToWrite->GetGeometry()->GetGeometryType()) { case(XDMF_GEOMETRY_XYZ): num_dim = 3; break; case(XDMF_GEOMETRY_XY): num_dim = 2; break; case(XDMF_GEOMETRY_X_Y_Z): num_dim = 3; break; case(XDMF_GEOMETRY_X_Y): num_dim = 2; break; default: std::cout << "Cannot write grid with geometry " << gridToWrite->GetGeometry()->GetGeometryTypeAsString() << " to exodus file." << std::endl; return; } int num_nodes = gridToWrite->GetGeometry()->GetNumberOfPoints(); int num_elem = gridToWrite->GetTopology()->GetNumberOfElements(); int num_elem_blk = 1; int num_node_sets = 0; int num_side_sets = 0; for (int i=0; iGetNumberOfSets(); ++i) { switch(gridToWrite->GetSets(i)->GetSetType()) { case(XDMF_SET_TYPE_CELL): { num_side_sets++; break; } case(XDMF_SET_TYPE_NODE): { num_node_sets++; break; } } } ex_put_init(exodusHandle, title.c_str(), num_dim, num_nodes, num_elem, num_elem_blk, num_node_sets, num_side_sets); // Write nodal coordinate values to exodus double * x = new double[num_nodes]; double * y = new double[num_nodes]; double * z = new double[num_nodes]; if(gridToWrite->GetGeometry()->GetGeometryType() == XDMF_GEOMETRY_XYZ || gridToWrite->GetGeometry()->GetGeometryType() == XDMF_GEOMETRY_XY) { gridToWrite->GetGeometry()->GetPoints()->GetValues(0, x, num_nodes, 3); gridToWrite->GetGeometry()->GetPoints()->GetValues(1, y, num_nodes, 3); if(gridToWrite->GetGeometry()->GetGeometryType() == XDMF_GEOMETRY_XYZ) { gridToWrite->GetGeometry()->GetPoints()->GetValues(2, z, num_nodes, 3); } } else if(gridToWrite->GetGeometry()->GetGeometryType() == XDMF_GEOMETRY_X_Y_Z || gridToWrite->GetGeometry()->GetGeometryType() == XDMF_GEOMETRY_X_Y) { gridToWrite->GetGeometry()->GetPoints()->GetValues(0, x, num_nodes); gridToWrite->GetGeometry()->GetPoints()->GetValues(num_nodes, y, num_nodes); if(gridToWrite->GetGeometry()->GetGeometryType() == XDMF_GEOMETRY_X_Y_Z) { gridToWrite->GetGeometry()->GetPoints()->GetValues(num_nodes*2, z, num_nodes); } } ex_put_coord(exodusHandle, x ,y ,z); delete [] x; delete [] y; delete [] z; // Write Element block parameters XdmfInt32 topType = gridToWrite->GetTopology()->GetTopologyType(); std::string cellType = this->DetermineExodusCellType(topType); if (cellType.compare("") == 0) { std::cout << "Cannot write grid with topology " << gridToWrite->GetTopology()->GetTopologyTypeAsString() << std::endl; return; } ex_put_elem_block(exodusHandle, 10, cellType.c_str(), num_elem, gridToWrite->GetTopology()->GetNodesPerElement(), num_side_sets); // Write Element Connectivity int * elem_connectivity = new int[num_elem * gridToWrite->GetTopology()->GetNodesPerElement()]; // Add 1 to connectivity array since exodus indices start at 1 *gridToWrite->GetTopology()->GetConnectivity() + 1; gridToWrite->GetTopology()->GetConnectivity()->GetValues(0, elem_connectivity, num_elem * gridToWrite->GetTopology()->GetNodesPerElement()); if(topType == XDMF_HEX_20 || topType == XDMF_HEX_27) { int * ptr = elem_connectivity; int k; int itmp[4]; // Exodus Node ordering does not match Xdmf, we must convert. for (int i=0; i globalComponents; std::vector nodalComponents; std::vector elementComponents; std::vector globalAttributeNames; std::vector nodalAttributeNames; std::vector elementAttributeNames; for(int i=0; iGetNumberOfAttributes(); ++i) { XdmfAttribute * currAttribute = gridToWrite->GetAttribute(i); currAttribute->Update(); int numComponents = 0; switch(currAttribute->GetAttributeCenter()) { case(XDMF_ATTRIBUTE_CENTER_GRID): { numComponents = currAttribute->GetValues()->GetNumberOfElements(); globalComponents.push_back(numComponents); numGlobalAttributes += numComponents; nameHandler->ConstructAttributeName(currAttribute->GetName(), globalAttributeNames, numComponents); break; } case(XDMF_ATTRIBUTE_CENTER_NODE): { numComponents = currAttribute->GetValues()->GetNumberOfElements() / num_nodes; nodalComponents.push_back(numComponents); numNodalAttributes += numComponents; nameHandler->ConstructAttributeName(currAttribute->GetName(), nodalAttributeNames, numComponents); break; } case(XDMF_ATTRIBUTE_CENTER_CELL): { numComponents = currAttribute->GetValues()->GetNumberOfElements() / num_elem; elementComponents.push_back(numComponents); numElementAttributes += numComponents; nameHandler->ConstructAttributeName(currAttribute->GetName(), elementAttributeNames, numComponents); break; } } } ex_put_var_param(exodusHandle, "g", numGlobalAttributes); ex_put_var_param(exodusHandle, "n", numNodalAttributes); ex_put_var_param(exodusHandle, "e", numElementAttributes); char ** globalNames = new char*[numGlobalAttributes]; char ** nodalNames = new char*[numNodalAttributes]; char ** elementNames = new char*[numElementAttributes]; for(int i=0; iGetNumberOfAttributes(); ++i) { XdmfAttribute * currAttribute = gridToWrite->GetAttribute(i); switch(currAttribute->GetAttributeCenter()) { case(XDMF_ATTRIBUTE_CENTER_GRID): { for(int j=0; jGetValues()->GetValues(j, &globalAttributeVals[globalIndex], 1); globalIndex++; } globalComponentIndex++; break; } case(XDMF_ATTRIBUTE_CENTER_NODE): { for(int j=0; jGetValues()->GetValues(j, nodalValues, num_nodes, nodalComponents[nodalComponentIndex]); ex_put_nodal_var(exodusHandle, 1, nodalIndex+1, num_nodes, nodalValues); ex_update(exodusHandle); delete [] nodalValues; nodalIndex++; } nodalComponentIndex++; break; } case(XDMF_ATTRIBUTE_CENTER_CELL): { for(int j=0; jGetValues()->GetValues(j, elementValues, num_elem, elementComponents[elementComponentIndex]); ex_put_elem_var(exodusHandle, 1, elementIndex+1, 10, num_elem, elementValues); ex_update(exodusHandle); delete [] elementValues; elementIndex++; } elementComponentIndex++; break; } } } ex_put_glob_vars(exodusHandle, 1, numGlobalAttributes, globalAttributeVals); ex_update(exodusHandle); delete [] globalAttributeVals; // Write Sets int setId = 20; for (int i=0; iGetNumberOfSets(); ++i) { XdmfSet * currSet = gridToWrite->GetSets(i); currSet->Update(); int numValues = currSet->GetIds()->GetNumberOfElements(); std::string name = currSet->GetName(); if(name.length() > MAX_STR_LENGTH) { name = name.substr(0, MAX_STR_LENGTH); } switch(currSet->GetSetType()) { case(XDMF_SET_TYPE_CELL): { ex_put_side_set_param(exodusHandle, setId, numValues, 0); int * values = new int[numValues]; // Add 1 to xdmf ids because exodus ids begin at 1 *currSet->GetIds() + 1; currSet->GetIds()->GetValues(0, values, numValues); ex_put_side_set(exodusHandle, setId, values, NULL); ex_put_name(exodusHandle, EX_SIDE_SET, setId, name.c_str()); setId++; delete [] values; break; } case(XDMF_SET_TYPE_NODE): { ex_put_node_set_param(exodusHandle, setId, numValues, 0); int * values = new int[numValues]; // Add 1 to xdmf ids because exodus ids begin at 1 *currSet->GetIds() + 1; currSet->GetIds()->GetValues(0, values, numValues); ex_put_node_set(exodusHandle, setId, values); ex_put_name(exodusHandle, EX_NODE_SET, setId, name.c_str()); setId++; delete [] values; break; } } } // Close Exodus File ex_close(exodusHandle); }