You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1649 lines
56 KiB
1649 lines
56 KiB
2 years ago
|
/*
|
||
|
* Copyright(C) 1999-2023, National Technology & Engineering Solutions
|
||
|
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
||
|
* NTESS, the U.S. Government retains certain rights in this software.
|
||
|
*
|
||
|
* See packages/seacas/LICENSE for details
|
||
|
*/
|
||
|
|
||
|
#include <EP_ExodusEntity.h> // for Block, Mesh
|
||
|
#include <EP_Internals.h> // for Internals, Redefine
|
||
|
|
||
|
#include <algorithm> // for sort
|
||
|
#include <copy_string_cpp.h>
|
||
|
#include <cstddef> // for size_t
|
||
|
#include <cstdint> // for int64_t
|
||
|
#include <cstdlib> // for exit, EXIT_FAILURE
|
||
|
#include <cstring> // for strlen, memset
|
||
|
#include <fmt/ostream.h>
|
||
|
#include <smart_assert.h> // for SMART_ASSERT
|
||
|
|
||
|
#include <string> // for string, basic_string
|
||
|
#include <vector> // for vector
|
||
|
|
||
|
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \
|
||
|
defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__)
|
||
|
#include <Shlwapi.h>
|
||
|
#endif
|
||
|
|
||
|
extern "C" {
|
||
|
#define NO_NETCDF_2
|
||
|
#include <exodusII.h>
|
||
|
#include <exodusII_int.h>
|
||
|
#include <netcdf.h>
|
||
|
}
|
||
|
|
||
|
// Explicit Initialization of the functions used...
|
||
|
namespace Excn {
|
||
|
template int Internals<int>::write_meta_data(const Mesh &mesh, const std::vector<Block> &blocks,
|
||
|
const std::vector<NodeSet<int>> &nodesets,
|
||
|
const std::vector<SideSet<int>> &sidesets,
|
||
|
const std::vector<EdgeBlock<int>> &edgeblock,
|
||
|
const std::vector<FaceBlock<int>> &faceblock,
|
||
|
const CommunicationMetaData &comm);
|
||
|
|
||
|
template bool Internals<int>::check_meta_data(const Mesh &mesh, const std::vector<Block> &blocks,
|
||
|
const std::vector<NodeSet<int>> &nodesets,
|
||
|
const std::vector<SideSet<int>> &sidesets,
|
||
|
const std::vector<EdgeBlock<int>> &edgeblock,
|
||
|
const std::vector<FaceBlock<int>> &faceblock,
|
||
|
const CommunicationMetaData &comm);
|
||
|
|
||
|
template int Internals<int64_t>::write_meta_data(const Mesh &mesh,
|
||
|
const std::vector<Block> &blocks,
|
||
|
const std::vector<NodeSet<int64_t>> &nodesets,
|
||
|
const std::vector<SideSet<int64_t>> &sidesets,
|
||
|
const std::vector<EdgeBlock<int64_t>> &edgeblock,
|
||
|
const std::vector<FaceBlock<int64_t>> &faceblock,
|
||
|
const CommunicationMetaData &comm);
|
||
|
|
||
|
template bool Internals<int64_t>::check_meta_data(
|
||
|
const Mesh &mesh, const std::vector<Block> &blocks,
|
||
|
const std::vector<NodeSet<int64_t>> &nodesets, const std::vector<SideSet<int64_t>> &sidesets,
|
||
|
const std::vector<EdgeBlock<int64_t>> &edgeblock,
|
||
|
const std::vector<FaceBlock<int64_t>> &faceblock, const CommunicationMetaData &comm);
|
||
|
} // namespace Excn
|
||
|
|
||
|
namespace {
|
||
|
bool lessOffset(const Excn::Block &b1, const Excn::Block &b2) { return b1.offset_ < b2.offset_; }
|
||
|
|
||
|
nc_type get_type(int exoid, unsigned int type)
|
||
|
{
|
||
|
if ((ex_int64_status(exoid) & type) != 0U) {
|
||
|
return NC_INT64;
|
||
|
}
|
||
|
|
||
|
return NC_INT;
|
||
|
}
|
||
|
|
||
|
int define_netcdf_vars(int exoid, const char *type, size_t count, const char *dim_num,
|
||
|
const char *stat_var, const char *id_var, const char *name_var);
|
||
|
|
||
|
template <typename INT>
|
||
|
int put_array(int exoid, const char *var_type, const std::vector<INT> &array);
|
||
|
|
||
|
int put_id_array(int exoid, const char *var_type, const std::vector<ex_entity_id> &ids);
|
||
|
|
||
|
int define_coordinate_vars(int exodusFilePtr, int64_t nodes, int node_dim, int dimension,
|
||
|
int dim_dim, int str_dim);
|
||
|
} // namespace
|
||
|
|
||
|
bool Excn::is_path_absolute(const std::string &path)
|
||
|
{
|
||
|
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \
|
||
|
defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__)
|
||
|
return path[0] == '\\' || path[1] == ':';
|
||
|
#else
|
||
|
return path[0] == '/';
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
Excn::Redefine::Redefine(int exoid) : exodusFilePtr(exoid)
|
||
|
{
|
||
|
// Enter define mode...
|
||
|
int status = nc_redef(exodusFilePtr);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
std::string errmsg;
|
||
|
errmsg = fmt::format("Error: failed to put file id {} into define mode", exodusFilePtr);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Excn::Redefine::~Redefine()
|
||
|
{
|
||
|
try {
|
||
|
int status = nc_enddef(exodusFilePtr);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
std::string errmsg;
|
||
|
errmsg = fmt::format("Error: failed to complete variable definitions in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
}
|
||
|
catch (...) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::write_meta_data(const Mesh &mesh, const std::vector<Block> &blocks,
|
||
|
const std::vector<NodeSet<INT>> &nodesets,
|
||
|
const std::vector<SideSet<INT>> &sidesets,
|
||
|
const std::vector<EdgeBlock<INT>> &edgeblocks,
|
||
|
const std::vector<FaceBlock<INT>> &faceblocks,
|
||
|
const CommunicationMetaData &comm)
|
||
|
{
|
||
|
SMART_ASSERT((int)blocks.size() == mesh.blockCount);
|
||
|
SMART_ASSERT((int)nodesets.size() == mesh.nodesetCount);
|
||
|
SMART_ASSERT((int)sidesets.size() == mesh.sidesetCount);
|
||
|
SMART_ASSERT((int)edgeblocks.size() == mesh.edgeBlockCount);
|
||
|
SMART_ASSERT((int)faceblocks.size() == mesh.faceBlockCount);
|
||
|
|
||
|
// May need to reorder the element blocks based on the 'offset_'
|
||
|
// member. An element block contains the elements from 'offset_+1'
|
||
|
// to 'offset_+elementCount'. Typically, this is the order that
|
||
|
// they appear in the 'blocks' array, but not always...
|
||
|
//
|
||
|
// This is a very hard error to track down, so we just copy the
|
||
|
// 'blocks' array to a new array and sort it on the 'offset_'
|
||
|
// member...
|
||
|
//
|
||
|
// All block-related calls after these meta-data calls are based on
|
||
|
// the block id and not the block order, so we don't need to fix
|
||
|
// them.
|
||
|
for (size_t i = 0; i < blocks.size(); i++) {
|
||
|
const_cast<Excn::Block &>(blocks[i]).position_ = i;
|
||
|
}
|
||
|
|
||
|
// Check whether current order is consistent. The problem with just
|
||
|
// sorting the data is that if a subset of the entire model is being
|
||
|
// joined, there may be zero-length element blocks. These blocks
|
||
|
// have an offset of zero since there is no "lowest id" to get the
|
||
|
// offset from.
|
||
|
//
|
||
|
// If all that is wanted is a single subset of the entire model, it
|
||
|
// doesn't matter if the blocks are reordered due to the zero
|
||
|
// offsets; however, if the user then later joins multiple subsets
|
||
|
// together, there will be issues of block ordering mismatches.
|
||
|
//
|
||
|
// So, to avoid sorting the data into incorrect order, we check
|
||
|
// whether the data are consistent before sorting and if so, don't
|
||
|
// do the sort. Concsistent means that all blocks that have a
|
||
|
// nonzero element count are in the correct order.
|
||
|
int64_t last_offset = 0;
|
||
|
bool order_ok = true;
|
||
|
for (const auto &block : blocks) {
|
||
|
if (block.elementCount > 0) {
|
||
|
if (block.offset_ < last_offset) {
|
||
|
order_ok = false;
|
||
|
break;
|
||
|
}
|
||
|
last_offset = block.offset_;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::vector<Block> sorted_blocks(blocks);
|
||
|
if (!order_ok) {
|
||
|
std::sort(sorted_blocks.begin(), sorted_blocks.end(), lessOffset);
|
||
|
|
||
|
// Now, update the position_ field based on the sorted order.
|
||
|
for (size_t i = 0; i < blocks.size(); i++) {
|
||
|
int orig_position = sorted_blocks[i].position_;
|
||
|
const_cast<Excn::Block &>(blocks[orig_position]).position_ = i;
|
||
|
SMART_ASSERT(blocks[orig_position].id == sorted_blocks[i].id);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int ierr;
|
||
|
{
|
||
|
Excn::Redefine the_database(exodusFilePtr);
|
||
|
|
||
|
ierr = put_metadata(mesh, comm);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_metadata(sorted_blocks);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_metadata(nodesets);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_metadata(sidesets);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_metadata(edgeblocks);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_metadata(faceblocks);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NON-Define mode output...
|
||
|
ierr = put_non_define_data(mesh, comm);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_non_define_data(sorted_blocks);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_non_define_data(nodesets);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_non_define_data(sidesets);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_non_define_data(edgeblocks);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
ierr = put_non_define_data(faceblocks);
|
||
|
if (ierr != EX_NOERR) {
|
||
|
return ierr;
|
||
|
}
|
||
|
|
||
|
// For now, put entity names using the ExodusII api...
|
||
|
{
|
||
|
int max_entity = mesh.blockCount;
|
||
|
if (mesh.nodesetCount > max_entity) {
|
||
|
max_entity = mesh.nodesetCount;
|
||
|
}
|
||
|
if (mesh.sidesetCount > max_entity) {
|
||
|
max_entity = mesh.sidesetCount;
|
||
|
}
|
||
|
if (mesh.edgeBlockCount > max_entity) {
|
||
|
max_entity = mesh.edgeBlockCount;
|
||
|
}
|
||
|
if (mesh.faceBlockCount > max_entity) {
|
||
|
max_entity = mesh.faceBlockCount;
|
||
|
}
|
||
|
if (mesh.blockCount > 0) {
|
||
|
for (int i = 0; i < mesh.blockCount; i++) {
|
||
|
if (blocks[i].attributeCount > max_entity) {
|
||
|
max_entity = blocks[i].attributeCount;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size_t name_size = ex_inquire_int(exodusFilePtr, EX_INQ_MAX_READ_NAME_LENGTH);
|
||
|
auto names = new char *[max_entity];
|
||
|
for (int i = 0; i < max_entity; i++) {
|
||
|
names[i] = new char[name_size + 1];
|
||
|
}
|
||
|
|
||
|
if (mesh.blockCount > 0) {
|
||
|
for (int i = 0; i < mesh.blockCount; i++) {
|
||
|
copy_string(names[i], sorted_blocks[i].name_, name_size + 1);
|
||
|
}
|
||
|
ex_put_names(exodusFilePtr, EX_ELEM_BLOCK, names);
|
||
|
|
||
|
for (int i = 0; i < mesh.blockCount; i++) {
|
||
|
if (blocks[i].attributeCount > 0) {
|
||
|
SMART_ASSERT((size_t)blocks[i].attributeCount == blocks[i].attributeNames.size());
|
||
|
for (int j = 0; j < blocks[i].attributeCount; j++) {
|
||
|
std::memset(names[j], '\0', name_size + 1);
|
||
|
if (!blocks[i].attributeNames[j].empty()) {
|
||
|
copy_string(names[j], blocks[i].attributeNames[j], name_size + 1);
|
||
|
}
|
||
|
}
|
||
|
ierr = ex_put_attr_names(exodusFilePtr, EX_ELEM_BLOCK, blocks[i].id, names);
|
||
|
SMART_ASSERT(ierr == 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mesh.nodesetCount > 0) {
|
||
|
for (int i = 0; i < mesh.nodesetCount; i++) {
|
||
|
copy_string(names[i], nodesets[i].name_, name_size + 1);
|
||
|
}
|
||
|
ex_put_names(exodusFilePtr, EX_NODE_SET, names);
|
||
|
}
|
||
|
|
||
|
if (mesh.sidesetCount > 0) {
|
||
|
for (int i = 0; i < mesh.sidesetCount; i++) {
|
||
|
copy_string(names[i], sidesets[i].name_, name_size + 1);
|
||
|
}
|
||
|
ex_put_names(exodusFilePtr, EX_SIDE_SET, names);
|
||
|
}
|
||
|
|
||
|
if (mesh.edgeBlockCount > 0) {
|
||
|
for (int i = 0; i < mesh.edgeBlockCount; i++) {
|
||
|
copy_string(names[i], edgeblocks[i].name_, name_size + 1);
|
||
|
}
|
||
|
ex_put_names(exodusFilePtr, EX_EDGE_BLOCK, names);
|
||
|
}
|
||
|
|
||
|
if (mesh.faceBlockCount > 0) {
|
||
|
for (int i = 0; i < mesh.faceBlockCount; i++) {
|
||
|
copy_string(names[i], faceblocks[i].name_, name_size + 1);
|
||
|
}
|
||
|
ex_put_names(exodusFilePtr, EX_FACE_BLOCK, names);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < max_entity; i++) {
|
||
|
delete[] names[i];
|
||
|
}
|
||
|
delete[] names;
|
||
|
}
|
||
|
|
||
|
ex_update(exodusFilePtr);
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
bool Excn::Internals<INT>::check_meta_data(const Mesh &mesh, const std::vector<Block> & /*unused*/,
|
||
|
const std::vector<NodeSet<INT>> & /*unused*/,
|
||
|
const std::vector<SideSet<INT>> & /*unused*/,
|
||
|
const std::vector<EdgeBlock<INT>> & /*unused*/,
|
||
|
const std::vector<FaceBlock<INT>> & /*unused*/,
|
||
|
const CommunicationMetaData & /*unused*/)
|
||
|
{
|
||
|
ex_init_params init_data{};
|
||
|
ex_get_init_ext(exodusFilePtr, &init_data);
|
||
|
|
||
|
bool matches = true;
|
||
|
if (mesh.dimensionality != init_data.num_dim) {
|
||
|
fmt::print(stderr,
|
||
|
"ERROR: (EPU) original mesh dimensionality ({}) does not match current "
|
||
|
"dimensionality ({})\n",
|
||
|
mesh.dimensionality, init_data.num_dim);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.nodeCount != init_data.num_nodes) {
|
||
|
fmt::print(
|
||
|
stderr,
|
||
|
"ERROR: (EPU) original mesh node count ({}) does not match current node count ({})\n",
|
||
|
mesh.nodeCount, init_data.num_nodes);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.elementCount != init_data.num_elem) {
|
||
|
fmt::print(
|
||
|
stderr,
|
||
|
"ERROR: (EPU) original mesh element count ({}) does not match current element count ({})\n",
|
||
|
mesh.elementCount, init_data.num_elem);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.blockCount != init_data.num_elem_blk) {
|
||
|
fmt::print(stderr,
|
||
|
"ERROR: (EPU) original mesh element block count ({}) does not match current element "
|
||
|
"block count ({})\n",
|
||
|
mesh.blockCount, init_data.num_elem_blk);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.nodesetCount != init_data.num_node_sets) {
|
||
|
fmt::print(
|
||
|
stderr,
|
||
|
"ERROR: (EPU) original mesh nodeset count ({}) does not match current nodeset count ({})\n",
|
||
|
mesh.nodesetCount, init_data.num_node_sets);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.sidesetCount != init_data.num_side_sets) {
|
||
|
fmt::print(
|
||
|
stderr,
|
||
|
"ERROR: (EPU) original mesh sideset count ({}) does not match current sideset count ({})\n",
|
||
|
mesh.sidesetCount, init_data.num_side_sets);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.edgeBlockCount != init_data.num_edge_blk) {
|
||
|
fmt::print(stderr,
|
||
|
"ERROR: (EPU) original mesh edgeblock count ({}) does not match current edgeblock "
|
||
|
"count ({})\n",
|
||
|
mesh.edgeBlockCount, init_data.num_edge_blk);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
if (mesh.faceBlockCount != init_data.num_face_blk) {
|
||
|
fmt::print(stderr,
|
||
|
"ERROR: (EPU) original mesh faceblock count ({}) does not match current faceblock "
|
||
|
"count ({})\n",
|
||
|
mesh.faceBlockCount, init_data.num_face_blk);
|
||
|
matches = false;
|
||
|
}
|
||
|
|
||
|
return matches;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_metadata(const Mesh &mesh, const CommunicationMetaData & /*unused*/)
|
||
|
{
|
||
|
int numdimdim = 0;
|
||
|
int timedim = 0;
|
||
|
int numnoddim = 0;
|
||
|
int namestrdim = 0;
|
||
|
|
||
|
int map_type = get_type(exodusFilePtr, EX_MAPS_INT64_DB);
|
||
|
|
||
|
std::string errmsg;
|
||
|
|
||
|
// define some attributes...
|
||
|
int status = nc_put_att_text(exodusFilePtr, NC_GLOBAL, ATT_TITLE, mesh.title.length() + 1,
|
||
|
mesh.title.c_str());
|
||
|
if (status != NC_NOERR) {
|
||
|
errmsg = fmt::format("Error: failed to define title attribute to file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// For use later to help readers know how much memory to allocate
|
||
|
// for name storage, we define an attribute containing the maximum
|
||
|
// size of any name.
|
||
|
{
|
||
|
int current_len = 0;
|
||
|
status = nc_put_att_int(exodusFilePtr, NC_GLOBAL, ATT_MAX_NAME_LENGTH, NC_INT, 1, ¤t_len);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define ATT_MAX_NAME_LENGTH attribute to file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// create name string length dimension
|
||
|
if (maximumNameLength < 32) {
|
||
|
maximumNameLength = 32;
|
||
|
}
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_STR_NAME, maximumNameLength + 1, &namestrdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define name string length in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// ...and some dimensions..
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_DIM, mesh.dimensionality, &numdimdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of dimensions in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
if ((status = nc_def_dim(exodusFilePtr, DIM_TIME, NC_UNLIMITED, &timedim)) != NC_NOERR) {
|
||
|
errmsg = fmt::format("Error: failed to define time dimension in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
int dim[1];
|
||
|
int varid = 0;
|
||
|
dim[0] = timedim;
|
||
|
if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, dim,
|
||
|
&varid)) != NC_NOERR) {
|
||
|
errmsg = fmt::format("Error: failed to define whole time step variable in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
struct ex__file_item *file = ex__find_file_item(exodusFilePtr);
|
||
|
if (file) {
|
||
|
file->time_varid = varid;
|
||
|
}
|
||
|
|
||
|
ex__compress_variable(exodusFilePtr, varid, -2); /* don't compress, but do set collective io */
|
||
|
}
|
||
|
|
||
|
if (mesh.nodeCount > 0) {
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_NODES, mesh.nodeCount, &numnoddim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define number of nodes in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Define the node map here to avoid a later redefine call
|
||
|
if (mesh.needNodeMap) {
|
||
|
int dims[1];
|
||
|
int varid = 0;
|
||
|
dims[0] = numnoddim;
|
||
|
status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg =
|
||
|
fmt::format("Error: node numbering map already exists in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to create node numbering map array in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mesh.elementCount > 0) {
|
||
|
int numelemdim = 0;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_ELEM, mesh.elementCount, &numelemdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of elements in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Define the element map here to avoid a later redefine call
|
||
|
if (mesh.needElementMap) {
|
||
|
int dims[1];
|
||
|
dims[0] = numelemdim;
|
||
|
int varid = 0;
|
||
|
status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: element numbering map already exists in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to create element numbering map in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mesh.blockCount > 0) {
|
||
|
status = define_netcdf_vars(exodusFilePtr, "element block", mesh.blockCount, DIM_NUM_EL_BLK,
|
||
|
VAR_STAT_EL_BLK, VAR_ID_EL_BLK, VAR_NAME_EL_BLK);
|
||
|
if (status != EX_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// node set id array:
|
||
|
if (mesh.nodesetCount > 0) {
|
||
|
status = define_netcdf_vars(exodusFilePtr, "node set", mesh.nodesetCount, DIM_NUM_NS,
|
||
|
VAR_NS_STAT, VAR_NS_IDS, VAR_NAME_NS);
|
||
|
if (status != EX_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// side set id array:
|
||
|
if (mesh.sidesetCount > 0) {
|
||
|
status = define_netcdf_vars(exodusFilePtr, "side set", mesh.sidesetCount, DIM_NUM_SS,
|
||
|
VAR_SS_STAT, VAR_SS_IDS, VAR_NAME_SS);
|
||
|
if (status != EX_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// edge block id array:
|
||
|
if (mesh.edgeBlockCount > 0) {
|
||
|
status = define_netcdf_vars(exodusFilePtr, "edge block", mesh.edgeBlockCount, DIM_NUM_ED_BLK,
|
||
|
VAR_STAT_ED_BLK, VAR_ID_ED_BLK, VAR_NAME_ED_BLK);
|
||
|
if (status != EX_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// face block id array:
|
||
|
if (mesh.faceBlockCount > 0) {
|
||
|
status = define_netcdf_vars(exodusFilePtr, "face block", mesh.faceBlockCount, DIM_NUM_FA_BLK,
|
||
|
VAR_STAT_FA_BLK, VAR_ID_FA_BLK, VAR_NAME_FA_BLK);
|
||
|
if (status != EX_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status = define_coordinate_vars(exodusFilePtr, mesh.nodeCount, numnoddim, mesh.dimensionality,
|
||
|
numdimdim, namestrdim);
|
||
|
if (status != EX_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT> int Excn::Internals<INT>::put_metadata(const std::vector<Block> &blocks)
|
||
|
{
|
||
|
std::string errmsg;
|
||
|
int dims[2];
|
||
|
|
||
|
int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB);
|
||
|
|
||
|
int status = 0; // clear error code
|
||
|
|
||
|
if (blocks.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// Get number of element blocks defined for this file
|
||
|
int dimid;
|
||
|
size_t num_elem_blk = 0;
|
||
|
status = nc_inq_dimid(exodusFilePtr, DIM_NUM_EL_BLK, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: no element blocks defined in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
int namestrdim;
|
||
|
status = nc_inq_dimid(exodusFilePtr, DIM_STR_NAME, &namestrdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to get name string length in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
status = nc_inq_dimlen(exodusFilePtr, dimid, &num_elem_blk);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to get number of element blocks in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
SMART_ASSERT(blocks.size() == num_elem_blk);
|
||
|
|
||
|
// Iterate over element blocks ...
|
||
|
for (size_t iblk = 0; iblk < num_elem_blk; iblk++) {
|
||
|
|
||
|
ex__inc_file_item(exodusFilePtr, ex__get_counter_list(EX_ELEM_BLOCK));
|
||
|
|
||
|
if (blocks[iblk].elementCount == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// define some dimensions and variables
|
||
|
int numelbdim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_EL_IN_BLK(iblk + 1), blocks[iblk].elementCount,
|
||
|
&numelbdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
if (status == NC_ENAMEINUSE) { // duplicate entry
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: element block {} already defined in file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of elements/block for block {} file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
int nelnoddim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_NOD_PER_EL(iblk + 1), blocks[iblk].nodesPerElement,
|
||
|
&nelnoddim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of nodes/element for block {} in file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// element attribute array
|
||
|
if (blocks[iblk].attributeCount > 0) {
|
||
|
int numattrdim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_ATT_IN_BLK(iblk + 1), blocks[iblk].attributeCount,
|
||
|
&numattrdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of attributes in block {} in file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
dims[0] = numelbdim;
|
||
|
dims[1] = numattrdim;
|
||
|
int varid = 0;
|
||
|
status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, dims,
|
||
|
&varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define attributes for element block {} in file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 2);
|
||
|
|
||
|
// Attribute name array...
|
||
|
dims[0] = numattrdim;
|
||
|
dims[1] = namestrdim;
|
||
|
|
||
|
status = nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format(
|
||
|
"Error: failed to define attribute name array for element block {} in file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// element connectivity array
|
||
|
dims[0] = numelbdim;
|
||
|
dims[1] = nelnoddim;
|
||
|
|
||
|
int connid;
|
||
|
status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims, &connid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to create connectivity array for block {} in file id {}",
|
||
|
blocks[iblk].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, connid, 1);
|
||
|
|
||
|
// store element type as attribute of connectivity variable
|
||
|
status = nc_put_att_text(exodusFilePtr, connid, ATT_NAME_ELB,
|
||
|
static_cast<int>(std::strlen(blocks[iblk].elType)) + 1,
|
||
|
blocks[iblk].elType);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to store element type name {} in file id {}",
|
||
|
blocks[iblk].elType, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_non_define_data(const Mesh & /*unused*/,
|
||
|
const CommunicationMetaData & /*unused*/)
|
||
|
{
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_non_define_data(const std::vector<Block> &blocks)
|
||
|
{
|
||
|
int num_elem_blk = blocks.size(); // Verified via SMART_ASSERT earlier...
|
||
|
|
||
|
if (num_elem_blk > 0) {
|
||
|
// first get id of element block ids array variable
|
||
|
std::vector<ex_entity_id> elem_blk_id(num_elem_blk);
|
||
|
for (int iblk = 0; iblk < num_elem_blk; iblk++) {
|
||
|
elem_blk_id[iblk] = blocks[iblk].id;
|
||
|
}
|
||
|
|
||
|
if (put_id_array(exodusFilePtr, VAR_ID_EL_BLK, elem_blk_id) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Now, write the element block status array
|
||
|
std::vector<int> elem_blk_status(num_elem_blk);
|
||
|
for (int iblk = 0; iblk < num_elem_blk; iblk++) {
|
||
|
elem_blk_status[iblk] = blocks[iblk].elementCount > 0 ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
if (put_array(exodusFilePtr, VAR_STAT_EL_BLK, elem_blk_status) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// ========================================================================
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_metadata(const std::vector<NodeSet<INT>> &nodesets)
|
||
|
{
|
||
|
if (nodesets.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
std::string errmsg;
|
||
|
int dims[2];
|
||
|
|
||
|
int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB);
|
||
|
|
||
|
int status = 0; // clear error code
|
||
|
|
||
|
// Get number of node sets defined for this file
|
||
|
int dimid;
|
||
|
status = nc_inq_dimid(exodusFilePtr, DIM_NUM_NS, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_EBADDIM) {
|
||
|
errmsg = fmt::format("Error: no node sets defined for file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to locate node sets defined in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// inquire how many node sets are to be stored
|
||
|
int num_node_sets = ex_inquire_int(exodusFilePtr, EX_INQ_NODE_SETS);
|
||
|
SMART_ASSERT(static_cast<int>(nodesets.size()) == num_node_sets);
|
||
|
|
||
|
for (int i = 0; i < num_node_sets; i++) {
|
||
|
|
||
|
// NOTE: ex__inc_file_item is used to find the number of node sets
|
||
|
// for a specific file and returns that value incremented.
|
||
|
int cur_num_node_sets =
|
||
|
(int)ex__inc_file_item(exodusFilePtr, ex__get_counter_list(EX_NODE_SET));
|
||
|
|
||
|
if (nodesets[i].nodeCount == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_NOD_NS(cur_num_node_sets + 1), nodesets[i].nodeCount,
|
||
|
&dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: node set {} already defined in file id {}", nodesets[i].id,
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to define number of nodes for set {} in file id {}",
|
||
|
nodesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// define variable to store node set node list here instead of in expns
|
||
|
dims[0] = dimid;
|
||
|
int varid = 0;
|
||
|
status =
|
||
|
nc_def_var(exodusFilePtr, VAR_NODE_NS(cur_num_node_sets + 1), bulk_type, 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: node set {} node list already defined in file id {}",
|
||
|
nodesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to create node set {} node list in file id {}",
|
||
|
nodesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 1);
|
||
|
|
||
|
// Create variable for distribution factors if required
|
||
|
if (nodesets[i].dfCount > 0) {
|
||
|
// num_dist_per_set should equal num_nodes_per_set
|
||
|
if (nodesets[i].dfCount != nodesets[i].nodeCount) {
|
||
|
status = EX_FATAL;
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: # dist fact ({}) not equal to # nodes ({}) "
|
||
|
"in node set {} file id {}",
|
||
|
nodesets[i].dfCount, nodesets[i].nodeCount, nodesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// create variable for distribution factors
|
||
|
status = nc_def_var(exodusFilePtr, VAR_FACT_NS(cur_num_node_sets + 1),
|
||
|
nc_flt_code(exodusFilePtr), 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: node set {} dist factors already exist in file id {}",
|
||
|
nodesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to create node set {} dist factors in file id {}",
|
||
|
nodesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 2);
|
||
|
}
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_non_define_data(const std::vector<NodeSet<INT>> &nodesets)
|
||
|
{
|
||
|
if (nodesets.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// Output nodeset ids...
|
||
|
size_t num_nodesets = nodesets.size();
|
||
|
std::vector<ex_entity_id> nodeset_id(num_nodesets);
|
||
|
for (size_t i = 0; i < num_nodesets; i++) {
|
||
|
nodeset_id[i] = nodesets[i].id;
|
||
|
}
|
||
|
|
||
|
if (put_id_array(exodusFilePtr, VAR_NS_IDS, nodeset_id) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Now, write the status array
|
||
|
std::vector<int> status(num_nodesets);
|
||
|
for (size_t i = 0; i < num_nodesets; i++) {
|
||
|
status[i] = nodesets[i].nodeCount > 0 ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
if (put_array(exodusFilePtr, VAR_NS_STAT, status) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// ========================================================================
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_metadata(const std::vector<SideSet<INT>> &sidesets)
|
||
|
{
|
||
|
if (sidesets.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
std::string errmsg;
|
||
|
int dims[2];
|
||
|
|
||
|
int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB);
|
||
|
|
||
|
int status = 0; // clear error code
|
||
|
|
||
|
// Get number of side sets defined for this file
|
||
|
int dimid;
|
||
|
status = nc_inq_dimid(exodusFilePtr, DIM_NUM_SS, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_EBADDIM) {
|
||
|
errmsg = fmt::format("Error: no side sets defined for file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to locate side sets defined in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
size_t num_side_sets = ex_inquire_int(exodusFilePtr, EX_INQ_SIDE_SETS);
|
||
|
SMART_ASSERT(sidesets.size() == num_side_sets);
|
||
|
|
||
|
for (size_t i = 0; i < num_side_sets; i++) {
|
||
|
|
||
|
// NOTE: ex__inc_file_item is used to find the number of side sets
|
||
|
// for a specific file and returns that value incremented.
|
||
|
int cur_num_side_sets =
|
||
|
(int)ex__inc_file_item(exodusFilePtr, ex__get_counter_list(EX_SIDE_SET));
|
||
|
|
||
|
if (sidesets[i].sideCount == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_SIDE_SS(cur_num_side_sets + 1),
|
||
|
sidesets[i].sideCount, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: side set {} already defined in file id {}", sidesets[i].id,
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to define number of sides for set {} in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
dims[0] = dimid;
|
||
|
int varid = 0;
|
||
|
status =
|
||
|
nc_def_var(exodusFilePtr, VAR_ELEM_SS(cur_num_side_sets + 1), bulk_type, 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: side set {} element list already defined in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to create side set {} element list in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 1);
|
||
|
|
||
|
// create side list variable for side set
|
||
|
status =
|
||
|
nc_def_var(exodusFilePtr, VAR_SIDE_SS(cur_num_side_sets + 1), bulk_type, 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: side list already exists for side set {} in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to create side list for side set {} in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 1);
|
||
|
|
||
|
// Create variable for distribution factors if required
|
||
|
if (sidesets[i].dfCount > 0) {
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_DF_SS(cur_num_side_sets + 1), sidesets[i].dfCount,
|
||
|
&dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: side set df count {} already defined in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg = fmt::format("Error: failed to define side set df count for set {} in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// create distribution factor list variable for side set
|
||
|
dims[0] = dimid;
|
||
|
status = nc_def_var(exodusFilePtr, VAR_FACT_SS(cur_num_side_sets + 1),
|
||
|
nc_flt_code(exodusFilePtr), 1, dims, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg =
|
||
|
fmt::format("Error: dist factor list already exists for side set {} in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to create dist factor list for side set {} in file id {}",
|
||
|
sidesets[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 2);
|
||
|
}
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_non_define_data(const std::vector<SideSet<INT>> &sidesets)
|
||
|
{
|
||
|
if (sidesets.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// Output sideset ids...
|
||
|
int num_sidesets = (int)sidesets.size();
|
||
|
std::vector<ex_entity_id> sideset_id(num_sidesets);
|
||
|
for (int i = 0; i < num_sidesets; i++) {
|
||
|
sideset_id[i] = sidesets[i].id;
|
||
|
}
|
||
|
|
||
|
if (put_id_array(exodusFilePtr, VAR_SS_IDS, sideset_id) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Now, write the status array
|
||
|
std::vector<int> status(num_sidesets);
|
||
|
for (int i = 0; i < num_sidesets; i++) {
|
||
|
status[i] = sidesets[i].sideCount > 0 ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
if (put_array(exodusFilePtr, VAR_SS_STAT, status) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// ========================================================================
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_metadata(const std::vector<EdgeBlock<INT>> &edgeblocks)
|
||
|
{
|
||
|
if (edgeblocks.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
std::string errmsg;
|
||
|
int dims[2];
|
||
|
|
||
|
int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB);
|
||
|
|
||
|
int status = 0; // clear error code
|
||
|
|
||
|
// Get number of edge blocks defined for this file
|
||
|
int dimid;
|
||
|
status = nc_inq_dimid(exodusFilePtr, DIM_NUM_ED_BLK, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_EBADDIM) {
|
||
|
errmsg = fmt::format("Error: no edge blocks defined for file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to locate edge blocks defined in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
size_t num_edge_blocks = ex_inquire_int(exodusFilePtr, EX_INQ_EDGE_BLK);
|
||
|
SMART_ASSERT(edgeblocks.size() == num_edge_blocks);
|
||
|
|
||
|
for (size_t i = 0; i < num_edge_blocks; i++) {
|
||
|
|
||
|
// NOTE: ex__inc_file_item is used to find the number of edge blocks
|
||
|
// for a specific file and returns that value incremented.
|
||
|
int cur_num_edge_blocks =
|
||
|
(int)ex__inc_file_item(exodusFilePtr, ex__get_counter_list(EX_EDGE_BLOCK));
|
||
|
|
||
|
if (edgeblocks[i].edgeCount == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int num_edges_in_edgeblock_dim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_ED_IN_EBLK(cur_num_edge_blocks + 1),
|
||
|
edgeblocks[i].edgeCount, &num_edges_in_edgeblock_dim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: edge block {} already defined in file id {}", edgeblocks[i].id,
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of edges for edge block {} in file id {}",
|
||
|
edgeblocks[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
int num_nodes_per_edge_dim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_NOD_PER_ED(cur_num_edge_blocks + 1),
|
||
|
edgeblocks[i].nodesPerEdge, &num_nodes_per_edge_dim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of nodes/edge for block {} in file id {}",
|
||
|
edgeblocks[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// element connectivity array
|
||
|
dims[0] = num_edges_in_edgeblock_dim;
|
||
|
dims[1] = num_nodes_per_edge_dim;
|
||
|
|
||
|
int connid;
|
||
|
status =
|
||
|
nc_def_var(exodusFilePtr, VAR_EBCONN(cur_num_edge_blocks + 1), bulk_type, 2, dims, &connid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to create connectivity array for edge block {} in file id {}",
|
||
|
edgeblocks[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, connid, 1);
|
||
|
|
||
|
// store edge type as attribute of connectivity variable
|
||
|
status = nc_put_att_text(exodusFilePtr, connid, ATT_NAME_ELB,
|
||
|
static_cast<int>(std::strlen(edgeblocks[i].elType)) + 1,
|
||
|
edgeblocks[i].elType);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to store edge type name {} in file id {}",
|
||
|
edgeblocks[i].elType, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_non_define_data(const std::vector<EdgeBlock<INT>> &edgeblocks)
|
||
|
{
|
||
|
if (edgeblocks.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// Output edgeblock ids...
|
||
|
int num_edgeblocks = (int)edgeblocks.size();
|
||
|
std::vector<ex_entity_id> edgeblock_id(num_edgeblocks);
|
||
|
for (int i = 0; i < num_edgeblocks; i++) {
|
||
|
edgeblock_id[i] = edgeblocks[i].id;
|
||
|
}
|
||
|
|
||
|
if (put_id_array(exodusFilePtr, VAR_ID_ED_BLK, edgeblock_id) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Now, write the status array
|
||
|
std::vector<int> status(num_edgeblocks);
|
||
|
for (int i = 0; i < num_edgeblocks; i++) {
|
||
|
status[i] = edgeblocks[i].edgeCount > 0 ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
if (put_array(exodusFilePtr, VAR_STAT_ED_BLK, status) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// ========================================================================
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_metadata(const std::vector<FaceBlock<INT>> &faceblocks)
|
||
|
{
|
||
|
if (faceblocks.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
std::string errmsg;
|
||
|
int dims[2];
|
||
|
|
||
|
int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB);
|
||
|
|
||
|
int status = 0; // clear error code
|
||
|
|
||
|
// Get number of face blocks defined for this file
|
||
|
int dimid;
|
||
|
status = nc_inq_dimid(exodusFilePtr, DIM_NUM_FA_BLK, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_EBADDIM) {
|
||
|
errmsg = fmt::format("Error: no face blocks defined for file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to locate face blocks defined in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
size_t num_face_blocks = ex_inquire_int(exodusFilePtr, EX_INQ_FACE_BLK);
|
||
|
SMART_ASSERT(faceblocks.size() == num_face_blocks);
|
||
|
|
||
|
for (size_t i = 0; i < num_face_blocks; i++) {
|
||
|
|
||
|
// NOTE: ex__inc_file_item is used to find the number of face blocks
|
||
|
// for a specific file and returns that value incremented.
|
||
|
int cur_num_face_blocks =
|
||
|
(int)ex__inc_file_item(exodusFilePtr, ex__get_counter_list(EX_FACE_BLOCK));
|
||
|
|
||
|
if (faceblocks[i].faceCount == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int num_faces_in_faceblock_dim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_FA_IN_FBLK(cur_num_face_blocks + 1),
|
||
|
faceblocks[i].faceCount, &num_faces_in_faceblock_dim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
if (status == NC_ENAMEINUSE) {
|
||
|
errmsg = fmt::format("Error: face block {} already defined in file id {}", faceblocks[i].id,
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
else {
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of faces for face block {} in file id {}",
|
||
|
faceblocks[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
}
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
int num_nodes_per_face_dim;
|
||
|
status = nc_def_dim(exodusFilePtr, DIM_NUM_NOD_PER_FA(cur_num_face_blocks + 1),
|
||
|
faceblocks[i].nodesPerFace, &num_nodes_per_face_dim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define number of nodes/face for block {} in file id {}",
|
||
|
faceblocks[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// element connectivity array
|
||
|
dims[0] = num_faces_in_faceblock_dim;
|
||
|
dims[1] = num_nodes_per_face_dim;
|
||
|
|
||
|
int connid;
|
||
|
status =
|
||
|
nc_def_var(exodusFilePtr, VAR_FBCONN(cur_num_face_blocks + 1), bulk_type, 2, dims, &connid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to create connectivity array for face block {} in file id {}",
|
||
|
faceblocks[i].id, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, connid, 1);
|
||
|
|
||
|
// store face type as attribute of connectivity variable
|
||
|
status = nc_put_att_text(exodusFilePtr, connid, ATT_NAME_ELB,
|
||
|
static_cast<int>(std::strlen(faceblocks[i].elType)) + 1,
|
||
|
faceblocks[i].elType);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to store face type name {} in file id {}",
|
||
|
faceblocks[i].elType, exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
template <typename INT>
|
||
|
int Excn::Internals<INT>::put_non_define_data(const std::vector<FaceBlock<INT>> &faceblocks)
|
||
|
{
|
||
|
if (faceblocks.empty()) {
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
// Output faceblock ids...
|
||
|
int num_faceblocks = (int)faceblocks.size();
|
||
|
std::vector<ex_entity_id> faceblock_id(num_faceblocks);
|
||
|
for (int i = 0; i < num_faceblocks; i++) {
|
||
|
faceblock_id[i] = faceblocks[i].id;
|
||
|
}
|
||
|
|
||
|
if (put_id_array(exodusFilePtr, VAR_ID_FA_BLK, faceblock_id) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// Now, write the status array
|
||
|
std::vector<int> status(num_faceblocks);
|
||
|
for (int i = 0; i < num_faceblocks; i++) {
|
||
|
status[i] = faceblocks[i].faceCount > 0 ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
if (put_array(exodusFilePtr, VAR_STAT_FA_BLK, status) != NC_NOERR) {
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
namespace {
|
||
|
template <typename INT>
|
||
|
int put_array(int exoid, const char *var_type, const std::vector<INT> &array)
|
||
|
{
|
||
|
std::string errmsg;
|
||
|
int var_id;
|
||
|
int status;
|
||
|
|
||
|
status = nc_inq_varid(exoid, var_type, &var_id);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to locate {} in file id {}", var_type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
if (sizeof(INT) == sizeof(int64_t)) {
|
||
|
status = nc_put_var_longlong(exoid, var_id, (long long int *)array.data());
|
||
|
}
|
||
|
else {
|
||
|
status = nc_put_var_int(exoid, var_id, array.data());
|
||
|
}
|
||
|
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to write {} array in file id {}", var_type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
int put_id_array(int exoid, const char *var_type, const std::vector<ex_entity_id> &ids)
|
||
|
{
|
||
|
std::string errmsg;
|
||
|
int var_id;
|
||
|
|
||
|
int status = nc_inq_varid(exoid, var_type, &var_id);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to locate {} in file id {}", var_type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
int id_type = get_type(exoid, EX_IDS_INT64_API);
|
||
|
|
||
|
if (id_type == NC_INT64) {
|
||
|
status = nc_put_var_longlong(exoid, var_id, (long long int *)ids.data());
|
||
|
}
|
||
|
else {
|
||
|
// Have ex_entity_id (long long), need ints...
|
||
|
std::vector<int> int_ids(ids.size());
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable : 4244)
|
||
|
#endif
|
||
|
int_ids.assign(ids.begin(), ids.end());
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(pop)
|
||
|
#endif
|
||
|
status = nc_put_var_int(exoid, var_id, int_ids.data());
|
||
|
}
|
||
|
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to write {} array in file id {}", var_type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
int define_coordinate_vars(int exodusFilePtr, int64_t nodes, int node_dim, int dimension,
|
||
|
int dim_dim, int str_dim)
|
||
|
{
|
||
|
std::string errmsg;
|
||
|
int status;
|
||
|
int dim[2];
|
||
|
int varid;
|
||
|
|
||
|
if (nodes > 0) {
|
||
|
// node coordinate arrays -- separate storage...
|
||
|
dim[0] = node_dim;
|
||
|
if (dimension > 0) {
|
||
|
status = nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define node x coordinate array in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 2);
|
||
|
}
|
||
|
|
||
|
if (dimension > 1) {
|
||
|
status = nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define node y coordinate array in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 2);
|
||
|
}
|
||
|
|
||
|
if (dimension > 2) {
|
||
|
status = nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define node z coordinate array in file id {}",
|
||
|
exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
ex__compress_variable(exodusFilePtr, varid, 2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// coordinate names array
|
||
|
dim[0] = dim_dim;
|
||
|
dim[1] = str_dim;
|
||
|
|
||
|
status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg =
|
||
|
fmt::format("Error: failed to define coordinate name array in file id {}", exodusFilePtr);
|
||
|
ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
|
||
|
int define_netcdf_vars(int exoid, const char *type, size_t count, const char *dim_num,
|
||
|
const char *stat_var, const char *id_var, const char *name_var)
|
||
|
{
|
||
|
int dimid = 0;
|
||
|
int varid = 0;
|
||
|
int dim[2];
|
||
|
int namestrdim = 0;
|
||
|
std::string errmsg;
|
||
|
|
||
|
int status = nc_inq_dimid(exoid, DIM_STR_NAME, &namestrdim);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to get string name dimension in file id {}", exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
status = nc_def_dim(exoid, dim_num, count, &dimid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define number of {}s in file id {}", type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// id status array:
|
||
|
dim[0] = dimid;
|
||
|
status = nc_def_var(exoid, stat_var, NC_INT, 1, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define side {} status in file id {}", type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// id array:
|
||
|
int ids_type = get_type(exoid, EX_IDS_INT64_DB);
|
||
|
status = nc_def_var(exoid, id_var, ids_type, 1, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define {} property in file id {}", type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
// store property name as attribute of property array variable
|
||
|
status = nc_put_att_text(exoid, varid, ATT_PROP_NAME, 3, "ID");
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to store {} property name {} in file id {}", type, "ID",
|
||
|
exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
|
||
|
dim[0] = dimid;
|
||
|
dim[1] = namestrdim;
|
||
|
|
||
|
status = nc_def_var(exoid, name_var, NC_CHAR, 2, dim, &varid);
|
||
|
if (status != NC_NOERR) {
|
||
|
ex_opts(EX_VERBOSE);
|
||
|
errmsg = fmt::format("Error: failed to define {} name array in file id {}", type, exoid);
|
||
|
ex_err_fn(exoid, __func__, errmsg.c_str(), status);
|
||
|
return EX_FATAL;
|
||
|
}
|
||
|
return EX_NOERR;
|
||
|
}
|
||
|
} // namespace
|