diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d36809819..3ea27aacdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(Seacas_ENABLE_Zoltan_DEFAULT ON) SET(TRIBITS_HIDE_DEPRECATED_INCLUDE_DIRECTORIES_OVERRIDE TRUE) # Define the TriBITS minimum required CMake version -SET(TRIBITS_CMAKE_MINIMUM_REQUIRED 3.17.0) +SET(TRIBITS_CMAKE_MINIMUM_REQUIRED 3.22.0) # CMake requires this be in the top file and not in an include file :-( CMAKE_MINIMUM_REQUIRED(VERSION ${TRIBITS_CMAKE_MINIMUM_REQUIRED} FATAL_ERROR) diff --git a/TPL/netcdf/runcmake.sh b/TPL/netcdf/runcmake.sh index 3b37d34a81..22a89b18c1 100755 --- a/TPL/netcdf/runcmake.sh +++ b/TPL/netcdf/runcmake.sh @@ -67,6 +67,7 @@ cmake .. -DCMAKE_C_COMPILER:FILEPATH=${CC} \ -DENABLE_MMAP:BOOL=ON \ -DENABLE_DAP:BOOL=OFF \ -DENABLE_BYTERANGE:BOOL=OFF \ + -DENABLE_NCZARR:BOOL=OFF \ -DENABLE_V2_API:BOOL=OFF \ -DENABLE_FILTER_TESTING:BOOL=OFF \ -DENABLE_TESTS:BOOL=OFF \ diff --git a/packages/seacas/CMakeLists.txt b/packages/seacas/CMakeLists.txt index b9eb3ab2be..81ca71b50e 100644 --- a/packages/seacas/CMakeLists.txt +++ b/packages/seacas/CMakeLists.txt @@ -18,6 +18,7 @@ TRIBITS_ADD_OPTION_AND_DEFINE( set(${PROJECT_NAME}_C_Standard_DEFAULT c99) SET(${PROJECT_NAME}_CMAKE_CXX_STANDARD_DEFAULT 17) +SET(CMAKE_CXX_STANDARD 17) SET(${PROJECT_NAME}_CMAKE_CXX_STANDARDS_ALLOWED "(14|17|20)") ADVANCED_SET(CMAKE_CXX_STANDARD ${${PROJECT_NAME}_CMAKE_CXX_STANDARD_DEFAULT} CACHE STRING diff --git a/packages/seacas/README.md b/packages/seacas/README.md index 96d53e54ce..3ec3a1142c 100644 --- a/packages/seacas/README.md +++ b/packages/seacas/README.md @@ -13,4 +13,3 @@ Sandia National Laboratories, We appreciate feedback from users of this package. Please send comments, suggestions, and bug reports to Greg Sjaardema , - diff --git a/packages/seacas/applications/blot/bl_version.f b/packages/seacas/applications/blot/bl_version.f index 727c9050c2..47529f19d8 100644 --- a/packages/seacas/applications/blot/bl_version.f +++ b/packages/seacas/applications/blot/bl_version.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2024 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -11,8 +11,8 @@ SUBROUTINE VERSION(QAINFO) CHARACTER*(MXQARC) QAINFO(6) QAINFO(1) = 'blot ' - QAINFO(2) = '2021/03/31 ' - QAINFO(3) = ' 3.141 ' + QAINFO(2) = '2024/03/25 ' + QAINFO(3) = ' 3.1415 ' QAINFO(4) = ' ' RETURN diff --git a/packages/seacas/applications/blot/matfac.f b/packages/seacas/applications/blot/matfac.f index 702e94d4ba..a847bb88e3 100644 --- a/packages/seacas/applications/blot/matfac.f +++ b/packages/seacas/applications/blot/matfac.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2024 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -101,6 +101,6 @@ INTEGER FUNCTION MATFAC (LINKF1, MAXNPF, NPFS, iel, numnp, IERR) 160 CONTINUE RETURN -10000 FORMAT (' Poss. Contiguity Prob. at Hex ', I7, - * ', Nodes ', 4(I7,1X), 10(I7,1X)) +10000 FORMAT (' Poss. Contiguity Prob. at Hex ', I11, + * ', Nodes ', 4(I11,1X), 10(I11,1X)) END diff --git a/packages/seacas/applications/blot/scaprt.f b/packages/seacas/applications/blot/scaprt.f index faddcf539a..20de2989a7 100644 --- a/packages/seacas/applications/blot/scaprt.f +++ b/packages/seacas/applications/blot/scaprt.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2024 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -94,7 +94,7 @@ SUBROUTINE SCAPRT (NAMECO, NAME, IVAR, TIMES, & STIM(2)(:LTIM), NUMMAX, ISTMAX 10000 FORMAT (4X, A7, 1X, A, 3X, 2 (1X, A), & 4X, A, 3X, A4, 3X, A4) -10010 FORMAT (4X, A7, 1X, A, 3X, 2 (1X, A), 4X, A, I7, I7) +10010 FORMAT (4X, A7, 1X, A, 3X, 2 (1X, A), 4X, A, I11, I11) ELSE WRITE (*, 10020) 'Range: ', SVAL(0)(:LVAL), & SXYZ0(1)(:LX), SXYZ0(2)(:LY), SXYZ0(3)(:LZ), diff --git a/packages/seacas/applications/grepos/gp_mapvar.f b/packages/seacas/applications/grepos/gp_mapvar.f index d55dd4d391..49858aec65 100644 --- a/packages/seacas/applications/grepos/gp_mapvar.f +++ b/packages/seacas/applications/grepos/gp_mapvar.f @@ -49,6 +49,7 @@ subroutine mapvar(nold, nnew, nvar, map, vars, scr) do 30 ivar = 1, nvar do 10 i = 1, nnew + write (*,*) i, map(i) scr(i) = vars(map(i) + nold * (ivar-1) ) 10 continue diff --git a/packages/seacas/applications/nem_slice/elb.h b/packages/seacas/applications/nem_slice/elb.h index df37f03f08..815c873e65 100644 --- a/packages/seacas/applications/nem_slice/elb.h +++ b/packages/seacas/applications/nem_slice/elb.h @@ -211,7 +211,7 @@ template struct Graph_Description std::vector adj{}; std::vector start{}; std::vector> sur_elem; - Graph_Description() = default; + Graph_Description() = default; }; /* Various constants */ diff --git a/packages/seacas/applications/slice/SL_Decompose.C b/packages/seacas/applications/slice/SL_Decompose.C index f7c872a5bd..cb27614147 100644 --- a/packages/seacas/applications/slice/SL_Decompose.C +++ b/packages/seacas/applications/slice/SL_Decompose.C @@ -45,6 +45,24 @@ extern double seacas_timer(); extern void progress(const std::string &output); namespace { + char **get_name_array(size_t count, int size) + { + auto *names = new char *[count]; + for (size_t i = 0; i < count; i++) { + names[i] = new char[size + 1]; + std::memset(names[i], '\0', size + 1); + } + return names; + } + + void delete_name_array(char **names, int count) + { + for (int i = 0; i < count; i++) { + delete[] names[i]; + } + delete[] names; + } + template void create_adjacency_list(const Ioss::Region ®ion, std::vector &pointer, std::vector &adjacency, INT) @@ -684,7 +702,7 @@ std::vector decompose_elements(const Ioss::Region ®ion, SystemInterface if (map_count > 0) { int max_name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_USED_NAME_LENGTH); max_name_length = max_name_length < 32 ? 32 : max_name_length; - char **names = Ioss::Utils::get_name_array(map_count, max_name_length); + char **names = get_name_array(map_count, max_name_length); int error = ex_get_names(exoid, EX_ELEM_MAP, names); if (error < 0) { exodus_error(__LINE__); @@ -701,7 +719,7 @@ std::vector decompose_elements(const Ioss::Region ®ion, SystemInterface break; } } - Ioss::Utils::delete_name_array(names, map_count); + delete_name_array(names, map_count); } if (!map_read) { diff --git a/packages/seacas/cmake/Dependencies.cmake b/packages/seacas/cmake/Dependencies.cmake index 3b1b3d6598..e75f5073f2 100644 --- a/packages/seacas/cmake/Dependencies.cmake +++ b/packages/seacas/cmake/Dependencies.cmake @@ -4,7 +4,7 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( Exodus_for libraries/exodus_for PT OPTIONAL ExoIIv2for32 libraries/exoIIv2for32 PT OPTIONAL Nemesis libraries/nemesis PT OPTIONAL - Ioss libraries/ioss PT REQUIRED + Ioss libraries/ioss PT OPTIONAL Chaco libraries/chaco PT OPTIONAL Aprepro_lib libraries/aprepro_lib PT OPTIONAL Supes libraries/supes PT OPTIONAL diff --git a/packages/seacas/libraries/exodus/CMakeLists.txt b/packages/seacas/libraries/exodus/CMakeLists.txt index 81ea023c27..d2be5f9fa8 100644 --- a/packages/seacas/libraries/exodus/CMakeLists.txt +++ b/packages/seacas/libraries/exodus/CMakeLists.txt @@ -35,6 +35,7 @@ TRIBITS_ADD_LIBRARY( ) set_property(TARGET exodus PROPERTY C_STANDARD 99) +set_property(TARGET exodus PROPERTY C_EXTENSIONS ON) if (SEACASExodus_ENABLE_SHARED) if (NOT BUILD_SHARED_LIBS) diff --git a/packages/seacas/libraries/exodus/include/exodus-element-types.md b/packages/seacas/libraries/exodus/include/exodus-element-types.md index 3eed7f1ea4..d90e7b05fa 100644 --- a/packages/seacas/libraries/exodus/include/exodus-element-types.md +++ b/packages/seacas/libraries/exodus/include/exodus-element-types.md @@ -78,7 +78,7 @@ library, the IOSS library, nem_slice, and nem_spread. | | 64 | X | X | | | Only the base topology name is required for the element type. For example, all -elements of a `hex` toplogy can be referred to by the name `hex` no +elements of a `hex` topology can be referred to by the name `hex` no matter how many nodes there are. However, it is also correct to append the node count to the topology type for the element name. For example, a 20-node hex could be named `hex20`. diff --git a/packages/seacas/libraries/exodus/include/exodusII.h b/packages/seacas/libraries/exodus/include/exodusII.h index 1377cf5e3e..67165d25c8 100644 --- a/packages/seacas/libraries/exodus/include/exodusII.h +++ b/packages/seacas/libraries/exodus/include/exodusII.h @@ -47,6 +47,9 @@ #include #include +/** Maximum length of name permitted by NetCDF */ +#define EX_MAX_NAME NC_MAX_NAME + #ifndef NC_INT64 #error "NetCDF version 4.1.2 or later is required." #endif @@ -282,6 +285,98 @@ enum ex_entity_type { }; typedef enum ex_entity_type ex_entity_type; +enum ex_field_type { + EX_FIELD_TYPE_INVALID = 0, + EX_FIELD_TYPE_USER_DEFINED, + EX_FIELD_TYPE_SEQUENCE, + EX_BASIS, + EX_QUADRATURE, + EX_SCALAR, + EX_VECTOR_1D, + EX_VECTOR_2D, + EX_VECTOR_3D, + EX_QUATERNION_2D, + EX_QUATERNION_3D, + EX_FULL_TENSOR_36, + EX_FULL_TENSOR_32, + EX_FULL_TENSOR_22, + EX_FULL_TENSOR_16, + EX_FULL_TENSOR_12, + EX_SYM_TENSOR_33, + EX_SYM_TENSOR_31, + EX_SYM_TENSOR_21, + EX_SYM_TENSOR_13, + EX_SYM_TENSOR_11, + EX_SYM_TENSOR_10, + EX_ASYM_TENSOR_03, + EX_ASYM_TENSOR_02, + EX_ASYM_TENSOR_01, + EX_MATRIX_2X2, + EX_MATRIX_3X3 +}; +typedef enum ex_field_type ex_field_type; + +#define EX_MAX_FIELD_NESTING 2 +typedef struct ex_field +{ + ex_entity_type entity_type; + int64_t entity_id; + char name[EX_MAX_NAME + 1]; /* Name of the field */ + /* + * For basis, user, quadrature -- what is name of the subtype. This + * is a comma-separated list of `nesting` names Use two consecutive + * commas for an empty type_name. Leave empty if no type_names + */ + int nesting; /* Number of composite fields (vector at each quadrature point = 2) */ + char type_name[EX_MAX_NAME + 1]; + ex_field_type type[EX_MAX_FIELD_NESTING]; /* ex_field_type of each nested field */ + int cardinality[EX_MAX_FIELD_NESTING]; /* 0 to calculate based on type */ + char component_separator[EX_MAX_FIELD_NESTING]; /* empty defaults to '_'; */ + char suffices[EX_MAX_NAME + 1]; /* Optional comma-separated list of suffices if type is + EX_FIELD_TYPE_USER_DEFINED */ +} ex_field; + +typedef struct ex_basis +{ + /* + clang-format off + * + * subc_dim: dimension of the subcell associated with the specified DoF ordinal + * -- 0 node, 1 edge, 2 face, 3 volume [Range: 0..3] + * subc_ordinal: ordinal of the subcell relative to its parent cell + * -- 0..n for each ordinal with the same subc dim [Range: <= DoF ordinal] + * subc_dof_ordinal: ordinal of the DoF relative to the subcell + * subc_num_dof: cardinality of the DoF set associated with this subcell. + * xi, eta, mu (ξ, η, ζ): Parametric coordinate location of the DoF + * -- (Only first ndim values are valid) + * + clang-format on + */ + + char name[EX_MAX_NAME + 1]; + int cardinality; /* number of `basis` points == dimension of non-null subc_*, xi, eta, mu */ + int *subc_dim; + int *subc_ordinal; + int *subc_dof_ordinal; + int *subc_num_dof; + double *xi; + double *eta; + double *zeta; +} ex_basis; + +typedef struct ex_quadrature +{ + char name[EX_MAX_NAME + 1]; + int cardinality; /* Number of quadrature points */ + int dimension; /* 1,2,3 -- spatial dimension of points */ + double *xi; /* xi (x) coordinate of points; dimension = cardinality or NULL */ + double * + eta; /* eta (y) coordinate of points; dimension = cardinality if dimension = 2 or 3 or NULL */ + double + *zeta; /* zeta (z) coordinate of points; dimension = cardinality if dimension == 3. or NULL */ + double *weight; /* weights for each point; dimension = cardinality or NULL */ +} ex_quadrature; + /*! * ex_opts() function codes - codes are OR'ed into exopts */ @@ -305,9 +400,6 @@ typedef enum ex_options ex_options; * @{ */ -/** Maximum length of name permitted by NetCDF */ -#define EX_MAX_NAME NC_MAX_NAME - /** Maximum length of QA record, element type name */ #define MAX_STR_LENGTH 32L /** Default maximum length of an entity name, attribute name, variable name. @@ -368,10 +460,10 @@ typedef enum ex_type ex_type; typedef struct ex_attribute { ex_entity_type entity_type; - ex_entity_id entity_id; - char name[NC_MAX_NAME + 1]; + int64_t entity_id; + char name[EX_MAX_NAME + 1]; ex_type type; /* int, double, text */ - size_t value_count; + int value_count; void *values; /* not accessed if NULL */ } ex_attribute; @@ -953,6 +1045,20 @@ EXODUS_EXPORT int ex_get_blob(int exoid, struct ex_blob *blob); EXODUS_EXPORT int ex_put_blobs(int exoid, size_t count, const struct ex_blob *blobs); EXODUS_EXPORT int ex_get_blobs(int exoid, struct ex_blob *blobs); +EXODUS_EXPORT int ex_put_field_metadata(int exoid, const ex_field field); +EXODUS_EXPORT int ex_put_field_suffices(int exoid, const ex_field field, const char *suffices); +EXODUS_EXPORT int ex_get_field_metadata(int exoid, ex_field *field); +EXODUS_EXPORT int ex_get_field_metadata_count(int exoid, ex_entity_type obj_type, ex_entity_id id); +EXODUS_EXPORT int ex_get_field_suffices(int exoid, const ex_field field, char *suffices); + +EXODUS_EXPORT int ex_get_basis_count(int exoid); +EXODUS_EXPORT int ex_get_basis(int exoid, ex_basis **pbasis, int *num_basis); +EXODUS_EXPORT int ex_put_basis(int exoid, const ex_basis basis); + +EXODUS_EXPORT int ex_get_quadrature_count(int exoid); +EXODUS_EXPORT int ex_get_quadrature(int exoid, ex_quadrature **pquad, int *num_quad); +EXODUS_EXPORT int ex_put_quadrature(int exoid, const ex_quadrature quad); + /* Write arbitrary integer, double, or text attributes on an entity */ EXODUS_EXPORT int ex_put_attribute(int exoid, const ex_attribute attributes); EXODUS_EXPORT int ex_put_attributes(int exoid, size_t attr_count, const ex_attribute *attributes); @@ -1202,6 +1308,17 @@ EXODUS_EXPORT int ex_put_elem_cmap(int exoid, /**< NetCDF/Exodus int processor /**< This processor ID */ ); +EXODUS_EXPORT int ex_initialize_basis_struct(ex_basis *basis, size_t num_basis, int mode); +EXODUS_EXPORT int ex_initialize_quadrature_struct(ex_quadrature *quad, size_t num_quad, int mode); + +EXODUS_EXPORT const char *ex_component_field_name(ex_field *field, + int component[EX_MAX_FIELD_NESTING]); +EXODUS_EXPORT const char *ex_field_component_suffix(ex_field *field, int nest_level, int component); +EXODUS_EXPORT int ex_field_cardinality(const ex_field_type field_type); +EXODUS_EXPORT const char *ex_field_type_name(const ex_field_type field_type); +EXODUS_EXPORT ex_field_type ex_string_to_field_type_enum(const char *field_name); +EXODUS_EXPORT const char *ex_field_type_enum_to_string(const ex_field_type field_type); + /*! @} */ /* Deprecated Code Handling Options: diff --git a/packages/seacas/libraries/exodus/include/exodusII_int.h b/packages/seacas/libraries/exodus/include/exodusII_int.h index 8cf09bf374..8657fa6755 100644 --- a/packages/seacas/libraries/exodus/include/exodusII_int.h +++ b/packages/seacas/libraries/exodus/include/exodusII_int.h @@ -1,6 +1,6 @@ /* - * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023, 2024 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. * @@ -88,6 +88,9 @@ extern "C" { #define EX_FILE_ID_MASK (0xffff0000) /**< Must match FILE_ID_MASK in NetCDF nc4internal.h */ #define EX_GRP_ID_MASK (0x0000ffff) /**< Must match GRP_ID_MASK in NetCDF nc4internal.h */ +/* Utility function to find variable to store entity attribute on */ +int exi_get_varid(int exoid, ex_entity_type obj_type, ex_entity_id id); + void exi_reset_error_status(void); #if defined(EXODUS_THREADSAFE) diff --git a/packages/seacas/libraries/exodus/src/ex_field_utils.c b/packages/seacas/libraries/exodus/src/ex_field_utils.c new file mode 100644 index 0000000000..cda2985cef --- /dev/null +++ b/packages/seacas/libraries/exodus/src/ex_field_utils.c @@ -0,0 +1,552 @@ +/* + * Copyright(C) 1999-2024 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 "exodusII.h" // for ex_err, etc +#include "exodusII_int.h" // for EX_FATAL, etc +#include +#include +#define _GNU_SOURCE +#include + +#define SIZE(X) sizeof(X) / sizeof(X[0]) + +char *my_strsep(char **stringp, const char *delim) +{ + char *rv = *stringp; + if (rv) { + *stringp += strcspn(*stringp, delim); + if (**stringp) + *(*stringp)++ = '\0'; + else + *stringp = NULL; + } + return rv; +} +size_t my_strlcat(char *restrict dst, const char *restrict src, size_t maxlen) +{ + const size_t srclen = strlen(src); + const size_t dstlen = strlen(dst); + if (dstlen == maxlen) + return maxlen + srclen; + if (srclen < maxlen - dstlen) { + memcpy(dst + dstlen, src, srclen + 1); + } + else { + memcpy(dst + dstlen, src, maxlen - 1); + dst[dstlen + maxlen - 1] = '\0'; + } + return dstlen + srclen; +} + +static int number_width(const size_t number) +{ + if (number == 0) { + return 1; + } + int width = (int)floor(log10(number)) + 1; + return width; +} + +static void verify_valid_component(int component, size_t cardinality, size_t suffix_size) +{ + assert(cardinality == suffix_size); + assert(component - 1 < suffix_size); +} + +const char *ex_component_field_name(ex_field *field, int component[EX_MAX_FIELD_NESTING]) +{ + // NOTE: This is not thread-safe. Return value is pointer to static `field_name` + // For thread-safety, it is up to calling code. + + // Return the name of the field corresponding to the specified 1-based component(s) + static char field_name[EX_MAX_NAME + 1]; + const char *suffices[EX_MAX_FIELD_NESTING] = {NULL}; + for (int i = 0; i < field->nesting; i++) { + suffices[i] = ex_field_component_suffix(field, i, component[i]); + } + + // Build up name incrementally which makes it easier to handle an empty component_separator... + sprintf(field_name, "%s", field->name); + + for (int i = 0; i < field->nesting; i++) { + if (field->component_separator[i]) { + size_t fnl = strlen(field_name); + field_name[fnl] = field->component_separator[i]; + field_name[fnl + 1] = '\0'; + } + my_strlcat(field_name, suffices[i], EX_MAX_NAME); + } + return field_name; +} + +int ex_initialize_basis_struct(ex_basis *basis, size_t num_basis, int mode) +{ + // Mode - 0 -- initialize struct to empty + // Mode > 0 -- allocate memory for dynamically sized fields. + // Mode < 0 -- deallocate memory for dynamically sized fields. + if (mode > 0) { + for (size_t i = 0; i < num_basis; i++) { + basis[i].subc_dim = calloc(basis[i].cardinality, sizeof(int)); + basis[i].subc_ordinal = calloc(basis[i].cardinality, sizeof(int)); + basis[i].subc_dof_ordinal = calloc(basis[i].cardinality, sizeof(int)); + basis[i].subc_num_dof = calloc(basis[i].cardinality, sizeof(int)); + basis[i].xi = calloc(basis[i].cardinality, sizeof(double)); + basis[i].eta = calloc(basis[i].cardinality, sizeof(double)); + basis[i].zeta = calloc(basis[i].cardinality, sizeof(double)); + if (basis[i].subc_dim == NULL || basis[i].subc_ordinal == NULL || + basis[i].subc_dof_ordinal == NULL || basis[i].subc_num_dof == NULL || + basis[i].xi == NULL || basis[i].eta == NULL || basis[i].zeta == NULL) { + return EX_FATAL; + } + } + } + if (mode < 0) { + for (size_t i = 0; i < num_basis; i++) { + free(basis[i].subc_dim); + free(basis[i].subc_ordinal); + free(basis[i].subc_dof_ordinal); + free(basis[i].subc_num_dof); + free(basis[i].xi); + free(basis[i].eta); + free(basis[i].zeta); + } + } + /* Fall through if `cardinality < 0` */ + if (mode <= 0) { + for (size_t i = 0; i < num_basis; i++) { + basis[i].name[0] = '\0'; + basis[i].cardinality = 0; + basis[i].subc_dim = NULL; + basis[i].subc_ordinal = NULL; + basis[i].subc_dof_ordinal = NULL; + basis[i].subc_num_dof = NULL; + basis[i].xi = NULL; + basis[i].eta = NULL; + basis[i].zeta = NULL; + } + } + return EX_NOERR; +} + +int ex_initialize_quadrature_struct(ex_quadrature *quad, size_t num_quad, int mode) +{ + // Mode - 0 -- initialize struct to empty + // Mode > 0 -- allocate memory for dynamically sized fields. + // Mode < 0 -- deallocate memory for dynamically sized fields. + if (mode > 0) { + for (size_t i = 0; i < num_quad; i++) { + quad[i].xi = calloc(quad[i].cardinality, sizeof(double)); + quad[i].eta = calloc(quad[i].cardinality, sizeof(double)); + quad[i].zeta = calloc(quad[i].cardinality, sizeof(double)); + quad[i].weight = calloc(quad[i].cardinality, sizeof(double)); + if (quad[i].xi == NULL || quad[i].eta == NULL || quad[i].zeta == NULL || + quad[i].weight == NULL) { + return EX_FATAL; + } + } + } + if (mode < 0) { + for (size_t i = 0; i < num_quad; i++) { + free(quad[i].xi); + free(quad[i].eta); + free(quad[i].zeta); + free(quad[i].weight); + } + } + if (mode <= 0) { + for (size_t i = 0; i < num_quad; i++) { + quad[i].name[0] = '\0'; + quad[i].cardinality = 0; + quad[i].xi = NULL; + quad[i].eta = NULL; + quad[i].zeta = NULL; + quad[i].weight = NULL; + } + } + return EX_NOERR; +} + +const char *ex_field_component_suffix(ex_field *field, int nest_level, int component) +{ +#define X "X" +#define Y "Y" +#define Z "Z" +#define Q "Q" +#define S "S" + +#define XX "XX" +#define YY "YY" +#define ZZ "ZZ" +#define XY "XY" +#define YZ "YZ" +#define ZX "ZC" +#define YX "YX" +#define ZY "ZY" +#define XZ "XZ" + + switch (field->type[nest_level]) { + case EX_VECTOR_1D: { + static const char *suffix[] = {X}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_VECTOR_2D: { + static const char *suffix[] = {X, Y}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_VECTOR_3D: { + static const char *suffix[] = {X, Y, Z}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + + case EX_QUATERNION_2D: { + static const char *suffix[] = {S, Q}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_QUATERNION_3D: { + static const char *suffix[] = {X, Y, Z, Q}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + + case EX_FULL_TENSOR_12: { + static const char *suffix[] = {XX, XY, YX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_FULL_TENSOR_16: { + static const char *suffix[] = {XX, XY, YZ, ZX, YX, ZY, XZ}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_FULL_TENSOR_22: { + static const char *suffix[] = {XX, YY, XY, YX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_FULL_TENSOR_32: { + static const char *suffix[] = {XX, YY, ZZ, XY, YX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_FULL_TENSOR_36: { + static const char *suffix[] = {XX, YY, ZZ, XY, YZ, ZX, YX, ZY, XZ}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + + case EX_SYM_TENSOR_10: { + static const char *suffix[] = {XX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_SYM_TENSOR_11: { + static const char *suffix[] = {XX, XY}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_SYM_TENSOR_13: { + static const char *suffix[] = {XX, XY, YZ, ZX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_SYM_TENSOR_21: { + static const char *suffix[] = {XX, YY, XY}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_SYM_TENSOR_31: { + static const char *suffix[] = {XX, YY, ZZ, XY}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_SYM_TENSOR_33: { + static const char *suffix[] = {XX, YY, ZZ, XY, YZ, ZX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + + case EX_ASYM_TENSOR_01: { + static const char *suffix[] = {XY}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_ASYM_TENSOR_02: { + static const char *suffix[] = {XY, YZ}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_ASYM_TENSOR_03: { + static const char *suffix[] = {XY, YZ, ZX}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + + case EX_MATRIX_2X2: { + static const char *suffix[] = {"11", "12", "21", "22"}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + case EX_MATRIX_3X3: { + static const char *suffix[] = {"11", "12", "13", "21", "22", "23", "31", "32", "33"}; + verify_valid_component(component, ex_field_cardinality(field->type[nest_level]), SIZE(suffix)); + return suffix[component - 1]; + } + + case EX_FIELD_TYPE_USER_DEFINED: { + if (field->suffices[0] != '\0') { + // `user_suffices` is a comma-separated string. Assume component is valid. + char *string = strdup(field->suffices); + char *tofree = string; + char *token = my_strsep(&string, ","); + for (int i = 0; i < component - 1; i++) { + token = my_strsep(&string, ","); + } + if (token != NULL) { + static char user_suffix[32 + 1]; + ex_copy_string(user_suffix, token, 32); + free(tofree); + return user_suffix; + } + free(tofree); + } + return "invalid"; + } + case EX_FIELD_TYPE_SEQUENCE: { + // Suffices are just 1...#components. + static char user_suffix[32]; + static char format[8]; + int width = number_width(field->cardinality[nest_level]); + sprintf(format, "%c%d%dd", '%', 0, width); + sprintf(user_suffix, format, component); + return user_suffix; + } + + case EX_BASIS: + case EX_QUADRATURE: { + // Suffices are just 0...#components-1. + static char user_suffix[32]; + static char format[8]; + int width = number_width(field->cardinality[nest_level]); + sprintf(format, "%c%d%dd", '%', 0, width); + sprintf(user_suffix, format, component - 1); + return user_suffix; + } + + case EX_SCALAR: + case EX_FIELD_TYPE_INVALID: + default: return "invalid"; + } +} + +int ex_field_cardinality(const ex_field_type field_type) +{ + switch (field_type) { + case EX_FIELD_TYPE_USER_DEFINED: return -1; + case EX_FIELD_TYPE_SEQUENCE: return -1; + case EX_QUADRATURE: return -1; + case EX_BASIS: return -1; + case EX_SCALAR: return 1; + + case EX_VECTOR_1D: return 1; + case EX_VECTOR_2D: return 2; + case EX_VECTOR_3D: return 3; + + case EX_QUATERNION_2D: return 2; + case EX_QUATERNION_3D: return 4; + + case EX_FULL_TENSOR_12: return 3; + case EX_FULL_TENSOR_16: return 7; + case EX_FULL_TENSOR_22: return 4; + case EX_FULL_TENSOR_32: return 5; + case EX_FULL_TENSOR_36: return 9; + + case EX_SYM_TENSOR_10: return 1; + case EX_SYM_TENSOR_11: return 2; + case EX_SYM_TENSOR_13: return 4; + case EX_SYM_TENSOR_21: return 3; + case EX_SYM_TENSOR_31: return 4; + case EX_SYM_TENSOR_33: return 6; + + case EX_ASYM_TENSOR_01: return 1; + case EX_ASYM_TENSOR_02: return 2; + case EX_ASYM_TENSOR_03: return 3; + + case EX_MATRIX_2X2: return 4; + case EX_MATRIX_3X3: return 9; + + case EX_FIELD_TYPE_INVALID: return -1; + } + return -1; +} + +/** The reverse of `field_type_enum_to_string` Used to convert the + * string into a `field_type` enum. The string is parsed from the + * database as a user-readable attribute. For example, EX_VECTOR_2D + * is on the database instead of a raw number 2 + */ +ex_field_type ex_string_to_field_type_enum(const char *field_name) +{ + if (strcmp(field_name, "EX_FIELD_TYPE_USER_DEFINED") == 0) { + return EX_FIELD_TYPE_USER_DEFINED; + } + if (strcmp(field_name, "EX_FIELD_TYPE_SEQUENCE") == 0) { + return EX_FIELD_TYPE_SEQUENCE; + } + if (strcmp(field_name, "EX_BASIS") == 0) { + return EX_BASIS; + } + if (strcmp(field_name, "EX_QUADRATURE") == 0) { + return EX_QUADRATURE; + } + if (strcmp(field_name, "EX_SCALAR") == 0) { + return EX_SCALAR; + } + if (strcmp(field_name, "EX_VECTOR_1D") == 0) { + return EX_VECTOR_1D; + } + if (strcmp(field_name, "EX_VECTOR_2D") == 0) { + return EX_VECTOR_2D; + } + if (strcmp(field_name, "EX_VECTOR_3D") == 0) { + return EX_VECTOR_3D; + } + if (strcmp(field_name, "EX_QUATERNION_2D") == 0) { + return EX_QUATERNION_2D; + } + if (strcmp(field_name, "EX_QUATERNION_3D") == 0) { + return EX_QUATERNION_3D; + } + if (strcmp(field_name, "EX_FULL_TENSOR_36") == 0) { + return EX_FULL_TENSOR_36; + } + if (strcmp(field_name, "EX_FULL_TENSOR_32") == 0) { + return EX_FULL_TENSOR_32; + } + if (strcmp(field_name, "EX_FULL_TENSOR_22") == 0) { + return EX_FULL_TENSOR_22; + } + if (strcmp(field_name, "EX_FULL_TENSOR_16") == 0) { + return EX_FULL_TENSOR_16; + } + if (strcmp(field_name, "EX_FULL_TENSOR_12") == 0) { + return EX_FULL_TENSOR_12; + } + if (strcmp(field_name, "EX_SYMMETRIC_TENSOR_33") == 0) { + return EX_SYM_TENSOR_33; + } + if (strcmp(field_name, "EX_SYMMETRIC_TENSOR_31") == 0) { + return EX_SYM_TENSOR_31; + } + if (strcmp(field_name, "EX_SYMMETRIC_TENSOR_21") == 0) { + return EX_SYM_TENSOR_21; + } + if (strcmp(field_name, "EX_SYMMETRIC_TENSOR_13") == 0) { + return EX_SYM_TENSOR_13; + } + if (strcmp(field_name, "EX_SYMMETRIC_TENSOR_11") == 0) { + return EX_SYM_TENSOR_11; + } + if (strcmp(field_name, "EX_SYMMETRIC_TENSOR_10") == 0) { + return EX_SYM_TENSOR_10; + } + if (strcmp(field_name, "EX_ASYMMETRIC_TENSOR_03") == 0) { + return EX_ASYM_TENSOR_03; + } + if (strcmp(field_name, "EX_ASYMMETRIC_TENSOR_02") == 0) { + return EX_ASYM_TENSOR_02; + } + if (strcmp(field_name, "EX_ASYMMETRIC_TENSOR_01") == 0) { + return EX_ASYM_TENSOR_01; + } + if (strcmp(field_name, "EX_MATRIX_2X2") == 0) { + return EX_MATRIX_2X2; + } + if (strcmp(field_name, "EX_MATRIX_3X3") == 0) { + return EX_MATRIX_3X3; + } + if (strcmp(field_name, "EX_FIELD_TYPE_INVALID") == 0) { + return EX_FIELD_TYPE_INVALID; + } + return EX_FIELD_TYPE_INVALID; +} + +/** Used to convert a `field_type` enum to a string so it can be + * written to the database as a user-readable attribute. For + * example, EX_VECTOR_2D would appear instead of a raw number 2 + */ +const char *ex_field_type_enum_to_string(const ex_field_type field_type) +{ + switch (field_type) { + case EX_FIELD_TYPE_USER_DEFINED: return "EX_FIELD_TYPE_USER_DEFINED"; + case EX_FIELD_TYPE_SEQUENCE: return "EX_FIELD_TYPE_SEQUENCE"; + case EX_BASIS: return "EX_BASIS"; + case EX_QUADRATURE: return "EX_QUADRATURE"; + case EX_SCALAR: return "EX_SCALAR"; + case EX_VECTOR_1D: return "EX_VECTOR_1D"; + case EX_VECTOR_2D: return "EX_VECTOR_2D"; + case EX_VECTOR_3D: return "EX_VECTOR_3D"; + case EX_QUATERNION_2D: return "EX_QUATERNION_2D"; + case EX_QUATERNION_3D: return "EX_QUATERNION_3D"; + case EX_FULL_TENSOR_36: return "EX_FULL_TENSOR_36"; + case EX_FULL_TENSOR_32: return "EX_FULL_TENSOR_32"; + case EX_FULL_TENSOR_22: return "EX_FULL_TENSOR_22"; + case EX_FULL_TENSOR_16: return "EX_FULL_TENSOR_16"; + case EX_FULL_TENSOR_12: return "EX_FULL_TENSOR_12"; + case EX_SYM_TENSOR_33: return "EX_SYMMETRIC_TENSOR_33"; + case EX_SYM_TENSOR_31: return "EX_SYMMETRIC_TENSOR_31"; + case EX_SYM_TENSOR_21: return "EX_SYMMETRIC_TENSOR_21"; + case EX_SYM_TENSOR_13: return "EX_SYMMETRIC_TENSOR_13"; + case EX_SYM_TENSOR_11: return "EX_SYMMETRIC_TENSOR_11"; + case EX_SYM_TENSOR_10: return "EX_SYMMETRIC_TENSOR_10"; + case EX_ASYM_TENSOR_03: return "EX_ASYMMETRIC_TENSOR_03"; + case EX_ASYM_TENSOR_02: return "EX_ASYMMETRIC_TENSOR_02"; + case EX_ASYM_TENSOR_01: return "EX_ASYMMETRIC_TENSOR_01"; + case EX_MATRIX_2X2: return "EX_MATRIX_2X2"; + case EX_MATRIX_3X3: return "EX_MATRIX_3X3"; + case EX_FIELD_TYPE_INVALID: return "EX_FIELD_TYPE_INVALID"; + } + return "EX_FIELD_TYPE_INVALID"; +} + +const char *ex_field_type_name(const ex_field_type field_type) +{ + switch (field_type) { + case EX_FIELD_TYPE_USER_DEFINED: return "user defined"; + case EX_FIELD_TYPE_SEQUENCE: return "sequence"; + case EX_BASIS: return "basis"; + case EX_QUADRATURE: return "quadrature"; + case EX_SCALAR: return "scalar"; + case EX_VECTOR_1D: return "vector 1D"; + case EX_VECTOR_2D: return "vector 2D"; + case EX_VECTOR_3D: return "vector 3D"; + case EX_QUATERNION_2D: return "quaternion 2D"; + case EX_QUATERNION_3D: return "quaternion 3D"; + case EX_FULL_TENSOR_36: return "full tensor 36"; + case EX_FULL_TENSOR_32: return "full tensor 32"; + case EX_FULL_TENSOR_22: return "full tensor 22"; + case EX_FULL_TENSOR_16: return "full tensor 16"; + case EX_FULL_TENSOR_12: return "full tensor 12"; + case EX_SYM_TENSOR_33: return "symmetric tensor 33"; + case EX_SYM_TENSOR_31: return "symmetric tensor 31"; + case EX_SYM_TENSOR_21: return "symmetric tensor 21"; + case EX_SYM_TENSOR_13: return "symmetric tensor 13"; + case EX_SYM_TENSOR_11: return "symmetric tensor 11"; + case EX_SYM_TENSOR_10: return "symmetric tensor 10"; + case EX_ASYM_TENSOR_03: return "asymmetric tensor 03"; + case EX_ASYM_TENSOR_02: return "asymmetric tensor 02"; + case EX_ASYM_TENSOR_01: return "asymmetric tensor 01"; + case EX_MATRIX_2X2: return "matrix 2x2"; + case EX_MATRIX_3X3: return "matrix 3x3"; + case EX_FIELD_TYPE_INVALID: return "invalid"; + } + return "invalid"; +} diff --git a/packages/seacas/libraries/exodus/src/ex_get_attribute.c b/packages/seacas/libraries/exodus/src/ex_get_attribute.c index 6ac12f47e3..261d7ebadf 100644 --- a/packages/seacas/libraries/exodus/src/ex_get_attribute.c +++ b/packages/seacas/libraries/exodus/src/ex_get_attribute.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2022, 2024 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. * @@ -28,7 +28,7 @@ static bool exi_is_internal_attribute(const char *name, ex_entity_type obj_type) if (name[0] == '_') { return true; } - else if ((strcmp(name, "elem_type") == 0) || (strcmp(name, "entity_type1") == 0) || + else if ((strcmp(name, ATT_NAME_ELB) == 0) || (strcmp(name, "entity_type1") == 0) || (strcmp(name, "entity_type2") == 0)) { return true; } @@ -42,62 +42,16 @@ static bool exi_is_internal_attribute(const char *name, ex_entity_type obj_type) (strcmp(name, ATT_LAST_WRITTEN_TIME) == 0))) { return true; } - return false; -} - -static int exi_get_varid(int exoid, ex_entity_type obj_type, ex_entity_id id) -{ - char errmsg[MAX_ERR_LENGTH]; - int status = 0; - - if (exi_check_valid_file_id(exoid, __func__) == EX_FATAL) { - return (EX_FATAL); - } - - /* First, locate index of this objects id `obj_type` id array */ - int id_ndx = exi_id_lkup(exoid, obj_type, id); - if (id_ndx <= 0) { - ex_get_err(NULL, NULL, &status); - if (status != 0) { - if (status == EX_NULLENTITY) { /* NULL object? */ - return EX_NOERR; - } - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in id array in file id %d", - ex_name_of_object(obj_type), id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return EX_FATAL; - } + else if (strncmp(name, "Field@", 6) == 0) { + return true; } - - const char *entryptr = NULL; - switch (obj_type) { - case EX_ASSEMBLY: entryptr = VAR_ENTITY_ASSEMBLY(id_ndx); break; - case EX_BLOB: entryptr = VAR_ENTITY_BLOB(id_ndx); break; - case EX_NODE_SET: entryptr = VAR_NODE_NS(id_ndx); break; - case EX_EDGE_SET: entryptr = VAR_EDGE_ES(id_ndx); break; - case EX_FACE_SET: entryptr = VAR_FACE_FS(id_ndx); break; - case EX_SIDE_SET: entryptr = VAR_ELEM_SS(id_ndx); break; - case EX_ELEM_SET: entryptr = VAR_ELEM_ELS(id_ndx); break; - case EX_EDGE_BLOCK: entryptr = VAR_EBCONN(id_ndx); break; - case EX_FACE_BLOCK: entryptr = VAR_FBCONN(id_ndx); break; - case EX_ELEM_BLOCK: entryptr = VAR_CONN(id_ndx); break; - default: - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: object type %d not supported in call to %s", obj_type, - __func__); - ex_err(__func__, errmsg, EX_BADPARAM); - return EX_FATAL; + else if (strncmp(name, "Basis@", 6) == 0) { + return true; } - - int varid = 0; - if ((status = nc_inq_varid(exoid, entryptr, &varid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate entity list array for %s %" PRId64 " in file id %d", - ex_name_of_object(obj_type), id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return EX_FATAL; + else if (strncmp(name, "Quad@", 5) == 0) { + return true; } - return varid; + return false; } static int exi_get_attribute_count(int exoid, ex_entity_type obj_type, ex_entity_id id, int *varid) diff --git a/packages/seacas/libraries/exodus/src/ex_get_field_metadata.c b/packages/seacas/libraries/exodus/src/ex_get_field_metadata.c new file mode 100644 index 0000000000..7d1dbdd70e --- /dev/null +++ b/packages/seacas/libraries/exodus/src/ex_get_field_metadata.c @@ -0,0 +1,568 @@ +/* + * Copyright(C) 1999-2024 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 "exodusII.h" // for ex_err, etc +#include "exodusII_int.h" // for EX_FATAL, etc +#include +#include + +static const char *exi_get_metadata_attribute(char *name, const char *prefix, int pre_len) +{ + /* + * Each field or basis attribute metadata attribute consists of 2 or more attributes. + * Return the string corresponding to {type} in an attribute of the form "Field@{name}@{type}" + * or "Basis@{name}@{type}" or "Quad@{name}@{type}". + */ + + if (strncmp(name, prefix, pre_len) == 0) { + /* Return the suffix (if any) following the last "@" */ + char *suffix = strrchr(name, '@'); + if (suffix != NULL) { + suffix++; + return suffix; + } + } + return NULL; +} + +static const char *exi_get_attribute_metadata_name(char *attrib, int offset) +{ + /* + * PRECONDITION: `attrib` is a basis or field metadata attribute of the form + * "Basis@{name}@{type}" or "Field@{name}@{type}" `offset` is the length + * of `Basis@` or `Field@` or `Quad@` + * + * Returns the `{name}` portion in `name` + */ + static char name[EX_MAX_NAME + 1]; + memset(name, '\0', EX_MAX_NAME + 1); + for (int i = 0; attrib[i + offset] != '@'; i++) { + name[i] = attrib[i + offset]; + } + return name; +} + +static int exi_get_attribute_count(int exoid, ex_entity_type obj_type, ex_entity_id id, int *varid) +{ + int att_count = 0; + int status; + + if (obj_type == EX_GLOBAL) { + *varid = NC_GLOBAL; + + if ((status = nc_inq(exoid, NULL, NULL, &att_count, NULL)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get GLOBAL attribute count"); + ex_err_fn(exoid, __func__, errmsg, status); + return EX_FATAL; + } + } + else { + *varid = exi_get_varid(exoid, obj_type, id); + if (*varid <= 0) { + /* Error message handled in exi_get_varid */ + return 0; + } + + if ((status = nc_inq_var(exoid, *varid, NULL, NULL, NULL, NULL, &att_count)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to get attribute count on %s with id %" PRId64, + ex_name_of_object(obj_type), id); + ex_err_fn(exoid, __func__, errmsg, status); + return EX_FATAL; + } + } + return att_count; +} + +int ex_get_field_metadata_count(int exoid, ex_entity_type obj_type, ex_entity_id id) +{ + EX_FUNC_ENTER(); + + int varid; + int att_count = exi_get_attribute_count(exoid, obj_type, id, &varid); + if (att_count < 0) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Negative attribute count (%d) on %s with id %" PRId64, + att_count, ex_name_of_object(obj_type), id); + ex_err_fn(exoid, __func__, errmsg, EX_INTERNAL); + EX_FUNC_LEAVE(EX_FATAL); + } + + /* Get names of each attribute and see if it is a 'Field metadata' name */ + int count = 0; + for (int i = 0; i < att_count; i++) { + char name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, i, name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to get attribute named %s on %s with id %" PRId64, name, + ex_name_of_object(obj_type), id); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + const char *type = exi_get_metadata_attribute(name, "Field@", 6); + if (type != NULL && strcmp("type", type) == 0) { + count++; + } + } + EX_FUNC_LEAVE(count); +} + +/*! Get the values for the specified attribute. */ +int ex_get_field_metadata(int exoid, ex_field *field) +{ + EX_FUNC_ENTER(); + + int varid; + int att_count = exi_get_attribute_count(exoid, field->entity_type, field->entity_id, &varid); + if (att_count < 0) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Negative attribute count (%d) on %s with id %" PRId64, + att_count, ex_name_of_object(field->entity_type), field->entity_id); + ex_err_fn(exoid, __func__, errmsg, EX_INTERNAL); + EX_FUNC_LEAVE(EX_FATAL); + } + + /* Iterate through each Field metadata field and populate `field` */ + int count = 0; + for (int i = 0; i < att_count; i++) { + char attr_name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, i, attr_name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to get attribute named %s on %s with id %" PRId64, attr_name, + ex_name_of_object(field->entity_type), field->entity_id); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + const char *fld_type = exi_get_metadata_attribute(attr_name, "Field@", 6); + if (fld_type != NULL) { + /* Get the field name. We know that the `name` is of the form "Field@{name}@{item}" */ + const char *fld_name = exi_get_attribute_metadata_name(attr_name, 6); + + /* If this is the first time we have seen this `fld_name`, then increment count and + * store the name */ + int found = -1; + int which = 0; + for (int ii = 0; ii < count; ii++) { + if (strcmp(field[ii].name, fld_name) == 0) { + found = ii; + which = ii; + break; + } + } + + if (found == -1) { + which = count; + strcpy(field[count].name, fld_name); + count++; + } + + nc_type type; /* integer, double, character, ... */ + size_t val_count; /* how many `type` values */ + if ((status = nc_inq_att(exoid, varid, attr_name, &type, &val_count)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to get parameters for attribute named %s on %s with id %" PRId64, + attr_name, ex_name_of_object(field->entity_type), field->entity_id); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (strcmp(fld_type, "type") == 0) { + status = nc_get_att_int(exoid, varid, attr_name, (int *)field[which].type); + if (field[which].nesting == 0) { + field[which].nesting = val_count; + } + } + else if (strcmp(fld_type, "separator") == 0) { + status = nc_get_att_text(exoid, varid, attr_name, field[which].component_separator); + } + else if (strcmp(fld_type, "cardinality") == 0) { + status = nc_get_att_int(exoid, varid, attr_name, field[which].cardinality); + if (field[which].nesting == 0) { + field[which].nesting = val_count; + } + } + else if (strcmp(fld_type, "type_name") == 0) { + status = nc_get_att_text(exoid, varid, attr_name, field[which].type_name); + } + else if (strcmp(fld_type, "suffices") == 0) { + status = nc_get_att_text(exoid, varid, attr_name, field[which].suffices); + } + else { + char errmsg[MAX_ERR_LENGTH]; + snprintf( + errmsg, MAX_ERR_LENGTH, + "ERROR: Invalid field metadata attribute type %s on field %s on %s with id %" PRId64, + fld_type, fld_name, ex_name_of_object(field->entity_type), field->entity_id); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + if (status != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to read field metadata attribute type %s on field %s on %s with id " + "%" PRId64, + fld_type, fld_name, ex_name_of_object(field->entity_type), field->entity_id); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + } + } + EX_FUNC_LEAVE(EX_NOERR); +} + +int exi_get_metadata_count(int exoid, const char *which) +{ + EX_FUNC_ENTER(); + + int varid; + int att_count = exi_get_attribute_count(exoid, EX_GLOBAL, 0, &varid); + if (att_count < 0) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Negative attribute count (%d)", att_count); + ex_err_fn(exoid, __func__, errmsg, EX_INTERNAL); + EX_FUNC_LEAVE(EX_FATAL); + } + + /* Get names of each attribute and see if it is a `which` metadata name */ + size_t att_len = strlen(which); + int count = 0; + for (int i = 0; i < att_count; i++) { + char name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, i, name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get attribute named %s", name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + const char *type = exi_get_metadata_attribute(name, which, att_len); + if (type != NULL && strcmp("cardinality", type) == 0) { + count++; + } + } + EX_FUNC_LEAVE(count); +} + +int ex_get_basis_count(int exoid) { return exi_get_metadata_count(exoid, "Basis@"); } + +int ex_get_quadrature_count(int exoid) { return exi_get_metadata_count(exoid, "Quad@"); } + +int ex_get_basis(int exoid, ex_basis **pbasis, int *num_basis) +{ + /* + * -- If this function is called and there is no basis metadata on the + * entity, it will return EX_NOTFOUND; + * + * -- If there are basis defined on the database, it will: + * - determine number of basis defined on database and return the count in `num_basis` + * - allocate `num_basis` copies of `ex_basis` + * - determine the cardinality of each basis and allocate the array members of each basis + * struct. + * - populate the array members for each basis. + * + * Upon return, the `pbasis` will contain `num_basis` structs fully populated. + */ + + // TODO: Should all array members of the struct be allocated and initialized to zero, or + // only the members that are actually defined on the database... + EX_FUNC_ENTER(); + + *num_basis = ex_get_basis_count(exoid); + if (*num_basis == 0) { + EX_FUNC_LEAVE(EX_NOTFOUND); + } + + int varid; + int att_count = exi_get_attribute_count(exoid, EX_GLOBAL, 0, &varid); + if (att_count < 0) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Negative attribute count (%d)", att_count); + ex_err_fn(exoid, __func__, errmsg, EX_INTERNAL); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (*pbasis == NULL) { + struct ex_basis *basis = (ex_basis *)calloc(*num_basis, sizeof(struct ex_basis)); + *pbasis = basis; + } + struct ex_basis *basis = *pbasis; + + // First, iterate through each attribute and get the basis name and cardinality + int count = 0; + for (int att = 0; att < att_count; att++) { + char attr_name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, att, attr_name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get attribute named %s", attr_name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (strncmp("Basis@", attr_name, 6) != 0) { + continue; + } + + const char *basis_type = exi_get_metadata_attribute(attr_name, "Basis@", 6); + if (basis_type != NULL && strcmp(basis_type, "cardinality") == 0) { + /* Get the basis name. We know that the `name` is of the form "Basis@{name}@{item}" */ + const char *basis_name = exi_get_attribute_metadata_name(attr_name, 6); + strcpy(basis[count].name, basis_name); + + int cardinality = 0; + status = nc_get_att_int(exoid, varid, attr_name, &cardinality); + basis[count].cardinality = cardinality; + count++; + if (count == *num_basis) { + break; + } + continue; + } + } + + if (count != *num_basis) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: Internal error populating basis name and cardinality. Did not find correct " + "number of basis attributes."); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + EX_FUNC_LEAVE(EX_FATAL); + } + + ex_initialize_basis_struct(basis, *num_basis, 1); + + // Now iterate the attributes again and fully populate the basis struct(s) + for (int att = 0; att < att_count; att++) { + char attr_name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, att, attr_name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get attribute named %s", attr_name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (strncmp("Basis@", attr_name, 6) != 0) { + continue; + } + + const char *basis_type = exi_get_metadata_attribute(attr_name, "Basis@", 6); + if (basis_type != NULL) { + /* Get the basis name. We know that the `name` is of the form "Basis@{name}@{item}" */ + const char *basis_name = exi_get_attribute_metadata_name(attr_name, 6); + + // There is no guarantee that we will be getting names in the same order as above since + // attributes can be in any order. But, the name and cardinality for each basis will already + // be set, so we just need to find the correct one... + int which = -1; + for (int i = 0; i < *num_basis; i++) { + if (strcmp(basis[i].name, basis_name) == 0) { + which = i; + break; + } + } + + if (which == -1) { + // Internal error... + } + + if (strcmp(basis_type, "cardinality") == 0) { + // Cardinality already set; skip + } + else if (strcmp(basis_type, "subc_dim") == 0) { + status = nc_get_att_int(exoid, varid, attr_name, basis[which].subc_dim); + } + else if (status == NC_NOERR && strcmp(basis_type, "subc_ordinal") == 0) { + status = nc_get_att_int(exoid, varid, attr_name, basis[which].subc_ordinal); + } + else if (status == NC_NOERR && strcmp(basis_type, "subc_dof_ordinal") == 0) { + status = nc_get_att_int(exoid, varid, attr_name, basis[which].subc_dof_ordinal); + } + else if (status == NC_NOERR && strcmp(basis_type, "subc_num_dof") == 0) { + status = nc_get_att_int(exoid, varid, attr_name, basis[which].subc_num_dof); + } + else if (status == NC_NOERR && strcmp(basis_type, "xi") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, basis[which].xi); + } + else if (status == NC_NOERR && strcmp(basis_type, "eta") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, basis[which].eta); + } + else if (status == NC_NOERR && strcmp(basis_type, "zeta") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, basis[which].zeta); + } + + if (status != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to read Basis %s metadata", + basis[which].name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + } + } + EX_FUNC_LEAVE(EX_NOERR); +} + +int ex_get_quadrature(int exoid, ex_quadrature **pquad, int *num_quad) +{ + /* + * -- If this function is called and there is no quadrature metadata on the + * entity, it will return EX_NOTFOUND; + * + * -- If there are quadrature defined on the database, it will: + * - determine number of quadrature defined on database and return the count in `num_quad` + * - allocate `num_quad` copies of `ex_quad` + * - determine the cardinality of each quadrature and allocate the array members of each + * quadrature struct. + * - populate the array members for each quadrature. + * + * Upon return, the `pquad` will contain `num_basis` structs fully populated. + */ + + // TODO: Should all array members of the struct(xi, eta, zeta, + // weight) be allocated and initialized to zero, or only the + // members that are actually defined on the database... + EX_FUNC_ENTER(); + + *num_quad = ex_get_quadrature_count(exoid); + if (*num_quad == 0) { + EX_FUNC_LEAVE(EX_NOTFOUND); + } + + int varid; + int att_count = exi_get_attribute_count(exoid, EX_GLOBAL, 0, &varid); + if (att_count < 0) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Negative attribute count (%d)", att_count); + ex_err_fn(exoid, __func__, errmsg, EX_INTERNAL); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (*pquad == NULL) { + struct ex_quadrature *quad = (ex_quadrature *)calloc(*num_quad, sizeof(struct ex_quadrature)); + *pquad = quad; + } + struct ex_quadrature *quad = *pquad; + + // First, iterate through each attribute and get the quadrature name and cardinality + int count = 0; + for (int att = 0; att < att_count; att++) { + char attr_name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, att, attr_name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get attribute named %s", attr_name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (strncmp("Quad@", attr_name, 5) != 0) { + continue; + } + + const char *quadrature_type = exi_get_metadata_attribute(attr_name, "Quad@", 5); + if (quadrature_type != NULL && strcmp(quadrature_type, "cardinality") == 0) { + /* Get the quadrature name. We know that the `name` is of the form "Quad@{name}@{item}" */ + const char *quadrature_name = exi_get_attribute_metadata_name(attr_name, 5); + strcpy(quad[count].name, quadrature_name); + + int cardinality = 0; + status = nc_get_att_int(exoid, varid, attr_name, &cardinality); + quad[count].cardinality = cardinality; + count++; + if (count == *num_quad) { + break; + } + continue; + } + } + + if (count != *num_quad) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: Internal error populating quadrature name and cardinality. Did not find " + "correct number of quadrature attributes."); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + EX_FUNC_LEAVE(EX_FATAL); + } + + ex_initialize_quadrature_struct(quad, *num_quad, 1); + + // Now iterate the attributes again and fully populate the quadrature struct(s) + for (int att = 0; att < att_count; att++) { + char attr_name[EX_MAX_NAME + 1]; + int status; + if ((status = nc_inq_attname(exoid, varid, att, attr_name)) != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get attribute named %s", attr_name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (strncmp("Quad@", attr_name, 5) != 0) { + continue; + } + + const char *quadrature_type = exi_get_metadata_attribute(attr_name, "Quad@", 5); + if (quadrature_type != NULL) { + + /* Get the quadrature name. We know that the `name` is of the form "Quad@{name}@{item}" */ + const char *quadrature_name = exi_get_attribute_metadata_name(attr_name, 5); + + // There is no guarantee that we will be getting names in the same order as above since + // attributes can be in any order. But, the name and cardinality for each quadrature will + // already be set, so we just need to find the correct one... + int which = -1; + for (int i = 0; i < *num_quad; i++) { + if (strcmp(quad[i].name, quadrature_name) == 0) { + which = i; + break; + } + } + + if (which == -1) { + // Internal error... + } + + if (strcmp(quadrature_type, "cardinality") == 0) { + // Cardinality already set; skip + } + else if (strcmp(quadrature_type, "xi") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, quad[which].xi); + } + else if (status == NC_NOERR && strcmp(quadrature_type, "eta") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, quad[which].eta); + } + else if (status == NC_NOERR && strcmp(quadrature_type, "zeta") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, quad[which].zeta); + } + else if (status == NC_NOERR && strcmp(quadrature_type, "weight") == 0) { + status = nc_get_att_double(exoid, varid, attr_name, quad[which].weight); + } + // NOTE: Do not put an else since will fall through if the + // arrays are NULL even though quadrature_type is valid. + + if (status != NC_NOERR) { + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to read Quadrature %s metadata", + quad[which].name); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + } + } + EX_FUNC_LEAVE(EX_NOERR); +} diff --git a/packages/seacas/libraries/exodus/src/ex_put_all_var_param_ext.c b/packages/seacas/libraries/exodus/src/ex_put_all_var_param_ext.c index 7f2a238f7b..074a79d84f 100644 --- a/packages/seacas/libraries/exodus/src/ex_put_all_var_param_ext.c +++ b/packages/seacas/libraries/exodus/src/ex_put_all_var_param_ext.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2023 National Technology & Engineering Solutions + * Copyright(C) 1999-2024 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. * @@ -29,11 +29,11 @@ static int *get_status_array(int exoid, int var_count, const char *VARIABLE, con static int put_truth_table(int exoid, int varid, int *table, const char *label); static int define_truth_table(ex_entity_type obj_type, int exoid, int num_ent, int num_var, int *var_tab, int *status_tab, void_int *ids, const char *label); -static int ex_define_vars(int exoid, ex_entity_type obj_type, const char *entity_name, - const char *entity_blk_name, int numvar, const char *DNAME, int dimid1, - int dimid2, int DVAL, void_int **entity_ids, const char *VNOV, - const char *VTV, int **status_var, int *truth_table, - int *truth_table_var); +static int exi_define_vars(int exoid, ex_entity_type obj_type, const char *entity_name, + const char *entity_blk_name, int numvar, const char *DNAME, int dimid1, + int dimid2, int DVAL, void_int **entity_ids, const char *VNOV, + const char *VTV, int **status_var, int *truth_table, + int *truth_table_var); #define EX_GET_IDS_STATUS(TNAME, NUMVAR, DNAME, DID, DVAL, VIDS, EIDS, VSTAT, VSTATVAL) \ if (NUMVAR > 0) { \ @@ -200,52 +200,53 @@ int ex_put_all_var_param_ext(int exoid, const ex_var_params *vp) } } - if (ex_define_vars(exoid, EX_EDGE_BLOCK, "edge", "edge block", vp->num_edge, DIM_NUM_EDG_VAR, - numedblkdim, numedvardim, num_edge_blk, &edblk_ids, VAR_NAME_EDG_VAR, - VAR_EBLK_TAB, &edblk_stat, vp->edge_var_tab, &edblk_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_EDGE_BLOCK, "edge", "edge block", vp->num_edge, DIM_NUM_EDG_VAR, + numedblkdim, numedvardim, num_edge_blk, &edblk_ids, VAR_NAME_EDG_VAR, + VAR_EBLK_TAB, &edblk_stat, vp->edge_var_tab, &edblk_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_FACE_BLOCK, "face", "face block", vp->num_face, DIM_NUM_FAC_VAR, - numfablkdim, numfavardim, num_face_blk, &fablk_ids, VAR_NAME_FAC_VAR, - VAR_FBLK_TAB, &fablk_stat, vp->face_var_tab, &fablk_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_FACE_BLOCK, "face", "face block", vp->num_face, DIM_NUM_FAC_VAR, + numfablkdim, numfavardim, num_face_blk, &fablk_ids, VAR_NAME_FAC_VAR, + VAR_FBLK_TAB, &fablk_stat, vp->face_var_tab, &fablk_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_ELEM_BLOCK, "element", "element block", vp->num_elem, - DIM_NUM_ELE_VAR, numelblkdim, numelvardim, num_elem_blk, &eblk_ids, - VAR_NAME_ELE_VAR, VAR_ELEM_TAB, &eblk_stat, vp->elem_var_tab, - &eblk_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_ELEM_BLOCK, "element", "element block", vp->num_elem, + DIM_NUM_ELE_VAR, numelblkdim, numelvardim, num_elem_blk, &eblk_ids, + VAR_NAME_ELE_VAR, VAR_ELEM_TAB, &eblk_stat, vp->elem_var_tab, + &eblk_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_NODE_SET, "nodeset", "node set", vp->num_nset, DIM_NUM_NSET_VAR, - numnsetdim, nsetvardim, num_nset, &nset_ids, VAR_NAME_NSET_VAR, VAR_NSET_TAB, - &nset_stat, vp->nset_var_tab, &nset_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_NODE_SET, "nodeset", "node set", vp->num_nset, DIM_NUM_NSET_VAR, + numnsetdim, nsetvardim, num_nset, &nset_ids, VAR_NAME_NSET_VAR, VAR_NSET_TAB, + &nset_stat, vp->nset_var_tab, &nset_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_EDGE_SET, "edgeset", "edge set", vp->num_eset, DIM_NUM_ESET_VAR, - numesetdim, esetvardim, num_eset, &eset_ids, VAR_NAME_ESET_VAR, VAR_ESET_TAB, - &eset_stat, vp->eset_var_tab, &eset_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_EDGE_SET, "edgeset", "edge set", vp->num_eset, DIM_NUM_ESET_VAR, + numesetdim, esetvardim, num_eset, &eset_ids, VAR_NAME_ESET_VAR, VAR_ESET_TAB, + &eset_stat, vp->eset_var_tab, &eset_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_FACE_SET, "faceset", "face set", vp->num_fset, DIM_NUM_FSET_VAR, - numfsetdim, fsetvardim, num_fset, &fset_ids, VAR_NAME_FSET_VAR, VAR_FSET_TAB, - &fset_stat, vp->fset_var_tab, &fset_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_FACE_SET, "faceset", "face set", vp->num_fset, DIM_NUM_FSET_VAR, + numfsetdim, fsetvardim, num_fset, &fset_ids, VAR_NAME_FSET_VAR, VAR_FSET_TAB, + &fset_stat, vp->fset_var_tab, &fset_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_SIDE_SET, "sideset", "side set", vp->num_sset, DIM_NUM_SSET_VAR, - numssetdim, ssetvardim, num_sset, &sset_ids, VAR_NAME_SSET_VAR, VAR_SSET_TAB, - &sset_stat, vp->sset_var_tab, &sset_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_SIDE_SET, "sideset", "side set", vp->num_sset, DIM_NUM_SSET_VAR, + numssetdim, ssetvardim, num_sset, &sset_ids, VAR_NAME_SSET_VAR, VAR_SSET_TAB, + &sset_stat, vp->sset_var_tab, &sset_varid) != EX_NOERR) { goto error_ret; } - if (ex_define_vars(exoid, EX_ELEM_SET, "elemset", "element set", vp->num_elset, DIM_NUM_ELSET_VAR, - numelsetdim, elsetvardim, num_elset, &elset_ids, VAR_NAME_ELSET_VAR, - VAR_ELSET_TAB, &elset_stat, vp->elset_var_tab, &elset_varid) != EX_NOERR) { + if (exi_define_vars(exoid, EX_ELEM_SET, "elemset", "element set", vp->num_elset, + DIM_NUM_ELSET_VAR, numelsetdim, elsetvardim, num_elset, &elset_ids, + VAR_NAME_ELSET_VAR, VAR_ELSET_TAB, &elset_stat, vp->elset_var_tab, + &elset_varid) != EX_NOERR) { goto error_ret; } @@ -517,10 +518,11 @@ static int define_truth_table(ex_entity_type obj_type, int exoid, int num_ent, i return NC_NOERR; } -static int ex_define_vars(int exoid, ex_entity_type obj_type, const char *entity_name, - const char *entity_blk_name, int numvar, const char *DNAME, int dimid1, - int dimid2, int DVAL, void_int **entity_ids, const char *VNOV, - const char *VTV, int **status_var, int *truth_table, int *truth_table_var) +static int exi_define_vars(int exoid, ex_entity_type obj_type, const char *entity_name, + const char *entity_blk_name, int numvar, const char *DNAME, int dimid1, + int dimid2, int DVAL, void_int **entity_ids, const char *VNOV, + const char *VTV, int **status_var, int *truth_table, + int *truth_table_var) { if (numvar > 0) { int status; diff --git a/packages/seacas/libraries/exodus/src/ex_put_attribute.c b/packages/seacas/libraries/exodus/src/ex_put_attribute.c index 7da9ee97be..370cfe31ef 100644 --- a/packages/seacas/libraries/exodus/src/ex_put_attribute.c +++ b/packages/seacas/libraries/exodus/src/ex_put_attribute.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2022, 2024 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. * @@ -22,88 +22,6 @@ attributes which are currently supported in Exodus. */ -static int exi_get_varid(int exoid, ex_entity_type obj_type, ex_entity_id id) -{ - const char *entryptr = NULL; - char errmsg[MAX_ERR_LENGTH]; - - int id_ndx = 0; - int status = 0; - int varid = 0; - - if (exi_check_valid_file_id(exoid, __func__) == EX_FATAL) { - EX_FUNC_LEAVE(EX_FATAL); - } - - if (obj_type == EX_GLOBAL) { - return NC_GLOBAL; - } - - if (obj_type == EX_ASSEMBLY) { - if ((status = nc_inq_varid(exoid, VAR_ENTITY_ASSEMBLY(id), &varid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in id array in file id %d", - ex_name_of_object(obj_type), id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return EX_FATAL; - } - return varid; - } - - if (obj_type == EX_BLOB) { - if ((status = nc_inq_varid(exoid, VAR_ENTITY_BLOB(id), &varid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in id array in file id %d", - ex_name_of_object(obj_type), id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return EX_FATAL; - } - return varid; - } - - /* Everything else ... */ - /* First, locate index of this objects id `obj_type` id array */ - id_ndx = exi_id_lkup(exoid, obj_type, id); - if (id_ndx <= 0) { - ex_get_err(NULL, NULL, &status); - if (status != 0) { - if (status == EX_NULLENTITY) { /* NULL object? */ - return EX_NOERR; - } - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in id array in file id %d", - ex_name_of_object(obj_type), id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return EX_FATAL; - } - } - - switch (obj_type) { - case EX_NODE_SET: entryptr = VAR_NODE_NS(id_ndx); break; - case EX_EDGE_SET: entryptr = VAR_EDGE_ES(id_ndx); break; - case EX_FACE_SET: entryptr = VAR_FACE_FS(id_ndx); break; - case EX_SIDE_SET: entryptr = VAR_ELEM_SS(id_ndx); break; - case EX_ELEM_SET: entryptr = VAR_ELEM_ELS(id_ndx); break; - case EX_EDGE_BLOCK: entryptr = VAR_EBCONN(id_ndx); break; - case EX_FACE_BLOCK: entryptr = VAR_FBCONN(id_ndx); break; - case EX_ELEM_BLOCK: entryptr = VAR_CONN(id_ndx); break; - default: - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: object type %d not supported in call to %s", obj_type, - __func__); - ex_err(__func__, errmsg, EX_BADPARAM); - return EX_FATAL; - } - - if ((status = nc_inq_varid(exoid, entryptr, &varid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate entity list array for %s %" PRId64 " in file id %d", - ex_name_of_object(obj_type), id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return EX_FATAL; - } - return varid; -} - /* define and output a double attribute */ int ex_put_double_attribute(int exoid, ex_entity_type obj_type, ex_entity_id id, const char *atr_name, int num_values, const double *values) diff --git a/packages/seacas/libraries/exodus/src/ex_put_field_metadata.c b/packages/seacas/libraries/exodus/src/ex_put_field_metadata.c new file mode 100644 index 0000000000..36ad8a30f8 --- /dev/null +++ b/packages/seacas/libraries/exodus/src/ex_put_field_metadata.c @@ -0,0 +1,292 @@ +/* + * Copyright(C) 2022, 2023, 2024 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 "exodusII.h" // for ex_err, etc +#include "exodusII_int.h" // for EX_FATAL, etc + +static int exi_print_type_error(int status, const char *name, const char *type, + const char *attribute, int exoid, const char *func) +{ + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to store '%s' for %s '%s' in file id %d", + attribute, type, name, exoid); + ex_err_fn(exoid, func, errmsg, status); + return EX_FATAL; +} + +static int exi_print_attribute_error(int status, const char *name, const char *attribute, + ex_entity_type entity_type, ex_entity_id entity_id, int exoid, + const char *func) +{ + char errmsg[MAX_ERR_LENGTH]; + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to store field metadata '%s' for field '%s' on %s with id %" PRId64 + " in file id %d", + attribute, name, ex_name_of_object(entity_type), entity_id, exoid); + ex_err_fn(exoid, func, errmsg, status); + return EX_FATAL; +} + +int ex_put_field_metadata(int exoid, const ex_field field) +{ + /* + * The attribute name is `Field@{name}@type` + * + * Field `nesting` is calculated as size of `type` field + * The `type` field is a sequence of integers which are the values of the `ex_field_type` enum. + * NOTE: For backward compatibility, we can only add new entries to this enum at the end. + * + * If size of `component_separator` == 0 then the default '_' separator used by all component + * levels If size of `component_separator` == 1 then that separator used by all component levels + * Else the size must equal nesting and it specifies a potentially different separator for each + * level. + */ +#if 0 + fprintf(stderr, + "ex_put_field_metadata: Field '%s' of type '%s' with separator '%s' on block %lld\n", + field.name, ex_field_type_enum_to_string(field.type[0]), field.component_separator, + field.entity_id); +#endif + + int status = 0; + static char *field_template = "Field@%s@%s"; + char attribute_name[NC_MAX_NAME + 1]; + sprintf(attribute_name, field_template, field.name, "type"); + if ((status = ex_put_integer_attribute(exoid, field.entity_type, field.entity_id, attribute_name, + field.nesting, field.type)) != EX_NOERR) { + return exi_print_attribute_error(status, field.name, "type", field.entity_type, field.entity_id, + exoid, __func__); + } + + sprintf(attribute_name, field_template, field.name, "type_name"); + if ((status = ex_put_text_attribute(exoid, field.entity_type, field.entity_id, attribute_name, + field.type_name)) != EX_NOERR) { + return exi_print_attribute_error(status, field.name, "type_name", field.entity_type, + field.entity_id, exoid, __func__); + } + + sprintf(attribute_name, field_template, field.name, "separator"); + if ((status = ex_put_text_attribute(exoid, field.entity_type, field.entity_id, attribute_name, + field.component_separator)) != EX_NOERR) { + return exi_print_attribute_error(status, field.name, "separator", field.entity_type, + field.entity_id, exoid, __func__); + } + + bool needs_cardinality = false; + for (int i = 0; i < field.nesting; i++) { + if (field.type[i] == EX_FIELD_TYPE_USER_DEFINED || field.type[i] == EX_FIELD_TYPE_SEQUENCE) { + needs_cardinality = true; + break; + } + } + if (needs_cardinality) { + sprintf(attribute_name, field_template, field.name, "cardinality"); + if ((status = ex_put_integer_attribute(exoid, field.entity_type, field.entity_id, + attribute_name, field.nesting, field.cardinality)) != + EX_NOERR) { + return exi_print_attribute_error(status, field.name, "cardinality", field.entity_type, + field.entity_id, exoid, __func__); + } + } + + return EX_NOERR; +} + +int exi_put_type_attribute(int exoid, const char *att_root, const char *name, const char *type, + ex_type value_type, int cardinality, const void *entry) +{ + int status = EX_NOERR; + if (entry != NULL) { + static char *template = "%s@%s@%s"; + char attribute_name[NC_MAX_NAME + 1]; + sprintf(attribute_name, template, att_root, name, type); + if (value_type == EX_INTEGER) { + status = ex_put_integer_attribute(exoid, EX_GLOBAL, 0, attribute_name, cardinality, entry); + } + else if (value_type == EX_DOUBLE) { + status = ex_put_double_attribute(exoid, EX_GLOBAL, 0, attribute_name, cardinality, entry); + } + } + return status; +} + +int exi_put_basis_attribute(int exoid, const char *basis_name, const char *type, ex_type value_type, + int cardinality, const void *basis_entry) +{ + return exi_put_type_attribute(exoid, "Basis", basis_name, type, value_type, cardinality, + basis_entry); +} + +int exi_put_quad_attribute(int exoid, const char *quad_name, const char *type, ex_type value_type, + int cardinality, const void *quad_entry) +{ + return exi_put_type_attribute(exoid, "Quad", quad_name, type, value_type, cardinality, + quad_entry); +} + +int ex_put_basis(int exoid, const ex_basis basis) +{ + /* + * typedef struct ex_basis { + * char name[EX_MAX_NAME + 1]; + * int cardinality; -- number of `basis` points == dimension of non-null subc_*, xi, eta, zeta + * int *subc_dim; + * int *subc_ordinal; + * int *subc_dof_ordinal; + * int *subc_num_dof; + * double *xi; + * double *eta; + * double *zeta; + * } ex_basis; + */ + + int status; + if ((status = exi_put_basis_attribute(exoid, basis.name, "cardinality", EX_INTEGER, 1, + &basis.cardinality)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "cardinality", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "subc_dim", EX_INTEGER, + basis.cardinality, basis.subc_dim)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "subc_dim", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "subc_ordinal", EX_INTEGER, + basis.cardinality, basis.subc_ordinal)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "subc_ordinal", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "subc_dof_ordinal", EX_INTEGER, + basis.cardinality, basis.subc_dof_ordinal)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "subc_dof_ordinal", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "subc_num_dof", EX_INTEGER, + basis.cardinality, basis.subc_num_dof)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "subc_num_dof", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "xi", EX_DOUBLE, basis.cardinality, + basis.xi)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "xi", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "eta", EX_DOUBLE, basis.cardinality, + basis.eta)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "eta", exoid, __func__); + } + + if ((status = exi_put_basis_attribute(exoid, basis.name, "zeta", EX_DOUBLE, basis.cardinality, + basis.zeta)) != EX_NOERR) { + return exi_print_type_error(status, basis.name, "basis", "zeta", exoid, __func__); + } + return EX_NOERR; +} + +int ex_put_quadrature(int exoid, const ex_quadrature quad) +{ + /* + * typedef struct ex_quad { + * char name[EX_MAX_NAME + 1]; + * int cardinality; -- number of `quad` points == dimension of non-null subc_*, xi, eta, zeta + * int *subc_dim; + * int *subc_ordinal; + * int *subc_dof_ordinal; + * int *subc_num_dof; + * double *xi; + * double *eta; + * double *zeta; + * } ex_quad; + */ + + int status; + if ((status = exi_put_quad_attribute(exoid, quad.name, "cardinality", EX_INTEGER, 1, + &quad.cardinality)) != EX_NOERR) { + return exi_print_type_error(status, quad.name, "quad", "cardinality", exoid, __func__); + } + + if ((status = exi_put_quad_attribute(exoid, quad.name, "xi", EX_DOUBLE, quad.cardinality, + quad.xi)) != EX_NOERR) { + return exi_print_type_error(status, quad.name, "quad", "xi", exoid, __func__); + } + + if ((status = exi_put_quad_attribute(exoid, quad.name, "eta", EX_DOUBLE, quad.cardinality, + quad.eta)) != EX_NOERR) { + return exi_print_type_error(status, quad.name, "quad", "eta", exoid, __func__); + } + + if ((status = exi_put_quad_attribute(exoid, quad.name, "zeta", EX_DOUBLE, quad.cardinality, + quad.zeta)) != EX_NOERR) { + return exi_print_type_error(status, quad.name, "quad", "zeta", exoid, __func__); + } + + if ((status = exi_put_quad_attribute(exoid, quad.name, "weight", EX_DOUBLE, quad.cardinality, + quad.weight)) != EX_NOERR) { + return exi_print_type_error(status, quad.name, "quad", "weight", exoid, __func__); + } + return EX_NOERR; +} + +int ex_put_field_suffices(int exoid, const ex_field field, const char *suffices) +{ + /* + * For a user-defined field metadata type, output the `cardinality`-count suffices. + * The suffices are in a single comma-separated string. + * This call is only valid if the field metadata type is user-defined. + * + * Example: cardinality = 4, type is EX_USER_DEFINED, name is "Species" + * Suffices = "h2o,gas,ch4,methane" + * The fields would be "Species_h2o", "Species_gas", "Species_ch4", "Species_methane" + * + * Accesses field.entity_type, field.entity_id, field.name, field.type, field.cardinality + * The attribute name is `Field@{name}@suffices` + */ + int status; + char errmsg[MAX_ERR_LENGTH]; + + char attribute_name[NC_MAX_NAME + 1]; + static char *field_template = "Field@%s@%s"; + + if (field.type[0] != EX_FIELD_TYPE_USER_DEFINED) { + snprintf( + errmsg, MAX_ERR_LENGTH, + "ERROR: Field '%s' is not of type EX_FIELD_TYPE_USER_DEFINED; cannot specify suffices.", + field.name); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + return EX_FATAL; + } + + /* Count the commas in the comma-separated list of suffices. Must be one less than the field + * cardinality... */ + int comma_count = 0; + for (size_t i = 0; i < strlen(suffices); i++) { + if (suffices[i] == ',') { + comma_count++; + } + } + if (comma_count + 1 != field.cardinality[0]) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: Field '%s' cardinality is %d but there were %d suffices defined. These must " + "be equal.", + field.name, field.cardinality[0], comma_count + 1); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + return EX_FATAL; + } + + sprintf(attribute_name, field_template, field.name, "suffices"); + if ((status = ex_put_text_attribute(exoid, field.entity_type, field.entity_id, attribute_name, + suffices)) != EX_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to store field suffices for field '%s' on %s with id %" PRId64 + " in file id %d", + field.name, ex_name_of_object(field.entity_type), field.entity_id, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return EX_FATAL; + } + return EX_NOERR; +} diff --git a/packages/seacas/libraries/exodus/src/ex_utils.c b/packages/seacas/libraries/exodus/src/ex_utils.c index d345477ecc..e23c6007b1 100644 --- a/packages/seacas/libraries/exodus/src/ex_utils.c +++ b/packages/seacas/libraries/exodus/src/ex_utils.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2023 National Technology & Engineering Solutions + * Copyright(C) 1999-2024 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. * @@ -11,8 +11,8 @@ * *****************************************************************************/ -#if defined(DEBUG_QSORT) -#endif +#define _GNU_SOURCE +#include #include #include @@ -2290,6 +2290,85 @@ char *ex_copy_string(char *dest, char const *source, size_t elements) return d; } +/* Used by the entity attribute code `ex_get_attribute(s)` and `ex_put_attribute(s)` */ +int exi_get_varid(int exoid, ex_entity_type obj_type, ex_entity_id id) +{ + if (exi_check_valid_file_id(exoid, __func__) == EX_FATAL) { + EX_FUNC_LEAVE(EX_FATAL); + } + + if (obj_type == EX_GLOBAL) { + return NC_GLOBAL; + } + + int status = 0; + char errmsg[MAX_ERR_LENGTH]; + + if (obj_type == EX_NODAL) { + /* For the nodal entity attributes, we store it on the + "coor_names" variable. Not exactly logical, but it exists in any + model that has nodes, so it at least gives us a place to put the + attribute. Another possibility would be the nodal x-coordinate + variable... + */ + int varid = 0; + if ((status = nc_inq_varid(exoid, VAR_NAME_COOR, &varid)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate node block variable id in file id %d", exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return EX_FATAL; + } + return varid; + } + + /* Everything else ... */ + /* First, locate index of this objects id `obj_type` id array */ + /* First, locate index of this objects id `obj_type` id array */ + int id_ndx = exi_id_lkup(exoid, obj_type, id); + if (id_ndx <= 0) { + ex_get_err(NULL, NULL, &status); + if (status != 0) { + if (status == EX_NULLENTITY) { /* NULL object? */ + return EX_NOERR; + } + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate %s id %" PRId64 " in id array in file id %d", + ex_name_of_object(obj_type), id, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return EX_FATAL; + } + } + + const char *entryptr = NULL; + switch (obj_type) { + case EX_ASSEMBLY: entryptr = VAR_ENTITY_ASSEMBLY(id_ndx); break; + case EX_BLOB: entryptr = VAR_ENTITY_BLOB(id_ndx); break; + case EX_NODE_SET: entryptr = VAR_NODE_NS(id_ndx); break; + case EX_EDGE_SET: entryptr = VAR_EDGE_ES(id_ndx); break; + case EX_FACE_SET: entryptr = VAR_FACE_FS(id_ndx); break; + case EX_SIDE_SET: entryptr = VAR_ELEM_SS(id_ndx); break; + case EX_ELEM_SET: entryptr = VAR_ELEM_ELS(id_ndx); break; + case EX_EDGE_BLOCK: entryptr = VAR_EBCONN(id_ndx); break; + case EX_FACE_BLOCK: entryptr = VAR_FBCONN(id_ndx); break; + case EX_ELEM_BLOCK: entryptr = VAR_CONN(id_ndx); break; + default: + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: object type %d not supported in call to %s", obj_type, + __func__); + ex_err(__func__, errmsg, EX_BADPARAM); + return EX_FATAL; + } + + int varid = 0; + if ((status = nc_inq_varid(exoid, entryptr, &varid)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate entity list array for %s %" PRId64 " in file id %d", + ex_name_of_object(obj_type), id, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return EX_FATAL; + } + return varid; +} + /* * Code from: * https://stackoverflow.com/questions/11034002/how-to-get-absolute-path-of-file-or-directory-that-does-not-exist diff --git a/packages/seacas/libraries/exodus/test/CMakeLists.txt b/packages/seacas/libraries/exodus/test/CMakeLists.txt index 1e8eea43c6..fc3596d894 100644 --- a/packages/seacas/libraries/exodus/test/CMakeLists.txt +++ b/packages/seacas/libraries/exodus/test/CMakeLists.txt @@ -66,6 +66,7 @@ endif() IF ( NETCDF_NCDUMP_BINARY ) SET(NETCDF_NCDUMP ${NETCDF_NCDUMP_BINARY}) SET( cbind_OLDTESTS + test-field-utils testwt testwtd testwtd-to-f @@ -108,6 +109,8 @@ IF ( NETCDF_NCDUMP_BINARY ) test-add-assembly testwt-blob testrd-blob + testwt-field-metadata + testrd-field-metadata ) IF (SEACASExodus_ENABLE_THREADSAFE) @@ -155,6 +158,15 @@ IF ( NETCDF_NCDUMP_BINARY ) set_property(TARGET ${testName} PROPERTY C_STANDARD 99) ENDFOREACH ( testName ) + TRIBITS_ADD_TEST( + test-field-utils + NOEXEPREFIX + NOEXESUFFIX + NAME exodus-test-field-utils + COMM mpi serial + NUM_MPI_PROCS 1 + ) + IF (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") TRIBITS_ADD_TEST( testall diff --git a/packages/seacas/libraries/exodus/test/test-add-assembly.dmp b/packages/seacas/libraries/exodus/test/test-add-assembly.dmp index 1f261ef724..e8c5d69146 100644 --- a/packages/seacas/libraries/exodus/test/test-add-assembly.dmp +++ b/packages/seacas/libraries/exodus/test/test-add-assembly.dmp @@ -91,7 +91,6 @@ variables: // global attributes: :file_size = 1 ; :title = "This is a test" ; - :SOLID_MODEL = "STEP-X-43-1547836-Rev 0" ; data: time_whole = 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 ; diff --git a/packages/seacas/libraries/exodus/test/test-field-utils.c b/packages/seacas/libraries/exodus/test/test-field-utils.c new file mode 100644 index 0000000000..9c8ae5aa83 --- /dev/null +++ b/packages/seacas/libraries/exodus/test/test-field-utils.c @@ -0,0 +1,74 @@ +#include +#include +#undef NDEBUG +#include + +#define SIZE(X) sizeof(X) / sizeof(X[0]) + +int main(int argc, char **argv) +{ + ex_field_type types[] = {EX_FIELD_TYPE_USER_DEFINED, + EX_FIELD_TYPE_SEQUENCE, + EX_QUADRATURE, + EX_BASIS, + EX_SCALAR, + EX_VECTOR_1D, + EX_VECTOR_2D, + EX_VECTOR_3D, + EX_QUATERNION_2D, + EX_QUATERNION_3D, + EX_FULL_TENSOR_12, + EX_FULL_TENSOR_16, + EX_FULL_TENSOR_22, + EX_FULL_TENSOR_32, + EX_FULL_TENSOR_36, + EX_SYM_TENSOR_10, + EX_SYM_TENSOR_11, + EX_SYM_TENSOR_13, + EX_SYM_TENSOR_21, + EX_SYM_TENSOR_31, + EX_SYM_TENSOR_33, + EX_ASYM_TENSOR_01, + EX_ASYM_TENSOR_02, + EX_ASYM_TENSOR_03, + EX_MATRIX_2X2, + EX_MATRIX_3X3, + EX_FIELD_TYPE_INVALID}; + + int num_enum = SIZE(types); + for (int i = 0; i < num_enum; i++) { + const char *string_type = ex_field_type_enum_to_string(types[i]); + ex_field_type return_type = ex_string_to_field_type_enum(string_type); + assert(return_type == types[i]); + } + + for (int i = 0; i < num_enum; i++) { + struct ex_field field = (ex_field){.entity_type = EX_ELEM_BLOCK, + .entity_id = 100, + .name = "Testing", + .type = {types[i]}, + .nesting = 1, + .component_separator[0] = '_'}; + + int cardinality = ex_field_cardinality(types[i]); + // Make sure the numeric suffices are formatted correctly "00", "01", ... "10" -- all same + // width. + if (cardinality == -1 && (types[i] == EX_FIELD_TYPE_SEQUENCE || types[i] == EX_BASIS)) { + field.cardinality[0] = 10; + cardinality = 10; + } + if (cardinality > 0 && types[i] != EX_SCALAR) { + fprintf(stderr, "%s (%s) components: ", ex_field_type_enum_to_string(field.type[0]), + ex_field_type_name(field.type[0])); + for (int j = 1; j <= cardinality; j++) { + fprintf(stderr, "%s%c", ex_field_component_suffix(&field, 0, j), + j == cardinality ? ' ' : ','); + } + fprintf(stderr, "\n"); + } + else { + fprintf(stderr, "%s (%s)\n", ex_field_type_enum_to_string(field.type[0]), + ex_field_type_name(field.type[0])); + } + } +} diff --git a/packages/seacas/libraries/exodus/test/testall.in b/packages/seacas/libraries/exodus/test/testall.in index 45d0a2e86f..889cf15434 100755 --- a/packages/seacas/libraries/exodus/test/testall.in +++ b/packages/seacas/libraries/exodus/test/testall.in @@ -1,5 +1,5 @@ #! /usr/bin/env bash -# Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions +# Copyright(C) 1999-2021, 2023, 2024 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. # @@ -41,7 +41,7 @@ ${PREFIX} ${BINDIR}/testwt${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee testwt.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end testwt, status = $ret_status" >> test.output echo "testrd - single precision read test..." @@ -55,7 +55,7 @@ echo "begin testcp_ss" >> test.output ${PREFIX} ${BINDIR}/testcp${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 testcp.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testcp_ss.dmp | tee testcp_ss.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testcp_ss, status = $ret_status" >> test.output echo "testcp_sd - single-to-double precision copy test..." @@ -63,7 +63,7 @@ echo "begin testcp_sd" >> test.output ${PREFIX} ${BINDIR}/testcpd${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 testcpd.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testcp_sd.dmp | tee testcp_sd.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testcp_sd, status = $ret_status" >> test.output echo "testcp_nl - normal_model to large_model single precision copy test..." @@ -71,7 +71,7 @@ echo "begin testcp_nl" >> test.output ${PREFIX} ${BINDIR}/testcp_nl${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 testcp_nl.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testcp_nl.dmp | tee testcp_nl.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testcp_nl, status = $ret_status" >> test.output echo "testcp_transient - copy mesh and transient data..." @@ -79,7 +79,7 @@ echo "begin testcp_tran" >> test.output ${PREFIX} ${BINDIR}/testcp_tran${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 testcp.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testcp_tran.dmp | tee testcp_tran.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testcp_tran, status = $ret_status" >> test.output echo "testwt_clb - single precision write test using concatenated puts..." @@ -87,7 +87,7 @@ echo "begin testwt_clb" >> test.output ${PREFIX} ${BINDIR}/testwt_clb${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/test_clb.dmp | tee testwt_clb.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt_clb, status = $ret_status" >> test.output echo "testwtd - double precision write test..." @@ -95,7 +95,7 @@ echo "begin testwtd" >> test.output ${PREFIX} ${BINDIR}/testwtd${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testd.dmp | tee testwtd.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwtd, status = $ret_status" >> test.output echo "testrdd - double precision read test..." @@ -109,7 +109,7 @@ echo "begin testcp_dd" >> test.output ${PREFIX} ${BINDIR}/testcpd${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 testcpd.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testcp_dd.dmp | tee testcp_dd.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testcp_dd, status = $ret_status" >> test.output echo "testcp_ds - double-to-single precision copy test..." @@ -117,7 +117,7 @@ echo "begin testcp_ds" >> test.output ${PREFIX} ${BINDIR}/testcp${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 testcp.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testcp_ds.dmp | tee testcp_ds.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testcp_ds, status = $ret_status" >> test.output echo "testwtd-to-f - double precision compute, convert to single precision on disk..." @@ -125,7 +125,7 @@ echo "begin testwtd-to-f" >> test.output ${PREFIX} ${BINDIR}/testwtd-to-f${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee testwtd-to-f.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end testwtd-to-f, status = $ret_status" >> test.output echo "testwt1 - single precision write files with several side sets..." @@ -134,7 +134,7 @@ echo "begin testwt1" >> test.output ${PREFIX} ${BINDIR}/testwt1${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/test1.dmp | tee testwt1.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt1, status = $ret_status" >> test.output echo "testrd1 - single precision read test of a file with several side sets..." @@ -151,7 +151,7 @@ echo "begin testwt_ss" >> test.output ${PREFIX} ${BINDIR}/testwt_ss${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testwt_ss.dmp | tee testwt_ss.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt_ss, status = $ret_status" >> test.output echo "testrd_ss - read test of a file with several side sets..." @@ -166,9 +166,9 @@ echo "begin testwt2" >> test.output ${PREFIX} ${BINDIR}/testwt2${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/test2-1.dmp | tee testwt2-1.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) ${NCDUMP} -d5,5 test2.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/test2-2.dmp | tee testwt2-2.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt2, status = $ret_status" >> test.output echo "testrdwt - read from one and write to another (simultaneously open) file..." @@ -176,7 +176,7 @@ echo "begin testrdwt" >> test.output ${PREFIX} ${BINDIR}/testrdwt${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test2.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/test2.dmp | tee testrdwt.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testrdwt, status = $ret_status" >> test.output echo "testwt_nc - write x y z components of coordinates separately..." @@ -185,7 +185,7 @@ ${PREFIX} ${BINDIR}/testwt_nc${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee testwt_nc.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end testwt_nc, status = $ret_status" >> test.output echo "testrd_nc - read x y z components of coordinates separately..." @@ -199,7 +199,7 @@ echo "begin testwt-zeron" >> test.output ${PREFIX} ${BINDIR}/testwt-zeron${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testwt-zeron.dmp | tee testwt-zeron.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt-zeron, status = $ret_status" >> test.output echo "testrd - read test of file with zero nodes and elements..." @@ -213,7 +213,7 @@ echo "begin testwt-zeroe" >> test.output ${PREFIX} ${BINDIR}/testwt-zeroe${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testwt-zeroe.dmp | tee testwt-zeroe.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt-zeroe, status = $ret_status" >> test.output echo "testrd - read test of file with zero elements..." @@ -233,7 +233,7 @@ echo "begin testwt-nsided" >> test.output ${PREFIX} ${BINDIR}/testwt-nsided${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test-nsided.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testwt-nsided.dmp | tee testwt-nsided.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt-nsided, status = $ret_status" >> test.output echo "testrd-nsided - read file with nsided elements..." @@ -247,7 +247,7 @@ echo "begin testwt-nfaced" >> test.output ${PREFIX} ${BINDIR}/testwt-nfaced${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test-nfaced.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size| ${DIFF} - ${SRCDIR}/testwt-nfaced.dmp | tee testwt-nfaced.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) echo "end testwt-nfaced, status = $ret_status" >> test.output echo "testrd-nfaced - read file with nfaced elements..." @@ -262,7 +262,7 @@ echo "begin testwt-long-name" >> test.output ${PREFIX} ${BINDIR}/testwt-long-name${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/testwt-long-name.dmp | tee testwt-long-name.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end testwt-long-name, status = $ret_status" >> test.output echo "testrd - read long name file truncating to 32 characters on read..." @@ -295,7 +295,7 @@ ${PREFIX} ${BINDIR}/testwt-results${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 ${NCDUMP} -d5,5 test-results.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/testwt-results.dmp | tee testwt-results.re -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end testwt-results, status = $ret_status" >> test.output echo "testwt-assembly - write file containing assembly data" @@ -303,8 +303,8 @@ echo "begin testwt-assembly" >> test.output ${PREFIX} ${BINDIR}/testwt-assembly${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 -${NCDUMP} -d5,5 test-assembly.exo | grep -v version | grep -v int64_status| grep -v floating_point | grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/testwt-assembly.dmp | tee testwt-assembly.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) +${NCDUMP} -d5,5 test-assembly.exo | grep -v version | grep -v int64_status| grep -v floating_point | grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | grep -v ":SOLID_MODEL" | ${DIFF} - ${SRCDIR}/testwt-assembly.dmp | tee testwt-assembly.res +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[8]})) echo "end testwt-assembly, status = $ret_status" >> test.output echo "testrd-assembly - read file containing assembly data" @@ -318,8 +318,8 @@ echo "begin test-add-assembly" >> test.output ${PREFIX} ${BINDIR}/test-add-assembly${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 -${NCDUMP} -d5,5 test-assembly.exo | grep -v version | grep -v int64_status | grep -v floating_point | grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/test-add-assembly.dmp | tee test-add-assembly.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) +${NCDUMP} -d5,5 test-assembly.exo | grep -v version | grep -v int64_status | grep -v floating_point | grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | grep -v ":SOLID_MODEL" | ${DIFF} - ${SRCDIR}/test-add-assembly.dmp | tee test-add-assembly.res +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[8]})) echo "end test-add-assembly, status = $ret_status" >> test.output echo "testwt-blob - write file containing blob data" @@ -327,8 +327,8 @@ echo "begin testwt-blob" >> test.output ${PREFIX} ${BINDIR}/testwt-blob${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 -${NCDUMP} -d5,5 test-blob.exo | grep -v version | grep -v int64_status | grep -v floating_point | grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/testwt-blob.dmp | tee testwt-blob.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) +${NCDUMP} -d5,5 test-blob.exo | grep -v version | grep -v int64_status | grep -v floating_point | grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | grep -v ":SOLID_MODEL" | ${DIFF} - ${SRCDIR}/testwt-blob.dmp | tee testwt-blob.res +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[8]})) echo "end testwt-blob, status = $ret_status" >> test.output echo "testrd-blob - read file containing blob data" @@ -343,7 +343,7 @@ ${PREFIX} ${BINDIR}/testwt-oned${SUFFIX} >> test.output ret_status=$((ret_status+$?)) # Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/testwt-oned.dmp | tee testwt-oned.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end testwt-oned, status = $ret_status" >> test.output echo "testrd - read test of 1D file..." @@ -352,6 +352,29 @@ ${PREFIX} ${BINDIR}/testrd${SUFFIX} | grep -v version | ${DIFF} - ${SRCDIR}/test ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[2]})) echo "end testrd 1D, status = $ret_status" >> test.output +echo "testwt-field-metadata - write mesh with enhanced field metadata..." +echo "begin testwt-field-metadata" >> test.output +${PREFIX} ${BINDIR}/testwt-field-metadata${SUFFIX} >> test.output +ret_status=$((ret_status+$?)) +# Filter out the "maximum_name_length" attribute. Moves around in ncdump output for nc4 vs nc3 +${NCDUMP} -d5,5 test-field-metadata.exo | grep @ |sort | ${DIFF} - ${SRCDIR}/testwt-field-metadata.dmp | tee testwt-field-metadata.res +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[3]})) +echo "end testwt-field-metadata, status = $ret_status" >> test.output + +# NOTE: netcdf-4 can put attributes in different order, so in that +# case, we only test the return status of the application, not diff +# the output. +echo "testrd-field-metadata - read test of enhanced field metadata file..." +echo "begin testrd-field-metadata" >> test.output +if [ "$1" == "netcdf4" ]; then + ${PREFIX} ${BINDIR}/testrd-field-metadata${SUFFIX} | tee testrd-field-metadata.res + ret_status=$((ret_status+$?)) +else + ${PREFIX} ${BINDIR}/testrd-field-metadata${SUFFIX} | ${DIFF} - ${SRCDIR}/testrd-field-metadata.dmp | tee testrd-field-metadata.res + ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[1]})) +fi +echo "end testrd-field-metadata, status = $ret_status" >> test.output + if [ "$THREAD_SAFE" == "YES" ]; then echo "test_ts_nvar - each thread writes data for a single nodal variable..." @@ -359,13 +382,13 @@ echo "begin test_ts_nvar" >> test.output ${PREFIX} ${BINDIR}/test_ts_nvar${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/test_ts_nvar.dmp | tee testwt-long-name.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end test_ts_nvar, status = $ret_status" >> test.output echo "test_ts_nvar_rd - each thread reads data for a single nodal variable..." echo "begin test_ts_nvar_rd" >> test.output ${PREFIX} ${BINDIR}/test_ts_nvar_rd${SUFFIX} | ${DIFF} - ${SRCDIR}/test_ts_nvar_rd.dmp | tee test_ts_nvar_rd.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[2]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[1]})) echo "end test_ts_nvar_rd, status = $ret_status" >> test.output @@ -374,7 +397,7 @@ echo "begin test_ts_partial_nvar" >> test.output ${PREFIX} ${BINDIR}/test_ts_partial_nvar${SUFFIX} >> test.output ret_status=$((ret_status+$?)) ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v "maximum_name_length" | ${DIFF} - ${SRCDIR}/test_ts_partial_nvar.dmp | tee testwt-long-name.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end test_ts_partial_nvar, status = $ret_status" >> test.output echo "test_ts_partial_nvar_rd - each thread reads data for a single nodal variable..." @@ -391,28 +414,28 @@ ${PREFIX} ${BINDIR}/test_ts_files${SUFFIX} >> test.output ret_status=$((ret_status+$?)) mv test0.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files0.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test1.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files1.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test2.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files2.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test3.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files3.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test4.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files4.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test5.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files5.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test6.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files6.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) mv test7.exo test.exo ${NCDUMP} -d5,5 test.exo | grep -v version | grep -v int64_status| grep -v _FillValue |grep -v word_size|grep -v maximum_name_length | ${DIFF} - ${SRCDIR}/test.dmp | tee test_ts_files7.res -ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[5]})) +ret_status=$((ret_status+${PIPESTATUS[0]}+${PIPESTATUS[6]})) echo "end test_ts_files, status = $ret_status" >> test.output echo "test_ts_errval - multiple threads calling ex_err and ex_get_err..." diff --git a/packages/seacas/libraries/exodus/test/testrd-field-metadata.c b/packages/seacas/libraries/exodus/test/testrd-field-metadata.c new file mode 100644 index 0000000000..21011c26a3 --- /dev/null +++ b/packages/seacas/libraries/exodus/test/testrd-field-metadata.c @@ -0,0 +1,318 @@ +/* + * Copyright(C) 1999-2024 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 + */ +#undef NDEBUG +#include "exodusII.h" +#include +#include +#include +#include + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +char *my_strdup(const char *s) +{ + size_t slen = strlen(s); + char *result = malloc(slen + 1); + if (result == NULL) { + return NULL; + } + + memcpy(result, s, slen + 1); + return result; +} + +char *my_strsep(char **stringp, const char *delim) +{ + assert(delim != NULL); + char *rv = *stringp; + if (rv) { + assert(stringp != NULL); + assert(*stringp != NULL); + *stringp += strcspn(*stringp, delim); + if (**stringp) + *(*stringp)++ = '\0'; + else + *stringp = NULL; + } + return rv; +} + +#define EXCHECK(funcall) \ + do { \ + int error = (funcall); \ + printf("after %s, error = %d\n", TOSTRING(funcall), error); \ + if (error != EX_NOERR) { \ + fprintf(stderr, "Error calling %s\n", TOSTRING(funcall)); \ + ex_close(exoid); \ + exit(-1); \ + } \ + } while (0) + +static char *get_type_name(char *type_name, size_t which) +{ + if (type_name != NULL && type_name[0] != '\0') { + char *string = my_strdup(type_name); + char *tofree = string; + char *token = my_strsep(&string, ","); + for (int i = 0; i < which; i++) { + token = my_strsep(&string, ","); + } + if (token != NULL) { + static char tmp_type_name[256 + 1]; + ex_copy_string(tmp_type_name, token, 256); + free(tofree); + return tmp_type_name; + } + free(tofree); + } + return NULL; +} + +static void get_field_cardinality(ex_field *field, ex_basis *basis, int bas_cnt, + ex_quadrature *quad, int quad_cnt) +{ + for (int j = 0; j < field->nesting; j++) { + if (field->cardinality[j] == 0) { + if (field->type[j] == EX_BASIS) { + int found = 0; + char *basis_type = get_type_name(field->type_name, j); + if (basis != NULL) { + for (int k = 0; k < bas_cnt; k++) { + if (strcmp(basis[k].name, basis_type) == 0) { + field->cardinality[j] = basis[k].cardinality; + found = 1; + break; + } + } + } + if (found == 0) { + fprintf(stderr, "ERROR: Could not find basis named `%s` for field `%s`\n", basis_type, + field->name); + } + } + else if (field->type[j] == EX_QUADRATURE) { + int found = 0; + char *quad_type = get_type_name(field->type_name, j); + if (quad != NULL) { + for (int k = 0; k < quad_cnt; k++) { + if (strcmp(quad[k].name, quad_type) == 0) { + field->cardinality[j] = quad[k].cardinality; + found = 1; + break; + } + } + } + if (found == 0) { + fprintf(stderr, "ERROR: Could not find quadrature named `%s` for field `%s`\n", quad_type, + field->name); + } + } + else { + field->cardinality[j] = ex_field_cardinality(field->type[j]); + } + } + } +} + +static void print_basis_metadata(ex_basis *basis, size_t num_basis) +{ + for (size_t j = 0; j < num_basis; j++) { + printf("\nBasis Metadata: Name: `%s`, Cardinality: %d\n", basis[j].name, basis[j].cardinality); + printf("ordinal,\t subc: _dim\t_ordinal\t_dof_ordinal\t_num_dof\t xi eta zeta\n"); + for (int i = 0; i < basis[j].cardinality; i++) { + double xi = basis[j].xi != NULL ? basis[j].xi[i] : 0.0; + double eta = basis[j].eta != NULL ? basis[j].eta[i] : 0.0; + double zeta = basis[j].zeta != NULL ? basis[j].zeta[i] : 0.0; + printf("%8d\t%8d\t%8d\t%8d\t%8d\t%6.3f\t%6.3f\t%6.3f\n", i, basis[j].subc_dim[i], + basis[j].subc_ordinal[i], basis[j].subc_dof_ordinal[i], basis[j].subc_num_dof[i], xi, + eta, zeta); + } + } +} + +static void print_quad_metadata(ex_quadrature *quad, size_t num_quad) +{ + for (size_t j = 0; j < num_quad; j++) { + printf("\nQuadrature Metadata: Name: `%s`, Cardinality: %d\n", quad[j].name, + quad[j].cardinality); + printf("ordinal,\t xi eta zeta weight\n"); + for (int i = 0; i < quad[j].cardinality; i++) { + double xi = quad[j].xi != NULL ? quad[j].xi[i] : 0.0; + double eta = quad[j].eta != NULL ? quad[j].eta[i] : 0.0; + double zeta = quad[j].zeta != NULL ? quad[j].zeta[i] : 0.0; + double wgt = quad[j].weight != NULL ? quad[j].weight[i] : 1.0; + printf("%8d\t%6.3f\t%6.3f\t%6.3f\t%6.3f\n", i, xi, eta, zeta, wgt); + } + } +} + +static void print_field_metadata(ex_field *field) +{ + printf("\n"); + printf("Field Metadata: Name: `%s`, Nesting: %d\n", field->name, field->nesting); + for (int j = 0; j < field->nesting; j++) { + char sep = field->component_separator[j] == 0 ? ' ' : field->component_separator[j]; + if (field->type[j] == EX_BASIS) { + char *basis_type = get_type_name(field->type_name, j); + printf("\tNesting level: %d, Type: %s (%s), Cardinality: %d, Separator: \"%c\"\n", j, + ex_field_type_enum_to_string(field->type[j]), basis_type, field->cardinality[j], sep); + } + else if (field->type[j] == EX_QUADRATURE) { + char *quad_type = get_type_name(field->type_name, j); + printf("\tNesting level: %d, Type: %s (%s), Cardinality: %d, Separator: \"%c\"\n", j, + ex_field_type_enum_to_string(field->type[j]), quad_type, field->cardinality[j], sep); + } + else { + printf("\tNesting level: %d, Type: %s, Cardinality: %d, Separator: \"%c\"\n", j, + ex_field_type_enum_to_string(field->type[j]), field->cardinality[j], sep); + } + if (field->type[0] == EX_FIELD_TYPE_USER_DEFINED) { + printf("\tUser-defined suffices: %s\n", field->suffices); + } + } +} + +static void print_full_field_names(ex_field *field) +{ + int component[EX_MAX_FIELD_NESTING]; + if (field->nesting == 1) { + for (int jj = 1; jj <= field->cardinality[0]; jj++) { + component[0] = jj; + const char *name = ex_component_field_name(field, component); + printf("\t\tComponent %d, Full name = %s\n", jj, name); + } + } + else if (field->nesting == 2) { + for (int kk = 1; kk <= field->cardinality[1]; kk++) { + for (int jj = 1; jj <= field->cardinality[0]; jj++) { + component[0] = jj; + component[1] = kk; + const char *name = ex_component_field_name(field, component); + printf("\t\tComponent %d %d, Full name = %s\n", jj, kk, name); + } + } + } +#if EX_MAX_FIELD_NESTING > 2 + else if (field->nesting == 3) { + for (int ii = 1; ii <= field->cardinality[2]; ii++) { + for (int kk = 1; kk <= field->cardinality[1]; kk++) { + for (int jj = 1; jj <= field->cardinality[0]; jj++) { + component[0] = jj; + component[1] = kk; + component[2] = ii; + const char *name = ex_component_field_name(field, component); + printf("\t\tComponent %d %d %d, Full name = %s\n", jj, kk, ii, name); + } + } + } + } +#endif +#if EX_MAX_FIELD_NESTING > 3 + else if (field->nesting == 4) { + for (int mm = 1; mm <= field->cardinality[3]; mm++) { + for (int ii = 1; ii <= field->cardinality[2]; ii++) { + for (int kk = 1; kk <= field->cardinality[1]; kk++) { + for (int jj = 1; jj <= field->cardinality[0]; jj++) { + component[0] = jj; + component[1] = kk; + component[2] = ii; + component[3] = mm; + const char *name = ex_component_field_name(field, component); + printf("\t\tComponent %d %d %d %d, Full name = %s\n", jj, kk, ii, mm, name); + } + } + } + } + } +#endif +} + +int main(int argc, char **argv) +{ + ex_opts(EX_VERBOSE | EX_ABORT); + + /* open EXODUS II files */ + float version; + int CPU_word_size = 0; /* sizeof(float) */ + int IO_word_size = 0; /* use what is stored in file */ + + int exoid = ex_open("test-field-metadata.exo", EX_READ, &CPU_word_size, &IO_word_size, &version); + + printf("\nafter ex_open\n"); + if (exoid < 0) { + exit(1); + } + + // ------------------------------------------------------------------------ + int quad_cnt = 0; + ex_quadrature *quad = NULL; + EXCHECK(ex_get_quadrature(exoid, &quad, &quad_cnt)); + print_quad_metadata(quad, quad_cnt); + + // ------------------------------------------------------------------------ + int bas_cnt = 0; + ex_basis *basis = NULL; + EXCHECK(ex_get_basis(exoid, &basis, &bas_cnt)); + print_basis_metadata(basis, bas_cnt); + + /* Check for nodal fields... */ + { + int fld_cnt = ex_get_field_metadata_count(exoid, EX_NODAL, 0); + assert(fld_cnt == 2); + ex_field fields[2] = {{.entity_type = EX_NODAL}, {.entity_type = EX_NODAL}}; + EXCHECK(ex_get_field_metadata(exoid, fields)); + + for (int i = 0; i < fld_cnt; i++) { + get_field_cardinality(&fields[i], NULL, 0, NULL, 0); + print_field_metadata(&fields[i]); + print_full_field_names(&fields[i]); + } + } + + { + int fld_cnt = ex_get_field_metadata_count(exoid, EX_ELEM_BLOCK, 10); + assert(fld_cnt == 2); + ex_field fields[2] = {{.entity_id = 10, .entity_type = EX_ELEM_BLOCK}, + {.entity_id = 10, .entity_type = EX_ELEM_BLOCK}}; + EXCHECK(ex_get_field_metadata(exoid, fields)); + + for (int i = 0; i < fld_cnt; i++) { + get_field_cardinality(&fields[i], NULL, 0, NULL, 0); + print_field_metadata(&fields[i]); + print_full_field_names(&fields[i]); + } + } + { + int fld_cnt = ex_get_field_metadata_count(exoid, EX_ELEM_BLOCK, 11); + assert(fld_cnt == 3); + ex_field fields[3] = {{.entity_id = 11, .entity_type = EX_ELEM_BLOCK}, + {.entity_id = 11, .entity_type = EX_ELEM_BLOCK}, + {.entity_id = 11, .entity_type = EX_ELEM_BLOCK}}; + EXCHECK(ex_get_field_metadata(exoid, fields)); + + for (int i = 0; i < fld_cnt; i++) { + get_field_cardinality(&fields[i], basis, bas_cnt, quad, quad_cnt); + print_field_metadata(&fields[i]); + print_full_field_names(&fields[i]); + } + } + + // Now, deallocate any memory allocated on the `basis` struct. + EXCHECK(ex_initialize_basis_struct(basis, bas_cnt, -1)); + EXCHECK(ex_initialize_quadrature_struct(quad, quad_cnt, -1)); + free(basis); + free(quad); + + int fld_cnt = ex_get_field_metadata_count(exoid, EX_ELEM_BLOCK, 12); + assert(fld_cnt == 0); + + int error = ex_close(exoid); + printf("\nafter ex_close, error = %3d\n", error); + return 0; +} diff --git a/packages/seacas/libraries/exodus/test/testrd-field-metadata.dmp b/packages/seacas/libraries/exodus/test/testrd-field-metadata.dmp new file mode 100644 index 0000000000..4e54650f27 --- /dev/null +++ b/packages/seacas/libraries/exodus/test/testrd-field-metadata.dmp @@ -0,0 +1,125 @@ + +after ex_open +after ex_get_quadrature(exoid, &quad, &quad_cnt), error = 0 + +Quadrature Metadata: Name: `2x2x2`, Cardinality: 8 +ordinal, xi eta zeta weight + 0 -0.577 -0.577 -0.577 1.000 + 1 0.577 -0.577 -0.577 1.000 + 2 -0.577 0.577 -0.577 1.000 + 3 0.577 0.577 -0.577 1.000 + 4 -0.577 -0.577 0.577 1.000 + 5 0.577 -0.577 0.577 1.000 + 6 -0.577 0.577 0.577 1.000 + 7 0.577 0.577 0.577 1.000 + +Quadrature Metadata: Name: `1x2x1`, Cardinality: 2 +ordinal, xi eta zeta weight + 0 -0.500 0.500 -0.500 1.000 + 1 0.500 -0.500 0.500 1.000 +after ex_get_basis(exoid, &basis, &bas_cnt), error = 0 + +Basis Metadata: Name: `HGRAD_QUAD_C2_FEM`, Cardinality: 9 +ordinal, subc: _dim _ordinal _dof_ordinal _num_dof xi eta zeta + 0 0 0 0 1 -1.000 -1.000 0.000 + 1 0 1 0 1 1.000 -1.000 0.000 + 2 0 2 0 1 1.000 1.000 0.000 + 3 0 3 0 1 -1.000 1.000 0.000 + 4 1 0 0 1 0.000 -1.000 0.000 + 5 1 1 0 1 1.000 0.000 0.000 + 6 1 2 0 1 0.000 1.000 0.000 + 7 1 3 0 1 -1.000 0.000 0.000 + 8 2 0 0 1 0.000 0.000 0.000 + +Basis Metadata: Name: `TESTING_SECOND_BASIS`, Cardinality: 3 +ordinal, subc: _dim _ordinal _dof_ordinal _num_dof xi eta zeta + 0 0 0 0 1 -1.000 -1.000 1.000 + 1 0 1 0 1 1.000 -1.000 -1.000 + 2 0 2 0 1 1.000 1.000 1.000 +after ex_get_field_metadata(exoid, fields), error = 0 + +Field Metadata: Name: `Disp`, Nesting: 1 + Nesting level: 0, Type: EX_VECTOR_3D, Cardinality: 3, Separator: " " + Component 1, Full name = DispX + Component 2, Full name = DispY + Component 3, Full name = DispZ + +Field Metadata: Name: `Velocity`, Nesting: 1 + Nesting level: 0, Type: EX_VECTOR_3D, Cardinality: 3, Separator: "%" + Component 1, Full name = Velocity%X + Component 2, Full name = Velocity%Y + Component 3, Full name = Velocity%Z +after ex_get_field_metadata(exoid, fields), error = 0 + +Field Metadata: Name: `Disp`, Nesting: 1 + Nesting level: 0, Type: EX_VECTOR_3D, Cardinality: 3, Separator: " " + Component 1, Full name = DispX + Component 2, Full name = DispY + Component 3, Full name = DispZ + +Field Metadata: Name: `Velocity`, Nesting: 1 + Nesting level: 0, Type: EX_VECTOR_3D, Cardinality: 3, Separator: "%" + Component 1, Full name = Velocity%X + Component 2, Full name = Velocity%Y + Component 3, Full name = Velocity%Z +after ex_get_field_metadata(exoid, fields), error = 0 + +Field Metadata: Name: `Gradient`, Nesting: 2 + Nesting level: 0, Type: EX_VECTOR_3D, Cardinality: 3, Separator: "-" + Nesting level: 1, Type: EX_BASIS (HGRAD_QUAD_C2_FEM), Cardinality: 9, Separator: "$" + Component 1 1, Full name = Gradient-X$0 + Component 2 1, Full name = Gradient-Y$0 + Component 3 1, Full name = Gradient-Z$0 + Component 1 2, Full name = Gradient-X$1 + Component 2 2, Full name = Gradient-Y$1 + Component 3 2, Full name = Gradient-Z$1 + Component 1 3, Full name = Gradient-X$2 + Component 2 3, Full name = Gradient-Y$2 + Component 3 3, Full name = Gradient-Z$2 + Component 1 4, Full name = Gradient-X$3 + Component 2 4, Full name = Gradient-Y$3 + Component 3 4, Full name = Gradient-Z$3 + Component 1 5, Full name = Gradient-X$4 + Component 2 5, Full name = Gradient-Y$4 + Component 3 5, Full name = Gradient-Z$4 + Component 1 6, Full name = Gradient-X$5 + Component 2 6, Full name = Gradient-Y$5 + Component 3 6, Full name = Gradient-Z$5 + Component 1 7, Full name = Gradient-X$6 + Component 2 7, Full name = Gradient-Y$6 + Component 3 7, Full name = Gradient-Z$6 + Component 1 8, Full name = Gradient-X$7 + Component 2 8, Full name = Gradient-Y$7 + Component 3 8, Full name = Gradient-Z$7 + Component 1 9, Full name = Gradient-X$8 + Component 2 9, Full name = Gradient-Y$8 + Component 3 9, Full name = Gradient-Z$8 + +Field Metadata: Name: `Curl`, Nesting: 1 + Nesting level: 0, Type: EX_QUADRATURE (2x2x2), Cardinality: 8, Separator: "@" + Component 1, Full name = Curl@0 + Component 2, Full name = Curl@1 + Component 3, Full name = Curl@2 + Component 4, Full name = Curl@3 + Component 5, Full name = Curl@4 + Component 6, Full name = Curl@5 + Component 7, Full name = Curl@6 + Component 8, Full name = Curl@7 + +Field Metadata: Name: `Species`, Nesting: 2 + Nesting level: 0, Type: EX_FIELD_TYPE_USER_DEFINED, Cardinality: 4, Separator: "_" + User-defined suffices: h2o,gas,ch4,methane + Nesting level: 1, Type: EX_QUADRATURE (1x2x1), Cardinality: 2, Separator: "-" + User-defined suffices: h2o,gas,ch4,methane + Component 1 1, Full name = Species_h2o-0 + Component 2 1, Full name = Species_gas-0 + Component 3 1, Full name = Species_ch4-0 + Component 4 1, Full name = Species_methane-0 + Component 1 2, Full name = Species_h2o-1 + Component 2 2, Full name = Species_gas-1 + Component 3 2, Full name = Species_ch4-1 + Component 4 2, Full name = Species_methane-1 +after ex_initialize_basis_struct(basis, bas_cnt, -1), error = 0 +after ex_initialize_quadrature_struct(quad, quad_cnt, -1), error = 0 + +after ex_close, error = 0 diff --git a/packages/seacas/libraries/exodus/test/testwt-assembly.dmp b/packages/seacas/libraries/exodus/test/testwt-assembly.dmp index 9f54305ddc..57ce632ef7 100644 --- a/packages/seacas/libraries/exodus/test/testwt-assembly.dmp +++ b/packages/seacas/libraries/exodus/test/testwt-assembly.dmp @@ -85,7 +85,6 @@ variables: // global attributes: :file_size = 1 ; :title = "This is a test" ; - :SOLID_MODEL = "STEP-X-43-1547836-Rev 0" ; data: time_whole = 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 ; diff --git a/packages/seacas/libraries/exodus/test/testwt-blob.c b/packages/seacas/libraries/exodus/test/testwt-blob.c index 1bbb9f1010..d9152fdeab 100644 --- a/packages/seacas/libraries/exodus/test/testwt-blob.c +++ b/packages/seacas/libraries/exodus/test/testwt-blob.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2021 National Technology & Engineering Solutions + * Copyright(C) 1999-2021, 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. * diff --git a/packages/seacas/libraries/exodus/test/testwt-blob.dmp b/packages/seacas/libraries/exodus/test/testwt-blob.dmp index 90b214dd06..6d32177ea0 100644 --- a/packages/seacas/libraries/exodus/test/testwt-blob.dmp +++ b/packages/seacas/libraries/exodus/test/testwt-blob.dmp @@ -44,7 +44,6 @@ variables: // global attributes: :file_size = 1 ; :title = "This is a test" ; - :SOLID_MODEL = "STEP-X-43-1547836-Rev 0" ; data: time_whole = 0.01, 0.02, 0.03, 0.04 ; diff --git a/packages/seacas/libraries/exodus/test/testwt-field-metadata.c b/packages/seacas/libraries/exodus/test/testwt-field-metadata.c new file mode 100644 index 0000000000..642aa5ba5f --- /dev/null +++ b/packages/seacas/libraries/exodus/test/testwt-field-metadata.c @@ -0,0 +1,272 @@ +/* + * Copyright(C) 2022, 2023, 2024 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 + */ + +#undef NDEBUG +#include +#include +#include +#include +#include + +#include "exodusII.h" + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#define EXCHECK(funcall) \ + do { \ + int error = (funcall); \ + printf("after %s, error = %d\n", TOSTRING(funcall), error); \ + if (error != EX_NOERR) { \ + fprintf(stderr, "Error calling %s\n", TOSTRING(funcall)); \ + ex_close(exoid); \ + exit(-1); \ + } \ + } while (0) + +int main(int argc, char **argv) +{ + ex_opts(EX_VERBOSE); + + /* Specify compute and i/o word size */ + int CPU_word_size = 8; + int IO_word_size = 8; + + /* create EXODUS II file */ + int exoid = ex_create("test-field-metadata.exo", /* filename path */ + EX_CLOBBER, /* create mode */ + &CPU_word_size, /* CPU double word size in bytes */ + &IO_word_size); /* I/O double word size in bytes */ + printf("after ex_create for test.exo, exoid = %d\n", exoid); + printf(" cpu word size: %d io word size: %d\n", CPU_word_size, IO_word_size); + + int num_elem_blk = 3; + { + ex_init_params par = {.num_dim = 3, + .num_nodes = 1, + .num_elem = 3, + .num_elem_blk = num_elem_blk, + .num_node_sets = 0, + .num_side_sets = 0, + .num_assembly = 0}; + + char *title = "This is a test"; + ex_copy_string(par.title, title, MAX_LINE_LENGTH + 1); + EXCHECK(ex_put_init_ext(exoid, &par)); + } + + double coord[] = {0.0}; + EXCHECK(ex_put_coord(exoid, coord, coord, coord)); + + /* ======================================================================== */ + /* write element block parameters */ + struct ex_block blocks[num_elem_blk]; + for (int i = 0; i < num_elem_blk; i++) { + blocks[i] = (ex_block){.type = EX_ELEM_BLOCK, .num_entry = 1, .id = i + 10}; + ex_copy_string(blocks[i].topology, "sphere", MAX_STR_LENGTH + 1); + blocks[i].num_nodes_per_entry = 1; + } + + EXCHECK(ex_put_block_params(exoid, num_elem_blk, blocks)); + + int connect[] = {1}; + for (int i = 0; i < num_elem_blk; i++) { + EXCHECK(ex_put_conn(exoid, EX_ELEM_BLOCK, blocks[i].id, connect, NULL, NULL)); + } + + /* Write element block names */ + for (int i = 0; i < num_elem_blk; i++) { + char block_names[32]; + sprintf(block_names, "block_%c", i + 'A'); + EXCHECK(ex_put_name(exoid, EX_ELEM_BLOCK, blocks[i].id, block_names)); + } + + { + int units[] = {1, 0, 0, -1}; + + EXCHECK(ex_put_integer_attribute(exoid, EX_ELEM_BLOCK, 11, "Units", 4, units)); + EXCHECK(ex_put_text_attribute(exoid, EX_GLOBAL, 0, "SOLID_MODEL", "STEP-X-43-1547836-Rev 0")); + } + + /* ======================================================================== */ + /* Transient Variables */ + char *var_names[] = { + "DispX", "DispY", "DispZ", "Velocity%X", "Velocity%Y", + "Velocity%Z", "Gradient-X$0", "Gradient-Y$0", "Gradient-Z$0", "Gradient-X$1", + "Gradient-Y$1", "Gradient-Z$1", "Gradient-X$2", "Gradient-Y$2", "Gradient-Z$2", + "Gradient-X$3", "Gradient-Y$3", "Gradient-Z$3", "Gradient-X$4", "Gradient-Y$4", + "Gradient-Z$4", "Gradient-X$5", "Gradient-Y$5", "Gradient-Z$5", "Gradient-X$6", + "Gradient-Y$6", "Gradient-Z$6", "Gradient-X$7", "Gradient-Y$7", "Gradient-Z$7", + "Gradient-X$8", "Gradient-Y$8", "Gradient-Z$8", "Curl@1", "Curl@2", + "Curl@3", "Curl@4", "Curl@5", "Curl@6", "Curl@7", + "Curl@8", "Species_h2o-0", "Species_gas-0", "Species_ch4-0", "Species_methane-0", + "Species_h2o-1", "Species_gas-1", "Species_ch4-1", "Species_methane-1"}; + int num_block_vars = sizeof(var_names) / sizeof(var_names[0]); + int num_node_vars = 6; + + EXCHECK(ex_put_variable_param(exoid, EX_ELEM_BLOCK, num_block_vars)); + EXCHECK(ex_put_variable_names(exoid, EX_ELEM_BLOCK, num_block_vars, var_names)); + EXCHECK(ex_put_variable_param(exoid, EX_NODAL, num_node_vars)); + EXCHECK(ex_put_variable_names(exoid, EX_NODAL, num_node_vars, var_names)); + + int vname = 0; + { + struct ex_field field = (ex_field){.entity_type = EX_ELEM_BLOCK, + .entity_id = blocks[0].id, + .name = "Disp", + .type = {EX_VECTOR_3D}, + .nesting = 1, + .component_separator[0] = 0}; + EXCHECK(ex_put_field_metadata(exoid, field)); + + /* Put same field on the nodes... */ + field.entity_type = EX_NODAL; + EXCHECK(ex_put_field_metadata(exoid, field)); + + int cardinality = + field.cardinality[0] != 0 ? field.cardinality[0] : ex_field_cardinality(field.type[0]); + for (int i = 0; i < cardinality; i++) { + const char *name = ex_component_field_name(&field, (int[]){i + 1}); + assert(strcmp(var_names[vname++], name) == 0); + } + } + + { + struct ex_field field = (ex_field){.entity_type = EX_ELEM_BLOCK, + .entity_id = blocks[0].id, + .name = "Velocity", + .type = {EX_VECTOR_3D}, + .nesting = 1, + .component_separator[0] = '%'}; + EXCHECK(ex_put_field_metadata(exoid, field)); + + /* Put same field on the nodes... */ + field.entity_type = EX_NODAL; + EXCHECK(ex_put_field_metadata(exoid, field)); + + int cardinality = + field.cardinality[0] != 0 ? field.cardinality[0] : ex_field_cardinality(field.type[0]); + for (int i = 0; i < cardinality; i++) { + const char *name = ex_component_field_name(&field, (int[]){i + 1}); + assert(strcmp(var_names[vname++], name) == 0); + } + } + + { + double Q = 1.0 / sqrt(3.0); + double xi[] = {-Q, Q, -Q, Q, -Q, Q, -Q, Q}; + double eta[] = {-Q, -Q, Q, Q, -Q, -Q, Q, Q}; + double zeta[] = {-Q, -Q, -Q, -Q, Q, Q, Q, Q}; + double weight[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + + struct ex_quadrature quad = (ex_quadrature){ + .name = "2x2x2", .cardinality = 8, .xi = xi, .eta = eta, .zeta = zeta, .weight = weight}; + EXCHECK(ex_put_quadrature(exoid, quad)); + } + + { + double xi[] = {-0.5, 0.5}; + double eta[] = {0.5, -0.5}; + double zeta[] = {-0.5, 0.5}; + double weight[] = {1.0, 1.0}; + + struct ex_quadrature quad = (ex_quadrature){ + .name = "1x2x1", .cardinality = 2, .xi = xi, .eta = eta, .zeta = zeta, .weight = weight}; + EXCHECK(ex_put_quadrature(exoid, quad)); + } + + { + int subc_dim[] = {0, 0, 0, 0, 1, 1, 1, 1, 2}; + int subc_ordinal[] = {0, 1, 2, 3, 0, 1, 2, 3, 0}; + int subc_dof_ordinal[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int subc_num_dof[] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; + double xi[] = {-1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, -1.0, 0.0}; + double eta[] = {-1.0, -1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 0.0}; + double zeta[] = {1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0}; + + struct ex_basis basis = (ex_basis){.name = "HGRAD_QUAD_C2_FEM", + .cardinality = 9, + .subc_dim = subc_dim, + .subc_ordinal = subc_ordinal, + .subc_dof_ordinal = subc_dof_ordinal, + .subc_num_dof = subc_num_dof, + .xi = xi, + .eta = eta, + .zeta = NULL}; + EXCHECK(ex_put_basis(exoid, basis)); + + struct ex_basis basis1 = (ex_basis){.name = "TESTING_SECOND_BASIS", + .cardinality = 3, + .subc_dim = subc_dim, + .subc_ordinal = subc_ordinal, + .subc_dof_ordinal = subc_dof_ordinal, + .subc_num_dof = subc_num_dof, + .xi = xi, + .eta = eta, + .zeta = zeta}; + + EXCHECK(ex_put_basis(exoid, basis1)); + + struct ex_field field = (ex_field){.entity_type = EX_ELEM_BLOCK, + .entity_id = blocks[1].id, + .name = "Gradient", + .type_name = {",HGRAD_QUAD_C2_FEM"}, + .type = {EX_VECTOR_3D, EX_BASIS}, + .nesting = 2, + .component_separator = {'-', '$'}}; + EXCHECK(ex_put_field_metadata(exoid, field)); + + struct ex_field field2 = (ex_field){.entity_type = EX_ELEM_BLOCK, + .entity_id = blocks[1].id, + .name = "Curl", + .type_name = {"2x2x2"}, + .type = {EX_QUADRATURE}, + .nesting = 1, + .component_separator = {'@'}}; + EXCHECK(ex_put_field_metadata(exoid, field2)); + } + + { + struct ex_field field = (ex_field){.entity_type = EX_ELEM_BLOCK, + .entity_id = blocks[1].id, + .name = "Species", + .type = {EX_FIELD_TYPE_USER_DEFINED, EX_QUADRATURE}, + .type_name = {",1x2x1"}, + .nesting = 2, + .cardinality = {4}, + .component_separator = {'_', '-'}}; + EXCHECK(ex_put_field_metadata(exoid, field)); + EXCHECK(ex_put_field_suffices(exoid, field, "h2o,gas,ch4,methane")); + } + + { /* Output time steps ... */ + for (int ts = 0; ts < 1; ts++) { + double time_val = (double)(ts + 1) / 100.0; + + EXCHECK(ex_put_time(exoid, ts + 1, &time_val)); + + /* write variables */ + for (int k = 0; k < num_elem_blk; k++) { + double *var_vals = (double *)calloc(blocks[k].num_entry, CPU_word_size); + for (int var_idx = 0; var_idx < num_block_vars; var_idx++) { + for (int elem = 0; elem < blocks[k].num_entry; elem++) { + var_vals[elem] = (double)(var_idx + 2) * time_val + elem; + } + EXCHECK(ex_put_var(exoid, ts + 1, EX_ELEM_BLOCK, var_idx + 1, blocks[k].id, + blocks[k].num_entry, var_vals)); + } + free(var_vals); + } + } + } + + /* close the EXODUS files + */ + EXCHECK(ex_close(exoid)); + return 0; +} diff --git a/packages/seacas/libraries/exodus/test/testwt-field-metadata.dmp b/packages/seacas/libraries/exodus/test/testwt-field-metadata.dmp new file mode 100644 index 0000000000..9b9e075aa8 --- /dev/null +++ b/packages/seacas/libraries/exodus/test/testwt-field-metadata.dmp @@ -0,0 +1,56 @@ + :Basis@HGRAD_QUAD_C2_FEM@cardinality = 9 ; + :Basis@HGRAD_QUAD_C2_FEM@eta = -1., -1., 1., 1., -1., 0., 1., 0., 0. ; + :Basis@HGRAD_QUAD_C2_FEM@subc_dim = 0, 0, 0, 0, 1, 1, 1, 1, 2 ; + :Basis@HGRAD_QUAD_C2_FEM@subc_dof_ordinal = 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + :Basis@HGRAD_QUAD_C2_FEM@subc_num_dof = 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + :Basis@HGRAD_QUAD_C2_FEM@subc_ordinal = 0, 1, 2, 3, 0, 1, 2, 3, 0 ; + :Basis@HGRAD_QUAD_C2_FEM@xi = -1., 1., 1., -1., 0., 1., 0., -1., 0. ; + :Basis@TESTING_SECOND_BASIS@cardinality = 3 ; + :Basis@TESTING_SECOND_BASIS@eta = -1., -1., 1. ; + :Basis@TESTING_SECOND_BASIS@subc_dim = 0, 0, 0 ; + :Basis@TESTING_SECOND_BASIS@subc_dof_ordinal = 0, 0, 0 ; + :Basis@TESTING_SECOND_BASIS@subc_num_dof = 1, 1, 1 ; + :Basis@TESTING_SECOND_BASIS@subc_ordinal = 0, 1, 2 ; + :Basis@TESTING_SECOND_BASIS@xi = -1., 1., 1. ; + :Basis@TESTING_SECOND_BASIS@zeta = 1., -1., 1. ; + :Quad@1x2x1@cardinality = 2 ; + :Quad@1x2x1@eta = 0.5, -0.5 ; + :Quad@1x2x1@weight = 1., 1. ; + :Quad@1x2x1@xi = -0.5, 0.5 ; + :Quad@1x2x1@zeta = -0.5, 0.5 ; + :Quad@2x2x2@cardinality = 8 ; + :Quad@2x2x2@eta = -0.57735, -0.57735, 0.57735, 0.57735, -0.57735, -0.57735, 0.57735, 0.57735 ; + :Quad@2x2x2@weight = 1., 1., 1., 1., 1., 1., 1., 1. ; + :Quad@2x2x2@xi = -0.57735, 0.57735, -0.57735, 0.57735, -0.57735, 0.57735, -0.57735, 0.57735 ; + :Quad@2x2x2@zeta = -0.57735, -0.57735, -0.57735, -0.57735, 0.57735, 0.57735, 0.57735, 0.57735 ; + connect1:Field@Disp@separator = "" ; + connect1:Field@Disp@type = 8 ; + connect1:Field@Disp@type_name = "" ; + connect1:Field@Velocity@separator = "%" ; + connect1:Field@Velocity@type = 8 ; + connect1:Field@Velocity@type_name = "" ; + connect2:Field@Curl@separator = "@" ; + connect2:Field@Curl@type = 4 ; + connect2:Field@Curl@type_name = "2x2x2" ; + connect2:Field@Gradient@separator = "-$" ; + connect2:Field@Gradient@type = 8, 3 ; + connect2:Field@Gradient@type_name = ",HGRAD_QUAD_C2_FEM" ; + connect2:Field@Species@cardinality = 4, 0 ; + connect2:Field@Species@separator = "_-" ; + connect2:Field@Species@suffices = "h2o,gas,ch4,methane" ; + connect2:Field@Species@type = 1, 4 ; + connect2:Field@Species@type_name = ",1x2x1" ; + coor_names:Field@Disp@separator = "" ; + coor_names:Field@Disp@type = 8 ; + coor_names:Field@Disp@type_name = "" ; + coor_names:Field@Velocity@separator = "%" ; + coor_names:Field@Velocity@type = 8 ; + coor_names:Field@Velocity@type_name = "" ; + "Curl@1", + "Curl@2", + "Curl@3", + "Curl@4", + "Curl@5", + "Curl@6", + "Curl@7", + "Curl@8", diff --git a/packages/seacas/libraries/ioss/src/Ioss_BasisVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_BasisVariableType.h new file mode 100644 index 0000000000..7a78e1cfa0 --- /dev/null +++ b/packages/seacas/libraries/ioss/src/Ioss_BasisVariableType.h @@ -0,0 +1,97 @@ +/* + * Copyright(C) 2024 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 + */ +#pragma once + +#include "ioss_export.h" + +#include "Ioss_CodeTypes.h" +#include + +#include "Ioss_VariableType.h" + +namespace Ioss { + struct BasisComponent + { + int subc_dim; + int subc_ordinal; + int subc_dof_ordinal; + int subc_num_dof; + double xi; + double eta; + double zeta; + }; + + struct Basis + { + size_t size() const { return basies.size(); } + std::vector basies; + }; + + class IOSS_EXPORT BasisVariableType : public VariableType + { + public: + // 'which' is 1-based + IOSS_NODISCARD std::string label(int which, const char /* suffix_sep */) const override + { + assert(which > 0 && which <= component_count()); + if (component_count() == 1) { + return ""; + } + return VariableType::numeric_label(which - 1, component_count(), name()); + } + + BasisVariableType(const std::string &my_name, const Ioss::Basis &basis, bool delete_me) + : Ioss::VariableType(my_name, basis.size(), delete_me), m_basis_type_(my_name), + m_basis_(basis) + { + } + + BasisVariableType(const BasisVariableType &) = delete; + + IOSS_NODISCARD VariableType::Type type() const override { return Type::BASIS; } + IOSS_NODISCARD std::string type_string() const override { return "Basis"; } + + IOSS_NODISCARD const Ioss::Basis &get_basis() const { return m_basis_; } + IOSS_NODISCARD const Ioss::BasisComponent &get_basis_component(int which) const + { + assert(which > 0 && which <= component_count()); + return m_basis_.basies[which - 1]; + } + + void print() const override final; + + private: + std::string m_basis_type_{}; + Ioss::Basis m_basis_{}; + }; +} // namespace Ioss + +#if 0 +typedef struct ex_basis +{ + /* + * subc_dim: dimension of the subcell associated with the specified DoF ordinal + * -- 0 node, 1 edge, 2 face, 3 volume [Range: 0..3] + * subc_ordinal: ordinal of the subcell relative to its parent cell + * -- 0..n for each ordinal with the same subc dim [Range: <= DoF ordinal] + * subc_dof_ordinal: ordinal of the DoF relative to the subcell + * subc_num_dof: cardinality of the DoF set associated with this subcell. + * xi, eta, mu (ξ, η, ζ): Parametric coordinate location of the DoF + * -- (Only first ndim values are valid) + */ + char name[EX_MAX_NAME + 1]; + int cardinality; /* number of `basis` points == dimension of non-null subc_*, xi, eta, mu */ + int *subc_dim; + int *subc_ordinal; + int *subc_dof_ordinal; + int *subc_num_dof; + double *xi; + double *eta; + double *zeta; +} ex_basis; +#endif diff --git a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C index f37e59d507..8f16e84524 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C @@ -1,4 +1,4 @@ -// Copyright(C) 2022, 2023 National Technology & Engineering Solutions +// Copyright(C) 2022, 2023, 2024 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. // @@ -46,15 +46,14 @@ namespace { return -1; } - std::vector get_adjacent_blocks(Ioss::Region ®ion, - const std::string &surface_list) + Ioss::NameList get_adjacent_blocks(Ioss::Region ®ion, const std::string &surface_list) { - std::vector adjacent_blocks; + Ioss::NameList adjacent_blocks; if (surface_list == "ALL") { const Ioss::SideSetContainer &fss = region.get_sidesets(); for (const auto &fs : fss) { // Save a list of all blocks that are adjacent to the surfaces... - std::vector blocks; + Ioss::NameList blocks; fs->block_membership(blocks); for (const auto &block : blocks) { adjacent_blocks.push_back(block); // May have duplicates at this point. @@ -67,7 +66,7 @@ namespace { auto *sset = region.get_sideset(surface); if (sset != nullptr) { // Save a list of all blocks that are adjacent to the surfaces... - std::vector blocks; + Ioss::NameList blocks; sset->block_membership(blocks); for (const auto &block : blocks) { adjacent_blocks.push_back(block); // May have duplicates at this point. @@ -88,7 +87,7 @@ namespace { const std::string &adj_block, Ioss::chain_t &element_chains, front_t &front) { - std::vector blocks; + Ioss::NameList blocks; fs->block_membership(blocks); for (const auto &fs_block : blocks) { if (fs_block == adj_block) { @@ -209,7 +208,7 @@ namespace Ioss { // Determine which element block(s) are adjacent to the faceset specifying "lines" // The `adjacent_blocks` contains the names of all element blocks that are adjacent to the // surface(s) that specify the faces at the 'root' of the lines... - std::vector adjacent_blocks = get_adjacent_blocks(region, surface_list); + Ioss::NameList adjacent_blocks = get_adjacent_blocks(region, surface_list); if (adjacent_blocks.empty()) { fmt::print("WARNING: No surfaces in the model matched the input surface list ({}).\n\tNo " "chains will be generated.\n", diff --git a/packages/seacas/libraries/ioss/src/Ioss_Compare.C b/packages/seacas/libraries/ioss/src/Ioss_Compare.C index 9de8877b9f..9d99ecb35d 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Compare.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Compare.C @@ -995,10 +995,8 @@ namespace { { bool overall_result = true; - const std::vector &in_information_records_1 = - input_region_1.get_information_records(); - const std::vector &in_information_records_2 = - input_region_2.get_information_records(); + const Ioss::NameList &in_information_records_1 = input_region_1.get_information_records(); + const Ioss::NameList &in_information_records_2 = input_region_2.get_information_records(); if (in_information_records_1.size() != in_information_records_2.size()) { fmt::print(Ioss::WarnOut(), COUNT_MISMATCH, "INFORMATION RECORD", @@ -1025,8 +1023,8 @@ namespace { // Each QA record consists of four strings. For now, require identical ordering // (i.e., records in the same order) for equality. - const std::vector &in_qa_1 = input_region_1.get_qa_records(); - const std::vector &in_qa_2 = input_region_2.get_qa_records(); + const Ioss::NameList &in_qa_1 = input_region_1.get_qa_records(); + const Ioss::NameList &in_qa_2 = input_region_2.get_qa_records(); bool printed = false; if (in_qa_1.size() != in_qa_2.size()) { diff --git a/packages/seacas/libraries/ioss/src/Ioss_ComposedVariableType.C b/packages/seacas/libraries/ioss/src/Ioss_ComposedVariableType.C new file mode 100644 index 0000000000..dd8e4313f2 --- /dev/null +++ b/packages/seacas/libraries/ioss/src/Ioss_ComposedVariableType.C @@ -0,0 +1,71 @@ +// Copyright(C) 1999-2020, 2024 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 "Ioss_ComposedVariableType.h" +#include "Ioss_VariableType.h" +#include +#include +#include + +namespace Ioss { + std::string ComposedVariableType::composed_name(const std::string &base, + const std::string &secondary) + { + static std::string SEPARATOR("*"); + std::string name = base; + name += SEPARATOR; + name += secondary; + return name; + } + + VariableType *ComposedVariableType::composed_variable_type(const VariableType *inst, + const VariableType *secondary) + { + // See if we already constructed this composed type... + std::string composed_type = + ComposedVariableType::composed_name(inst->name(), secondary->name()); + + VariableType *comp_inst = nullptr; + auto iter = registry().find(composed_type); + if (iter == registry().end()) { + // Not found, construct new type... + comp_inst = new ComposedVariableType(inst, secondary, true); + } + else { + comp_inst = (*iter).second; + } + return comp_inst; + } + + ComposedVariableType::ComposedVariableType(const VariableType *base_type, + const VariableType *secondary_type, bool delete_me) + : VariableType(composed_name(base_type->name(), secondary_type->name()), + base_type->component_count() * secondary_type->component_count(), delete_me), + baseType(base_type), secondaryType(secondary_type) + { + } + + std::string ComposedVariableType::label(int which, const char suffix_sep) const + { + static char tmp_sep[2]; + + // NOTE: 'which' is 1-based + assert(which > 0 && which <= component_count()); + + int base_comp = baseType->component_count(); + int copies = secondaryType->component_count(); + int which_instance = (which - 1) / base_comp; + int which_base = (which - 1) % base_comp; + + std::string my_label = baseType->label(which_base + 1); + if (suffix_sep != 0 && base_comp > 1) { + tmp_sep[0] = suffix_sep; + my_label += tmp_sep; + } + my_label += VariableType::numeric_label(which_instance, copies, name()); + return my_label; + } +} // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_ComposedVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_ComposedVariableType.h new file mode 100644 index 0000000000..0a1bf8a797 --- /dev/null +++ b/packages/seacas/libraries/ioss/src/Ioss_ComposedVariableType.h @@ -0,0 +1,40 @@ +// Copyright(C) 1999-2020, 2022, 2024 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 + +#pragma once + +#include "ioss_export.h" + +#include "Ioss_CodeTypes.h" +#include "Ioss_VariableType.h" // for VariableType +#include // for string + +namespace Ioss { + class IOSS_EXPORT ComposedVariableType : public VariableType + { + public: + IOSS_NODISCARD static std::string composed_name(const std::string &base, + const std::string &secondary); + IOSS_NODISCARD static VariableType *composed_variable_type(const VariableType *inst, + const VariableType *secondary); + + IOSS_NODISCARD VariableType::Type type() const override { return Type::COMPOSED; } + IOSS_NODISCARD std::string type_string() const override; + + IOSS_NODISCARD std::string label(int which, char suffix_sep = '_') const override; + + ComposedVariableType(const VariableType *base_type, const VariableType *secondary, + bool delete_me); + ComposedVariableType(const ComposedVariableType &) = delete; + + IOSS_NODISCARD const VariableType *get_base_type() const { return baseType; } + IOSS_NODISCARD const VariableType *get_secondary_type() const { return secondaryType; } + + private: + const VariableType *baseType{nullptr}; + const VariableType *secondaryType{nullptr}; + }; +} // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.C b/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.C index 2885411505..6265c03f17 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.C +++ b/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2024 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. // @@ -63,7 +63,7 @@ namespace Ioss { int which_instance = (which - 1) / base_comp; int which_base = (which - 1) % base_comp; - std::string my_label = baseType->label(which_base + 1, suffix_sep); + std::string my_label = baseType->label(which_base + 1); if (suffix_sep != 0 && base_comp > 1) { tmp_sep[0] = suffix_sep; my_label += tmp_sep; @@ -71,9 +71,4 @@ namespace Ioss { my_label += VariableType::numeric_label(which_instance + 1, copies_, name()); return my_label; } - - const VariableType *CompositeVariableType::GetBaseType() const { return baseType; } - - int CompositeVariableType::GetNumCopies() const { return copies_; } - } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.h index f2da831fb0..904fef550b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_CompositeVariableType.h @@ -20,13 +20,23 @@ namespace Ioss { IOSS_NODISCARD static VariableType *composite_variable_type(const VariableType *inst, int copies); + IOSS_NODISCARD VariableType::Type type() const override { return Type::COMPOSITE; } + IOSS_NODISCARD std::string type_string() const override; + IOSS_NODISCARD std::string label(int which, char suffix_sep = '_') const override; CompositeVariableType(const std::string &my_name, int number_components, bool delete_me); CompositeVariableType(const VariableType *base_type, int copies, bool delete_me); CompositeVariableType(const CompositeVariableType &) = delete; - IOSS_NODISCARD const VariableType *GetBaseType() const; - IOSS_NODISCARD int GetNumCopies() const; + IOSS_NODISCARD const VariableType *get_base_type() const { return baseType; } + IOSS_NODISCARD int get_num_copies() const { return copies_; } + + // Kept for backward compatibility... + IOSS_NODISCARD __attribute__((__deprecated__)) const VariableType *getBaseType() const + { + return baseType; + } + IOSS_NODISCARD __attribute__((__deprecated__)) int getNumCopies() const { return copies_; } private: const VariableType *baseType; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C index 6b25267b48..9cc8d00999 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023, 2024 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. // @@ -91,7 +91,7 @@ std::string Ioss::Invalid_Storage::label(int /*which*/, const char /*suffix_sep* } std::string Ioss::Invalid_Storage::label_name(const std::string &base, int /*which*/, - const char /*suffix_sep*/, + const char /*suffix_sep*/, const char /*suffix_sep*/, bool /*suffices_uppercase*/) const { return base; @@ -115,7 +115,8 @@ std::string Ioss::Scalar::label(IOSS_MAYBE_UNUSED int which, const char /*suffix } std::string Ioss::Scalar::label_name(const std::string &base, int /*which*/, - const char /*suffix_sep*/, bool /*suffices_uppercase*/) const + const char /*suffix_sep*/, const char /*suffix_sep*/, + bool /*suffices_uppercase*/) const { return base; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.h index 25e62ebd0b..890333d9af 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.h @@ -28,6 +28,9 @@ namespace Ioss { static void factory(); \ X(const X &) = delete; \ \ + IOSS_NODISCARD VariableType::Type type() const override { return Type::STANDARD; } \ + IOSS_NODISCARD std::string type_string() const override { return "Standard"; } \ + \ protected: \ X(); \ \ @@ -39,11 +42,14 @@ namespace Ioss { public: Invalid_Storage(const Invalid_Storage &) = delete; IOSS_NODISCARD std::string label(int which, char suffix_sep = '_') const override; - IOSS_NODISCARD std::string label_name(const std::string &base, int /*which*/, char suffix_sep, - bool suffices_uppercase) const override; + IOSS_NODISCARD std::string label_name(const std::string &base, int /*which*/, char suffix_sep1, + char suffix_sep2, bool suffices_uppercase) const override; IOSS_NODISCARD int suffix_count() const override { return 0; } static void factory(); + IOSS_NODISCARD VariableType::Type type() const override { return Type::UNKNOWN; } + IOSS_NODISCARD std::string type_string() const override { return "Invalid"; } + protected: Invalid_Storage(); }; @@ -53,11 +59,14 @@ namespace Ioss { public: Scalar(const Scalar &) = delete; IOSS_NODISCARD std::string label(int which, char suffix_sep = '_') const override; - IOSS_NODISCARD std::string label_name(const std::string &base, int /*which*/, char suffix_sep, - bool suffices_uppercase) const override; + IOSS_NODISCARD std::string label_name(const std::string &base, int /*which*/, char suffix_sep1, + char suffix_sep2, bool suffices_uppercase) const override; IOSS_NODISCARD int suffix_count() const override { return 0; } static void factory(); + IOSS_NODISCARD VariableType::Type type() const override { return Type::SCALAR; } + IOSS_NODISCARD std::string type_string() const override { return "Scalar"; } + protected: Scalar(); }; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ConstructedVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_ConstructedVariableType.h index c22b2bcbaf..34673148bb 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ConstructedVariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ConstructedVariableType.h @@ -16,6 +16,10 @@ namespace Ioss { { public: IOSS_NODISCARD std::string label(int which, char suffix_sep = '_') const override; + + IOSS_NODISCARD VariableType::Type type() const override { return Type::CONSTRUCTED; } + IOSS_NODISCARD std::string type_string() const override { return "Constructed"; } + ConstructedVariableType(const std::string &my_name, int number_components, bool delete_me); explicit ConstructedVariableType(int number_components, bool delete_me); ConstructedVariableType(const ConstructedVariableType &) = delete; diff --git a/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C b/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C index d65f4ce7e4..7b7473c5e0 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C +++ b/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C @@ -1204,8 +1204,6 @@ namespace { size_t isize = ige->get_field(field_name).get_size(); assert(isize == oge->get_field(field_name).get_size()); - int basic_type = ige->get_field(field_name).get_type(); - if (field_name == "mesh_model_coordinates_x") { return; } @@ -1261,25 +1259,6 @@ namespace { switch (options.data_storage_type) { case 1: ige->get_field_data(field_name, pool.data.data(), isize); break; - case 2: - if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { - ige->get_field_data(field_name, pool.data); - } - else if (basic_type == Ioss::Field::INT32) { - ige->get_field_data(field_name, pool.data_int); - } - else if (basic_type == Ioss::Field::INT64) { - ige->get_field_data(field_name, pool.data_int64); - } - else if (basic_type == Ioss::Field::REAL) { - ige->get_field_data(field_name, pool.data_double); - } - else if (basic_type == Ioss::Field::COMPLEX) { - ige->get_field_data(field_name, pool.data_complex); - } - else { - } - break; #ifdef SEACAS_HAVE_KOKKOS case 3: if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { @@ -1355,25 +1334,6 @@ namespace { switch (options.data_storage_type) { case 1: oge->put_field_data(field_name, pool.data.data(), isize); break; - case 2: - if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { - oge->put_field_data(field_name, pool.data); - } - else if (basic_type == Ioss::Field::INT32) { - oge->put_field_data(field_name, pool.data_int); - } - else if (basic_type == Ioss::Field::INT64) { - oge->put_field_data(field_name, pool.data_int64); - } - else if (basic_type == Ioss::Field::REAL) { - oge->put_field_data(field_name, pool.data_double); - } - else if (basic_type == Ioss::Field::COMPLEX) { - oge->put_field_data(field_name, pool.data_complex); - } - else { - } - break; #ifdef SEACAS_HAVE_KOKKOS case 3: if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { @@ -1448,7 +1408,7 @@ namespace { { out.add_information_records(in.get_information_records()); - const std::vector &qa = in.get_qa_records(); + const Ioss::NameList &qa = in.get_qa_records(); for (size_t i = 0; i < qa.size(); i += 4) { out.add_qa_record(qa[i + 0], qa[i + 1], qa[i + 2], qa[i + 3]); } diff --git a/packages/seacas/libraries/ioss/src/Ioss_DataPool.h b/packages/seacas/libraries/ioss/src/Ioss_DataPool.h index c7dcb9c4a5..b1ffb25188 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DataPool.h +++ b/packages/seacas/libraries/ioss/src/Ioss_DataPool.h @@ -1,4 +1,4 @@ -// Copyright(C) 2020, 2021, 2022 National Technology & Engineering Solutions +// Copyright(C) 2020, 2021, 2022, 2024 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. // @@ -16,11 +16,7 @@ namespace Ioss { struct IOSS_EXPORT DataPool { // Data space shared by most field input/output routines... - std::vector data{}; - std::vector data_int{}; - std::vector data_int64{}; - std::vector data_double{}; - std::vector data_complex{}; + std::vector data{}; #ifdef SEACAS_HAVE_KOKKOS Kokkos::View data_view_char{}; Kokkos::View data_view_int{}; diff --git a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C index 7751bcdb41..bee5f80d1d 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2023 National Technology & Engineering Solutions +// Copyright(C) 1999-2024 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. // @@ -717,10 +717,10 @@ namespace Ioss { return; } - std::string prop = properties.get(property_name).get_string(); - std::vector groups = tokenize(prop, ":"); + std::string prop = properties.get(property_name).get_string(); + Ioss::NameList groups = tokenize(prop, ":"); for (auto &group : groups) { - std::vector group_spec = tokenize(group, ","); + Ioss::NameList group_spec = tokenize(group, ","); // group_spec should contain the name of the new group as // the first location and the members of the group as subsequent @@ -741,7 +741,7 @@ namespace Ioss { template void DatabaseIO::create_group(EntityType /*type*/, const std::string &type_name, - const std::vector &group_spec, const T * /*set_type*/) + const Ioss::NameList &group_spec, const T * /*set_type*/) { fmt::print(Ioss::WarnOut(), "Grouping of {0} sets is not yet implemented.\n" @@ -750,9 +750,8 @@ namespace Ioss { } template <> - void DatabaseIO::create_group(EntityType type, const std::string & /*type_name*/, - const std::vector &group_spec, - const SideSet * /*set_type*/) + void DatabaseIO::create_group(EntityType type, const std::string &/*type_name*/, + const Ioss::NameList &group_spec, const SideSet * /*set_type*/) { // Not generalized yet... This only works for T == SideSet if (type != SIDESET) { @@ -840,7 +839,7 @@ namespace Ioss { * * \param[in] info The strings to add. */ - void DatabaseIO::add_information_records(const std::vector &info) + void DatabaseIO::add_information_records(const Ioss::NameList &info) { informationRecords.reserve(informationRecords.size() + info.size()); informationRecords.insert(informationRecords.end(), info.begin(), info.end()); @@ -874,8 +873,8 @@ namespace Ioss { qaRecords.push_back(time); } - void DatabaseIO::set_block_omissions(const std::vector &omissions, - const std::vector &inclusions) + void DatabaseIO::set_block_omissions(const Ioss::NameList &omissions, + const Ioss::NameList &inclusions) { if (!omissions.empty() && !inclusions.empty()) { // Only one can be non-empty @@ -915,8 +914,8 @@ namespace Ioss { } } - void DatabaseIO::set_assembly_omissions(const std::vector &omissions, - const std::vector &inclusions) + void DatabaseIO::set_assembly_omissions(const Ioss::NameList &omissions, + const Ioss::NameList &inclusions) { if (!omissions.empty() && !inclusions.empty()) { // Only one can be non-empty @@ -1020,7 +1019,7 @@ namespace Ioss { } void DatabaseIO::get_block_adjacencies_nl(const Ioss::ElementBlock *eb, - std::vector &block_adjacency) const + Ioss::NameList &block_adjacency) const { if (!blockAdjacenciesCalculated) { compute_block_adjacencies(); diff --git a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h index 90a83ffe2b..f5edcdb3b4 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h @@ -344,11 +344,11 @@ namespace Ioss { * * \returns The informative strings. */ - IOSS_NODISCARD const std::vector &get_information_records() const + IOSS_NODISCARD const Ioss::NameList &get_information_records() const { return informationRecords; } - void add_information_records(const std::vector &info); + void add_information_records(const Ioss::NameList &info); void add_information_record(const std::string &info); // QA Records: @@ -368,7 +368,7 @@ namespace Ioss { * \returns All QA records in a single vector. Every 4 consecutive elements of the * vector make up a single QA record. */ - IOSS_NODISCARD const std::vector &get_qa_records() const { return qaRecords; } + IOSS_NODISCARD const Ioss::NameList &get_qa_records() const { return qaRecords; } void add_qa_record(const std::string &code, const std::string &code_qa, const std::string &date, const std::string &time); @@ -480,19 +480,17 @@ namespace Ioss { void set_surface_split_type(Ioss::SurfaceSplitType split_type) { splitType = split_type; } IOSS_NODISCARD Ioss::SurfaceSplitType get_surface_split_type() const { return splitType; } - void set_block_omissions(const std::vector &omissions, - const std::vector &inclusions = {}); + void set_block_omissions(const Ioss::NameList &omissions, + const Ioss::NameList &inclusions = {}); - void set_assembly_omissions(const std::vector &omissions, - const std::vector &inclusions = {}); + void set_assembly_omissions(const Ioss::NameList &omissions, + const Ioss::NameList &inclusions = {}); - void get_block_adjacencies(const Ioss::ElementBlock *eb, - std::vector &block_adjacency) const + void get_block_adjacencies(const Ioss::ElementBlock *eb, Ioss::NameList &block_adjacency) const { return get_block_adjacencies_nl(eb, block_adjacency); } - void compute_block_membership(Ioss::SideBlock *efblock, - std::vector &block_membership) const + void compute_block_membership(Ioss::SideBlock *efblock, Ioss::NameList &block_membership) const { return compute_block_membership_nl(efblock, block_membership); } @@ -625,7 +623,7 @@ namespace Ioss { const std::string &type_name, const T *set_type); template void create_group(EntityType type, const std::string &type_name, - const std::vector &group_spec, const T *set_type); + const Ioss::NameList &group_spec, const T *set_type); // Create new sets as groups of existing exodus sets... void handle_groups(); @@ -718,13 +716,13 @@ namespace Ioss { // element ids and offsets are still calculated assuming that the // blocks exist in the model... // Only one of these can have values and the other must be empty. - std::vector blockOmissions{}; - std::vector blockInclusions{}; - std::vector assemblyOmissions{}; - std::vector assemblyInclusions{}; + Ioss::NameList blockOmissions{}; + Ioss::NameList blockInclusions{}; + Ioss::NameList assemblyOmissions{}; + Ioss::NameList assemblyInclusions{}; - std::vector informationRecords{}; - std::vector qaRecords{}; + Ioss::NameList informationRecords{}; + Ioss::NameList qaRecords{}; //---Node Map -- Maps internal (1..NUMNP) ids to global ids used on the // application side. global = nodeMap[local] @@ -780,11 +778,10 @@ namespace Ioss { virtual bool end_state_nl(int state, double time); void get_block_adjacencies_nl(const Ioss::ElementBlock *eb, - std::vector &block_adjacency) const; + Ioss::NameList &block_adjacency) const; - virtual void - compute_block_membership_nl(Ioss::SideBlock * /* efblock */, - std::vector & /* block_membership */) const + virtual void compute_block_membership_nl(Ioss::SideBlock * /* efblock */, + Ioss::NameList & /* block_membership */) const { } diff --git a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C index 13ff0e6b05..efda361b47 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2023 National Technology & Engineering Solutions + * Copyright(C) 1999-2024 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. * @@ -138,29 +138,29 @@ namespace { namespace Ioss { - IOSS_EXPORT const std::vector &valid_decomp_methods() + IOSS_EXPORT const Ioss::NameList &valid_decomp_methods() { - static const std::vector valid_methods{"EXTERNAL" + static const Ioss::NameList valid_methods{"EXTERNAL" #ifdef SEACAS_HAVE_MPI - , - "LINEAR", - "MAP", - "VARIABLE" + , + "LINEAR", + "MAP", + "VARIABLE" #if !defined(NO_ZOLTAN_SUPPORT) - , - "BLOCK", - "CYCLIC", - "RANDOM", - "RCB", - "RIB", - "HSFC" + , + "BLOCK", + "CYCLIC", + "RANDOM", + "RCB", + "RIB", + "HSFC" #endif #if !defined(NO_PARMETIS_SUPPORT) - , - "KWAY", - "KWAY_GEOM", - "GEOM_KWAY", - "METIS_SFC" + , + "KWAY", + "KWAY_GEOM", + "GEOM_KWAY", + "METIS_SFC" #endif #endif }; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h index a22334a068..5bae8e227b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h @@ -39,7 +39,7 @@ #endif namespace Ioss { - IOSS_EXPORT const std::vector &valid_decomp_methods(); + IOSS_EXPORT const Ioss::NameList &valid_decomp_methods(); class IOSS_EXPORT BlockDecompositionData { diff --git a/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.C b/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.C index ed8928d348..c917486520 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.C +++ b/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023, 2024 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. // @@ -54,4 +54,4 @@ Ioss::Property Ioss::EdgeSet::get_implicit_property(const std::string &my_name) return Ioss::EntitySet::get_implicit_property(my_name); } -void Ioss::EdgeSet::block_membership(std::vector & /*block_members*/) {} +void Ioss::EdgeSet::block_membership(Ioss::NameList & /*block_members*/) {} diff --git a/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h b/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h index de9e578707..438d20ab70 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h @@ -43,7 +43,7 @@ namespace Ioss { // An example would be 'element_block_count' for a region. IOSS_NODISCARD Property get_implicit_property(const std::string &my_name) const override; - void block_membership(std::vector &block_membership) override; + void block_membership(Ioss::NameList &block_membership) override; protected: int64_t internal_get_field_data(const Field &field, void *data, diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.C b/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.C index 2762da54a8..a7decd5544 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.C @@ -60,14 +60,14 @@ namespace Ioss { return get_database()->get_zc_field(this, field, data, data_size); } - void ElementBlock::get_block_adjacencies(std::vector &block_adjacency) const + void ElementBlock::get_block_adjacencies(Ioss::NameList &block_adjacency) const { get_database()->get_block_adjacencies(this, block_adjacency); } - std::vector ElementBlock::get_block_adjacencies() const + Ioss::NameList ElementBlock::get_block_adjacencies() const { - std::vector block_adjacency; + Ioss::NameList block_adjacency; get_database()->get_block_adjacencies(this, block_adjacency); return block_adjacency; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h b/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h index 2a849b8d25..317263ca27 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h @@ -43,8 +43,8 @@ namespace Ioss { // An example would be 'element_block_count' for a region. IOSS_NODISCARD Property get_implicit_property(const std::string &my_name) const override; - IOSS_NODISCARD std::vector get_block_adjacencies() const; - void get_block_adjacencies(std::vector &block_adjacency) const; + IOSS_NODISCARD Ioss::NameList get_block_adjacencies() const; + void get_block_adjacencies(Ioss::NameList &block_adjacency) const; IOSS_NODISCARD AxisAlignedBoundingBox get_bounding_box() const; IOSS_NODISCARD bool operator==(const Ioss::ElementBlock &rhs) const; IOSS_NODISCARD bool operator!=(const Ioss::ElementBlock &rhs) const; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementSet.C b/packages/seacas/libraries/ioss/src/Ioss_ElementSet.C index b6ee6f0a5c..465f69a5e7 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementSet.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementSet.C @@ -53,4 +53,4 @@ Ioss::Property Ioss::ElementSet::get_implicit_property(const std::string &my_nam return Ioss::EntitySet::get_implicit_property(my_name); } -void Ioss::ElementSet::block_membership(std::vector & /*block_members*/) {} +void Ioss::ElementSet::block_membership(Ioss::NameList & /*block_members*/) {} diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h b/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h index e4e846db90..87667706f4 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h @@ -43,7 +43,7 @@ namespace Ioss { // An example would be 'element_block_count' for a region. IOSS_NODISCARD Property get_implicit_property(const std::string &my_name) const override; - void block_membership(std::vector &block_membership) override; + void block_membership(Ioss::NameList &block_membership) override; protected: int64_t internal_get_field_data(const Field &field, void *data, diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C b/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C index 6bdb9de951..0e4690835b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C @@ -10,13 +10,13 @@ #include "Ioss_Super.h" // for Super #include "Ioss_Utils.h" -#include // for assert -#include // for size_t +#include +#include #include -#include // for basic_ostream, etc -#include // for string, char_traits, etc -#include // for pair -#include // for vector +#include +#include +#include +#include void Ioss::ETRegistry::insert(const Ioss::ETM_VP &value, bool delete_me) { diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_ElementVariableType.h index 7488407dd0..d47c3d59b0 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementVariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementVariableType.h @@ -21,13 +21,16 @@ namespace Ioss { return ""; } IOSS_NODISCARD std::string label_name(const std::string &base, int /*which*/, - const char /*suffix_sep*/, + const char /*suffix_sep*/, const char /*suffix_sep*/, bool /* suffices_uppercase */) const override { return base; } IOSS_NODISCARD int suffix_count() const override { return 0; } + IOSS_NODISCARD VariableType::Type type() const override { return Type::ELEMENT; } + IOSS_NODISCARD std::string type_string() const override { return "Element"; } + protected: ElementVariableType(const std::string &type, int comp_count); }; diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceSet.C b/packages/seacas/libraries/ioss/src/Ioss_FaceSet.C index 44307bfb0e..4d033ce976 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceSet.C +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceSet.C @@ -54,4 +54,4 @@ Ioss::Property Ioss::FaceSet::get_implicit_property(const std::string &my_name) return Ioss::EntitySet::get_implicit_property(my_name); } -void Ioss::FaceSet::block_membership(std::vector & /*block_members*/) {} +void Ioss::FaceSet::block_membership(Ioss::NameList & /*block_members*/) {} diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h b/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h index e5d1a3b766..7e3eb0e87b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h @@ -43,7 +43,7 @@ namespace Ioss { // An example would be 'element_block_count' for a region. IOSS_NODISCARD Property get_implicit_property(const std::string &my_name) const override; - void block_membership(std::vector &block_membership) override; + void block_membership(Ioss::NameList &block_membership) override; protected: int64_t internal_get_field_data(const Field &field, void *data, diff --git a/packages/seacas/libraries/ioss/src/Ioss_Field.C b/packages/seacas/libraries/ioss/src/Ioss_Field.C index c1f9f51a69..c110b825c5 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Field.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Field.C @@ -35,6 +35,31 @@ namespace { } // namespace +namespace Ioss { + std::ostream &operator<<(std::ostream &os, const Field &fld) + { + Ioss::NameList components(fld.get_component_count(Field::InOut::INPUT)); + for (size_t i = 0; i < components.size(); i++) { + components[i] = fld.get_component_name(i + 1, Field::InOut::INPUT, 1); + } + auto storage = fld.raw_storage()->name(); + if (storage == "scalar") { + fmt::print(os, "\tField: {}, Storage: {}\t{}\t{}\n", fld.get_name(), + fld.raw_storage()->name(), fld.type_string(), fld.role_string()); + } + else { + fmt::print(os, + "\tField: {}, Storage: {} ({}),\t{},\t{}, Sep1: '{}', Sep2: '{}'\n" + "\t\t\tComponents ({}): {}\n", + fld.get_name(), fld.raw_storage()->name(), fld.raw_storage()->type_string(), + fld.type_string(), fld.role_string(), fld.get_suffix_separator(0), + fld.get_suffix_separator(1), fld.get_component_count(Field::InOut::INPUT), + fmt::join(components, ", ")); + } + return os; + } +} // namespace Ioss + /** \brief Create an empty field. */ Ioss::Field::Field() { rawStorage_ = transStorage_ = Ioss::VariableType::factory("invalid"); } @@ -103,6 +128,27 @@ Ioss::Field::Field(std::string name, const Ioss::Field::BasicType type, size_ = internal_get_size(type_, rawCount_, rawStorage_); } +/** \brief Create a field. + * + * \param[in] name The name of the field + * \param[in] type The basic data type of data held in the field. + * \param[in] storage The storage class of the data (ConstructedVariableType, + * CompositeVariableType, etc) + * \param[in] secondary The secondary storage class of the data (typically "basis") [For a + * ComposedVariableType field] \param[in] role The category of information held in the field (MESH, + * ATTRIBUTE, TRANSIENT, REDUCTION, etc) \param[in] value_count The number of items in the field. + * \param[in] index + * + */ +Ioss::Field::Field(std::string name, BasicType type, const std::string &storage, + const std::string &secondary, RoleType role, size_t value_count, size_t index) + : name_(std::move(name)), rawCount_(value_count), transCount_(value_count), index_(index), + type_(type), role_(role) +{ + rawStorage_ = transStorage_ = Ioss::VariableType::factory(storage, secondary); + size_ = internal_get_size(type_, rawCount_, rawStorage_); +} + int Ioss::Field::get_component_count(Ioss::Field::InOut in_out) const { const auto *storage = (in_out == InOut::INPUT) ? raw_storage() : transformed_storage(); @@ -111,12 +157,16 @@ int Ioss::Field::get_component_count(Ioss::Field::InOut in_out) const std::string Ioss::Field::get_component_name(int component_index, InOut in_out, char suffix) const { - char suffix_separator = get_suffix_separator(); - if (suffix_separator == 1) { - suffix_separator = suffix != 1 ? suffix : '_'; + char suffix_separator0 = get_suffix_separator(0); + if (suffix_separator0 == 1) { + suffix_separator0 = suffix != 1 ? suffix : '_'; + } + char suffix_separator1 = get_suffix_separator(1); + if (suffix_separator1 == 1) { + suffix_separator1 = suffix != 1 ? suffix : '_'; } const auto *storage = (in_out == InOut::INPUT) ? raw_storage() : transformed_storage(); - return storage->label_name(get_name(), component_index, suffix_separator, + return storage->label_name(get_name(), component_index, suffix_separator0, suffix_separator1, get_suffices_uppercase()); } @@ -280,47 +330,47 @@ bool Ioss::Field::equal_(const Ioss::Field &rhs, bool quiet) const if (this->type_ != rhs.type_) { if (!quiet) { - fmt::print(Ioss::OUTPUT(), "\tFIELD type mismatch ({} v. {})\n", this->type_string(), - rhs.type_string()); + fmt::print(Ioss::OUTPUT(), "\tFIELD {} type mismatch ({} v. {})\n", this->name_, + this->type_string(), rhs.type_string()); } is_same = false; } if (this->role_ != rhs.role_) { if (!quiet) { - fmt::print(Ioss::OUTPUT(), "\tFIELD role mismatch ({} v. {})\n", this->role_string(), - rhs.role_string()); + fmt::print(Ioss::OUTPUT(), "\tFIELD {} role mismatch ({} v. {})\n", this->name_, + this->role_string(), rhs.role_string()); } is_same = false; } if (this->rawCount_ != rhs.rawCount_) { if (!quiet) { - fmt::print(Ioss::OUTPUT(), "\tFIELD rawCount mismatch ({} v. {})\n", this->rawCount_, - rhs.rawCount_); + fmt::print(Ioss::OUTPUT(), "\tFIELD {} rawCount mismatch ({} v. {})\n", this->name_, + this->rawCount_, rhs.rawCount_); } is_same = false; } if (this->transCount_ != rhs.transCount_) { if (!quiet) { - fmt::print(Ioss::OUTPUT(), "\tFIELD transCount mismatch ({} v. {})\n", this->transCount_, - rhs.transCount_); + fmt::print(Ioss::OUTPUT(), "\tFIELD {} transCount mismatch ({} v. {})\n", this->name_, + this->transCount_, rhs.transCount_); } is_same = false; } if (this->get_size() != rhs.get_size()) { if (!quiet) { - fmt::print(Ioss::OUTPUT(), "\tFIELD size mismatch ({} v. {})\n", this->get_size(), - rhs.get_size()); + fmt::print(Ioss::OUTPUT(), "\tFIELD {} size mismatch ({} v. {})\n", this->name_, + this->get_size(), rhs.get_size()); } is_same = false; } if (!quiet) { if (this->get_suffices_uppercase() != rhs.get_suffices_uppercase()) { - fmt::print(Ioss::OUTPUT(), "\tFIELD suffices_uppercase mismatch ({} v. {})\n", + fmt::print(Ioss::OUTPUT(), "\tFIELD {} suffices_uppercase mismatch ({} v. {})\n", this->name_, this->get_suffices_uppercase(), rhs.get_suffices_uppercase()); is_same = false; } @@ -328,7 +378,7 @@ bool Ioss::Field::equal_(const Ioss::Field &rhs, bool quiet) const if (!quiet) { if (this->zero_copy_enabled() != rhs.zero_copy_enabled()) { - fmt::print(Ioss::OUTPUT(), "\tFIELD zero_copy_enabled mismatch ({} v. {})\n", + fmt::print(Ioss::OUTPUT(), "\tFIELD {} zero_copy_enabled mismatch ({} v. {})\n", this->name_, this->zero_copy_enabled(), rhs.zero_copy_enabled()); is_same = false; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_Field.h b/packages/seacas/libraries/ioss/src/Ioss_Field.h index 897fafb4bb..80c7aae156 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Field.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Field.h @@ -8,6 +8,9 @@ #include "Ioss_CodeTypes.h" #include // for size_t +#if !defined BUILT_IN_SIERRA +#include +#endif #include #include // for string #include // for vector @@ -108,6 +111,9 @@ namespace Ioss { Field(std::string name, BasicType type, const std::string &storage, int copies, RoleType role, size_t value_count = 0, size_t index = 0); + Field(std::string name, BasicType type, const std::string &storage, + const std::string &secondary, RoleType role, size_t value_count = 0, size_t index = 0); + Field(std::string name, BasicType type, const VariableType *storage, RoleType role, size_t value_count = 0, size_t index = 0); @@ -136,13 +142,17 @@ namespace Ioss { char suffix = 1) const; IOSS_NODISCARD int get_component_count(InOut in_out) const; - Field &set_suffix_separator(char suffix_separator) + Field &set_suffix_separator(char suffix_separator1, char suffix_separator2 = 2) { - suffixSeparator_ = suffix_separator; + suffixSeparator1_ = suffix_separator1; + suffixSeparator2_ = suffix_separator2 == 2 ? suffix_separator1 : suffix_separator2; return *this; } - IOSS_NODISCARD char get_suffix_separator() const { return suffixSeparator_; } - Field &set_suffices_uppercase(bool true_false) + IOSS_NODISCARD char get_suffix_separator(int index = 0) const + { + return index == 0 ? suffixSeparator1_ : suffixSeparator2_; + } + Field &set_suffices_uppercase(bool true_false) { sufficesUppercase_ = true_false; return *this; @@ -228,10 +238,22 @@ namespace Ioss { const VariableType *transStorage_{nullptr}; // Storage type after transformation std::vector transforms_{}; - char suffixSeparator_{1}; // Value = 1 means unset; use database default. + char suffixSeparator1_{1}; // Value = 1 means unset; use database default. + char suffixSeparator2_{1}; // Value = 1 means unset; use database default. bool sufficesUppercase_{false}; // True if the suffices are uppercase on database... mutable bool zeroCopyable_{false}; // True if the field is zero-copyable. bool equal_(const Ioss::Field &rhs, bool quiet) const; }; + IOSS_EXPORT std::ostream &operator<<(std::ostream &os, const Field &fld); } // namespace Ioss + +#if !defined BUILT_IN_SIERRA +#if FMT_VERSION >= 90000 +namespace fmt { + template <> struct formatter : ostream_formatter + { + }; +} // namespace fmt +#endif +#endif diff --git a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C index 59f6b2da75..0050e99304 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C +++ b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C @@ -550,14 +550,12 @@ bool Ioss::GroupingEntity::equal_(const Ioss::GroupingEntity &rhs, bool quiet) c } } - if (rhs_fields.size() > lhs_fields.size()) { - // See which fields are missing from input #1... - // NOTE: `quiet` mode has already exited by this point. - for (auto &field : rhs_fields) { - if (!this->field_exists(field)) { - fmt::print(Ioss::OUTPUT(), "{}: FIELD ({}) not found in input #1\n", name(), field); - same = false; - } + // See which fields are missing from input #1... + // NOTE: `quiet` mode has already exited by this point. + for (auto &field : rhs_fields) { + if (!this->field_exists(field)) { + fmt::print(Ioss::OUTPUT(), "{}: FIELD ({}) not found in input #1\n", name(), field); + same = false; } } return same; diff --git a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h index 6c7faec5b1..e6123be18c 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h +++ b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h @@ -128,7 +128,7 @@ namespace Ioss { * Entries are pushed onto the "block_members" vector, so it will be * appended to if it is not empty at entry to the function. */ - virtual void block_membership(std::vector & /* block_members */) {} + virtual void block_membership(Ioss::NameList & /* block_members */) {} IOSS_NODISCARD std::string get_filename() const; diff --git a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h index 2467a21b7b..5d07acda3f 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h @@ -24,7 +24,7 @@ namespace Ioss { class IOFactory; - using NameList = std::vector; + using NameList = Ioss::NameList; using IOFactoryMap = std::map>; class DatabaseIO; diff --git a/packages/seacas/libraries/ioss/src/Ioss_NamedSuffixVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_NamedSuffixVariableType.h index 0d7d647439..c81c922d40 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_NamedSuffixVariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_NamedSuffixVariableType.h @@ -32,12 +32,17 @@ namespace Ioss { } NamedSuffixVariableType(const NamedSuffixVariableType &) = delete; + IOSS_NODISCARD VariableType::Type type() const override { return Type::NAMED_SUFFIX; } + IOSS_NODISCARD std::string type_string() const override { return "NamedSuffix"; } + //! Define the suffix list for this field. // 'which' is 1-based to conform to the 'label' function usage. // If user doesn't add suffices, then 'label' will return "UNSET" void add_suffix(size_t which, const std::string &suffix) { suffixList[which - 1] = suffix; } + void print() const override final; + private: - std::vector suffixList{}; + Ioss::NameList suffixList{}; }; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C b/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C index f81486815d..47938091e2 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C @@ -55,11 +55,11 @@ void Ioss::ParallelUtils::add_environment_properties(Ioss::PropertyManager &prop if (get_environment("IOSS_PROPERTIES", env_props, parallel_size() > 1)) { // env_props string should be of the form // "PROP1=VALUE1:PROP2=VALUE2:..." - std::vector prop_val = tokenize(env_props, ":"); + Ioss::NameList prop_val = tokenize(env_props, ":"); int rank = parallel_rank(); for (auto &elem : prop_val) { - std::vector property = tokenize(elem, "="); + Ioss::NameList property = tokenize(elem, "="); if (property.size() != 2) { std::ostringstream errmsg; fmt::print( diff --git a/packages/seacas/libraries/ioss/src/Ioss_QuadratureVariableType.h b/packages/seacas/libraries/ioss/src/Ioss_QuadratureVariableType.h new file mode 100644 index 0000000000..ea52aeded2 --- /dev/null +++ b/packages/seacas/libraries/ioss/src/Ioss_QuadratureVariableType.h @@ -0,0 +1,82 @@ +/* + * Copyright(C) 2024 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 + */ +#pragma once + +#include "ioss_export.h" + +#include "Ioss_CodeTypes.h" +#include + +#include "Ioss_VariableType.h" + +namespace Ioss { + struct QuadraturePoint + { + double xi; + double eta; + double zeta; + double weight; + }; + + class IOSS_EXPORT QuadratureVariableType : public VariableType + { + public: + // 'which' is 1-based + IOSS_NODISCARD std::string label(int which, const char /* suffix_sep */) const override + { + assert(which > 0 && which <= component_count()); + if (component_count() == 1) { + return ""; + } + return VariableType::numeric_label(which, component_count(), name()); + } + + QuadratureVariableType(const std::string &my_name, + const std::vector &quad_points, bool delete_me) + : Ioss::VariableType(Ioss::Utils::lowercase(my_name), quad_points.size(), delete_me), + m_quadratureType_(my_name), m_quadrature_(quad_points) + { + } + + QuadratureVariableType(const QuadratureVariableType &) = delete; + + IOSS_NODISCARD VariableType::Type type() const override { return Type::QUADRATURE; } + IOSS_NODISCARD std::string type_string() const override { return "Quadrature"; } + + IOSS_NODISCARD std::vector get_quadrature() const + { + return m_quadrature_; + } + IOSS_NODISCARD Ioss::QuadraturePoint get_quadrature_component(int which) const + { + assert(which > 0 && which <= component_count()); + return m_quadrature_[which - 1]; + } + + void print() const override final; + + private: + std::string m_quadratureType_{}; + std::vector m_quadrature_{}; + }; +} // namespace Ioss + +#if 0 +typedef struct ex_quadrature +{ + char name[EX_MAX_NAME + 1]; + int cardinality; /* Number of quadrature points */ + int dimension; /* 1,2,3 -- spatial dimension of points */ + double *xi; /* xi (x) coordinate of points; dimension = cardinality or NULL */ + double * + eta; /* eta (y) coordinate of points; dimension = cardinality if dimension = 2 or 3 or NULL */ + double + *zeta; /* zeta (z) coordinate of points; dimension = cardinality if dimension == 3. or NULL */ + double *weight; /* weights for each point; dimension = cardinality or NULL */ +} ex_quadrature; +#endif diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.C b/packages/seacas/libraries/ioss/src/Ioss_Region.C index 7f220b7381..a3660c18f6 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.C @@ -1718,7 +1718,7 @@ namespace Ioss { * */ int Region::get_aliases(const std::string &my_name, EntityType type, - std::vector &aliases) const + Ioss::NameList &aliases) const { IOSS_FUNC_ENTER(m_); size_t size = aliases.size(); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.h b/packages/seacas/libraries/ioss/src/Ioss_Region.h index b6aeb52fd1..730693ad61 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.h @@ -229,8 +229,7 @@ namespace Ioss { IOSS_NODISCARD const AliasMap &get_alias_map(EntityType entity_type) const; /// Get a map containing all aliases defined for the entity with basename 'my_name' - int get_aliases(const std::string &my_name, EntityType type, - std::vector &aliases) const; + int get_aliases(const std::string &my_name, EntityType type, Ioss::NameList &aliases) const; // This routine transfers all relevant aliases from the 'this' // region and applies them to the 'to' file. @@ -268,11 +267,11 @@ namespace Ioss { // An example would be 'element_block_count' for a region. IOSS_NODISCARD Property get_implicit_property(const std::string &my_name) const override; - IOSS_NODISCARD const std::vector &get_information_records() const; - void add_information_records(const std::vector &info); - void add_information_record(const std::string &info); + IOSS_NODISCARD const Ioss::NameList &get_information_records() const; + void add_information_records(const Ioss::NameList &info); + void add_information_record(const std::string &info); - IOSS_NODISCARD const std::vector &get_qa_records() const; + IOSS_NODISCARD const Ioss::NameList &get_qa_records() const; void add_qa_record(const std::string &code, const std::string &code_qa, const std::string &date = "", const std::string &time = ""); @@ -356,7 +355,7 @@ inline int64_t Ioss::Region::node_global_to_local(int64_t global, bool must_exis * * \returns The informative strings. */ -inline const std::vector &Ioss::Region::get_information_records() const +inline const Ioss::NameList &Ioss::Region::get_information_records() const { IOSS_FUNC_ENTER(m_); return get_database()->get_information_records(); @@ -366,7 +365,7 @@ inline const std::vector &Ioss::Region::get_information_records() c * * \param[in] info The strings to add. */ -inline void Ioss::Region::add_information_records(const std::vector &info) +inline void Ioss::Region::add_information_records(const Ioss::NameList &info) { IOSS_FUNC_ENTER(m_); return get_database()->add_information_records(info); @@ -414,7 +413,7 @@ inline void Ioss::Region::add_qa_record(const std::string &code, const std::stri * \returns All QA records in a single vector. Every 4 consecutive elements of the * vector make up a single QA record. */ -inline const std::vector &Ioss::Region::get_qa_records() const +inline const Ioss::NameList &Ioss::Region::get_qa_records() const { IOSS_FUNC_ENTER(m_); return get_database()->get_qa_records(); diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C index f84221658a..53b9600da7 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C @@ -143,7 +143,7 @@ Ioss::Property Ioss::SideBlock::get_implicit_property(const std::string &my_name return Ioss::EntityBlock::get_implicit_property(my_name); } -void Ioss::SideBlock::block_membership(std::vector &block_members) +void Ioss::SideBlock::block_membership(Ioss::NameList &block_members) { // Simplest case. If the surfaces are split by element block, then this will // return non-null diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h index 8807d86afb..c400456a08 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h @@ -79,7 +79,7 @@ namespace Ioss { IOSS_NODISCARD const SideSet *owner() const { return owner_; } IOSS_NODISCARD const Ioss::GroupingEntity *contained_in() const override { return owner_; } - void block_membership(std::vector &block_members) override; + void block_membership(Ioss::NameList &block_members) override; // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. @@ -137,8 +137,8 @@ namespace Ioss { const EntityBlock *parentBlock_{nullptr}; // Pointer to the SideSet (if any) that contains this side block. - std::vector blockMembership{}; // What element blocks do the - // elements in this sideset belong to. + Ioss::NameList blockMembership{}; // What element blocks do the + // elements in this sideset belong to. mutable int consistentSideNumber{-1}; }; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideSet.C b/packages/seacas/libraries/ioss/src/Ioss_SideSet.C index 2fb019a420..b23927a37e 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideSet.C +++ b/packages/seacas/libraries/ioss/src/Ioss_SideSet.C @@ -165,12 +165,12 @@ int Ioss::SideSet::max_parametric_dimension() const return max_par_dim; } -void Ioss::SideSet::block_membership(std::vector &block_members) +void Ioss::SideSet::block_membership(Ioss::NameList &block_members) { IOSS_FUNC_ENTER(m_); if (blockMembership.empty()) { for (auto &sb : sideBlocks) { - std::vector blocks; + Ioss::NameList blocks; sb->block_membership(blocks); blockMembership.insert(blockMembership.end(), blocks.begin(), blocks.end()); } @@ -202,11 +202,11 @@ bool Ioss::SideSet::equal_(const SideSet &rhs, const bool /* quiet */) const } // COMPARE block membership - std::vector lhs_block_membership = this->blockMembership; - std::vector rhs_block_membership = rhs.blockMembership; + Ioss::NameList lhs_block_membership = this->blockMembership; + Ioss::NameList rhs_block_membership = rhs.blockMembership; for (const auto &lhs_block_member : lhs_block_membership) { - std::vector::iterator it; + Ioss::NameList::iterator it; for (it = rhs_block_membership.begin(); it != rhs_block_membership.end(); ++it) { if ((*it) == lhs_block_member) { break; diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideSet.h b/packages/seacas/libraries/ioss/src/Ioss_SideSet.h index 71fbcc9679..1032a59626 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_SideSet.h @@ -45,7 +45,7 @@ namespace Ioss { IOSS_NODISCARD size_t block_count() const { return sideBlocks.size(); } IOSS_NODISCARD SideBlock *get_block(size_t which) const; - void block_membership(std::vector &block_members) override; + void block_membership(Ioss::NameList &block_members) override; // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. @@ -70,8 +70,8 @@ namespace Ioss { bool equal_(const SideSet &rhs, bool quiet) const; private: - SideBlockContainer sideBlocks; - std::vector blockMembership; // What element blocks do the - // elements in this sideset belong to. + SideBlockContainer sideBlocks; + Ioss::NameList blockMembership; // What element blocks do the + // elements in this sideset belong to. }; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_Utils.C b/packages/seacas/libraries/ioss/src/Ioss_Utils.C index a9c8978fc8..71f6d5fd16 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Utils.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Utils.C @@ -74,12 +74,12 @@ namespace { //////////////////////////////////////////////////////////////////////// bool is_separator(const char separator, const char value) { return separator == value; } - int match(const char *name1, const char *name2) + size_t match(const char *name1, const char *name2) { - int l1 = static_cast(std::strlen(name1)); - int l2 = static_cast(std::strlen(name2)); - int len = l1 < l2 ? l1 : l2; - for (int i = 0; i < len; i++) { + auto l1 = std::strlen(name1); + auto l2 = std::strlen(name2); + auto len = l1 < l2 ? l1 : l2; + for (size_t i = 0; i < len; i++) { if (name1[i] != name2[i]) { while (i > 0 && (isdigit(name1[i - 1]) != 0) && (isdigit(name2[i - 1]) != 0)) { i--; @@ -91,6 +91,11 @@ namespace { return len; } + size_t match(const std::string &name1, const std::string &name2) + { + return match(name1.c_str(), name2.c_str()); + } + // Split 'str' into 'tokens' based on the 'separator' character. // If 'str' starts with 1 or more 'separator', they are part of the // first token and not used for splitting. If there are multiple @@ -99,8 +104,7 @@ namespace { // characters of the next token. // `__this___is_a_string__for_tokens` will split to 6 tokens: // `__this` `__is` `a` `string` `_for` `tokens` - void field_tokenize(const std::string &str, const char separator, - std::vector &tokens) + Ioss::NameList field_tokenize(const std::string &str, const char separator) { std::string curr_token; // Skip leading separators... @@ -108,6 +112,7 @@ namespace { while (i < str.length() && is_separator(separator, str[i])) { curr_token += str[i++]; } + Ioss::NameList tokens; for (; i < str.length(); ++i) { char curr_char = str[i]; @@ -129,6 +134,7 @@ namespace { if (!curr_token.empty()) { tokens.push_back(curr_token); } + return tokens; } } // namespace @@ -275,24 +281,6 @@ std::string Ioss::Utils::encode_entity_name(const std::string &entity_type, int6 return fmt::format("{}_{}", entity_type, id); } -char **Ioss::Utils::get_name_array(size_t count, int size) -{ - auto *names = new char *[count]; - for (size_t i = 0; i < count; i++) { - names[i] = new char[size + 1]; - std::memset(names[i], '\0', size + 1); - } - return names; -} - -void Ioss::Utils::delete_name_array(char **names, int count) -{ - for (int i = 0; i < count; i++) { - delete[] names[i]; - } - delete[] names; -} - std::string Ioss::Utils::fixup_type(const std::string &base, int nodes_per_element, int spatial) { std::string type = base; @@ -388,8 +376,9 @@ int Ioss::Utils::field_warning(const Ioss::GroupingEntity *ge, const Ioss::Field } namespace { - const Ioss::VariableType *match_composite_field(char **names, Ioss::IntVector &which_names, - const char suffix_separator) + const Ioss::VariableType *match_composite_field(Ioss::NameList &names, + Ioss::IntVector &which_names, + const char suffix_separator) { // ASSUME: Fields are in order... // The field we are trying to match will be a composite field of @@ -456,7 +445,7 @@ namespace { return type; } - const Ioss::VariableType *match_single_field(char **names, Ioss::IntVector &which_names, + const Ioss::VariableType *match_single_field(Ioss::NameList &names, Ioss::IntVector &which_names, const char suffix_separator, bool ignore_realn_fields) { @@ -478,9 +467,9 @@ namespace { return type; } - Ioss::Field get_next_field(char **names, int num_names, size_t count, - Ioss::Field::RoleType fld_role, const char suffix_separator, - const int *truth_table, bool ignore_realn_fields) + Ioss::Field get_next_field(Ioss::NameList &names, size_t count, Ioss::Field::RoleType fld_role, + const char suffix_separator, const int *truth_table, + bool ignore_realn_fields) { // NOTE: 'names' are all lowercase at this point. @@ -488,12 +477,12 @@ namespace { // must have an field_suffix_sep in the name separating the suffixes from // the main name. - // Find first unused name (used names have '\0' as first character... - int index = 0; - bool found_valid = false; - for (index = 0; index < num_names; index++) { + // Find first unused name (used names are empty()) + size_t index = 0; + bool found_valid = false; + for (index = 0; index < names.size(); index++) { assert(truth_table == nullptr || truth_table[index] == 1 || truth_table[index] == 0); - if ((truth_table == nullptr || truth_table[index] == 1) && names[index][0] != '\0') { + if ((truth_table == nullptr || truth_table[index] == 1) && !names[index].empty()) { found_valid = true; break; } @@ -507,10 +496,10 @@ namespace { // At this point, name[index] should be a valid potential field // name and all names[i] with i < index are either already used or // not valid for this grouping entity (truth_table entry == 0). - assert(index < num_names && names[index][0] != '\0' && + assert(index < names.size() && !names[index].empty() && (truth_table == nullptr || truth_table[index] == 1)); - char *name = names[index]; - auto name_length = strlen(name); + auto name = names[index]; + auto name_length = name.length(); // Split the name up into tokens separated by the // 'suffix_separator'. Note that the basename itself could @@ -520,8 +509,7 @@ namespace { // (back_stress_xx_01). At the current time, a composite variable // type can only contain two non-composite variable types, so we // only need to look to be concerned with the last 1 or 2 tokens... - std::vector tokens; - field_tokenize(name, suffix_separator, tokens); + auto tokens = field_tokenize(name, suffix_separator); size_t num_tokens = tokens.size(); // Check that tokenizer did not return empty tokens... @@ -531,7 +519,7 @@ namespace { // Return a SCALAR field Ioss::Field field(name, Ioss::Field::REAL, IOSS_SCALAR(), fld_role, count); field.set_index(index); - names[index][0] = '\0'; + names[index] = ""; return field; } @@ -571,13 +559,13 @@ namespace { // It is possible that the first name(s) that match with two // suffices have a basename that match other names with only a // single suffix lc_cam_x, lc_cam_y, lc_sfarea. - for (int id = index + 1; id < num_names; id++) { - char *tst_name = names[id]; - std::vector subtokens; - field_tokenize(tst_name, suffix_separator, subtokens); + for (size_t id = index + 1; id < names.size(); id++) { + auto tst_name = names[id]; + auto subtokens = field_tokenize(tst_name, suffix_separator); if ((truth_table == nullptr || truth_table[id] == 1) && // Defined on this entity - std::strncmp(name, tst_name, bn_len) == 0 && // base portion must match - (!same_length || (strlen(tst_name) == name_length)) && + Ioss::Utils::str_equal(name.substr(0, bn_len), + tst_name.substr(0, bn_len)) && // base portion must match + (!same_length || tst_name.length() == name_length) && subtokens.size() == num_tokens) { which_names.push_back(id); } @@ -605,18 +593,18 @@ namespace { field.set_suffix_separator(suffix_separator); } // Are suffices upper or lowercase... - std::vector tmp; - field_tokenize(names[which_names[0]], suffix_separator, tmp); + auto tmp = field_tokenize(names[which_names[0]], suffix_separator); // If a composite variable, then need to check the interior suffix, not the last (which // will be 1,2,...) bool is_composite = dynamic_cast( field.transformed_storage()) != nullptr; + Ioss::Suffix suffix{tmp[tmp.size() - (is_composite ? 2 : 1)]}; field.set_suffices_uppercase(suffix.is_uppercase()); field.set_index(index); for (const auto &which_name : which_names) { - names[which_name][0] = '\0'; + names[which_name] = ""; } return field; } @@ -626,12 +614,11 @@ namespace { Ioss::Field field(name, Ioss::Field::REAL, IOSS_SCALAR(), fld_role, count); // Are suffices upper or lowercase... - std::vector tmp; - field_tokenize(names[which_names[0]], suffix_separator, tmp); + auto tmp = field_tokenize(names[which_names[0]], suffix_separator); Ioss::Suffix suffix{tmp[tmp.size() - 1]}; field.set_suffices_uppercase(suffix.is_uppercase()); field.set_index(index); - names[index][0] = '\0'; + names[index] = ""; return field; } } @@ -641,7 +628,7 @@ namespace { } // common - bool define_field(size_t nmatch, size_t match_length, char **names, + bool define_field(size_t nmatch, size_t match_length, Ioss::NameList &names, size_t index, std::vector &suffices, size_t entity_count, Ioss::Field::RoleType fld_role, std::vector &fields, bool strip_trailing_, bool ignore_realn_fields, char suffix_separator) @@ -655,12 +642,11 @@ namespace { nmatch = 1; } else { - char *name = names[0]; - name[match_length] = '\0'; - auto suffix = suffix_separator; - if (strip_trailing_ && name[match_length - 1] == '_') { - name[match_length - 1] = '\0'; - suffix = '_'; + auto name = names[index].substr(0, match_length); + auto suffix = suffix_separator; + if (strip_trailing_ && name.back() == '_') { + name = name.substr(0, name.length() - 1); + suffix = '_'; } Ioss::Field field(name, Ioss::Field::REAL, type, fld_role, entity_count); if (suffix != suffix_separator) { @@ -672,7 +658,7 @@ namespace { fields.push_back(field); } for (size_t j = 0; j < nmatch; j++) { - names[j][0] = '\0'; + names[index + j] = ""; } return true; } @@ -681,11 +667,11 @@ namespace { // NOTE: nmatch could be reset inside previous if block. // This is not an 'else' block, it is a new if block. if (nmatch == 1) { - Ioss::Field field(names[0], Ioss::Field::REAL, IOSS_SCALAR(), fld_role, entity_count); + Ioss::Field field(names[index], Ioss::Field::REAL, IOSS_SCALAR(), fld_role, entity_count); if (field.is_valid()) { fields.push_back(field); } - names[0][0] = '\0'; + names[index] = ""; return false; } return false; // Can't get here... Quiet the compiler @@ -694,9 +680,8 @@ namespace { // Read scalar fields off an input database and determine whether // they are components of a higher order type (vector, tensor, ...). -void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in this entity. - char **names, // Raw list of field names from exodus - int num_names, // Number of names in list +void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in this entity. + Ioss::NameList &names, // Raw list of field names from exodus Ioss::Field::RoleType fld_role, // Role of field const Ioss::DatabaseIO *db, int *local_truth, // Truth table for this entity; @@ -710,19 +695,19 @@ void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in t if (!enable_field_recognition) { // Create a separate field for each name. - for (int i = 0; i < num_names; i++) { - if (local_truth == nullptr || local_truth[i] == 1) { + for (size_t i = 0; i < names.size(); i++) { + if (!names[i].empty() && (local_truth == nullptr || local_truth[i] == 1)) { Ioss::Field field(names[i], Ioss::Field::REAL, IOSS_SCALAR(), fld_role, entity_count); field.set_index(i); fields.push_back(field); - names[i][0] = '\0'; + names[i] = ""; } } } else if (suffix_separator != 0) { while (true) { // NOTE: 'get_next_field' determines storage type (vector, tensor,...) - Ioss::Field field = get_next_field(names, num_names, entity_count, fld_role, suffix_separator, + Ioss::Field field = get_next_field(names, entity_count, fld_role, suffix_separator, local_truth, ignore_realn_fields); if (field.is_valid()) { fields.push_back(field); @@ -735,19 +720,22 @@ void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in t else { // This routine is used if there is no field component separator. E.g., // fieldx, fieldy, fieldz instead of field_x field_y field_z - int nmatch = 1; - int ibeg = 0; - int pmat = 0; + size_t nmatch = 1; + size_t ibeg = 0; + size_t pmat = 0; std::vector suffices; top: - while (ibeg + nmatch < num_names) { + while (ibeg + nmatch < names.size()) { if (local_truth != nullptr) { - while (ibeg < num_names && local_truth[ibeg] == 0) { + while (ibeg < names.size() && local_truth[ibeg] == 0) { ibeg++; } } - for (int i = ibeg + 1; i < num_names; i++) { + while (ibeg < names.size() && names[ibeg].empty()) { + ibeg++; + } + for (size_t i = ibeg + 1; i < names.size(); i++) { auto mat = match(names[ibeg], names[i]); if (local_truth != nullptr && local_truth[i] == 0) { mat = 0; @@ -763,8 +751,7 @@ void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in t // should match only 3 characters of the basename (sig), but // sigxx and sigxy will match 4 characters) so consider a // valid match if the match length is >= previous match length. - if ((std::strlen(names[ibeg]) == std::strlen(names[i])) && mat > 0 && - (pmat == 0 || mat >= pmat)) { + if ((names[ibeg].length() == names[i].length()) && mat > 0 && (pmat == 0 || mat >= pmat)) { nmatch++; if (nmatch == 2) { // Get suffix for first field in the match @@ -779,7 +766,7 @@ void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in t else { bool multi_component = - define_field(nmatch, pmat, &names[ibeg], suffices, entity_count, fld_role, fields, + define_field(nmatch, pmat, names, ibeg, suffices, entity_count, fld_role, fields, strip_trailing_, ignore_realn_fields, suffix_separator); if (!multi_component) { // Although we matched multiple suffices, it wasn't a @@ -803,10 +790,10 @@ void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in t // have forms a multi-component field; if not, then define a // scalar field and jump up to the loop again to handle the others // that had been gathered. - if (ibeg < num_names) { + if (ibeg < names.size()) { if (local_truth == nullptr || local_truth[ibeg] == 1) { bool multi_component = - define_field(nmatch, pmat, &names[ibeg], suffices, entity_count, fld_role, fields, + define_field(nmatch, pmat, names, ibeg, suffices, entity_count, fld_role, fields, strip_trailing_, ignore_realn_fields, suffix_separator); clear(suffices); if (nmatch > 1 && !multi_component) { @@ -1037,7 +1024,7 @@ double Ioss::Utils::timer() return std::chrono::duration(now - initial_time).count(); } -void Ioss::Utils::input_file(const std::string &file_name, std::vector *lines, +void Ioss::Utils::input_file(const std::string &file_name, Ioss::NameList *lines, size_t max_line_length) { // Create an ifstream for the input file. This does almost the same @@ -1357,7 +1344,7 @@ std::string Ioss::Utils::get_type_from_file(const std::string &filename) } void Ioss::Utils::info_fields(const Ioss::GroupingEntity *ige, Ioss::Field::RoleType role, - const std::string &header, const std::string &suffix) + const std::string &header, const std::string &suffix, bool detail) { Ioss::NameList fields = ige->field_describe(role); @@ -1380,13 +1367,19 @@ void Ioss::Utils::info_fields(const Ioss::GroupingEntity *ige, Ioss::Field::Role cur_out = header.size() + suffix.size() + 16; // Assume 2 tabs... } for (const auto &field_name : fields) { - const Ioss::VariableType *var_type = ige->get_field(field_name).raw_storage(); - int comp_count = var_type->component_count(); - fmt::print("{1:>{0}s}:{2} ", max_width, field_name, comp_count); - cur_out += max_width + 4; - if (cur_out + max_width >= width) { - fmt::print(suffix); - cur_out = 8; + if (detail) { + const auto &field_ref = ige->get_fieldref(field_name); + fmt::print("{}{}", field_ref, suffix); + } + else { + const Ioss::VariableType *var_type = ige->get_field(field_name).raw_storage(); + int comp_count = var_type->component_count(); + fmt::print("{1:>{0}s}:{2} ", max_width, field_name, comp_count); + cur_out += max_width + 4; + if (cur_out + max_width >= width) { + fmt::print(suffix); + cur_out = 8; + } } } if (!header.empty()) { diff --git a/packages/seacas/libraries/ioss/src/Ioss_Utils.h b/packages/seacas/libraries/ioss/src/Ioss_Utils.h index e0479488ec..cb623ce1c1 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Utils.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Utils.h @@ -309,9 +309,6 @@ namespace Ioss { IOSS_NODISCARD static int log_power_2(uint64_t value); - IOSS_NODISCARD static char **get_name_array(size_t count, int size); - static void delete_name_array(char **names, int count); - /** \brief Get formatted time and date strings. * * Fill time_string and date_string with current time and date @@ -476,7 +473,7 @@ namespace Ioss { const std::string &type, const std::string &working_directory); - static void get_fields(int64_t entity_count, char **names, int num_names, + static void get_fields(int64_t entity_count, Ioss::NameList &names, Ioss::Field::RoleType fld_role, const DatabaseIO *db, int *local_truth, std::vector &fields); @@ -519,7 +516,7 @@ namespace Ioss { * \param[out] lines The vector of strings containing the lines of the file * \param[in] max_line_length The maximum number of characters in any line of the file. */ - static void input_file(const std::string &file_name, std::vector *lines, + static void input_file(const std::string &file_name, Ioss::NameList *lines, size_t max_line_length = 0); template IOSS_NODISCARD static std::string to_string(const T &t) @@ -565,14 +562,14 @@ namespace Ioss { static void generate_history_mesh(Ioss::Region *region); static void info_fields(const Ioss::GroupingEntity *ige, Ioss::Field::RoleType role, - const std::string &header, const std::string &suffix = "\n\t"); + const std::string &header, const std::string &suffix = "\n\t", + bool detail = false); static void info_property(const Ioss::GroupingEntity *ige, Ioss::Property::Origin origin, const std::string &header, const std::string &suffix = "\n\t", bool print_empty = false); - static void insert_sort_and_unique(const std::vector &src, - std::vector &dest) + static void insert_sort_and_unique(const Ioss::NameList &src, Ioss::NameList &dest) { dest.insert(dest.end(), src.begin(), src.end()); std::sort(dest.begin(), dest.end(), std::less<>()); diff --git a/packages/seacas/libraries/ioss/src/Ioss_VariableType.C b/packages/seacas/libraries/ioss/src/Ioss_VariableType.C index 8ff109ba0b..c14a7cfa15 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_VariableType.C +++ b/packages/seacas/libraries/ioss/src/Ioss_VariableType.C @@ -1,12 +1,15 @@ -// Copyright(C) 1999-2023 National Technology & Engineering Solutions +// Copyright(C) 1999-2024 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 "Ioss_BasisVariableType.h" +#include "Ioss_ComposedVariableType.h" #include "Ioss_CompositeVariableType.h" #include "Ioss_ConstructedVariableType.h" #include "Ioss_NamedSuffixVariableType.h" +#include "Ioss_QuadratureVariableType.h" #include "Ioss_Utils.h" #include "Ioss_VariableType.h" #include @@ -43,19 +46,62 @@ namespace Ioss { { std::string low_type = Utils::lowercase(type); registry().insert(VTM_ValuePair(low_type, this), delete_me); + } + + VariableType::Type VariableType::type() const { return Type::UNKNOWN; } + std::string VariableType::type_string() const { return "Unknown"; } + std::string CompositeVariableType::type_string() const + { + return fmt::format("Composite: {}*{}", baseType->type_string(), copies_); + } + std::string ComposedVariableType::type_string() const + { + return fmt::format("Composed: {}*{}", baseType->type_string(), secondaryType->type_string()); + } + + void VariableType::print() const + { + fmt::print("\tVariableType '{}' of type '{}' with {} components.\n\n", name(), type_string(), + component_count()); + } + + void BasisVariableType::print() const + { + fmt::print("\tVariableType '{}' of type '{}' with {} components\n\t\tordinal subc: _dim, " + "_ordinal, _dof_ordinal, _num_dof\t xi eta zeta\n", + name(), type_string(), component_count()); + for (int i = 0; i < component_count(); i++) { + auto basis = get_basis_component(i + 1); + fmt::print("\t\t {:6}\t\t{:6}\t{:6}\t{:6}\t{:6}\t\t{:6.3}\t{:6.3}\t{:6.3}\n", i + 1, + basis.subc_dim, basis.subc_ordinal, basis.subc_dof_ordinal, basis.subc_num_dof, + basis.xi, basis.eta, basis.zeta); + } + fmt::print("\n"); + } + + void QuadratureVariableType::print() const + { + fmt::print("\tVariableType '{}' of type '{}' with {} components\n\t\t\t xi eta zeta " + "weight\n", + name(), type_string(), component_count()); + for (int i = 0; i < component_count(); i++) { + auto quad = get_quadrature_component(i + 1); + fmt::print("\t\t{}\t{:6.3}\t{:6.3}\t{:6.3}\t{:6.3}\n", i + 1, quad.xi, quad.eta, quad.zeta, + quad.weight); + } + fmt::print("\n"); + } - // Register uppercase version also - std::string up_type = Utils::uppercase(type); - registry().insert(VTM_ValuePair(up_type, this), false); + void NamedSuffixVariableType::print() const + { + fmt::print("\tVariableType '{}' of type '{}' with {} components\n\t\tSuffices: {}\n\n", name(), + type_string(), component_count(), fmt::join(suffixList, ", ")); } void VariableType::alias(const std::string &base, const std::string &syn) { registry().insert( VTM_ValuePair(Utils::lowercase(syn), const_cast(factory(base))), false); - // Register uppercase version also - std::string up_type = Utils::uppercase(syn); - registry().insert(VTM_ValuePair(up_type, const_cast(factory(base))), false); } Registry &VariableType::registry() @@ -90,6 +136,24 @@ namespace Ioss { return names; } + std::vector VariableType::external_types(Ioss::VariableType::Type type) + { + auto vars = registry().m_deleteThese; + + std::vector user_vars; + if (type == Ioss::VariableType::Type::UNKNOWN) { + user_vars = vars; + } + else { + for (auto *var : vars) { + if (var->type() == type) { + user_vars.push_back(var); + } + } + } + return user_vars; + } + bool VariableType::add_field_type_mapping(const std::string &raw_field, const std::string &raw_type) { @@ -104,8 +168,8 @@ namespace Ioss { return registry().customFieldTypes.insert(std::make_pair(field, type)).second; } - bool VariableType::create_named_suffix_field_type(const std::string &type_name, - const std::vector &suffices) + bool VariableType::create_named_suffix_type(const std::string &type_name, + const Ioss::NameList &suffices) { size_t count = suffices.size(); if (count < 1) { @@ -128,6 +192,40 @@ namespace Ioss { return true; } + bool VariableType::create_basis_type(const std::string &type_name, const Ioss::Basis &basis) + { + // See if the variable already exists... + std::string basis_name = Utils::lowercase(type_name); + if (registry().find(basis_name) != registry().end()) { + return false; + } + + // Create the variable. Note that the 'true' argument means Ioss will delete + // the pointer. + new BasisVariableType(type_name, basis, true); + return true; + } + + bool VariableType::create_quadrature_type(const std::string &type_name, + const std::vector &quad_points) + { + size_t count = quad_points.size(); + if (count < 1) { + return false; + } + + // See if the variable already exists... + std::string quad_name = Utils::lowercase(type_name); + if (registry().find(quad_name) != registry().end()) { + return false; + } + + // Create the variable. Note that the 'true' argument means Ioss will delete + // the pointer. + auto *var_type = new QuadratureVariableType(type_name, quad_points, true); + return (var_type != nullptr); + } + bool VariableType::get_field_type_mapping(const std::string &field, std::string *type) { // Returns true if a mapping exists, 'type' contains the mapped type. @@ -171,6 +269,39 @@ namespace Ioss { return inst; } + const VariableType *VariableType::factory(const std::string &raw_name, + const std::string &secondary) + { + VariableType *inst = nullptr; + std::string lc_name = Utils::lowercase(raw_name); + auto iter = registry().find(lc_name); + if (iter == registry().end()) { + bool can_construct = build_variable_type(lc_name); + if (can_construct) { + iter = registry().find(lc_name); + assert(iter != registry().end()); + inst = (*iter).second; + } + else { + std::ostringstream errmsg; + fmt::print(errmsg, "ERROR: The variable type '{}' is not supported.\n", raw_name); + IOSS_ERROR(errmsg); + } + } + else { + inst = (*iter).second; + } + + if (!secondary.empty()) { + auto *sec_type = factory(secondary); + if (sec_type != nullptr) { + inst = ComposedVariableType::composed_variable_type(inst, sec_type); + } + } + assert(inst != nullptr); + return inst; + } + const VariableType *VariableType::factory(const std::vector &suffices, bool ignore_realn_fields) { @@ -238,14 +369,14 @@ namespace Ioss { return result; } - std::string VariableType::label_name(const std::string &base, int which, const char suffix_sep, - bool suffices_uppercase) const + std::string VariableType::label_name(const std::string &base, int which, const char suffix_sep1, + const char suffix_sep2, bool suffices_uppercase) const { std::string my_name = base; - std::string suffix = label(which, suffix_sep); + std::string suffix = label(which, suffix_sep2); if (!suffix.empty()) { - if (suffix_sep != 0) { - my_name += suffix_sep; + if (suffix_sep1 != 0) { + my_name += suffix_sep1; } if (suffices_uppercase) { my_name += Ioss::Utils::uppercase(suffix); diff --git a/packages/seacas/libraries/ioss/src/Ioss_VariableType.h b/packages/seacas/libraries/ioss/src/Ioss_VariableType.h index 4d7efaf43e..c34670f23b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_VariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_VariableType.h @@ -17,6 +17,8 @@ #include "ioss_export.h" namespace Ioss { + struct Basis; + struct QuadraturePoint; class VariableType; } // namespace Ioss @@ -67,11 +69,42 @@ namespace Ioss { class IOSS_EXPORT VariableType { public: + enum class Type { + UNKNOWN, + SCALAR, + STANDARD, + COMPOSED, + COMPOSITE, + CONSTRUCTED, + ELEMENT, + NAMED_SUFFIX, + BASIS, + QUADRATURE + }; + static void alias(const std::string &base, const std::string &syn); static int describe(NameList *names); IOSS_NODISCARD static NameList describe(); - static bool create_named_suffix_field_type(const std::string &type_name, - const std::vector &suffices); + + // Return a list of types that have been defined + // externally... Basically a subset of the types in the + // `Registry::m_deleteThese` list... + IOSS_NODISCARD static std::vector + external_types(Ioss::VariableType::Type type); + + static bool create_named_suffix_type(const std::string &type_name, + const Ioss::NameList &suffices); + + // Backward compatibility... + __attribute__((__deprecated__)) static bool + create_named_suffix_field_type(const std::string &type_name, const Ioss::NameList &suffices) + { + return create_named_suffix_type(type_name, suffices); + } + + static bool create_basis_type(const std::string &type_name, const Ioss::Basis &basis); + static bool create_quadrature_type(const std::string &type_name, + const std::vector &quad_points); static bool get_field_type_mapping(const std::string &field, std::string *type); static bool add_field_type_mapping(const std::string &raw_field, const std::string &raw_type); @@ -79,28 +112,35 @@ namespace Ioss { VariableType &operator=(const VariableType &) = delete; virtual ~VariableType() = default; + virtual void print() const; + IOSS_NODISCARD int component_count() const; // Override this function if the derived class has no suffices // For example, a 'vector_2d' has suffices "x" and "y" // A 'quad4' has no suffices... IOSS_NODISCARD virtual int suffix_count() const; - IOSS_NODISCARD std::string name() const; + IOSS_NODISCARD std::string name() const; + IOSS_NODISCARD virtual Type type() const = 0; + IOSS_NODISCARD virtual std::string type_string() const = 0; IOSS_NODISCARD static std::string numeric_label(int which, int ncomp, const std::string &name); IOSS_NODISCARD virtual std::string label(int which, char suffix_sep = '_') const = 0; IOSS_NODISCARD virtual std::string label_name(const std::string &base, int which, - char suffix_sep = '_', + char suffix_sep1 = '_', char suffix_sep2 = '_', bool suffices_uppercase = false) const; IOSS_NODISCARD virtual bool match(const std::vector &suffices) const; IOSS_NODISCARD static const VariableType *factory(const std::string &raw_name, int copies = 1); + IOSS_NODISCARD static const VariableType *factory(const std::string &raw_name, + const std::string &secondary); IOSS_NODISCARD static const VariableType *factory(const std::vector &suffices, bool ignore_realn_fields = false); + static Registry ®istry(); + protected: VariableType(const std::string &type, int comp_count, bool delete_me = false); - static Registry ®istry(); private: const std::string name_; diff --git a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_CatalystManager.C b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_CatalystManager.C index 18eb533f41..991c8b28fa 100644 --- a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_CatalystManager.C +++ b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_CatalystManager.C @@ -295,8 +295,8 @@ namespace Iocatalyst { void CatalystManager::broadCastString(IOSS_MAYBE_UNUSED std::string &s, IOSS_MAYBE_UNUSED const Ioss::ParallelUtils &putils) { - IOSS_MAYBE_UNUSED(s); - IOSS_MAYBE_UNUSED(putils); + IOSS_PAR_UNUSED(s); + IOSS_PAR_UNUSED(putils); #ifdef SEACAS_HAVE_MPI int size = s.size(); putils.broadcast(size); @@ -310,8 +310,8 @@ namespace Iocatalyst { void CatalystManager::broadCastStatusCode(IOSS_MAYBE_UNUSED bool &statusCode, IOSS_MAYBE_UNUSED const Ioss::ParallelUtils &putils) { - IOSS_MAYBE_UNUSED(statusCode); - IOSS_MAYBE_UNUSED(putils); + IOSS_PAR_UNUSED(statusCode); + IOSS_PAR_UNUSED(putils); #ifdef SEACAS_HAVE_MPI int code = statusCode; diff --git a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C index 69224c565a..d682ff764e 100644 --- a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_DatabaseIO.C @@ -7,8 +7,8 @@ #include #include -#include "Ioss_CommSet.h" // for CommSet #include "Ioss_CodeTypes.h" // for IOSS_SCALAR() +#include "Ioss_CommSet.h" // for CommSet #include "Ioss_DBUsage.h" // for DatabaseUsage, etc #include "Ioss_DatabaseIO.h" // for DatabaseIO #include "Ioss_EdgeBlock.h" // for EdgeBlock @@ -142,7 +142,7 @@ namespace Iocatalyst { inline static const std::string RANGEEND = "m_rangeEnd"; inline static const std::string FACE = "m_face"; - inline static const std::string SURFACESPLITTYPE = "surface_split_type"; + inline static const std::string SURFACESPLITTYPE = "surface_split_type"; std::string getValuePath(const std::string &prop) { @@ -308,9 +308,10 @@ namespace Iocatalyst { bool defineModel(Ioss::Region *region) { - if(!region->model_defined()) { + if (!region->model_defined()) { std::ostringstream errmsg; - errmsg << "Catalyst Write in defineModel(): model isn't defined in region"<<"\n"; + errmsg << "Catalyst Write in defineModel(): model isn't defined in region" + << "\n"; IOSS_ERROR(errmsg); } @@ -818,22 +819,17 @@ namespace Iocatalyst { template bool readFields(const conduit_cpp::Node &&parent, GroupingEntityT *block) const { - //Assumption: count = entity_count (in block) - Ioss::DatabaseIO *dbase = block->get_database(); - Ioss::EntityType b_t = block->type(); - bool is_entity_block = false; - if(b_t == Ioss::EntityType::ELEMENTBLOCK || - b_t == Ioss::EntityType::EDGEBLOCK || - b_t == Ioss::EntityType::FACEBLOCK || - b_t == Ioss::EntityType::NODEBLOCK || - b_t == Ioss::EntityType::SIDEBLOCK || - b_t == Ioss::EntityType::STRUCTUREDBLOCK) { - is_entity_block = true; + // Assumption: count = entity_count (in block) + Ioss::DatabaseIO *dbase = block->get_database(); + Ioss::EntityType b_t = block->type(); + bool is_entity_block = false; + if (b_t == Ioss::EntityType::ELEMENTBLOCK || b_t == Ioss::EntityType::EDGEBLOCK || + b_t == Ioss::EntityType::FACEBLOCK || b_t == Ioss::EntityType::NODEBLOCK || + b_t == Ioss::EntityType::SIDEBLOCK || b_t == Ioss::EntityType::STRUCTUREDBLOCK) { + is_entity_block = true; } - const int FNAME_MAX_LENGTH = 255; - size_t field_count = 0; - char **field_names = - Ioss::Utils::get_name_array(parent.number_of_children(), FNAME_MAX_LENGTH); + Ioss::NameList field_names; + field_names.reserve(parent.number_of_children()); size_t entity_count = 0; for (conduit_index_t idx = 0, max = parent.number_of_children(); idx < max; ++idx) { @@ -845,17 +841,15 @@ namespace Iocatalyst { const auto index = child[detail::INDEX].as_int64(); const auto storage = child[detail::STORAGE].as_string(); if (!block->field_exists(name)) { - if(storage == IOSS_SCALAR() && role==Ioss::Field::TRANSIENT && is_entity_block) { - //Add to get_fields() call - char field_name[FNAME_MAX_LENGTH + 1]; - Ioss::Utils::copy_string(field_name, name, FNAME_MAX_LENGTH + 1); - Ioss::Utils::copy_string(field_names[field_count++], field_name, FNAME_MAX_LENGTH + 1); - if(entity_count == 0) + if (storage == IOSS_SCALAR() && role == Ioss::Field::TRANSIENT && is_entity_block) { + // Add to get_fields() call + field_names.push_back(name); + if (entity_count == 0) entity_count = count; } else { block->field_add( - Ioss::Field(name, type, storage, role, count, index).set_zero_copy_enabled()); + Ioss::Field(name, type, storage, role, count, index).set_zero_copy_enabled()); } } else { @@ -864,22 +858,23 @@ namespace Iocatalyst { if (!field_block.has_transform()) { block->get_fieldref(name).set_zero_copy_enabled(); } - auto field_conduit = Ioss::Field(name, type, storage, role, count, index).set_zero_copy_enabled(); - if(field_block != field_conduit) { + auto field_conduit = + Ioss::Field(name, type, storage, role, count, index).set_zero_copy_enabled(); + if (field_block != field_conduit) { std::ostringstream errmsg; - errmsg << "Catalyst Read: Field '"<name().c_str()<< - "' of type '"<type_string()<<"' and differs from it\n"; + errmsg << "Catalyst Read: Field '" << name << "' from conduit " + << "already exists in block '" << block->name().c_str() << "' of type '" + << block->type_string() << "' and differs from it\n"; IOSS_ERROR(errmsg); } } } - - //Apply Exodus Properties to Scalar Fields in Entity Blocks - if(field_count > 0) { + + // Apply Exodus Properties to Scalar Fields in Entity Blocks + if (!field_names.empty()) { std::vector fields; - Ioss::Utils::get_fields(entity_count, field_names, field_count, Ioss::Field::TRANSIENT, - dbase, nullptr, fields); + Ioss::Utils::get_fields(entity_count, field_names, Ioss::Field::TRANSIENT, dbase, nullptr, + fields); for (const auto &field : fields) { block->field_add(field.set_zero_copy_enabled()); } @@ -1091,10 +1086,10 @@ namespace Iocatalyst { auto &node = this->DBNode; region->get_database()->set_int_byte_size_api( static_cast(node[detail::getAPISizePath()].as_int8())); - const auto write_split_type = - static_cast(node[detail::SURFACESPLITTYPE].as_int8()); - if(write_split_type != region->get_database()->get_surface_split_type()) { - static_cast(region->get_database())->set_split_type_changed(true); + const auto write_split_type = + static_cast(node[detail::SURFACESPLITTYPE].as_int8()); + if (write_split_type != region->get_database()->get_surface_split_type()) { + static_cast(region->get_database())->set_split_type_changed(true); } auto tpath = detail::REGION + detail::FS + detail::TIME; @@ -1107,9 +1102,9 @@ namespace Iocatalyst { this->readEntityGroup(node[detail::EDGEBLOCKS], region); this->readEntityGroup(node[detail::FACEBLOCKS], region); - bool surface_split_changed = - static_cast(region->get_database())->split_type_changed(); - if(!surface_split_changed) { + bool surface_split_changed = + static_cast(region->get_database())->split_type_changed(); + if (!surface_split_changed) { this->readEntityGroup(node[detail::SIDEBLOCKS], region); this->readEntityGroup(node[detail::SIDESETS], region); } @@ -1180,17 +1175,19 @@ namespace Iocatalyst { bool DatabaseIO::end_nl(Ioss::State state) { - if(this->dbState != state) { + if (this->dbState != state) { std::ostringstream errmsg; - errmsg << "Catalyst: dbState != state in end_nl"<<"\n"; + errmsg << "Catalyst: dbState != state in end_nl" + << "\n"; IOSS_ERROR(errmsg); } if (!is_input()) { auto region = this->get_region(); - if(region == nullptr) { + if (region == nullptr) { std::ostringstream errmsg; - errmsg << "Catalyst: region is nullptr in end_nl"<<"\n"; + errmsg << "Catalyst: region is nullptr in end_nl" + << "\n"; IOSS_ERROR(errmsg); } @@ -1252,9 +1249,10 @@ namespace Iocatalyst { void DatabaseIO::read_meta_data_nl() { auto region = this->get_region(); - if(region == nullptr) { + if (region == nullptr) { std::ostringstream errmsg; - errmsg << "Catalyst: region is nullptr in read_meta_data_nl()"<<"\n"; + errmsg << "Catalyst: region is nullptr in read_meta_data_nl()" + << "\n"; IOSS_ERROR(errmsg); } @@ -1265,9 +1263,10 @@ namespace Iocatalyst { void DatabaseIO::get_step_times_nl() { auto region = this->get_region(); - if(region == nullptr) { + if (region == nullptr) { std::ostringstream errmsg; - errmsg << "Catalyst: region is nullptr in get_step_times_nl()"<<"\n"; + errmsg << "Catalyst: region is nullptr in get_step_times_nl()" + << "\n"; IOSS_ERROR(errmsg); } @@ -1500,7 +1499,9 @@ namespace Iocatalyst { int64_t DatabaseIO::get_field_internal(const Ioss::SideBlock *sb, const Ioss::Field &field, void *data, size_t data_size) const { - if(split_type_changed()) { return -1; } + if (split_type_changed()) { + return -1; + } auto &impl = (*this->Impl.get()); return impl.getField(detail::SIDEBLOCKS, sb, field, data, data_size); } @@ -1531,7 +1532,9 @@ namespace Iocatalyst { int64_t DatabaseIO::get_field_internal(const Ioss::SideSet *ss, const Ioss::Field &field, void *data, size_t data_size) const { - if(split_type_changed()) { return -1; } + if (split_type_changed()) { + return -1; + } auto &impl = (*this->Impl.get()); return impl.getField(detail::SIDESETS, ss, field, data, data_size); } @@ -1613,7 +1616,9 @@ namespace Iocatalyst { int64_t DatabaseIO::get_zc_field_internal(const Ioss::SideBlock *sb, const Ioss::Field &field, void **data, size_t *data_size) const { - if(split_type_changed()) { return -1; } + if (split_type_changed()) { + return -1; + } auto &impl = (*this->Impl.get()); return impl.getFieldZeroCopy(detail::SIDEBLOCKS, sb, field, data, data_size); } @@ -1644,7 +1649,9 @@ namespace Iocatalyst { int64_t DatabaseIO::get_zc_field_internal(const Ioss::SideSet *ss, const Ioss::Field &field, void **data, size_t *data_size) const { - if(split_type_changed()) { return -1; } + if (split_type_changed()) { + return -1; + } auto &impl = (*this->Impl.get()); return impl.getFieldZeroCopy(detail::SIDESETS, ss, field, data, data_size); } diff --git a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_IOFactory.C b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_IOFactory.C index 1a13b1bc37..9579fe9c94 100644 --- a/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_IOFactory.C +++ b/packages/seacas/libraries/ioss/src/catalyst/Iocatalyst_IOFactory.C @@ -4,9 +4,9 @@ // // See packages/seacas/LICENSE for details -#include "Ioss_DBUsage.h" // for DatabaseUsage -#include "Ioss_IOFactory.h" // for IOFactory -#include // for DatabaseIO +#include "Ioss_DBUsage.h" // for DatabaseUsage +#include "Ioss_IOFactory.h" // for IOFactory +#include #include #include // for nullptr #include // for string diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C index 52e8bca91c..e0b17839a3 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C @@ -1058,8 +1058,8 @@ namespace Iocgns { int tot_names = util().gather(num_bc, CGNS_MAX_NAME_LENGTH + 1, bc_names, all_bc_names); if (myProcessor == 0) { - int off_name = 0; - std::vector bc; + int off_name = 0; + Ioss::NameList bc; for (int ibc = 0; ibc < tot_names; ibc++) { bc.emplace_back(&all_bc_names[off_name]); off_name += CGNS_MAX_NAME_LENGTH + 1; @@ -1079,8 +1079,8 @@ namespace Iocgns { bc_names.resize(tot_names * (CGNS_MAX_NAME_LENGTH + 1)); util().broadcast(bc_names); - std::vector bc; - int off_name = 0; + Ioss::NameList bc; + int off_name = 0; for (int ibc = 0; ibc < tot_names; ibc++) { bc.emplace_back(&bc_names[off_name]); off_name += CGNS_MAX_NAME_LENGTH + 1; @@ -1631,7 +1631,7 @@ namespace Iocgns { m_zoneOffset.resize(num_zones + 1); // use 1-based zones... elementCount = - Utils::common_write_meta_data(get_file_pointer(), *get_region(), m_zoneOffset, false); + Utils::common_write_metadata(get_file_pointer(), *get_region(), m_zoneOffset, false); } void DatabaseIO::get_step_times_nl() diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_IOFactory.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_IOFactory.C index 26c87a87ff..1c445a6f45 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_IOFactory.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_IOFactory.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023, 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. // diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C index 16f4bdd027..3ba956c993 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C @@ -797,7 +797,7 @@ namespace Iocgns { m_zoneOffset.resize(num_zones + 1); // use 1-based zones... elementCount = - Utils::common_write_meta_data(get_file_pointer(), *get_region(), m_zoneOffset, true); + Utils::common_write_metadata(get_file_pointer(), *get_region(), m_zoneOffset, true); } void ParallelDatabaseIO::get_step_times_nl() diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C index af70a4ba3f..f4fa782a21 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C @@ -448,6 +448,7 @@ namespace { fmt::print("\t+{2:-^{0}}+{2:-^{1}}+\n", max_name, max_face, ""); } #endif + } // namespace std::pair Iocgns::Utils::decompose_name(const std::string &name, bool is_parallel) @@ -893,7 +894,7 @@ namespace { // Now clean out existing ZGC lists for all blocks and add on the consolidated instances. // Also create a vector for mapping from zone to sb name. - std::vector sb_names(structured_blocks.size() + 1); + Ioss::NameList sb_names(structured_blocks.size() + 1); for (auto &sb : structured_blocks) { sb->m_zoneConnectivity.clear(); auto zone = sb->get_property("zone").get_int(); @@ -1066,8 +1067,8 @@ void Iocgns::Utils::write_state_meta_data(int file_ptr, const Ioss::Region ®i } } -size_t Iocgns::Utils::common_write_meta_data(int file_ptr, const Ioss::Region ®ion, - std::vector &zone_offset, bool is_parallel_io) +size_t Iocgns::Utils::common_write_metadata(int file_ptr, const Ioss::Region ®ion, + std::vector &zone_offset, bool is_parallel_io) { #if !IOSS_ENABLE_HYBRID // Make sure mesh is not hybrid... @@ -1081,7 +1082,7 @@ size_t Iocgns::Utils::common_write_meta_data(int file_ptr, const Ioss::Region &r } #endif - region.get_database()->progress("\tEnter common_write_meta_data"); + region.get_database()->progress("\tEnter common_write_metadata"); int base = 0; int phys_dimension = region.get_property("spatial_dimension").get_int(); CGERR(cg_base_write(file_ptr, "Base", phys_dimension, phys_dimension, &base)); @@ -1433,7 +1434,7 @@ size_t Iocgns::Utils::common_write_meta_data(int file_ptr, const Ioss::Region &r } } - region.get_database()->progress("\tReturn from common_write_meta_data"); + region.get_database()->progress("\tReturn from common_write_metadata"); return element_count; } @@ -2302,19 +2303,20 @@ void Iocgns::Utils::add_transient_variables(int cgns_file_ptr, const std::vector int field_count = 0; CGCHECK(cg_nfields(cgns_file_ptr, b, z, sol, &field_count)); - char **field_names = Ioss::Utils::get_name_array(field_count, CGNS_MAX_NAME_LENGTH); + Ioss::NameList field_names; + field_names.reserve(field_count); for (int field = 1; field <= field_count; field++) { CGNS_ENUMT(DataType_t) data_type; char field_name[CGNS_MAX_NAME_LENGTH + 1]; CGCHECK(cg_field_info(cgns_file_ptr, b, z, sol, field, &data_type, field_name)); - Ioss::Utils::copy_string(field_names[field - 1], field_name, CGNS_MAX_NAME_LENGTH + 1); + field_names.emplace_back(field_name); } // Convert raw field names into composite fields (a_x, a_y, a_z ==> 3D vector 'a') std::vector fields; if (grid_loc == CGNS_ENUMV(CellCenter)) { size_t entity_count = block->entity_count(); - Ioss::Utils::get_fields(entity_count, field_names, field_count, Ioss::Field::TRANSIENT, + Ioss::Utils::get_fields(entity_count, field_names, Ioss::Field::TRANSIENT, region->get_database(), nullptr, fields); size_t index = 1; for (const auto &field : fields) { @@ -2338,7 +2340,7 @@ void Iocgns::Utils::add_transient_variables(int cgns_file_ptr, const std::vector IOSS_ERROR(errmsg); } size_t entity_count = nb->entity_count(); - Ioss::Utils::get_fields(entity_count, field_names, field_count, Ioss::Field::TRANSIENT, + Ioss::Utils::get_fields(entity_count, field_names, Ioss::Field::TRANSIENT, region->get_database(), nullptr, fields); size_t index = 1; for (const auto &field : fields) { @@ -2347,8 +2349,6 @@ void Iocgns::Utils::add_transient_variables(int cgns_file_ptr, const std::vector nb->field_add(field); } } - - Ioss::Utils::delete_name_array(field_names, field_count); } }; // ========================================== @@ -2420,7 +2420,7 @@ void Iocgns::Utils::set_line_decomposition(int cgns_file_ptr, const std::string int num_families = 0; CGCHECKNP(cg_nfamilies(cgns_file_ptr, base, &num_families)); - std::vector families; + Ioss::NameList families; families.reserve(num_families); for (int family = 1; family <= num_families; family++) { char name[CGNS_MAX_NAME_LENGTH + 1]; diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h index 15c6f727e7..874f0dd79f 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h @@ -300,7 +300,7 @@ namespace Iocgns { static void write_state_meta_data(int file_ptr, const Ioss::Region ®ion, bool is_parallel_io); - static size_t common_write_meta_data(int file_ptr, const Ioss::Region ®ion, + static size_t common_write_metadata(int file_ptr, const Ioss::Region ®ion, std::vector &zone_offset, bool is_parallel); static size_t resolve_nodes(Ioss::Region ®ion, int my_processor, bool is_parallel); IOSS_NODISCARD static std::vector>> diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C index 6e0cbdc8a6..5e73880d35 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C @@ -20,8 +20,11 @@ #include "Ioex_Utils.h" #include "Ioss_Assembly.h" +#include "Ioss_BasisVariableType.h" #include "Ioss_Blob.h" #include "Ioss_CodeTypes.h" +#include "Ioss_ComposedVariableType.h" +#include "Ioss_CompositeVariableType.h" #include "Ioss_DBUsage.h" #include "Ioss_DatabaseIO.h" #include "Ioss_EdgeBlock.h" @@ -30,6 +33,7 @@ #include "Ioss_ElementSet.h" #include "Ioss_EntityBlock.h" #include "Ioss_EntityType.h" +#include "Ioss_Enumerate.h" #include "Ioss_FaceBlock.h" #include "Ioss_FaceSet.h" #include "Ioss_Field.h" @@ -38,11 +42,13 @@ #include "Ioss_IOFactory.h" #include "Ioss_Map.h" #include "Ioss_MeshType.h" +#include "Ioss_NamedSuffixVariableType.h" #include "Ioss_NodeBlock.h" #include "Ioss_NodeSet.h" #include "Ioss_ParallelUtils.h" #include "Ioss_Property.h" #include "Ioss_PropertyManager.h" +#include "Ioss_QuadratureVariableType.h" #include "Ioss_Region.h" #include "Ioss_SerializeIO.h" #include "Ioss_SideBlock.h" @@ -93,7 +99,7 @@ namespace { { } - void update_list_from_assembly_tree(size_t assemblyIndex, std::vector &list) + void update_list_from_assembly_tree(size_t assemblyIndex, Ioss::NameList &list) { // Walk the tree without cyclic dependency if (assemblyIndex < m_assemblies.size()) { @@ -136,7 +142,7 @@ namespace { } } - void update_assembly_filter_list(std::vector &assemblyFilterList) + void update_assembly_filter_list(Ioss::NameList &assemblyFilterList) { for (size_t i = 0; i < m_assemblies.size(); ++i) { if (m_visitedAssemblies[i]) { @@ -193,6 +199,7 @@ namespace { delete[] assembly.name; } } + } // namespace namespace Ioex { @@ -604,7 +611,7 @@ namespace Ioex { if (!using_parallel_io() || myProcessor == 0) { // dump info records, include the product_registry // See if the input file was specified as a property on the database... - std::vector input_lines; + Ioss::NameList input_lines; if (get_region()->property_exists("input_file_name")) { std::string filename = get_region()->get_property("input_file_name").get_string(); // Determine size of input file so can embed it in info records... @@ -629,7 +636,7 @@ namespace Ioex { total_lines = in_lines + qa_lines + info_rec_size + config_lines; // 'total_lines' pointers to char buffers - info = Ioss::Utils::get_name_array(total_lines, max_line_length); + info = Ioex::get_name_array(total_lines, max_line_length); int i = 0; Ioss::Utils::copy_string(info[i++], Ioss::Utils::platform_information(), max_line_length + 1); @@ -656,7 +663,7 @@ namespace Ioex { int ierr = 0; if (!using_parallel_io() || myProcessor == 0) { ierr = ex_put_info(get_file_pointer(), total_lines, info); - Ioss::Utils::delete_name_array(info, total_lines); + Ioex::delete_name_array(info, total_lines); } else { // This call only sets the `total_lines` metadata on the other ranks... @@ -692,8 +699,8 @@ namespace Ioex { // Query number of assemblies... auto assemblies = get_exodus_assemblies(get_file_pointer()); if (!assemblies.empty()) { - std::vector exclusions; - std::vector inclusions; + Ioss::NameList exclusions; + Ioss::NameList inclusions; AssemblyTreeFilter inclusionFilter(get_region(), Ioss::ELEMENTBLOCK, assemblies); AssemblyTreeFilter exclusionFilter(get_region(), Ioss::ELEMENTBLOCK, assemblies); @@ -1004,8 +1011,8 @@ namespace Ioex { } // common - void BaseDatabaseIO::compute_block_membership_nl(Ioss::SideBlock *efblock, - std::vector &block_membership) const + void BaseDatabaseIO::compute_block_membership_nl(Ioss::SideBlock *efblock, + Ioss::NameList &block_membership) const { const Ioss::ElementBlockContainer &element_blocks = get_region()->get_element_blocks(); assert(Ioss::Utils::check_block_order(element_blocks)); @@ -1602,6 +1609,7 @@ namespace Ioex { } if (nvar > 0) { + if (truth_table.empty()) { truth_table.resize(block_count * nvar); @@ -1636,55 +1644,177 @@ namespace Ioex { // Get the variable names and add as fields. Need to decode these // into vector/tensor/... eventually, for now store all as // scalars. - char **names = Ioss::Utils::get_name_array(nvar, maximumNameLength); // Read the names... // (Currently, names are read for every block. We could save them...) + Ioss::NameList names; { Ioss::SerializeIO serializeIO_(this); + names = Ioex::get_variable_names(nvar, maximumNameLength, get_file_pointer(), type); + } + + // Add to VariableNameMap so can determine exodusII index given a + // Sierra field name. exodusII index is just 'i+1' + for (int i = 0; i < nvar; i++) { + std::string var = names[i]; + if (lowerCaseVariableNames) { + Ioss::Utils::fixup_name(var); + } + variables.insert(VNMValuePair(var, i + 1)); + } + + int offset = position * nvar; + int *local_truth = nullptr; + if (!truth_table.empty()) { + local_truth = &truth_table[offset]; + } + + // If the file contains field metadata, define fields via that mechanism... + auto fields = get_fields_via_field_metadata(entity, type, names); + + // Now, either get all fields via suffix matching, or if the file did not + // specify all fields in the field metadata, get the rest... + Ioss::Utils::get_fields(entity->entity_count(), names, Ioss::Field::TRANSIENT, this, + local_truth, fields); + + for (auto &field : fields) { + if (lowerCaseVariableNames) { + Ioss::Utils::fixup_name(field.get_name()); + } + entity->field_add(field); + } + + for (auto [i, name] : Ioss::enumerate(names)) { + // Verify that all names were used for a field... + SMART_ASSERT(name.empty() || (local_truth && local_truth[i] == 0))(i)(name); + } + } + return nvar; + } - int ierr = ex_get_variable_names(get_file_pointer(), type, nvar, names); + std::vector + Ioex::BaseDatabaseIO::get_fields_via_field_metadata(Ioss::GroupingEntity *entity, + ex_entity_type type, Ioss::NameList &names) + { + std::vector fields; + if (!entity->get_database()->get_field_recognition()) { + return fields; + } + // See if this entity is using enhanced field attributes... + auto id = entity->get_optional_property("id", 0); + int enhanced_fld_cnt; + { + Ioss::SerializeIO serializeIO_(this); + enhanced_fld_cnt = ex_get_field_metadata_count(get_file_pointer(), type, id); + } + + if (enhanced_fld_cnt > 0) { + std::vector exo_fields(enhanced_fld_cnt); + for (auto &field : exo_fields) { + field.entity_type = type; + field.entity_id = id; + } + + { + Ioss::SerializeIO serializeIO_(this); + int ierr = ex_get_field_metadata(get_file_pointer(), Data(exo_fields)); if (ierr < 0) { Ioex::exodus_error(get_file_pointer(), __LINE__, __func__, __FILE__); } + } - // Add to VariableNameMap so can determine exodusII index given a - // Sierra field name. exodusII index is just 'i+1' - for (int i = 0; i < nvar; i++) { - std::string var = names[i]; - if (lowerCaseVariableNames) { - Ioss::Utils::fixup_name(var); - } - variables.insert(VNMValuePair(var, i + 1)); - } + for (const auto &exo_field : exo_fields) { + std::string ios_field_type{}; - int offset = position * nvar; - int *local_truth = nullptr; - if (!truth_table.empty()) { - local_truth = &truth_table[offset]; + auto type_names = Ioss::tokenize(exo_field.type_name, ",", true); + if (exo_field.type[0] == EX_FIELD_TYPE_SEQUENCE) { + ios_field_type = fmt::format("Real[{}]", exo_field.cardinality[0]); + } + else if (exo_field.type[0] == EX_FIELD_TYPE_USER_DEFINED) { + auto suffices = Ioss::tokenize(exo_field.suffices, ","); + Ioss::VariableType::create_named_suffix_type(exo_field.name, suffices); + ios_field_type = exo_field.name; + } + else if (exo_field.type[0] == EX_BASIS || exo_field.type[0] == EX_QUADRATURE) { + ios_field_type = Ioss::Utils::lowercase(type_names[0]); + } + else { + ios_field_type = Ioex::map_ioss_field_type(exo_field.type[0]); } - std::vector fields; - int64_t count = entity->entity_count(); - Ioss::Utils::get_fields(count, names, nvar, Ioss::Field::TRANSIENT, this, local_truth, - fields); + int num_copies = 1; + std::string secondary_field_type{}; - for (auto &field : fields) { - if (lowerCaseVariableNames) { - Ioss::Utils::fixup_name(field.get_name()); + if (exo_field.nesting == 2) { + // For IOSS, the nesting is basically N copies of the field + // at nesting level 1, so we just need to verify that the + // field type is `EX_FIELD_TYPE_SEQUENCE`, `EX_BASIS`, or + // `EX_QUADRATURE` and then get the cardinality... + if (exo_field.type[1] == EX_FIELD_TYPE_SEQUENCE) { + num_copies = exo_field.cardinality[1]; + } + else if (exo_field.type[1] == EX_BASIS || exo_field.type[1] == EX_QUADRATURE) { + secondary_field_type = Ioss::Utils::lowercase(type_names[1]); + } + else { + fmt::print("ERROR: Unrecognized field type for nested field.\n"); } - entity->field_add(field); + } + if (secondary_field_type.empty()) { + fields.emplace_back(exo_field.name, Ioss::Field::REAL, ios_field_type, num_copies, + Ioss::Field::TRANSIENT, entity->entity_count()); + } + else { + fields.emplace_back(exo_field.name, Ioss::Field::REAL, ios_field_type, + secondary_field_type, Ioss::Field::TRANSIENT, entity->entity_count()); } - for (int i = 0; i < nvar; i++) { - // Verify that all names were used for a field... - assert(names[i][0] == '\0' || (local_truth && local_truth[i] == 0)); - delete[] names[i]; + auto &field = fields.back(); + if (exo_field.nesting == 1) { + field.set_suffix_separator(exo_field.component_separator[0]); + } + else { + field.set_suffix_separator(exo_field.component_separator[0], + exo_field.component_separator[1]); + } + + if (lowerCaseVariableNames) { + field.set_suffices_uppercase(false); + } + + // Now remove the used field+component names from `names` to verify that we found all + // fields on this entity... (Also set suffices_uppercase...) + for (int i = 0; i < field.get_component_count(Ioss::Field::InOut::INPUT); i++) { + auto comp_name = field.get_component_name(i + 1, Ioss::Field::InOut::INPUT); + // Find `comp_name` in `names`... + for (size_t j = 0; j < names.size(); j++) { + if (Ioss::Utils::str_equal(comp_name, names[j])) { + if (!lowerCaseVariableNames && + field.get_component_count(Ioss::Field::InOut::INPUT) > 1 && i == 0) { + // Find the last-most alphabetic character... + auto len = names[j].length(); + for (size_t k = 0; k < len; k++) { + if (isalpha(names[j][len - k - 1])) { + field.set_suffices_uppercase(isupper(names[j][len - k - 1])); + break; + } + } + } + names[j] = ""; + break; + } + } + } + +#if IOSS_DEBUG_OUTPUT + if (myProcessor == 0) { + fmt::print(Ioss::DebugOut(), "Enhanced Field: Adding to {} {}:\n\t{}\n", + entity->type_string(), entity->name(), field); } - delete[] names; +#endif } } - return nvar; + return fields; } // common @@ -1705,45 +1835,36 @@ namespace Ioex { // Get the variable names and add as fields. Need to decode these // into vector/tensor/... eventually, for now store all as // scalars. - char **names = Ioss::Utils::get_name_array(nvar, maximumNameLength); - - // Read the names... - // (Currently, names are read for every block. We could save them...) + Ioss::NameList names; { Ioss::SerializeIO serializeIO_(this); + names = + Ioex::get_reduction_variable_names(nvar, maximumNameLength, get_file_pointer(), type); + } - int ierr = ex_get_reduction_variable_names(get_file_pointer(), type, nvar, names); - if (ierr < 0) { - Ioex::exodus_error(get_file_pointer(), __LINE__, __func__, __FILE__); - } - - // Add to VariableNameMap so can determine exodusII index given a - // Sierra field name. exodusII index is just 'i+1' - auto &variables = m_reductionVariables[type]; - for (int i = 0; i < nvar; i++) { - if (lowerCaseVariableNames) { - Ioss::Utils::fixup_name(names[i]); - } - variables.insert(VNMValuePair(std::string(names[i]), i + 1)); + // Add to VariableNameMap so can determine exodusII index given a + // Sierra field name. exodusII index is just 'i+1' + auto &variables = m_reductionVariables[type]; + for (int i = 0; i < nvar; i++) { + if (lowerCaseVariableNames) { + Ioss::Utils::fixup_name(names[i]); } + variables.insert(VNMValuePair(std::string(names[i]), i + 1)); + } - int *local_truth = nullptr; + int *local_truth = nullptr; - std::vector fields; - int64_t count = 1; - Ioss::Utils::get_fields(count, names, nvar, Ioss::Field::REDUCTION, this, local_truth, - fields); + std::vector fields; + int64_t count = 1; + Ioss::Utils::get_fields(count, names, Ioss::Field::REDUCTION, this, local_truth, fields); - for (const auto &field : fields) { - entity->field_add(field); - } + for (const auto &field : fields) { + entity->field_add(field); + } - for (int i = 0; i < nvar; i++) { - // Verify that all names were used for a field... - assert(names[i][0] == '\0' || (local_truth && local_truth[i] == 0)); - delete[] names[i]; - } - delete[] names; + for (int i = 0; i < nvar; i++) { + // Verify that all names were used for a field... + assert(names[i].empty() || (local_truth && local_truth[i] == 0)); } } return nvar; @@ -1868,9 +1989,232 @@ namespace Ioex { output_results_names(type, m_reductionVariables[type], true); } } + + // Output field metadata + output_field_metadata(); } } + namespace { + void internal_output_field_metadata(int exoid, ex_entity_type type, + Ioss::GroupingEntity *entity) + { + // Get all transient fields on this entity... + char default_separator = entity->get_database()->get_field_separator(); + auto results_fields = entity->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : results_fields) { + const auto &field = entity->get_fieldref(field_name); + + ex_field exo_field{}; + Ioss::Utils::copy_string(exo_field.name, field_name); + exo_field.entity_type = type; + exo_field.entity_id = entity->get_optional_property("id", 0); + + auto *storage = field.transformed_storage(); + auto storage_type = storage->type(); + + if (storage_type == Ioss::VariableType::Type::COMPOSED) { + exo_field.nesting = 2; + + const auto *composed = dynamic_cast(storage); + assert(composed != nullptr); + exo_field.type[0] = Ioex::map_ioss_field_type(composed->get_base_type()); + exo_field.cardinality[0] = composed->get_base_type()->component_count(); + char separator0 = field.get_suffix_separator(); + exo_field.component_separator[0] = separator0 == 1 ? default_separator : separator0; + + if (exo_field.type[0] == EX_FIELD_TYPE_USER_DEFINED) { + assert(composed->get_base_type()->type() == Ioss::VariableType::Type::NAMED_SUFFIX); + auto nsvt = + dynamic_cast(composed->get_base_type()); + assert(nsvt != nullptr); + std::string suffices{}; + for (int i = 0; i < nsvt->component_count(); i++) { + if (i > 0) { + suffices += ","; + } + suffices += nsvt->label(i + 1, 0); + } + Ioss::Utils::copy_string(exo_field.suffices, suffices.c_str(), EX_MAX_NAME + 1); + } + + exo_field.type[1] = Ioex::map_ioss_field_type(composed->get_secondary_type()); + exo_field.cardinality[1] = composed->get_secondary_type()->component_count(); + char separator1 = field.get_suffix_separator(1); + exo_field.component_separator[1] = separator1 == 1 ? default_separator : separator1; + if (exo_field.type[1] == EX_BASIS || exo_field.type[1] == EX_QUADRATURE) { + exo_field.type_name[0] = ','; + Ioss::Utils::copy_string(&exo_field.type_name[1], + composed->get_secondary_type()->name(), EX_MAX_NAME); + } + } + else if (storage_type == Ioss::VariableType::Type::COMPOSITE) { + exo_field.nesting = 2; + + const auto *composite = dynamic_cast(storage); + assert(composite != nullptr); + exo_field.type[0] = Ioex::map_ioss_field_type(composite->get_base_type()); + exo_field.cardinality[0] = composite->get_base_type()->component_count(); + char separator0 = field.get_suffix_separator(); + exo_field.component_separator[0] = separator0 == 1 ? default_separator : separator0; + + exo_field.type[1] = EX_FIELD_TYPE_SEQUENCE; + exo_field.cardinality[1] = composite->get_num_copies(); + char separator1 = field.get_suffix_separator(1); + exo_field.component_separator[1] = separator1 == 1 ? default_separator : separator1; + } + else { + exo_field.nesting = 1; + exo_field.type[0] = Ioex::map_ioss_field_type(storage); + if (exo_field.type[0] == EX_FIELD_TYPE_SEQUENCE) { + exo_field.cardinality[0] = storage->component_count(); + } + if (exo_field.type[0] == EX_BASIS) { + assert(storage->type() == Ioss::VariableType::Type::BASIS); + const auto *basis = dynamic_cast(storage); + assert(basis != nullptr); + exo_field.cardinality[0] = storage->component_count(); + Ioss::Utils::copy_string(exo_field.type_name, basis->name()); + } + if (exo_field.type[0] == EX_QUADRATURE) { + assert(storage->type() == Ioss::VariableType::Type::QUADRATURE); + const auto *quad = dynamic_cast(storage); + assert(quad != nullptr); + exo_field.cardinality[0] = storage->component_count(); + Ioss::Utils::copy_string(exo_field.type_name, quad->name()); + } + if (exo_field.type[0] == EX_FIELD_TYPE_USER_DEFINED) { + assert(storage->type() == Ioss::VariableType::Type::NAMED_SUFFIX); + auto nsvt = dynamic_cast(storage); + assert(nsvt != nullptr); + exo_field.cardinality[0] = nsvt->component_count(); + std::string suffices{}; + for (int i = 0; i < nsvt->component_count(); i++) { + if (i > 0) { + suffices += ","; + } + suffices += nsvt->label(i + 1, 0); + } + Ioss::Utils::copy_string(exo_field.suffices, suffices.c_str(), EX_MAX_NAME + 1); + } + char separator = field.get_suffix_separator(); + exo_field.component_separator[0] = separator == 1 ? default_separator : separator; + } + + if (exo_field.type[0] != EX_SCALAR) { + ex_put_field_metadata(exoid, exo_field); + if (exo_field.type[0] == EX_FIELD_TYPE_USER_DEFINED) { + ex_put_field_suffices(exoid, exo_field, exo_field.suffices); + } + } + } + } + + void output_basis(int exoid, const Ioss::VariableType *var) + { + const auto *basis = dynamic_cast(var); + assert(basis != nullptr); + ex_basis exo_basis{}; + exo_basis.cardinality = basis->component_count(); + ex_initialize_basis_struct(&exo_basis, 1, 1); + Ioss::Utils::copy_string(exo_basis.name, basis->name(), EX_MAX_NAME); + for (int i = 0; i < basis->component_count(); i++) { + auto component = basis->get_basis_component(i + 1); + exo_basis.subc_dim[i] = component.subc_dim; + exo_basis.subc_ordinal[i] = component.subc_ordinal; + exo_basis.subc_dof_ordinal[i] = component.subc_dof_ordinal; + exo_basis.subc_num_dof[i] = component.subc_num_dof; + exo_basis.xi[i] = component.xi; + exo_basis.eta[i] = component.eta; + exo_basis.zeta[i] = component.zeta; + } + ex_put_basis(exoid, exo_basis); + ex_initialize_basis_struct(&exo_basis, 1, -1); + } + + void output_quad(int exoid, const Ioss::VariableType *var) + { + const auto *quadrature = dynamic_cast(var); + assert(quadrature != nullptr); + ex_quadrature exo_quadrature{}; + exo_quadrature.cardinality = quadrature->component_count(); + ex_initialize_quadrature_struct(&exo_quadrature, 1, 1); + Ioss::Utils::copy_string(exo_quadrature.name, quadrature->name(), EX_MAX_NAME); + const auto &quad = quadrature->get_quadrature(); + for (const auto &[i, component] : Ioss::enumerate(quad)) { + exo_quadrature.xi[i] = component.xi; + exo_quadrature.eta[i] = component.eta; + exo_quadrature.zeta[i] = component.zeta; + exo_quadrature.weight[i] = component.weight; + } + ex_put_quadrature(exoid, exo_quadrature); + ex_initialize_quadrature_struct(&exo_quadrature, 1, -1); + } + + void output_type_metadata(int exoid) + { + // Iterate the list and output the `quadrature` and `basis` types... + auto basis_list = Ioss::VariableType::external_types(Ioss::VariableType::Type::BASIS); + for (auto &var : basis_list) { + output_basis(exoid, var); + } + + auto quad_list = Ioss::VariableType::external_types(Ioss::VariableType::Type::QUADRATURE); + for (auto &var : quad_list) { + output_quad(exoid, var); + } + } + + template + void internal_output_field_metadata(int exoid, ex_entity_type type, std::vector entities) + { + for (const auto &entity : entities) { + internal_output_field_metadata(exoid, type, entity); + } + } + } // namespace + + void BaseDatabaseIO::output_field_metadata() + { + Ioss::SerializeIO serializeIO_(this); + // Output the 'basis' and 'quadrature' type metadata... + output_type_metadata(get_file_pointer()); + + const Ioss::NodeBlockContainer &node_blocks = get_region()->get_node_blocks(); + assert(node_blocks.size() <= 1); + internal_output_field_metadata(get_file_pointer(), EX_NODE_BLOCK, node_blocks); + + const Ioss::EdgeBlockContainer &edge_blocks = get_region()->get_edge_blocks(); + internal_output_field_metadata(get_file_pointer(), EX_EDGE_BLOCK, edge_blocks); + + const Ioss::FaceBlockContainer &face_blocks = get_region()->get_face_blocks(); + internal_output_field_metadata(get_file_pointer(), EX_FACE_BLOCK, face_blocks); + + const Ioss::ElementBlockContainer &element_blocks = get_region()->get_element_blocks(); + internal_output_field_metadata(get_file_pointer(), EX_ELEM_BLOCK, element_blocks); + + const Ioss::NodeSetContainer &nodesets = get_region()->get_nodesets(); + internal_output_field_metadata(get_file_pointer(), EX_NODE_SET, nodesets); + + const Ioss::EdgeSetContainer &edgesets = get_region()->get_edgesets(); + internal_output_field_metadata(get_file_pointer(), EX_EDGE_SET, edgesets); + + const Ioss::FaceSetContainer &facesets = get_region()->get_facesets(); + internal_output_field_metadata(get_file_pointer(), EX_FACE_SET, facesets); + + const Ioss::ElementSetContainer &elementsets = get_region()->get_elementsets(); + internal_output_field_metadata(get_file_pointer(), EX_ELEM_SET, elementsets); + + const auto &blobs = get_region()->get_blobs(); + internal_output_field_metadata(get_file_pointer(), EX_BLOB, blobs); + + const auto &assemblies = get_region()->get_assemblies(); + internal_output_field_metadata(get_file_pointer(), EX_ASSEMBLY, assemblies); + + const Ioss::SideSetContainer &sidesets = get_region()->get_sidesets(); + internal_output_field_metadata(get_file_pointer(), EX_SIDE_SET, sidesets); + } + // common template void BaseDatabaseIO::internal_gather_results_metadata(ex_entity_type type, @@ -2044,8 +2388,8 @@ namespace Ioex { if (var_count > 0) { size_t name_length = 0; // Push into a char** array... - std::vector var_names(var_count); - std::vector variable_names(var_count); + std::vector var_names(var_count); + Ioss::NameList variable_names(var_count); for (const auto &variable : variables) { size_t index = variable.second; assert(index > 0 && index <= var_count); @@ -2217,12 +2561,6 @@ namespace Ioex { assert(block != nullptr); if (attribute_count > 0) { - size_t my_element_count = block->entity_count(); - - // Get the attribute names. May not exist or may be blank... - char **names = Ioss::Utils::get_name_array(attribute_count, maximumNameLength); - int64_t id = block->get_property("id").get_int(); - // Some older applications do not want to used named // attributes; in this case, just create a field for each // attribute named "attribute_1", "attribute_2", ..., "attribute_#" @@ -2231,19 +2569,26 @@ namespace Ioex { bool attributes_named = true; // Possibly reset below; note that even if ignoring // attribute names, they are still 'named' + size_t my_element_count = block->entity_count(); + Ioss::NameList names; + names.reserve(attribute_count); if (properties.exists("IGNORE_ATTRIBUTE_NAMES")) { for (int i = 0; i < attribute_count; i++) { - std::string tmp = fmt::format("attribute_{}", i + 1); - Ioss::Utils::copy_string(names[i], tmp, maximumNameLength + 1); + names.emplace_back(fmt::format("attribute_{}", i + 1)); } } else { // Use attribute names if they exist. + + // Get the attribute names. May not exist or may be blank... + char **cnames = Ioex::get_name_array(attribute_count, maximumNameLength); + int64_t id = block->get_property("id").get_int(); + { Ioss::SerializeIO serializeIO_(this); if (block->entity_count() != 0) { ex_entity_type entity_type = Ioex::map_exodus_type(block->type()); - int ierr = ex_get_attr_names(get_file_pointer(), entity_type, id, &names[0]); + int ierr = ex_get_attr_names(get_file_pointer(), entity_type, id, &cnames[0]); if (ierr < 0) { Ioex::exodus_error(get_file_pointer(), __LINE__, __func__, __FILE__); } @@ -2255,30 +2600,37 @@ namespace Ioex { std::vector cname(attribute_count * (maximumNameLength + 1)); if (block->entity_count() != 0) { for (int i = 0; i < attribute_count; i++) { - std::memcpy(&cname[i * (maximumNameLength + 1)], names[i], maximumNameLength + 1); + std::memcpy(&cname[i * (maximumNameLength + 1)], cnames[i], maximumNameLength + 1); } } util().attribute_reduction(attribute_count * (maximumNameLength + 1), Data(cname)); for (int i = 0; i < attribute_count; i++) { - std::memcpy(names[i], &cname[i * (maximumNameLength + 1)], maximumNameLength + 1); + std::memcpy(cnames[i], &cname[i * (maximumNameLength + 1)], maximumNameLength + 1); } } // Convert to lowercase. attributes_named = true; for (int i = 0; i < attribute_count; i++) { - fix_bad_name(names[i]); - Ioss::Utils::fixup_name(names[i]); - if (names[i][0] == '\0' || (!(std::isalnum(names[i][0]) || names[i][0] == '_'))) { + if (cnames[i][0] == '\0' || (!(std::isalnum(cnames[i][0]) || cnames[i][0] == '_'))) { attributes_named = false; } } + if (attributes_named) { + for (int i = 0; i < attribute_count; i++) { + fix_bad_name(cnames[i]); + Ioss::Utils::fixup_name(cnames[i]); + names.emplace_back(cnames[i]); + } + } + // Release memory... + Ioex::delete_name_array(cnames, attribute_count); } if (attributes_named) { std::vector attributes; - Ioss::Utils::get_fields(my_element_count, names, attribute_count, Ioss::Field::ATTRIBUTE, - this, nullptr, attributes); + Ioss::Utils::get_fields(my_element_count, names, Ioss::Field::ATTRIBUTE, this, nullptr, + attributes); int offset = 1; for (const auto &field : attributes) { if (block->field_exists(field.get_name())) { @@ -2423,13 +2775,10 @@ namespace Ioex { block->field_add(Ioss::Field(std::move(att_name), Ioss::Field::REAL, storage, Ioss::Field::ATTRIBUTE, my_element_count, 1)); - - // Release memory... - Ioss::Utils::delete_name_array(names, attribute_count); } } - void BaseDatabaseIO::common_write_meta_data(Ioss::IfDatabaseExistsBehavior behavior) + void BaseDatabaseIO::common_write_metadata(Ioss::IfDatabaseExistsBehavior behavior) { Ioss::Region *region = get_region(); @@ -2663,7 +3012,7 @@ namespace Ioex { } } - void BaseDatabaseIO::output_other_meta_data() + void BaseDatabaseIO::output_other_metadata() { // Write attribute names (if any)... write_attribute_names(get_file_pointer(), EX_NODE_SET, get_region()->get_nodesets()); @@ -2754,7 +3103,7 @@ namespace Ioex { } if (node_map_cnt > 0) { - char **names = Ioss::Utils::get_name_array(node_map_cnt, maximumNameLength); + char **names = Ioex::get_name_array(node_map_cnt, maximumNameLength); auto *node_block = get_region()->get_node_blocks()[0]; // If there are node_maps, then there is a node_block auto node_map_fields = node_block->field_describe(Ioss::Field::MAP); @@ -2772,11 +3121,11 @@ namespace Ioex { } } ex_put_names(get_file_pointer(), EX_NODE_MAP, names); - Ioss::Utils::delete_name_array(names, node_map_cnt); + Ioex::delete_name_array(names, node_map_cnt); } if (elem_map_cnt > 0) { - char **names = Ioss::Utils::get_name_array(elem_map_cnt, maximumNameLength); + char **names = Ioex::get_name_array(elem_map_cnt, maximumNameLength); for (const auto &field_name : elem_map_fields) { // Now, we need to find an element block that has this field... for (const auto &block : blocks) { @@ -2805,7 +3154,7 @@ namespace Ioex { } } ex_put_names(get_file_pointer(), EX_ELEM_MAP, names); - Ioss::Utils::delete_name_array(names, elem_map_cnt); + Ioex::delete_name_array(names, elem_map_cnt); } // Write coordinate frame data... @@ -2828,8 +3177,8 @@ namespace { check_attribute_index_order(ge); - std::vector names(attribute_count); - std::vector names_str(attribute_count); + std::vector names(attribute_count); + Ioss::NameList names_str(attribute_count); // Get the attribute fields... Ioss::NameList results_fields = ge->field_describe(Ioss::Field::ATTRIBUTE); diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h index 217d7536f5..1d05234f8a 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h @@ -125,8 +125,8 @@ namespace Ioex { Ioss::Map &entity_map, void *ids, size_t num_to_get, size_t offset) const; - void compute_block_membership_nl(Ioss::SideBlock *efblock, - std::vector &block_membership) const override; + void compute_block_membership_nl(Ioss::SideBlock *efblock, + Ioss::NameList &block_membership) const override; IOSS_NODISCARD int int_byte_size_db() const override; void set_int_byte_size_api(Ioss::DataSize size) const override; @@ -238,8 +238,9 @@ namespace Ioex { void add_attribute_fields(Ioss::GroupingEntity *block, int attribute_count, const std::string &type); - void common_write_meta_data(Ioss::IfDatabaseExistsBehavior behavior); - void output_other_meta_data(); + void common_write_metadata(Ioss::IfDatabaseExistsBehavior behavior); + void output_other_metadata(); + void output_field_metadata(); int64_t internal_add_results_fields(ex_entity_type type, Ioss::GroupingEntity *entity, int64_t position, int64_t block_count, @@ -248,6 +249,9 @@ namespace Ioex { int64_t add_results_fields(Ioss::GroupingEntity *entity, int64_t position = 0); int64_t add_reduction_results_fields(Ioss::GroupingEntity *entity); void add_mesh_reduction_fields(int64_t id, Ioss::GroupingEntity *entity); + std::vector get_fields_via_field_metadata(Ioss::GroupingEntity *entity, + ex_entity_type type, + Ioss::NameList &names); void add_region_fields(); void store_reduction_field(const Ioss::Field &field, const Ioss::GroupingEntity *ge, diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C index a9399e8681..0dea422a17 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C @@ -480,6 +480,9 @@ namespace Ioex { read_region(); read_communication_metadata(); + + Ioex::read_exodus_basis(get_file_pointer()); + Ioex::read_exodus_quadrature(get_file_pointer()); } get_step_times_nl(); @@ -622,13 +625,13 @@ namespace Ioex { // Get information records from database and add to informationRecords... int num_info = ex_inquire_int(get_file_pointer(), EX_INQ_INFO); if (num_info > 0) { - char **info_rec = Ioss::Utils::get_name_array( - num_info, max_line_length); // 'total_lines' pointers to char buffers + char **info_rec = + Ioex::get_name_array(num_info, max_line_length); // 'total_lines' pointers to char buffers ex_get_info(get_file_pointer(), info_rec); for (int i = 0; i < num_info; i++) { add_information_record(info_rec[i]); } - Ioss::Utils::delete_name_array(info_rec, num_info); + Ioex::delete_name_array(info_rec, num_info); } } @@ -982,7 +985,7 @@ namespace Ioex { bool map_read = false; int map_count = ex_inquire_int(get_file_pointer(), inquiry_type); if (read_exodus_map && map_count > 0) { - char **names = Ioss::Utils::get_name_array(map_count, maximumNameLength); + char **names = Ioex::get_name_array(map_count, maximumNameLength); int ierr = ex_get_names(get_file_pointer(), entity_type, names); if (ierr < 0) { Ioex::exodus_error(get_file_pointer(), __LINE__, __func__, __FILE__); @@ -1012,7 +1015,7 @@ namespace Ioex { } } } - Ioss::Utils::delete_name_array(names, map_count); + Ioex::delete_name_array(names, map_count); } if (!map_read) { @@ -5338,7 +5341,7 @@ namespace Ioex { void DatabaseIO::write_meta_data(Ioss::IfDatabaseExistsBehavior behavior) { Ioss::Region *region = get_region(); - common_write_meta_data(behavior); + common_write_metadata(behavior); char the_title[max_line_length + 1]; @@ -5396,7 +5399,7 @@ namespace Ioex { if (ierr < 0) { Ioex::exodus_error(get_file_pointer(), __LINE__, __func__, __FILE__); } - output_other_meta_data(); + output_other_metadata(); } } } diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C index b3edaccb2e..0c4ab1e54b 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C @@ -16,26 +16,26 @@ #include "Ioss_Utils.h" #include "exodus/Ioex_Utils.h" -#include // for lower_bound, copy, etc -#include // for assert -#include // for INT_MAX +#include +#include +#include #include -#include // for exit, EXIT_FAILURE +#include #include #include -#include // for operator<<, ostringstream, etc -#include // for distance -#include // for map -#include // for accumulate -#include // for pair, make_pair +#include +#include +#include +#include +#include #if !defined(NO_PARMETIS_SUPPORT) -#include // for ParMETIS_V3_Mesh2Dual, etc +#include #endif #if !defined(NO_ZOLTAN_SUPPORT) -#include // for Zoltan_Initialize -#include // for Zoltan +#include +#include #endif namespace { @@ -185,7 +185,7 @@ namespace Ioex { if (map_count > 0) { int max_name_length = ex_inquire_int(filePtr, EX_INQ_DB_MAX_USED_NAME_LENGTH); max_name_length = max_name_length < 32 ? 32 : max_name_length; - char **names = Ioss::Utils::get_name_array(map_count, max_name_length); + char **names = Ioex::get_name_array(map_count, max_name_length); ex_get_names(filePtr, EX_ELEM_MAP, names); for (int i = 0; i < map_count; i++) { @@ -197,7 +197,7 @@ namespace Ioex { break; } } - Ioss::Utils::delete_name_array(names, map_count); + Ioex::delete_name_array(names, map_count); } if (!map_read) { @@ -221,7 +221,7 @@ namespace Ioex { if (var_count > 0) { int max_name_length = ex_inquire_int(filePtr, EX_INQ_DB_MAX_USED_NAME_LENGTH); max_name_length = max_name_length < 32 ? 32 : max_name_length; - char **names = Ioss::Utils::get_name_array(var_count, max_name_length); + char **names = Ioex::get_name_array(var_count, max_name_length); ex_get_variable_names(filePtr, EX_ELEM_BLOCK, var_count, names); for (int i = 0; i < var_count; i++) { @@ -230,7 +230,7 @@ namespace Ioex { break; } } - Ioss::Utils::delete_name_array(names, var_count); + Ioex::delete_name_array(names, var_count); } if (var_index == 0) { diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h index 5ad1e1e407..651476b517 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h @@ -33,10 +33,10 @@ namespace Ioss { namespace Ioex { struct IOEX_EXPORT BlockFieldData { - int64_t id{0}; - size_t comp_count{0}; - std::vector var_name; - std::vector var_index; + int64_t id{0}; + size_t comp_count{0}; + Ioss::NameList var_name; + std::vector var_index; BlockFieldData() : id(0), comp_count(0) {} BlockFieldData(const int64_t id_) : id(id_), comp_count(0) {} diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C index b565b761af..ec617e93d6 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C @@ -648,7 +648,7 @@ namespace Ioex { } } - // Check whether we are on a NFS filesyste -- composed output is sometimes slow/hangs + // Check whether we are on a NFS filesystem -- composed output is sometimes slow/hangs // on NFS if (myProcessor == 0) { if (file.is_nfs()) { @@ -782,6 +782,9 @@ namespace Ioex { decomp->decompose_model(exoid); read_region(); + Ioex::read_exodus_basis(get_file_pointer()); + Ioex::read_exodus_quadrature(get_file_pointer()); + get_elemblocks(); get_step_times_nl(); @@ -893,13 +896,13 @@ namespace Ioex { // Get information records from database and add to informationRecords... int num_info = ex_inquire_int(get_file_pointer(), EX_INQ_INFO); if (num_info > 0) { - char **info_rec = Ioss::Utils::get_name_array( - num_info, max_line_length); // 'total_lines' pointers to char buffers + char **info_rec = + Ioex::get_name_array(num_info, max_line_length); // 'total_lines' pointers to char buffers ex_get_info(get_file_pointer(), info_rec); for (int i = 0; i < num_info; i++) { add_information_record(info_rec[i]); } - Ioss::Utils::delete_name_array(info_rec, num_info); + Ioex::delete_name_array(info_rec, num_info); } } @@ -1019,7 +1022,7 @@ namespace Ioex { bool map_read = false; int map_count = ex_inquire_int(get_file_pointer(), inquiry_type); if (map_count > 0) { - char **names = Ioss::Utils::get_name_array(map_count, maximumNameLength); + char **names = Ioex::get_name_array(map_count, maximumNameLength); int ierr = ex_get_names(get_file_pointer(), entity_type, names); if (ierr < 0) { Ioex::exodus_error(get_file_pointer(), __LINE__, __func__, __FILE__); @@ -1041,7 +1044,7 @@ namespace Ioex { map_read = true; } } - Ioss::Utils::delete_name_array(names, map_count); + Ioex::delete_name_array(names, map_count); } if (!map_read) { @@ -4797,7 +4800,7 @@ namespace Ioex { void ParallelDatabaseIO::write_meta_data(Ioss::IfDatabaseExistsBehavior behavior) { Ioss::Region *region = get_region(); - common_write_meta_data(behavior); + common_write_metadata(behavior); char the_title[max_line_length + 1]; @@ -4846,7 +4849,7 @@ namespace Ioex { if (behavior != Ioss::DB_APPEND && behavior != Ioss::DB_MODIFY) { output_node_map(); - output_other_meta_data(); + output_other_metadata(); } } diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C index e6a341a4fa..d922e6fafd 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C @@ -11,7 +11,6 @@ #include "Ioss_VariableType.h" #include "exodus/Ioex_Utils.h" #include -#include #include #include #include @@ -19,14 +18,18 @@ #include #include +#include "Ioss_BasisVariableType.h" #include "Ioss_CoordinateFrame.h" #include "Ioss_DatabaseIO.h" #include "Ioss_ElementBlock.h" #include "Ioss_Field.h" #include "Ioss_GroupingEntity.h" +#include "Ioss_NamedSuffixVariableType.h" #include "Ioss_ParallelUtils.h" #include "Ioss_Property.h" +#include "Ioss_QuadratureVariableType.h" #include "exodusII.h" +#include "exodusII_int.h" namespace { size_t match(const std::string &name1, const std::string &name2) @@ -97,7 +100,6 @@ namespace { } } } - } // namespace namespace Ioex { @@ -118,6 +120,128 @@ namespace Ioex { } } + std::string map_ioss_field_type(ex_field_type type) + { + if (type == EX_VECTOR_2D) + return "vector_2d"; + if (type == EX_VECTOR_3D) + return "vector_3d"; + if (type == EX_SCALAR) + return "scalar"; + if (type == EX_VECTOR_1D) + return "vector_1d"; + if (type == EX_QUATERNION_2D) + return "quaternion_2d"; + if (type == EX_QUATERNION_3D) + return "quaternion_3d"; + if (type == EX_FULL_TENSOR_36) + return "full_tensor_36"; + if (type == EX_FULL_TENSOR_32) + return "full_tensor_32"; + if (type == EX_FULL_TENSOR_22) + return "full_tensor_22"; + if (type == EX_FULL_TENSOR_16) + return "full_tensor_16"; + if (type == EX_FULL_TENSOR_12) + return "full_tensor_12"; + if (type == EX_SYM_TENSOR_33) + return "sym_tensor_33"; + if (type == EX_SYM_TENSOR_31) + return "sym_tensor_31"; + if (type == EX_SYM_TENSOR_21) + return "sym_tensor_21"; + if (type == EX_SYM_TENSOR_13) + return "sym_tensor_13"; + if (type == EX_SYM_TENSOR_11) + return "sym_tensor_11"; + if (type == EX_SYM_TENSOR_10) + return "sym_tensor_10"; + if (type == EX_ASYM_TENSOR_03) + return "asym_tensor_03"; + if (type == EX_ASYM_TENSOR_02) + return "asym_tensor_02"; + if (type == EX_ASYM_TENSOR_01) + return "asym_tensor_01"; + if (type == EX_MATRIX_2X2) + return "matrix_22"; + if (type == EX_MATRIX_3X3) + return "matrix_33"; + if (type == EX_FIELD_TYPE_SEQUENCE) + return "Real"; + if (type == EX_BASIS) + return "Basis"; + if (type == EX_QUADRATURE) + return "Quadrature"; + return "invalid"; + } + + ex_field_type map_ioss_field_type(const Ioss::VariableType *type) + { + if (type->name() == "vector_2d") + return EX_VECTOR_2D; + if (type->name() == "vector_3d") + return EX_VECTOR_3D; + if (type->name() == "scalar") + return EX_SCALAR; + if (type->name() == "vector_1d") + return EX_VECTOR_1D; + if (type->name() == "quaternion_2d") + return EX_QUATERNION_2D; + if (type->name() == "quaternion_3d") + return EX_QUATERNION_3D; + if (type->name() == "full_tensor_36") + return EX_FULL_TENSOR_36; + if (type->name() == "full_tensor_32") + return EX_FULL_TENSOR_32; + if (type->name() == "full_tensor_22") + return EX_FULL_TENSOR_22; + if (type->name() == "full_tensor_16") + return EX_FULL_TENSOR_16; + if (type->name() == "full_tensor_12") + return EX_FULL_TENSOR_12; + if (type->name() == "sym_tensor_33") + return EX_SYM_TENSOR_33; + if (type->name() == "sym_tensor_31") + return EX_SYM_TENSOR_31; + if (type->name() == "sym_tensor_21") + return EX_SYM_TENSOR_21; + if (type->name() == "sym_tensor_13") + return EX_SYM_TENSOR_13; + if (type->name() == "sym_tensor_11") + return EX_SYM_TENSOR_11; + if (type->name() == "sym_tensor_10") + return EX_SYM_TENSOR_10; + if (type->name() == "asym_tensor_03") + return EX_ASYM_TENSOR_03; + if (type->name() == "asym_tensor_02") + return EX_ASYM_TENSOR_02; + if (type->name() == "asym_tensor_01") + return EX_ASYM_TENSOR_01; + if (type->name() == "matrix_22") + return EX_MATRIX_2X2; + if (type->name() == "matrix_33") + return EX_MATRIX_3X3; + + if (Ioss::Utils::substr_equal("Real", type->name())) + return EX_FIELD_TYPE_SEQUENCE; + + // This may be a basis, quadratur, or user type... + auto nsvt = dynamic_cast(type); + if (nsvt != nullptr) { + return EX_FIELD_TYPE_USER_DEFINED; + } + auto bvt = dynamic_cast(type); + if (bvt != nullptr) { + return EX_BASIS; + } + auto qvt = dynamic_cast(type); + if (qvt != nullptr) { + return EX_QUADRATURE; + } + + return EX_FIELD_TYPE_INVALID; + } + Ioss::EntityType map_exodus_type(ex_entity_type type) { switch (type) { @@ -137,6 +261,62 @@ namespace Ioex { } } + int read_exodus_basis(int exoid) + { + auto bas_cnt = ex_get_basis_count(exoid); + if (bas_cnt == 0) { + return 0; + } + std::vector exo_basis(bas_cnt); + auto *pbasis = Data(exo_basis); + ex_get_basis(exoid, &pbasis, &bas_cnt); + + for (const auto &ebasis : exo_basis) { + Ioss::Basis basis; + for (int i = 0; i < ebasis.cardinality; i++) { + Ioss::BasisComponent bc{ + ebasis.subc_dim[i], ebasis.subc_ordinal[i], ebasis.subc_dof_ordinal[i], + ebasis.subc_num_dof[i], ebasis.xi[i], ebasis.eta[i], + ebasis.zeta[i]}; + basis.basies.push_back(bc); + } + Ioss::VariableType::create_basis_type(ebasis.name, basis); + } + + // deallocate any memory allocated in the 'ex_basis' structs. + ex_initialize_basis_struct(Data(exo_basis), exo_basis.size(), -1); + + return bas_cnt; + } + + int read_exodus_quadrature(int exoid) + { + auto quad_cnt = ex_get_quadrature_count(exoid); + if (quad_cnt == 0) { + return quad_cnt; + } + + std::vector exo_quadrature(quad_cnt); + auto *pquad = Data(exo_quadrature); + ex_get_quadrature(exoid, &pquad, &quad_cnt); + + for (const auto &equadrature : exo_quadrature) { + std::vector quadrature; + quadrature.reserve(equadrature.cardinality); + for (int i = 0; i < equadrature.cardinality; i++) { + Ioss::QuadraturePoint q{equadrature.xi[i], equadrature.eta[i], equadrature.zeta[i], + equadrature.weight[i]}; + quadrature.push_back(q); + } + Ioss::VariableType::create_quadrature_type(equadrature.name, quadrature); + } + + // deallocate any memory allocated in the 'ex_quadrature' structs. + ex_initialize_quadrature_struct(Data(exo_quadrature), exo_quadrature.size(), -1); + + return quad_cnt; + } + ex_entity_type map_exodus_type(Ioss::EntityType type) { switch (type) { @@ -158,6 +338,59 @@ namespace Ioex { } } + char **get_name_array(size_t count, int size) + { + auto *names = new char *[count]; + for (size_t i = 0; i < count; i++) { + names[i] = new char[size + 1]; + std::memset(names[i], '\0', size + 1); + } + return names; + } + + void delete_name_array(char **names, int count) + { + for (int i = 0; i < count; i++) { + delete[] names[i]; + } + delete[] names; + } + + Ioss::NameList get_variable_names(int nvar, int maximumNameLength, int exoid, ex_entity_type type) + { + char **names = get_name_array(nvar, maximumNameLength); + int ierr = ex_get_variable_names(exoid, type, nvar, names); + if (ierr < 0) { + Ioex::exodus_error(exoid, __LINE__, __func__, __FILE__); + } + + Ioss::NameList name_str; + name_str.reserve(nvar); + for (int i = 0; i < nvar; i++) { + name_str.emplace_back(names[i]); + } + delete_name_array(names, nvar); + return name_str; + } + + Ioss::NameList get_reduction_variable_names(int nvar, int maximumNameLength, int exoid, + ex_entity_type type) + { + char **names = get_name_array(nvar, maximumNameLength); + int ierr = ex_get_reduction_variable_names(exoid, type, nvar, names); + if (ierr < 0) { + Ioex::exodus_error(exoid, __LINE__, __func__, __FILE__); + } + + Ioss::NameList name_str; + name_str.reserve(nvar); + for (int i = 0; i < nvar; i++) { + name_str.emplace_back(names[i]); + } + delete_name_array(names, nvar); + return name_str; + } + bool read_last_time_attribute(int exodusFilePtr, double *value) { // Check whether the "last_written_time" attribute exists. If it does, @@ -534,7 +767,7 @@ namespace Ioex { } // Get the names of the maps... - char **names = Ioss::Utils::get_name_array(map_count, name_length); + char **names = get_name_array(map_count, name_length); int ierr = ex_get_names(exoid, EX_ELEM_MAP, names); if (ierr < 0) { Ioex::exodus_error(exoid, __LINE__, __func__, __FILE__); @@ -584,7 +817,7 @@ namespace Ioex { i = ii - 1; } - Ioss::Utils::delete_name_array(names, map_count); + delete_name_array(names, map_count); return map_count; } diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h index a08f9d80f1..70be7426c8 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h @@ -88,6 +88,12 @@ namespace Ioex { IOSS_NODISCARD IOEX_EXPORT Ioss::EntityType map_exodus_type(ex_entity_type type); IOSS_NODISCARD IOEX_EXPORT ex_entity_type map_exodus_type(Ioss::EntityType type); + IOSS_NODISCARD IOEX_EXPORT ex_field_type map_ioss_field_type(const Ioss::VariableType *type); + IOSS_NODISCARD IOEX_EXPORT std::string map_ioss_field_type(ex_field_type type); + + IOEX_EXPORT int read_exodus_basis(int exoid); + IOEX_EXPORT int read_exodus_quadrature(int exoid); + IOEX_EXPORT void update_last_time_attribute(int exodusFilePtr, double value); IOEX_EXPORT bool read_last_time_attribute(int exodusFilePtr, double *value); @@ -106,6 +112,13 @@ namespace Ioex { IOEX_EXPORT int add_map_fields(int exoid, Ioss::ElementBlock *block, int64_t my_element_count, size_t name_length); + IOSS_NODISCARD IOEX_EXPORT char **get_name_array(size_t count, int size); + IOEX_EXPORT void delete_name_array(char **names, int count); + IOSS_NODISCARD IOEX_EXPORT Ioss::NameList get_variable_names(int nvar, int maximumNameLength, + int exoid, ex_entity_type type); + IOSS_NODISCARD IOEX_EXPORT Ioss::NameList + get_reduction_variable_names(int nvar, int maximumNameLength, int exoid, ex_entity_type type); + IOEX_EXPORT void add_coordinate_frames(int exoid, Ioss::Region *region); IOEX_EXPORT void write_coordinate_frames(int exoid, const Ioss::CoordinateFrameContainer &frames); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C index e8497735fa..b97dea9003 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C @@ -62,8 +62,6 @@ namespace { EX_NODE_SET, EX_EDGE_SET, EX_FACE_SET, EX_ELEM_SET, EX_SIDE_SET}); - const size_t max_line_length = MAX_LINE_LENGTH; - void check_variable_consistency(const ex_var_params &exo_params, int my_processor, const std::string &filename, const Ioss::ParallelUtils &util); @@ -71,6 +69,25 @@ namespace { template void write_attribute_names(int exoid, ex_entity_type type, const std::vector &entities); + + char **get_name_array(size_t count, int size) + { + auto *names = new char *[count]; + for (size_t i = 0; i < count; i++) { + names[i] = new char[size + 1]; + std::memset(names[i], '\0', size + 1); + } + return names; + } + + void delete_name_array(char **names, int count) + { + for (int i = 0; i < count; i++) { + delete[] names[i]; + } + delete[] names; + } + } // namespace namespace Ioexnl { @@ -266,67 +283,7 @@ namespace Ioexnl { } // common - void BaseDatabaseIO::put_info() - { - int total_lines = 0; - char **info = nullptr; - - if (!using_parallel_io() || myProcessor == 0) { - // dump info records, include the product_registry - // See if the input file was specified as a property on the database... - std::vector input_lines; - if (get_region()->property_exists("input_file_name")) { - std::string filename = get_region()->get_property("input_file_name").get_string(); - // Determine size of input file so can embed it in info records... - Ioss::Utils::input_file(filename, &input_lines, max_line_length); - } - - // Get configuration information for IOSS library. - // Split into strings and remove empty lines... - std::string config = Ioss::IOFactory::show_configuration(); - std::replace(std::begin(config), std::end(config), '\t', ' '); - auto lines = Ioss::tokenize(config, "\n"); - lines.erase(std::remove_if(lines.begin(), lines.end(), - [](const std::string &line) { return line.empty(); }), - lines.end()); - - // See if the client added any "information_records" - size_t info_rec_size = informationRecords.size(); - size_t in_lines = input_lines.size(); - size_t qa_lines = 1; // Platform info - size_t config_lines = lines.size(); - - total_lines = in_lines + qa_lines + info_rec_size + config_lines; - - // 'total_lines' pointers to char buffers - info = Ioss::Utils::get_name_array(total_lines, max_line_length); - - int i = 0; - Ioss::Utils::copy_string(info[i++], Ioss::Utils::platform_information(), max_line_length + 1); - - // Copy input file lines into 'info' array... - for (size_t j = 0; j < input_lines.size(); j++, i++) { - Ioss::Utils::copy_string(info[i], input_lines[j], max_line_length + 1); - } - - // Copy "information_records" property data ... - for (size_t j = 0; j < informationRecords.size(); j++, i++) { - Ioss::Utils::copy_string(info[i], informationRecords[j], max_line_length + 1); - } - - for (size_t j = 0; j < lines.size(); j++, i++) { - Ioss::Utils::copy_string(info[i], lines[j], max_line_length + 1); - } - } - - if (using_parallel_io()) { - util().broadcast(total_lines); - } - - if (!using_parallel_io() || myProcessor == 0) { - Ioss::Utils::delete_name_array(info, total_lines); - } - } + void BaseDatabaseIO::put_info() {} // common int BaseDatabaseIO::get_current_state() const @@ -423,8 +380,8 @@ namespace Ioexnl { } // common - void BaseDatabaseIO::compute_block_membership_nl(Ioss::SideBlock *efblock, - std::vector &block_membership) const + void BaseDatabaseIO::compute_block_membership_nl(Ioss::SideBlock *efblock, + Ioss::NameList &block_membership) const { const Ioss::ElementBlockContainer &element_blocks = get_region()->get_element_blocks(); assert(Ioss::Utils::check_block_order(element_blocks)); @@ -1046,7 +1003,7 @@ namespace Ioexnl { void BaseDatabaseIO::finalize_write(int, double) {} - void BaseDatabaseIO::common_write_meta_data(Ioss::IfDatabaseExistsBehavior behavior) + void BaseDatabaseIO::common_write_metadata(Ioss::IfDatabaseExistsBehavior behavior) { Ioss::Region *region = get_region(); @@ -1280,7 +1237,7 @@ namespace Ioexnl { } } - void BaseDatabaseIO::output_other_meta_data() + void BaseDatabaseIO::output_other_metadata() { // Write attribute names (if any)... write_attribute_names(get_file_pointer(), EX_NODE_SET, get_region()->get_nodesets()); @@ -1356,7 +1313,7 @@ namespace Ioexnl { } if (node_map_cnt > 0) { - char **names = Ioss::Utils::get_name_array(node_map_cnt, maximumNameLength); + char **names = get_name_array(node_map_cnt, maximumNameLength); auto *node_block = get_region()->get_node_blocks()[0]; // If there are node_maps, then there is a node_block auto node_map_fields = node_block->field_describe(Ioss::Field::MAP); @@ -1373,11 +1330,11 @@ namespace Ioexnl { } } } - Ioss::Utils::delete_name_array(names, node_map_cnt); + delete_name_array(names, node_map_cnt); } if (elem_map_cnt > 0) { - char **names = Ioss::Utils::get_name_array(elem_map_cnt, maximumNameLength); + char **names = get_name_array(elem_map_cnt, maximumNameLength); for (const auto &field_name : elem_map_fields) { // Now, we need to find an element block that has this field... for (const auto &block : blocks) { @@ -1405,7 +1362,7 @@ namespace Ioexnl { } } } - Ioss::Utils::delete_name_array(names, elem_map_cnt); + delete_name_array(names, elem_map_cnt); } // Write coordinate frame data... @@ -1428,8 +1385,8 @@ namespace { check_attribute_index_order(ge); - std::vector names(attribute_count); - std::vector names_str(attribute_count); + std::vector names(attribute_count); + Ioss::NameList names_str(attribute_count); // Get the attribute fields... Ioss::NameList results_fields = ge->field_describe(Ioss::Field::ATTRIBUTE); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h index 50334df262..bb004b5be2 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h @@ -121,8 +121,8 @@ namespace Ioexnl { Ioss::Map &entity_map, void *ids, size_t num_to_get, size_t offset) const; - void compute_block_membership_nl(Ioss::SideBlock *efblock, - std::vector &block_membership) const override; + void compute_block_membership_nl(Ioss::SideBlock *efblock, + Ioss::NameList &block_membership) const override; IOSS_NODISCARD int int_byte_size_db() const override; void set_int_byte_size_api(Ioss::DataSize size) const override; @@ -216,8 +216,8 @@ namespace Ioexnl { void add_attribute_fields(Ioss::GroupingEntity *block, int attribute_count, const std::string &type); - void common_write_meta_data(Ioss::IfDatabaseExistsBehavior behavior); - void output_other_meta_data(); + void common_write_metadata(Ioss::IfDatabaseExistsBehavior behavior); + void output_other_metadata(); int64_t internal_add_results_fields(ex_entity_type type, Ioss::GroupingEntity *entity, int64_t position, int64_t block_count, diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.C index 236a36b0a1..bb23b829f5 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.C @@ -1247,7 +1247,7 @@ namespace Ioexnl { void DatabaseIO::write_meta_data(Ioss::IfDatabaseExistsBehavior behavior) { Ioss::Region *region = get_region(); - common_write_meta_data(behavior); + common_write_metadata(behavior); char the_title[max_line_length + 1]; @@ -1297,7 +1297,7 @@ namespace Ioexnl { put_info(); } - output_other_meta_data(); + output_other_metadata(); } } } diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C index 6e8152754e..84848ee2bc 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C @@ -16,18 +16,18 @@ #include "Ioss_Utils.h" #include "exonull/Ioexnl_Utils.h" -#include // for lower_bound, copy, etc -#include // for assert -#include // for INT_MAX +#include +#include +#include #include -#include // for exit, EXIT_FAILURE +#include #include #include -#include // for operator<<, ostringstream, etc -#include // for distance -#include // for map -#include // for accumulate -#include // for pair, make_pair +#include +#include +#include +#include +#include namespace Ioexnl { template DecompositionData::DecompositionData(const Ioss::PropertyManager &props, diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.C index 5bd79bc573..4676a8a85a 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.C @@ -1407,7 +1407,7 @@ namespace Ioexnl { void ParallelDatabaseIO::write_meta_data(Ioss::IfDatabaseExistsBehavior behavior) { Ioss::Region *region = get_region(); - common_write_meta_data(behavior); + common_write_metadata(behavior); char the_title[max_line_length + 1]; @@ -1447,7 +1447,7 @@ namespace Ioexnl { if (behavior != Ioss::DB_APPEND && behavior != Ioss::DB_MODIFY) { output_node_map(); - output_other_meta_data(); + output_other_metadata(); } } diff --git a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.C b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.C index de7eace03e..4e0cf39be1 100644 --- a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.C @@ -517,7 +517,7 @@ namespace Iogs { sideset->property_add(Ioss::Property("guid", util().generate_guid(ifs + 1))); get_region()->add(sideset); - std::vector touching_blocks = m_generatedMesh->sideset_touching_blocks(ifs + 1); + Ioss::NameList touching_blocks = m_generatedMesh->sideset_touching_blocks(ifs + 1); if (touching_blocks.size() == 1) { std::string sd_block_name = name + "_quad4"; std::string side_topo_name = "quad4"; diff --git a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.h b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.h index 523823fba5..3a71d0a480 100644 --- a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_DatabaseIO.h @@ -87,10 +87,7 @@ namespace Iogs { void setGeneratedMesh(Iogs::GeneratedMesh *generatedMesh) { m_generatedMesh = generatedMesh; } - IOSS_NODISCARD const std::vector &get_sideset_names() const - { - return m_sideset_names; - } + IOSS_NODISCARD const Ioss::NameList &get_sideset_names() const { return m_sideset_names; } private: void read_meta_data_nl() override; @@ -151,8 +148,8 @@ namespace Iogs { void add_transient_fields(Ioss::GroupingEntity *entity); - GeneratedMesh *m_generatedMesh{nullptr}; - std::vector m_sideset_names{}; + GeneratedMesh *m_generatedMesh{nullptr}; + Ioss::NameList m_sideset_names{}; double currentTime{0.0}; int spatialDimension{3}; diff --git a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.C b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.C index 6a13fec34d..d558e39241 100644 --- a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.C +++ b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.C @@ -156,7 +156,7 @@ namespace Iogs { offZ = off_z; } - void GeneratedMesh::parse_options(const std::vector &groups) + void GeneratedMesh::parse_options(const Ioss::NameList &groups) { for (size_t i = 1; i < groups.size(); i++) { auto option = Ioss::tokenize(groups[i], ":"); @@ -822,9 +822,9 @@ namespace Iogs { element_surface_map(loc, elem_sides); } - std::vector GeneratedMesh::sideset_touching_blocks(int64_t /*set_id*/) const + Ioss::NameList GeneratedMesh::sideset_touching_blocks(int64_t /*set_id*/) const { - std::vector result(1, "block_1"); + Ioss::NameList result(1, "block_1"); return result; } diff --git a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h index 6c13764803..a45b2ea9a2 100644 --- a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h +++ b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h @@ -356,7 +356,7 @@ namespace Iogs { */ virtual void sideset_elem_sides(int64_t id, Ioss::Int64Vector &elem_sides) const; - IOSS_NODISCARD virtual std::vector sideset_touching_blocks(int64_t set_id) const; + IOSS_NODISCARD virtual Ioss::NameList sideset_touching_blocks(int64_t set_id) const; IOSS_NODISCARD int64_t get_num_x() const { return numX; } IOSS_NODISCARD int64_t get_num_y() const { return numY; } @@ -376,7 +376,7 @@ namespace Iogs { GeneratedMesh &operator=(const GeneratedMesh &); void set_variable_count(const std::string &type, size_t count); - void parse_options(const std::vector &groups); + void parse_options(const Ioss::NameList &groups); void show_parameters() const; void initialize(); diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C index 953ffaa7d1..074774cb14 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C @@ -350,7 +350,7 @@ namespace Iogn { } } - std::vector ExodusMesh::sideset_touching_blocks(int64_t setId) const + Ioss::NameList ExodusMesh::sideset_touching_blocks(int64_t setId) const { return mExodusData.sidesetTouchingBlocks[setId - 1]; } diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h index 3e5f9fa672..673d987eb3 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h @@ -63,17 +63,16 @@ namespace Iogn { // element side (1-based) The side id is: side_id = // 10*element_id + local_side_number This assumes that all // sides in a sideset are boundary sides. - std::vector> sidesetConnectivity; - std::vector> sidesetTouchingBlocks; + std::vector> sidesetConnectivity; + std::vector sidesetTouchingBlocks; ExodusData() = delete; ExodusData(std::vector coords, std::vector> elemBlockConnectivity, std::vector globalNumOfElemsInBlock, std::vector localNumOfElemsInBlock, std::vector blockTopoData, int globalNumNodes, std::vector globalIdsOfLocalElems, std::vector globalIdsLocalNodes, - std::vector> sidesetConn = std::vector>(), - std::vector> sidesetBlocks = - std::vector>()) + std::vector> sidesetConn = std::vector>(), + std::vector sidesetBlocks = std::vector()) : coordinates(std::move(coords)), elementBlockConnectivity(std::move(elemBlockConnectivity)), globalNumberOfElementsInBlock(std::move(globalNumOfElemsInBlock)), @@ -226,7 +225,7 @@ namespace Iogn { void sideset_elem_sides(int64_t setId, std::vector &elem_sides) const override; - std::vector sideset_touching_blocks(int64_t setId) const override; + Ioss::NameList sideset_touching_blocks(int64_t setId) const override; void nodeset_nodes(int64_t nset_id, std::vector &nodes) const override; diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.C b/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.C index 086e9325e4..aab00bca2b 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.C @@ -671,7 +671,7 @@ namespace Iogn { sideset->property_add(Ioss::Property("guid", util().generate_guid(iss + 1))); get_region()->add(sideset); - std::vector touching_blocks = m_generatedMesh->sideset_touching_blocks(iss + 1); + Ioss::NameList touching_blocks = m_generatedMesh->sideset_touching_blocks(iss + 1); if (touching_blocks.size() == 1) { std::string sd_block_name = name; sd_block_name += "_"; diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.h b/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.h index c7e3aa04d6..7ee2e50488 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DatabaseIO.h @@ -96,7 +96,7 @@ namespace Iogn { void setGeneratedMesh(Iogn::GeneratedMesh *generatedMesh) { m_generatedMesh = generatedMesh; } - const std::vector &get_sideset_names() const { return m_sideset_names; } + const Ioss::NameList &get_sideset_names() const { return m_sideset_names; } private: void read_meta_data_nl() override; @@ -159,8 +159,8 @@ namespace Iogn { void add_transient_fields(Ioss::GroupingEntity *entity); - GeneratedMesh *m_generatedMesh{nullptr}; - std::vector m_sideset_names{}; + GeneratedMesh *m_generatedMesh{nullptr}; + Ioss::NameList m_sideset_names{}; double currentTime{0.0}; int spatialDimension{3}; diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C index 7c22d6467d..9fa3400924 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C @@ -213,7 +213,7 @@ namespace Iogn { offZ = off_z; } - void GeneratedMesh::parse_options(const std::vector &groups) + void GeneratedMesh::parse_options(const Ioss::NameList &groups) { for (size_t i = 1; i < groups.size(); i++) { auto option = Ioss::tokenize(groups[i], ":"); @@ -1661,9 +1661,9 @@ namespace Iogn { } } - std::vector GeneratedMesh::sideset_touching_blocks(int64_t /*set_id*/) const + Ioss::NameList GeneratedMesh::sideset_touching_blocks(int64_t /*set_id*/) const { - std::vector result(1, "block_1"); + Ioss::NameList result(1, "block_1"); return result; } diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h index 0595e4c59c..aac60376b5 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h @@ -452,7 +452,7 @@ namespace Iogn { */ virtual void sideset_elem_sides(int64_t id, Ioss::Int64Vector &elem_sides) const; - virtual std::vector sideset_touching_blocks(int64_t set_id) const; + virtual Ioss::NameList sideset_touching_blocks(int64_t set_id) const; IOSS_NODISCARD int64_t get_num_x() const { return numX; } IOSS_NODISCARD int64_t get_num_y() const { return numY; } @@ -469,7 +469,7 @@ namespace Iogn { template void raw_connectivity(int64_t block_number, INT *connect) const; void set_variable_count(const std::string &type, size_t count); - void parse_options(const std::vector &groups); + void parse_options(const Ioss::NameList &groups); void show_parameters() const; void initialize(); diff --git a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C index d793f3941c..850afe05fb 100644 --- a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C +++ b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2023 National Technology & Engineering Solutions +// Copyright(C) 1999-2024 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. // @@ -316,7 +316,7 @@ namespace { } } - // In Iocgns::Utils::common_write_meta_data, there is code to make + // In Iocgns::Utils::common_write_metadata, there is code to make // sure that the zgc.m_connectionName is unique for all zgc instances on // a zone / processor pair (if !parallel_io which is file-per-processor) // The uniquification appends a letter from 'A' to 'Z' to the name diff --git a/packages/seacas/libraries/ioss/src/main/info_interface.C b/packages/seacas/libraries/ioss/src/main/info_interface.C index a6699f0f44..2e10d616c6 100644 --- a/packages/seacas/libraries/ioss/src/main/info_interface.C +++ b/packages/seacas/libraries/ioss/src/main/info_interface.C @@ -77,6 +77,9 @@ void Info::Interface::enroll_options() "\t\tPrimarily used for testing", nullptr); + options_.enroll("detailed_field_info", Ioss::GetLongOption::NoValue, + "Output very detailed information about each field", nullptr); + options_.enroll("use_generic_names", Ioss::GetLongOption::NoValue, "Use generic names (type_id) instead of names in database", nullptr); @@ -199,6 +202,7 @@ bool Info::Interface::parse_options(int argc, char **argv) summary_ = options_.retrieve("summary") != nullptr; showConfig_ = options_.retrieve("configuration") != nullptr; queryTimeOnly_ = options_.retrieve("query_timesteps_only") != nullptr; + fieldDetails_ = options_.retrieve("detailed_field_info") != nullptr; filetype_ = options_.get_option_value("db_type", filetype_); filetype_ = options_.get_option_value("in_type", filetype_); diff --git a/packages/seacas/libraries/ioss/src/main/info_interface.h b/packages/seacas/libraries/ioss/src/main/info_interface.h index 65d304582c..a5191171ea 100644 --- a/packages/seacas/libraries/ioss/src/main/info_interface.h +++ b/packages/seacas/libraries/ioss/src/main/info_interface.h @@ -32,6 +32,7 @@ namespace Info { bool list_groups() const { return listGroups_; } bool show_config() const { return showConfig_; } bool query_timesteps_only() const { return queryTimeOnly_; } + bool field_details() const { return fieldDetails_; } int surface_split_scheme() const { return surfaceSplitScheme_; } char field_suffix_separator() const { return fieldSuffixSeparator_; } @@ -66,6 +67,7 @@ namespace Info { bool showConfig_{false}; bool summary_{false}; bool queryTimeOnly_{false}; + bool fieldDetails_{false}; char fieldSuffixSeparator_{'_'}; diff --git a/packages/seacas/libraries/ioss/src/main/io_info.C b/packages/seacas/libraries/ioss/src/main/io_info.C index e3dabc7cbd..c8f25eaf60 100644 --- a/packages/seacas/libraries/ioss/src/main/io_info.C +++ b/packages/seacas/libraries/ioss/src/main/io_info.C @@ -64,15 +64,15 @@ namespace { void info_timesteps(Ioss::Region ®ion); void info_nodeblock(Ioss::Region ®ion, const Info::Interface &interFace); - void info_edgeblock(Ioss::Region ®ion); - void info_faceblock(Ioss::Region ®ion); + void info_edgeblock(Ioss::Region ®ion, const Info::Interface &interFace); + void info_faceblock(Ioss::Region ®ion, const Info::Interface &interFace); void info_elementblock(Ioss::Region ®ion, const Info::Interface &interFace); void info_structuredblock(Ioss::Region ®ion, const Info::Interface &interFace); - void info_nodesets(Ioss::Region ®ion); - void info_edgesets(Ioss::Region ®ion); - void info_facesets(Ioss::Region ®ion); - void info_elementsets(Ioss::Region ®ion); + void info_nodesets(Ioss::Region ®ion, const Info::Interface &interFace); + void info_edgesets(Ioss::Region ®ion, const Info::Interface &interFace); + void info_facesets(Ioss::Region ®ion, const Info::Interface &interFace); + void info_elementsets(Ioss::Region ®ion, const Info::Interface &interFace); void info_sidesets(Ioss::Region ®ion, const Info::Interface &interFace); void info_coordinate_frames(Ioss::Region ®ion); @@ -83,6 +83,14 @@ namespace { void info_aliases(const Ioss::Region ®ion, const Ioss::GroupingEntity *ige, bool nl_pre, bool nl_post); + void info_variable_types() + { + auto var_list = Ioss::VariableType::external_types(Ioss::VariableType::Type::UNKNOWN); + for (auto &var : var_list) { + var->print(); + } + } + void file_info(const Info::Interface &interFace); void group_info(Info::Interface &interFace); @@ -206,7 +214,7 @@ namespace { if (!custom_field.empty()) { auto suffices = Ioss::tokenize(custom_field, ","); if (suffices.size() > 1) { - Ioss::VariableType::create_named_suffix_field_type("UserDefined", suffices); + Ioss::VariableType::create_named_suffix_type("UserDefined", suffices); } } @@ -265,7 +273,8 @@ namespace { Ioss::Utils::info_fields(&nb, Ioss::Field::ATTRIBUTE, prefix + "\tAttributes: ", "\n\t\t" + prefix); Ioss::Utils::info_fields(&nb, Ioss::Field::TRANSIENT, - prefix + "\tTransient: ", "\n\t\t" + prefix); + prefix + "\tTransient: ", "\n\t\t" + prefix, + interFace.field_details()); if (interFace.compute_bbox() && region.mesh_type() != Ioss::MeshType::STRUCTURED) { print_bbox(nb); @@ -299,7 +308,8 @@ namespace { fmt::group_digits(num_node)); info_aliases(region, sb, true, false); - Ioss::Utils::info_fields(sb, Ioss::Field::TRANSIENT, "\n\tTransient: "); + Ioss::Utils::info_fields(sb, Ioss::Field::TRANSIENT, "\n\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(sb, Ioss::Field::REDUCTION, "\n\tTransient (Reduction): ", "\t"); info_nodeblock(region, sb->get_node_block(), interFace, "\t"); fmt::print("\n"); @@ -344,6 +354,7 @@ namespace { Ioss::Utils::info_property(®ion, Ioss::Property::ATTRIBUTE, "\tAttributes (Reduction): ", "\t"); Ioss::Utils::info_fields(®ion, Ioss::Field::REDUCTION, "\tTransient (Reduction): ", "\t"); + info_variable_types(); } void info_assemblies(Ioss::Region ®ion) @@ -397,13 +408,14 @@ namespace { Ioss::Utils::info_property(eb, Ioss::Property::ATTRIBUTE, "\tAttributes (Reduction): ", "\t"); if (interFace.adjacencies()) { - std::vector blocks = eb->get_block_adjacencies(); + Ioss::NameList blocks = eb->get_block_adjacencies(); fmt::print("\n\tAdjacent to {} element block(s):\t", blocks.size()); for (const auto &block : blocks) { fmt::print("{} ", block); } } - Ioss::Utils::info_fields(eb, Ioss::Field::TRANSIENT, "\n\tTransient: "); + Ioss::Utils::info_fields(eb, Ioss::Field::TRANSIENT, "\n\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(eb, Ioss::Field::REDUCTION, "\n\tTransient (Reduction): "); if (interFace.compute_bbox()) { @@ -412,7 +424,7 @@ namespace { } } - void info_edgeblock(Ioss::Region ®ion) + void info_edgeblock(Ioss::Region ®ion, const Info::Interface &interFace) { const Ioss::EdgeBlockContainer &ebs = region.get_edge_blocks(); for (auto &eb : ebs) { @@ -427,19 +439,20 @@ namespace { Ioss::Utils::info_fields(eb, Ioss::Field::ATTRIBUTE, "\tAttributes: "); #if 0 - std::vector blocks = eb->get_block_adjacencies(); + Ioss::NameList blocks = eb->get_block_adjacencies(); fmt::print("\tAdjacent to {} edge block(s):\t", blocks.size()); for (auto &block : blocks) { fmt::print("{} ", block); } #endif - Ioss::Utils::info_fields(eb, Ioss::Field::TRANSIENT, "\n\tTransient: "); + Ioss::Utils::info_fields(eb, Ioss::Field::TRANSIENT, "\n\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(eb, Ioss::Field::REDUCTION, "\n\tTransient (Reduction): "); fmt::print("\n"); } } - void info_faceblock(Ioss::Region ®ion) + void info_faceblock(Ioss::Region ®ion, const Info::Interface &interFace) { const Ioss::FaceBlockContainer &ebs = region.get_face_blocks(); for (auto &eb : ebs) { @@ -454,13 +467,14 @@ namespace { Ioss::Utils::info_fields(eb, Ioss::Field::ATTRIBUTE, "\tAttributes: "); #if 0 - std::vector blocks = eb->get_block_adjacencies(); + Ioss::NameList blocks = eb->get_block_adjacencies(); fmt::print("\tAdjacent to {} face block(s):\t", blocks.size()); for (auto &block : blocks) { fmt::print("{} ", block); } #endif - Ioss::Utils::info_fields(eb, Ioss::Field::TRANSIENT, "\n\tTransient: "); + Ioss::Utils::info_fields(eb, Ioss::Field::TRANSIENT, "\n\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(eb, Ioss::Field::REDUCTION, "\n\tTransient (Reduction): "); fmt::print("\n"); } @@ -480,10 +494,11 @@ namespace { #endif } info_aliases(region, fs, true, false); - Ioss::Utils::info_fields(fs, Ioss::Field::TRANSIENT, "\n\tTransient: "); + Ioss::Utils::info_fields(fs, Ioss::Field::TRANSIENT, "\n\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(fs, Ioss::Field::REDUCTION, "\n\tTransient (Reduction): "); if (interFace.adjacencies()) { - std::vector blocks; + Ioss::NameList blocks; fs->block_membership(blocks); fmt::print("\n\t\tTouches {} element block(s):\t", blocks.size()); for (const auto &block : blocks) { @@ -499,14 +514,15 @@ namespace { fmt::print("\t{}, {:8} sides, {:3d} attributes, {:8} distribution factors.\n", name(fb), fmt::group_digits(count), num_attrib, fmt::group_digits(num_dist)); info_df(fb, "\t\t"); - Ioss::Utils::info_fields(fb, Ioss::Field::TRANSIENT, "\t\tTransient: ", "\n\t\t"); + Ioss::Utils::info_fields(fb, Ioss::Field::TRANSIENT, "\t\tTransient: ", "\n\t\t", + interFace.field_details()); Ioss::Utils::info_fields(fb, Ioss::Field::REDUCTION, "\t\tTransient (Reduction): ", "\n\t\t"); } } } - void info_nodesets(Ioss::Region ®ion) + void info_nodesets(Ioss::Region ®ion, const Info::Interface &interFace) { const Ioss::NodeSetContainer &nss = region.get_nodesets(); for (auto &ns : nss) { @@ -519,12 +535,13 @@ namespace { info_aliases(region, ns, false, true); info_df(ns, "\t"); Ioss::Utils::info_fields(ns, Ioss::Field::ATTRIBUTE, "\tAttributes: "); - Ioss::Utils::info_fields(ns, Ioss::Field::TRANSIENT, "\tTransient: "); + Ioss::Utils::info_fields(ns, Ioss::Field::TRANSIENT, "\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(ns, Ioss::Field::REDUCTION, "\tTransient (Reduction): "); } } - void info_edgesets(Ioss::Region ®ion) + void info_edgesets(Ioss::Region ®ion, const Info::Interface &interFace) { const Ioss::EdgeSetContainer &nss = region.get_edgesets(); for (auto &ns : nss) { @@ -535,12 +552,13 @@ namespace { info_aliases(region, ns, false, true); info_df(ns, "\t"); Ioss::Utils::info_fields(ns, Ioss::Field::ATTRIBUTE, "\tAttributes: "); - Ioss::Utils::info_fields(ns, Ioss::Field::TRANSIENT, "\tTransient: "); + Ioss::Utils::info_fields(ns, Ioss::Field::TRANSIENT, "\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(ns, Ioss::Field::REDUCTION, "\tTransient (Reduction): "); } } - void info_facesets(Ioss::Region ®ion) + void info_facesets(Ioss::Region ®ion, const Info::Interface &interFace) { const Ioss::FaceSetContainer &fss = region.get_facesets(); for (auto &fs : fss) { @@ -551,12 +569,13 @@ namespace { info_aliases(region, fs, false, true); info_df(fs, "\t"); Ioss::Utils::info_fields(fs, Ioss::Field::ATTRIBUTE, "\tAttributes: "); - Ioss::Utils::info_fields(fs, Ioss::Field::TRANSIENT, "\tTransient: "); + Ioss::Utils::info_fields(fs, Ioss::Field::TRANSIENT, "\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(fs, Ioss::Field::REDUCTION, "\tTransient (Reduction): "); } } - void info_elementsets(Ioss::Region ®ion) + void info_elementsets(Ioss::Region ®ion, const Info::Interface &interFace) { const Ioss::ElementSetContainer &ess = region.get_elementsets(); for (auto &es : ess) { @@ -565,7 +584,8 @@ namespace { info_aliases(region, es, false, true); info_df(es, "\t"); Ioss::Utils::info_fields(es, Ioss::Field::ATTRIBUTE, "\tAttributes: "); - Ioss::Utils::info_fields(es, Ioss::Field::TRANSIENT, "\tTransient: "); + Ioss::Utils::info_fields(es, Ioss::Field::TRANSIENT, "\tTransient: ", "\n\t", + interFace.field_details()); Ioss::Utils::info_fields(es, Ioss::Field::REDUCTION, "\tTransient (Reduction): "); } } @@ -590,7 +610,7 @@ namespace { void info_aliases(const Ioss::Region ®ion, const Ioss::GroupingEntity *ige, bool nl_pre, bool nl_post) { - std::vector aliases; + Ioss::NameList aliases; if (region.get_aliases(ige->name(), ige->type(), aliases) > 0) { if (nl_pre) { fmt::print("\n"); @@ -688,15 +708,15 @@ namespace Ioss { info_region(region); info_assemblies(region); info_nodeblock(region, interFace); - info_edgeblock(region); - info_faceblock(region); + info_edgeblock(region, interFace); + info_faceblock(region, interFace); info_elementblock(region, interFace); info_structuredblock(region, interFace); - info_nodesets(region); - info_edgesets(region); - info_facesets(region); - info_elementsets(region); + info_nodesets(region, interFace); + info_edgesets(region, interFace); + info_facesets(region, interFace); + info_elementsets(region, interFace); info_sidesets(region, interFace); info_blobs(region); diff --git a/packages/seacas/libraries/ioss/src/main/io_modify.C b/packages/seacas/libraries/ioss/src/main/io_modify.C index 698302263f..b0461dc297 100644 --- a/packages/seacas/libraries/ioss/src/main/io_modify.C +++ b/packages/seacas/libraries/ioss/src/main/io_modify.C @@ -118,17 +118,16 @@ namespace { Ioss::NameList get_name_list(const Ioss::Region ®ion, Ioss::EntityType type); void handle_help(const std::string &topic); - bool handle_delete(const std::vector &tokens, Ioss::Region ®ion); - void handle_list(const std::vector &tokens, const Ioss::Region ®ion, + bool handle_delete(const Ioss::NameList &tokens, Ioss::Region ®ion); + void handle_list(const Ioss::NameList &tokens, const Ioss::Region ®ion, bool show_attribute = false); - void handle_graph(const std::vector &tokens, const Ioss::Region ®ion); - bool handle_assembly(const std::vector &tokens, Ioss::Region ®ion, - bool allow_modify); - bool handle_attribute(const std::vector &tokens, Ioss::Region ®ion); - bool handle_geometry(const std::vector &tokens, Ioss::Region ®ion); - bool handle_time(const std::vector &tokens, Ioss::Region ®ion); - bool handle_rename(const std::vector &tokens, Ioss::Region ®ion); - void update_assembly_info(Ioss::Region ®ion, const Modify::Interface &interFace); + void handle_graph(const Ioss::NameList &tokens, const Ioss::Region ®ion); + bool handle_assembly(const Ioss::NameList &tokens, Ioss::Region ®ion, bool allow_modify); + bool handle_attribute(const Ioss::NameList &tokens, Ioss::Region ®ion); + bool handle_geometry(const Ioss::NameList &tokens, Ioss::Region ®ion); + bool handle_time(const Ioss::NameList &tokens, Ioss::Region ®ion); + bool handle_rename(const Ioss::NameList &tokens, Ioss::Region ®ion); + void update_assembly_info(Ioss::Region ®ion, const Modify::Interface &interFace); void modify_time(Ioss::Region ®ion, double scale, double offset); @@ -153,7 +152,7 @@ namespace { void info_time(const Ioss::Region ®ion); template - void info_entities(const std::vector &entities, const std::vector &tokens, + void info_entities(const std::vector &entities, const Ioss::NameList &tokens, const Ioss::Region ®ion, const std::string &type, bool show_property = false) { @@ -696,8 +695,7 @@ namespace { } } - void handle_list(const std::vector &tokens, const Ioss::Region ®ion, - bool show_attribute) + void handle_list(const Ioss::NameList &tokens, const Ioss::Region ®ion, bool show_attribute) { if (tokens.size() > 1) { if (Ioss::Utils::substr_equal(tokens[1], "summary")) { @@ -764,9 +762,9 @@ namespace { class Graph { - std::map m_vertices; - std::vector m_vertex; - std::vector> m_adj; // Pointer to an array containing adjacency std::lists + std::map m_vertices; + Ioss::NameList m_vertex; + std::vector m_adj; // Pointer to an array containing adjacency std::lists bool is_cyclic_internal(int v, std::vector &visited, std::vector &recStack); int vertex(const std::string &node); @@ -854,7 +852,7 @@ namespace { return false; } - void handle_graph(const std::vector &tokens, const Ioss::Region ®ion) + void handle_graph(const Ioss::NameList &tokens, const Ioss::Region ®ion) { if (tokens.size() == 1) { handle_help("graph"); @@ -915,7 +913,7 @@ namespace { } } - bool handle_delete(const std::vector &tokens, Ioss::Region ®ion) + bool handle_delete(const Ioss::NameList &tokens, Ioss::Region ®ion) { // Returns true if requested assembly was deleted. // False if assembly does not exist, or was not deletable (not created during this run) @@ -957,7 +955,7 @@ namespace { return false; } - bool handle_attribute(const std::vector &tokens, Ioss::Region ®ion) + bool handle_attribute(const Ioss::NameList &tokens, Ioss::Region ®ion) { // 0 1 2 3 4 5... // ATTRIBUTE {{ent_name}} ADD {{att_name}} STRING {{values...}} @@ -1023,7 +1021,7 @@ namespace { ge->property_add(Ioss::Property(att_name, values, Ioss::Property::ATTRIBUTE)); } else if (Ioss::Utils::substr_equal(tokens[4], "integer")) { - std::vector values(value_count); + Ioss::IntVector values(value_count); for (size_t i = 0; i < value_count; i++) { try { int val = std::stoi(tokens[i + 5]); @@ -1085,7 +1083,7 @@ namespace { return false; } - bool handle_rename(const std::vector &tokens, Ioss::Region ®ion) + bool handle_rename(const Ioss::NameList &tokens, Ioss::Region ®ion) { // 0 1 2 3 4 // RENAME {{ent_name}} TO {{new_name}} @@ -1193,14 +1191,14 @@ namespace { auto node_count = region.get_property("node_count").get_int(); if (blocks.empty() || blocks.size() == (size_t)region.get_property("element_block_count").get_int()) { - return std::vector(node_count, 1); + return Ioss::IntVector(node_count, 1); } else { - std::vector node_filter(node_count); + Ioss::IntVector node_filter(node_count); // Iterate all element blocks in 'blocks', get connectivity_raw // and set `node_filter` to 1 for nodes in connectivity list. if (region.get_database()->int_byte_size_api() == 4) { - std::vector connect; + Ioss::IntVector connect; for (const auto *block : blocks) { block->get_field_data("connectivity_raw", connect); for (auto node : connect) { @@ -1221,7 +1219,7 @@ namespace { } } - bool handle_time(const std::vector &tokens, Ioss::Region ®ion) + bool handle_time(const Ioss::NameList &tokens, Ioss::Region ®ion) { // 0 1 2 // TIME SCALE {{scale}} @@ -1254,7 +1252,7 @@ namespace { return false; } - bool handle_geometry(const std::vector &tokens, Ioss::Region ®ion) + bool handle_geometry(const Ioss::NameList &tokens, Ioss::Region ®ion) { // 0 1 2 3 4 5... // GEOMETRY ROTATE {{X|Y|Z}} {{angle}} ... @@ -1461,8 +1459,7 @@ namespace { return false; } - bool handle_assembly(const std::vector &tokens, Ioss::Region ®ion, - bool allow_modify) + bool handle_assembly(const Ioss::NameList &tokens, Ioss::Region ®ion, bool allow_modify) { bool changed = false; Ioss::Assembly *assem = nullptr; diff --git a/packages/seacas/libraries/ioss/src/main/io_shell.C b/packages/seacas/libraries/ioss/src/main/io_shell.C index 251fe49cf6..b4f7f5e76e 100644 --- a/packages/seacas/libraries/ioss/src/main/io_shell.C +++ b/packages/seacas/libraries/ioss/src/main/io_shell.C @@ -122,7 +122,7 @@ int main(int argc, char *argv[]) if (!interFace.customField.empty()) { auto suffices = Ioss::tokenize(interFace.customField, ","); if (suffices.size() > 1) { - Ioss::VariableType::create_named_suffix_field_type("UserDefined", suffices); + Ioss::VariableType::create_named_suffix_type("UserDefined", suffices); } } std::string in_file = interFace.inputFile[0]; diff --git a/packages/seacas/libraries/ioss/src/main/io_shell_ts.C b/packages/seacas/libraries/ioss/src/main/io_shell_ts.C index f2db27fcf4..45bf61a950 100644 --- a/packages/seacas/libraries/ioss/src/main/io_shell_ts.C +++ b/packages/seacas/libraries/ioss/src/main/io_shell_ts.C @@ -984,25 +984,6 @@ namespace { pool.data.resize(isize); switch (interFace.data_storage_type) { case 1: ige->get_field_data(field_name, Data(pool.data), isize); break; - case 2: - if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { - ige->get_field_data(field_name, Data(pool.data), isize); - } - else if ((basic_type == Ioss::Field::INTEGER) || (basic_type == Ioss::Field::INT32)) { - ige->get_field_data(field_name, pool.data_int); - } - else if (basic_type == Ioss::Field::INT64) { - ige->get_field_data(field_name, pool.data_int64); - } - else if (basic_type == Ioss::Field::REAL) { - ige->get_field_data(field_name, pool.data_double); - } - else if (basic_type == Ioss::Field::COMPLEX) { - ige->get_field_data(field_name, pool.data_complex); - } - else { - } - break; #ifdef SEACAS_HAVE_KOKKOS case 3: if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { @@ -1078,25 +1059,6 @@ namespace { switch (interFace.data_storage_type) { case 1: oge->put_field_data(out_field_name, Data(pool.data), osize); break; - case 2: - if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { - oge->put_field_data(field_name, Data(pool.data), osize); - } - else if ((basic_type == Ioss::Field::INTEGER) || (basic_type == Ioss::Field::INT32)) { - oge->put_field_data(field_name, pool.data_int); - } - else if (basic_type == Ioss::Field::INT64) { - oge->put_field_data(field_name, pool.data_int64); - } - else if (basic_type == Ioss::Field::REAL) { - oge->put_field_data(field_name, pool.data_double); - } - else if (basic_type == Ioss::Field::COMPLEX) { - oge->put_field_data(field_name, pool.data_complex); - } - else { - } - break; #ifdef SEACAS_HAVE_KOKKOS case 3: if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { @@ -1258,25 +1220,6 @@ namespace { pool.data.resize(isize); switch (interFace.data_storage_type) { case 1: ige->get_field_data(field_name, Data(pool.data), isize); break; - case 2: - if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { - ige->get_field_data(field_name, Data(pool.data), isize); - } - else if ((basic_type == Ioss::Field::INTEGER) || (basic_type == Ioss::Field::INT32)) { - ige->get_field_data(field_name, pool.data_int); - } - else if (basic_type == Ioss::Field::INT64) { - ige->get_field_data(field_name, pool.data_int64); - } - else if (basic_type == Ioss::Field::REAL) { - ige->get_field_data(field_name, pool.data_double); - } - else if (basic_type == Ioss::Field::COMPLEX) { - ige->get_field_data(field_name, pool.data_complex); - } - else { - } - break; #ifdef SEACAS_HAVE_KOKKOS case 3: if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { @@ -1352,25 +1295,6 @@ namespace { switch (interFace.data_storage_type) { case 1: oge->put_field_data(field_name, Data(pool.data), isize); break; - case 2: - if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { - oge->put_field_data(field_name, Data(pool.data), isize); - } - else if ((basic_type == Ioss::Field::INTEGER) || (basic_type == Ioss::Field::INT32)) { - oge->put_field_data(field_name, pool.data_int); - } - else if (basic_type == Ioss::Field::INT64) { - oge->put_field_data(field_name, pool.data_int64); - } - else if (basic_type == Ioss::Field::REAL) { - oge->put_field_data(field_name, pool.data_double); - } - else if (basic_type == Ioss::Field::COMPLEX) { - oge->put_field_data(field_name, pool.data_complex); - } - else { - } - break; #ifdef SEACAS_HAVE_KOKKOS case 3: if ((basic_type == Ioss::Field::CHARACTER) || (basic_type == Ioss::Field::STRING)) { @@ -1446,7 +1370,7 @@ namespace { { out.add_information_records(in.get_information_records()); - const std::vector &qa = in.get_qa_records(); + const Ioss::NameList &qa = in.get_qa_records(); for (size_t i = 0; i < qa.size(); i += 4) { out.add_qa_record(qa[i + 0], qa[i + 1], qa[i + 2], qa[i + 3]); } diff --git a/packages/seacas/libraries/ioss/src/main/shell_interface.C b/packages/seacas/libraries/ioss/src/main/shell_interface.C index b505caba4a..b9a9284621 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_interface.C +++ b/packages/seacas/libraries/ioss/src/main/shell_interface.C @@ -648,9 +648,6 @@ bool IOShell::Interface::parse_options(int argc, char **argv, int my_processor) if (std::strcmp(temp, "POINTER") == 0) { data_storage_type = 1; } - else if (std::strcmp(temp, "STD_VECTOR") == 0) { - data_storage_type = 2; - } #ifdef SEACAS_HAVE_KOKKOS else if (std::strcmp(temp, "KOKKOS_VIEW_1D") == 0) { data_storage_type = 3; @@ -667,10 +664,10 @@ bool IOShell::Interface::parse_options(int argc, char **argv, int my_processor) if (my_processor == 0) { fmt::print(stderr, "ERROR: Option data_storage must be one of\n"); #ifdef SEACAS_HAVE_KOKKOS - fmt::print(stderr, " POINTER, STD_VECTOR, KOKKOS_VIEW_1D, KOKKOS_VIEW_2D, or " + fmt::print(stderr, " POINTER, KOKKOS_VIEW_1D, KOKKOS_VIEW_2D, or " "KOKKOS_VIEW_2D_LAYOUTRIGHT_HOSTSPACE\n"); #else - fmt::print(stderr, " POINTER, or STD_VECTOR\n"); + fmt::print(stderr, " POINTER\n"); #endif } return false; diff --git a/packages/seacas/libraries/ioss/src/main/skinner.C b/packages/seacas/libraries/ioss/src/main/skinner.C index 38a335bdb1..6ab0a4f0bc 100644 --- a/packages/seacas/libraries/ioss/src/main/skinner.C +++ b/packages/seacas/libraries/ioss/src/main/skinner.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2023 National Technology & Engineering Solutions +// Copyright(C) 1999-2024 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. // @@ -51,7 +51,7 @@ namespace { std::string version = "1.02"; void transfer_field_data(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge, - Ioss::Field::RoleType role, const std::vector &ref_nodes); + Ioss::Field::RoleType role, const Ioss::IntVector &ref_nodes); void transfer_field_data(Ioss::EntityBlock *ige, Ioss::EntityBlock *oge, Ioss::Field::RoleType role, @@ -85,13 +85,13 @@ namespace { fmt::print("\t+{2:-^{0}}+{2:-^{1}}+\n", max_name, max_face, ""); } - std::vector get_selected_steps(Ioss::Region ®ion, const Skinner::Interface &options) + Ioss::IntVector get_selected_steps(Ioss::Region ®ion, const Skinner::Interface &options) { // This routine checks all steps of the input database and selects those which // meet the requirements specified in `options`. The returned (1-based) vector will have a // value of `1` if the step is to be output and `0` if skipped. - int step_count = (int)region.get_property("state_count").get_int(); - std::vector selected_steps(step_count + 1); + int step_count = (int)region.get_property("state_count").get_int(); + Ioss::IntVector selected_steps(step_count + 1); // If user specified a list of times to transfer to output database, // process the list and find the times on the input database that are @@ -242,8 +242,8 @@ namespace { } // Iterate the boundary faces and determine which nodes are referenced... - size_t my_node_count = region.get_property("node_count").get_int(); - std::vector ref_nodes(my_node_count); + size_t my_node_count = region.get_property("node_count").get_int(); + Ioss::IntVector ref_nodes(my_node_count); for (const auto &boundaries : boundary_faces) { for (const auto &face : boundaries.second) { for (auto &gnode : face.connectivity_) { @@ -263,15 +263,15 @@ namespace { Ioss::NodeBlock *nb = region.get_node_blocks()[0]; nb->get_field_data("mesh_model_coordinates", coord_in); - std::vector ids; + Ioss::IntVector ids; nb->get_field_data("ids", ids); - std::vector owner; + Ioss::IntVector owner; nb->get_field_data("owning_processor", owner); - std::vector ref_ids(ref_count); + Ioss::IntVector ref_ids(ref_count); std::vector coord_out(3 * ref_count); - std::vector owner_out(ref_count); + Ioss::IntVector owner_out(ref_count); size_t j = 0; for (size_t i = 0; i < ref_nodes.size(); i++) { @@ -357,8 +357,8 @@ namespace { auto *block = output_region.get_element_block(name); size_t node_count = block->topology()->number_corner_nodes(); - std::vector conn; - std::vector elids; + Ioss::IntVector conn; + Ioss::IntVector elids; conn.reserve(node_count * boundary.size()); elids.reserve(boundary.size()); @@ -493,8 +493,7 @@ namespace { } void transfer_field_data_internal(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge, - const std::string &field_name, - const std::vector &ref_nodes) + const std::string &field_name, const Ioss::IntVector &ref_nodes) { if (oge->field_exists(field_name)) { std::vector in; @@ -520,7 +519,7 @@ namespace { } void transfer_field_data(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge, - Ioss::Field::RoleType role, const std::vector &ref_nodes) + Ioss::Field::RoleType role, const Ioss::IntVector &ref_nodes) { // Iterate through the TRANSIENT-role fields of the input // database and transfer to output database. diff --git a/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C b/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C index 76ae6a309b..60322ee6d7 100644 --- a/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C @@ -1473,8 +1473,8 @@ namespace Iopg { return elemMap; } - void DatabaseIO::compute_block_membership_nl(Ioss::SideBlock *sideblock, - std::vector &block_membership) const + void DatabaseIO::compute_block_membership_nl(Ioss::SideBlock *sideblock, + Ioss::NameList &block_membership) const { Ioss::IntVector block_ids(elementBlockCount); if (elementBlockCount == 1) { diff --git a/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.h b/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.h index 810bb10e21..4a06939971 100644 --- a/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.h @@ -80,8 +80,8 @@ namespace Iopg { IOSS_NODISCARD std::string title() const { return databaseTitle; } IOSS_NODISCARD int maximum_symbol_length() const override { return 32; } - void compute_block_membership_nl(Ioss::SideBlock *efblock, - std::vector &block_membership) const override; + void compute_block_membership_nl(Ioss::SideBlock *efblock, + Ioss::NameList &block_membership) const override; private: void read_meta_data_nl() override; diff --git a/packages/seacas/libraries/ioss/src/tokenize.C b/packages/seacas/libraries/ioss/src/tokenize.C index ba43c4c0f4..94f1dff747 100644 --- a/packages/seacas/libraries/ioss/src/tokenize.C +++ b/packages/seacas/libraries/ioss/src/tokenize.C @@ -8,14 +8,14 @@ #include using TokenList = std::vector; -TokenList Ioss::tokenize(const std::string &str, const std::string &separators) +TokenList Ioss::tokenize(const std::string &str, const std::string &separators, bool allow_empty) { TokenList tokens; auto first = std::begin(str); while (first != std::end(str)) { const auto second = std::find_first_of(first, std::end(str), std::begin(separators), std::end(separators)); - if (first != second) { + if (allow_empty || (first != second)) { tokens.emplace_back(first, second); } if (second == std::end(str)) { diff --git a/packages/seacas/libraries/ioss/src/tokenize.h b/packages/seacas/libraries/ioss/src/tokenize.h index 57c518bb9e..73bc21f20d 100644 --- a/packages/seacas/libraries/ioss/src/tokenize.h +++ b/packages/seacas/libraries/ioss/src/tokenize.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2024 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. * @@ -17,6 +17,6 @@ namespace Ioss { * Take the 'str' argument and split it using the list of characters * in separators as separators. Use tokens to return the result. */ - IOSS_EXPORT std::vector tokenize(const std::string &str, - const std::string &separators); + IOSS_EXPORT std::vector + tokenize(const std::string &str, const std::string &separators, bool allow_empty = false); } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C b/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C index ae51e88236..7713bf98ef 100644 --- a/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C +++ b/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C @@ -154,7 +154,7 @@ void check_split_assign(std::vector &zones, } } - // In Iocgns::Utils::common_write_meta_data, there is code to make + // In Iocgns::Utils::common_write_metadata, there is code to make // sure that the zgc.m_connectionName is unique for all zgc instances on // a zone / processor pair (if !parallel_io which is file-per-processor) // The uniquification appends a letter from 'A' to 'Z' to the name diff --git a/packages/seacas/libraries/ioss/src/visualization/cgns/Iovs_cgns_IOFactory.h b/packages/seacas/libraries/ioss/src/visualization/cgns/Iovs_cgns_IOFactory.h index 3a0e75b6d3..4cddabaf2d 100644 --- a/packages/seacas/libraries/ioss/src/visualization/cgns/Iovs_cgns_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/visualization/cgns/Iovs_cgns_IOFactory.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions +// Copyright(C) 1999-2021, 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. // diff --git a/packages/seacas/libraries/ioss/src/visualization/exodus/Iovs_exodus_IOFactory.h b/packages/seacas/libraries/ioss/src/visualization/exodus/Iovs_exodus_IOFactory.h index 28a5d01441..0d0fca14ad 100644 --- a/packages/seacas/libraries/ioss/src/visualization/exodus/Iovs_exodus_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/visualization/exodus/Iovs_exodus_IOFactory.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions +// Copyright(C) 1999-2021, 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. // diff --git a/signatures/version1/cla.json b/signatures/version1/cla.json index b42bc58b74..7516f5c063 100644 --- a/signatures/version1/cla.json +++ b/signatures/version1/cla.json @@ -161,4 +161,4 @@ "pullRequestNo": 448 } ] -} \ No newline at end of file +}