1 /*
2 * Copyright(C) 1999-2021 National Technology & Engineering Solutions
3 * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
4 * NTESS, the U.S. Government retains certain rights in this software.
5 *
6 * See packages/seacas/LICENSE for details
7 */
8
9 #include "exodusII.h"
10 #include "exodusII_int.h"
11
12 /*! \cond INTERNAL */
ex__get_dimension_value(int exoid,int64_t * var,int default_value,const char * dimension_name,int missing_ok)13 static int ex__get_dimension_value(int exoid, int64_t *var, int default_value,
14 const char *dimension_name, int missing_ok)
15 {
16 int status;
17 char errmsg[MAX_ERR_LENGTH];
18 size_t idum;
19 int dimid;
20
21 if ((status = nc_inq_dimid(exoid, dimension_name, &dimid)) != NC_NOERR) {
22 *var = default_value;
23 if (missing_ok) {
24 return (EX_NOERR);
25 }
26 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to retrieve dimension %s for file id %d",
27 dimension_name, exoid);
28 ex_err_fn(exoid, __func__, errmsg, status);
29 return (EX_FATAL);
30 }
31 if ((status = nc_inq_dimlen(exoid, dimid, &idum)) != NC_NOERR) {
32 *var = default_value;
33 snprintf(errmsg, MAX_ERR_LENGTH,
34 "ERROR: failed to retrieve value for dimension %s for file id %d", dimension_name,
35 exoid);
36 ex_err_fn(exoid, __func__, errmsg, status);
37 return (EX_FATAL);
38 }
39 *var = idum;
40 return (EX_NOERR);
41 }
42
ex_get_concat_set_len(int exoid,int64_t * set_length,const char * set_name,const char * set_num_dim,const char * set_stat_var,const char * set_size_root,int missing_ok)43 static int ex_get_concat_set_len(int exoid, int64_t *set_length, const char *set_name,
44 const char *set_num_dim, const char *set_stat_var,
45 const char *set_size_root, int missing_ok)
46 {
47 int i;
48 int status;
49 char errmsg[MAX_ERR_LENGTH];
50 size_t idum;
51 int dimid, varid;
52 size_t num_sets;
53 int * stat_vals = NULL;
54
55 *set_length = 0; /* default return value */
56
57 if ((status = nc_inq_dimid(exoid, set_num_dim, &dimid)) == NC_NOERR) {
58 if ((status = nc_inq_dimlen(exoid, dimid, &num_sets)) != NC_NOERR) {
59 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of %s sets in file id %d",
60 set_name, exoid);
61 ex_err_fn(exoid, __func__, errmsg, status);
62 return (EX_FATAL);
63 }
64
65 /* Allocate space for stat array */
66 if (!(stat_vals = malloc((int)num_sets * sizeof(int)))) {
67 snprintf(errmsg, MAX_ERR_LENGTH,
68 "ERROR: failed to allocate memory for %s set status "
69 "array for file id %d",
70 set_name, exoid);
71 ex_err_fn(exoid, __func__, errmsg, EX_MEMFAIL);
72 return (EX_FATAL);
73 }
74
75 /* get variable id of status array */
76 if ((status = nc_inq_varid(exoid, set_stat_var, &varid)) == NC_NOERR) {
77 /* if status array exists, use it, otherwise assume, object exists
78 to be backward compatible */
79 if ((status = nc_get_var_int(exoid, varid, stat_vals)) != NC_NOERR) {
80 free(stat_vals);
81 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get %s set status array from file id %d",
82 set_name, exoid);
83 ex_err_fn(exoid, __func__, errmsg, status);
84 return (EX_FATAL);
85 }
86 }
87 else { /* default: status is true */
88 for (i = 0; i < num_sets; i++) {
89 stat_vals[i] = 1;
90 }
91 }
92
93 for (i = 0; i < num_sets; i++) {
94 if (stat_vals[i] == 0) { /* is this object null? */
95 continue;
96 }
97
98 if ((status = nc_inq_dimid(exoid, ex__catstr(set_size_root, i + 1), &dimid)) != NC_NOERR) {
99 if (missing_ok) {
100 idum = 0;
101 }
102 else {
103 *set_length = 0;
104 free(stat_vals);
105 return (EX_FATAL);
106 }
107 }
108 else {
109 if ((status = nc_inq_dimlen(exoid, dimid, &idum)) != NC_NOERR) {
110 *set_length = 0;
111 free(stat_vals);
112 return (EX_FATAL);
113 }
114 }
115
116 *set_length += idum;
117 }
118
119 free(stat_vals);
120 }
121 return (EX_NOERR);
122 }
123
flt_cvt(float * xptr,double x)124 static void flt_cvt(float *xptr, double x) { *xptr = (float)x; }
125 /*! \endcond */
126
ex_inquire_internal(int exoid,int req_info,int64_t * ret_int,float * ret_float,char * ret_char)127 static int ex_inquire_internal(int exoid, int req_info, int64_t *ret_int, float *ret_float,
128 char *ret_char)
129 {
130 int dimid, varid, rootid;
131 void_int *ids = NULL;
132 size_t i;
133 size_t ldum = 0;
134 size_t num_sets, idum;
135 int * stat_vals;
136 char errmsg[MAX_ERR_LENGTH];
137 int status;
138 char tmp_title[2048];
139 int num_var;
140
141 if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) {
142 return (EX_FATAL);
143 }
144
145 if (ret_char) {
146 *ret_char = '\0'; /* Only needs to be non-null for TITLE and some GROUP NAME inquiries */
147 }
148 if (!ret_int) {
149 snprintf(errmsg, MAX_ERR_LENGTH, "Warning: integer argument is NULL which is not allowed.");
150 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
151 return (EX_FATAL);
152 }
153
154 rootid = exoid & EX_FILE_ID_MASK;
155
156 switch (req_info) {
157 case EX_INQ_FILE_TYPE:
158
159 /* obsolete call */
160 /*returns "r" for regular EXODUS file or "h" for history EXODUS file*/
161 snprintf(errmsg, MAX_ERR_LENGTH, "Warning: file type inquire is obsolete");
162 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
163 return (EX_WARN);
164
165 case EX_INQ_API_VERS:
166 /* returns the EXODUS API version number */
167 if (!ret_float) {
168 snprintf(errmsg, MAX_ERR_LENGTH,
169 "Warning: float argument is NULL for EX_INQ_API_VERS "
170 "which is not allowed.");
171 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
172 return (EX_FATAL);
173 }
174
175 if (nc_get_att_float(rootid, NC_GLOBAL, ATT_API_VERSION, ret_float) !=
176 NC_NOERR) { /* try old (prior to db version 2.02) attribute name */
177 if ((status = nc_get_att_float(rootid, NC_GLOBAL, ATT_API_VERSION_BLANK, ret_float)) !=
178 NC_NOERR) {
179 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get EXODUS API version for file id %d",
180 rootid);
181 ex_err_fn(exoid, __func__, errmsg, status);
182 return (EX_FATAL);
183 }
184 }
185
186 break;
187
188 case EX_INQ_DB_VERS:
189 /* returns the EXODUS database version number */
190 if (!ret_float) {
191 snprintf(errmsg, MAX_ERR_LENGTH,
192 "Warning: float argument is NULL for EX_INQ_DB_VERS "
193 "which is not allowed.");
194 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
195 return (EX_FATAL);
196 }
197
198 if ((status = nc_get_att_float(rootid, NC_GLOBAL, ATT_VERSION, ret_float)) != NC_NOERR) {
199 snprintf(errmsg, MAX_ERR_LENGTH,
200 "ERROR: failed to get EXODUS database version for file id %d", rootid);
201 ex_err_fn(exoid, __func__, errmsg, status);
202 return (EX_FATAL);
203 }
204 break;
205
206 case EX_INQ_LIB_VERS:
207 /* returns the EXODUS Library version number */
208 if (ret_float) {
209 float version_major = EXODUS_VERSION_MAJOR;
210 float version_minor = EXODUS_VERSION_MINOR;
211 float version = version_major + version_minor / 100.0;
212 flt_cvt(ret_float, version);
213 }
214
215 if (ret_int) {
216 *ret_int = EX_API_VERS_NODOT;
217 }
218 break;
219
220 case EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH:
221 /* Return the MAX_NAME_LENGTH size for this database
222 It will not include the space for the trailing null, so if it
223 is defined as 33 on the database, 32 will be returned.
224 */
225 if ((status = nc_inq_dimid(rootid, DIM_STR_NAME, &dimid)) != NC_NOERR) {
226 /* If not found, then an older database */
227 *ret_int = 32;
228 }
229 else {
230 /* Get the name string length */
231 size_t name_length = 0;
232 if ((status = nc_inq_dimlen(rootid, dimid, &name_length)) != NC_NOERR) {
233 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get name string length in file id %d",
234 exoid);
235 ex_err_fn(exoid, __func__, errmsg, status);
236 return (EX_FATAL);
237 }
238
239 *ret_int = name_length - 1;
240 }
241 break;
242
243 case EX_INQ_DB_FLOAT_SIZE: {
244 nc_get_att_longlong(rootid, NC_GLOBAL, ATT_FLT_WORDSIZE, (long long *)ret_int);
245 } break;
246
247 case EX_INQ_DB_MAX_USED_NAME_LENGTH:
248 /* Return the value of the ATT_MAX_NAME_LENGTH attribute (if it
249 exists) which is the maximum length of any entity, variable,
250 attribute, property name written to this database. If the
251 attribute does not exist, then '32' is returned. The length
252 does not include the trailing null.
253 */
254 {
255 nc_type att_type = NC_NAT;
256 size_t att_len = 0;
257
258 *ret_int = 32; /* Default size consistent with older databases */
259
260 status = nc_inq_att(rootid, NC_GLOBAL, ATT_MAX_NAME_LENGTH, &att_type, &att_len);
261 if (status == NC_NOERR && att_type == NC_INT) {
262 /* The attribute exists, return it... */
263 nc_get_att_longlong(rootid, NC_GLOBAL, ATT_MAX_NAME_LENGTH, (long long *)ret_int);
264 }
265 }
266 break;
267
268 case EX_INQ_MAX_READ_NAME_LENGTH: {
269 /* Returns the user-specified maximum size of names that will be
270 * returned to the user by any of the ex_get_ routines. If the
271 * name is longer than this value, it will be truncated. The
272 * default if not set by the client is 32 characters. The value
273 * does not include the trailing null.
274 */
275 struct ex__file_item *file = ex__find_file_item(rootid);
276
277 if (!file) {
278 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: unknown file id %d for ex_inquire_int().", rootid);
279 ex_err_fn(exoid, __func__, errmsg, EX_BADFILEID);
280 *ret_int = 0;
281 }
282 else {
283 *ret_int = file->maximum_name_length;
284 }
285 } break;
286
287 case EX_INQ_TITLE:
288 if (!ret_char) {
289 snprintf(errmsg, MAX_ERR_LENGTH,
290 "ERROR: Requested title, but character pointer was null "
291 "for file id %d",
292 rootid);
293 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
294 return (EX_FATAL);
295 }
296 else {
297 /* returns the title of the database */
298 /* Title is stored at root level... */
299 if ((status = nc_get_att_text(rootid, NC_GLOBAL, ATT_TITLE, tmp_title)) != NC_NOERR) {
300 *ret_char = '\0';
301 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get database title for file id %d",
302 exoid);
303 ex_err_fn(exoid, __func__, errmsg, status);
304 return (EX_FATAL);
305 }
306 ex_copy_string(ret_char, tmp_title, MAX_LINE_LENGTH + 1);
307 }
308 break;
309
310 case EX_INQ_DIM:
311 /* returns the dimensionality (2 or 3, for 2-d or 3-d) of the database */
312 if (ex__get_dimension(exoid, DIM_NUM_DIM, "database dimensionality", &ldum, &dimid, __func__) !=
313 NC_NOERR) {
314 return (EX_FATAL);
315 }
316 *ret_int = ldum;
317 break;
318
319 case EX_INQ_ASSEMBLY:
320 /* returns the number of assemblies */
321 {
322 *ret_int = 0;
323 struct ex__file_item *file = ex__find_file_item(exoid);
324 if (file) {
325 *ret_int = file->assembly_count;
326 }
327 }
328 break;
329
330 case EX_INQ_BLOB:
331 /* returns the number of blobs */
332 {
333 *ret_int = 0;
334 struct ex__file_item *file = ex__find_file_item(exoid);
335 if (file) {
336 *ret_int = file->blob_count;
337 }
338 }
339 break;
340
341 case EX_INQ_NODES:
342 /* returns the number of nodes */
343 if (ex__get_dimension(exoid, DIM_NUM_NODES, "nodes", &ldum, &dimid, NULL) != NC_NOERR) {
344 *ret_int = 0;
345 }
346 else {
347 *ret_int = ldum;
348 }
349 break;
350
351 case EX_INQ_ELEM:
352 /* returns the number of elements */
353 if (ex__get_dimension(exoid, DIM_NUM_ELEM, "elements", &ldum, &dimid, NULL) != NC_NOERR) {
354 *ret_int = 0;
355 }
356 else {
357 *ret_int = ldum;
358 }
359 break;
360
361 case EX_INQ_ELEM_BLK:
362 /* returns the number of element blocks */
363 if (ex__get_dimension(exoid, DIM_NUM_EL_BLK, "element blocks", &ldum, &dimid, NULL) !=
364 NC_NOERR) {
365 *ret_int = 0;
366 }
367 else {
368 *ret_int = ldum;
369 }
370 break;
371
372 case EX_INQ_NODE_SETS:
373 /* returns the number of node sets */
374 if (ex__get_dimension(exoid, DIM_NUM_NS, "node sets", &ldum, &dimid, NULL) != NC_NOERR) {
375 *ret_int = 0;
376 }
377 else {
378 *ret_int = ldum;
379 }
380 break;
381
382 case EX_INQ_NS_NODE_LEN:
383 /* returns the length of the concatenated node sets node list */
384 ex_get_concat_set_len(exoid, ret_int, "node", DIM_NUM_NS, VAR_NS_STAT, "num_nod_ns", 0);
385 break;
386
387 case EX_INQ_NS_DF_LEN:
388 /* returns the length of the concatenated node sets dist factor list */
389
390 /*
391 Determine the concatenated node sets distribution factor length:
392
393 2. Check see if the dist factor variable for a node set id exists.
394 3. If it exists, goto step 4, else the length is zero.
395 4. Get the dimension of the number of nodes in the node set -0
396 use this value as the length as by definition they are the same.
397 5. Sum the individual lengths for the total list length.
398 */
399
400 *ret_int = 0; /* default value if no node sets defined */
401
402 if (nc_inq_dimid(exoid, DIM_NUM_NS, &dimid) == NC_NOERR) {
403 if ((status = nc_inq_dimlen(exoid, dimid, &num_sets)) != NC_NOERR) {
404 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of node sets in file id %d",
405 exoid);
406 ex_err_fn(exoid, __func__, errmsg, status);
407 return (EX_FATAL);
408 }
409
410 for (i = 0; i < num_sets; i++) {
411 if ((status = nc_inq_varid(exoid, VAR_FACT_NS(i + 1), &varid)) != NC_NOERR) {
412 if (status == NC_ENOTVAR) {
413 idum = 0; /* this dist factor doesn't exist */
414 }
415 else {
416 *ret_int = 0;
417 snprintf(
418 errmsg, MAX_ERR_LENGTH,
419 "ERROR: failed to locate number of dist fact for %zu'th node set in file id %d", i,
420 exoid);
421 ex_err_fn(exoid, __func__, errmsg, status);
422 return (EX_FATAL);
423 }
424 }
425 else {
426 if ((status = nc_inq_dimid(exoid, DIM_NUM_NOD_NS(i + 1), &dimid)) != NC_NOERR) {
427 *ret_int = 0;
428 snprintf(errmsg, MAX_ERR_LENGTH,
429 "ERROR: failed to locate number of nodes in %zu'th node set in file id %d", i,
430 exoid);
431 ex_err_fn(exoid, __func__, errmsg, status);
432 return (EX_FATAL);
433 }
434 if ((status = nc_inq_dimlen(exoid, dimid, &idum)) != NC_NOERR) {
435 *ret_int = 0;
436 snprintf(errmsg, MAX_ERR_LENGTH,
437 "ERROR: failed to get number of nodes in %zu'th node set in file id %d", i,
438 exoid);
439 ex_err_fn(exoid, __func__, errmsg, status);
440 return (EX_FATAL);
441 }
442 }
443 *ret_int += idum;
444 }
445 }
446
447 break;
448
449 case EX_INQ_SIDE_SETS:
450 /* returns the number of side sets */
451 if (ex__get_dimension(exoid, DIM_NUM_SS, "side sets", &ldum, &dimid, NULL) != NC_NOERR) {
452 *ret_int = 0;
453 }
454 else {
455 *ret_int = ldum;
456 }
457 break;
458
459 case EX_INQ_SS_NODE_LEN:
460
461 /* returns the length of the concatenated side sets node list */
462
463 *ret_int = 0; /* default return value */
464
465 if (nc_inq_dimid(exoid, DIM_NUM_SS, &dimid) == NC_NOERR) {
466 if ((status = nc_inq_dimlen(exoid, dimid, &num_sets)) != NC_NOERR) {
467 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
468 exoid);
469 ex_err_fn(exoid, __func__, errmsg, status);
470 return (EX_FATAL);
471 }
472
473 if (!(ids = malloc(num_sets * sizeof(int64_t)))) { /* May be getting 2x what is
474 needed, but should be OK */
475 snprintf(errmsg, MAX_ERR_LENGTH,
476 "ERROR: failed to allocate memory for side set ids for file id %d", exoid);
477 ex_err_fn(exoid, __func__, errmsg, EX_MEMFAIL);
478 return (EX_FATAL);
479 }
480
481 if (ex_get_ids(exoid, EX_SIDE_SET, ids) == EX_FATAL) {
482 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get side set ids in file id %d", exoid);
483 ex_err_fn(exoid, __func__, errmsg, EX_LASTERR);
484 free(ids);
485 return (EX_FATAL);
486 }
487
488 /* allocate space for stat array */
489 if (!(stat_vals = malloc((int)num_sets * sizeof(int)))) {
490 free(ids);
491 snprintf(errmsg, MAX_ERR_LENGTH,
492 "ERROR: failed to allocate memory for side set status "
493 "array for file id %d",
494 exoid);
495 ex_err_fn(exoid, __func__, errmsg, EX_MEMFAIL);
496 return (EX_FATAL);
497 }
498 /* get variable id of status array */
499 if ((status = nc_inq_varid(exoid, VAR_SS_STAT, &varid)) == NC_NOERR) {
500 /* if status array exists, use it, otherwise assume, object exists
501 to be backward compatible */
502
503 if ((status = nc_get_var_int(exoid, varid, stat_vals)) != NC_NOERR) {
504 free(ids);
505 free(stat_vals);
506 snprintf(errmsg, MAX_ERR_LENGTH,
507 "ERROR: failed to get element block status array from file id %d", exoid);
508 ex_err_fn(exoid, __func__, errmsg, status);
509 return (EX_FATAL);
510 }
511 }
512 else { /* default: status is true */
513 for (i = 0; i < num_sets; i++) {
514 stat_vals[i] = 1;
515 }
516 }
517
518 /* walk id list, get each side set node length and sum for total */
519
520 for (i = 0; i < num_sets; i++) {
521 ex_entity_id id;
522 if (stat_vals[i] == 0) { /* is this object null? */
523 continue;
524 }
525
526 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
527 int64_t tmp_len = 0;
528 id = ((int64_t *)ids)[i];
529 status = ex_get_side_set_node_list_len(exoid, id, &tmp_len);
530 if (status != EX_FATAL) {
531 *ret_int += tmp_len;
532 }
533 }
534 else {
535 int tmp_len = 0;
536 id = ((int *)ids)[i];
537 status = ex_get_side_set_node_list_len(exoid, id, &tmp_len);
538 if (status != EX_FATAL) {
539 *ret_int += tmp_len;
540 }
541 }
542
543 if (status == EX_FATAL) {
544 *ret_int = 0;
545 snprintf(errmsg, MAX_ERR_LENGTH,
546 "ERROR: failed to side set %" PRId64 " node length in file id %d", id, exoid);
547 ex_err_fn(exoid, __func__, errmsg, status);
548 free(stat_vals);
549 free(ids);
550 return (EX_FATAL);
551 }
552 }
553
554 free(stat_vals);
555 free(ids);
556 }
557
558 break;
559
560 case EX_INQ_SS_ELEM_LEN:
561 /* returns the length of the concatenated side sets element list */
562 ex_get_concat_set_len(exoid, ret_int, "side", DIM_NUM_SS, VAR_SS_STAT, "num_side_ss", 0);
563 break;
564
565 case EX_INQ_SS_DF_LEN:
566
567 /* returns the length of the concatenated side sets dist factor list */
568
569 /*
570 Determine the concatenated side sets distribution factor length:
571
572 1. Get the side set ids list.
573 2. Check see if the dist factor dimension for a side set id exists.
574 3. If it exists, goto step 4, else set the individual length to zero.
575 4. Sum the dimension value into the running total length.
576 */
577
578 *ret_int = 0;
579
580 /* first check see if any side sets exist */
581
582 if (nc_inq_dimid(exoid, DIM_NUM_SS, &dimid) == NC_NOERR) {
583 if ((status = nc_inq_dimlen(exoid, dimid, &num_sets)) != NC_NOERR) {
584 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
585 exoid);
586 ex_err_fn(exoid, __func__, errmsg, status);
587 return (EX_FATAL);
588 }
589
590 for (i = 0; i < num_sets; i++) {
591 if ((status = nc_inq_dimid(exoid, DIM_NUM_DF_SS(i + 1), &dimid)) != NC_NOERR) {
592 if (status == NC_EBADDIM) {
593 ldum = 0; /* this dist factor doesn't exist */
594 }
595 else {
596 *ret_int = 0;
597 snprintf(
598 errmsg, MAX_ERR_LENGTH,
599 "ERROR: failed to locate number of dist fact for %zu'th side set in file id %d", i,
600 exoid);
601 ex_err_fn(exoid, __func__, errmsg, status);
602 return (EX_FATAL);
603 }
604 }
605 else {
606 if ((status = nc_inq_dimlen(exoid, dimid, &ldum)) != NC_NOERR) {
607 *ret_int = 0;
608 snprintf(errmsg, MAX_ERR_LENGTH,
609 "ERROR: failed to get number of dist factors in %zu'th side set in file id %d",
610 i, exoid);
611 ex_err_fn(exoid, __func__, errmsg, status);
612 return (EX_FATAL);
613 }
614 }
615 *ret_int += ldum;
616 }
617 }
618
619 break;
620
621 case EX_INQ_QA:
622 /* returns the number of QA records */
623 if (ex__get_dimension(rootid, DIM_NUM_QA, "QA records", &ldum, &dimid, NULL) != NC_NOERR) {
624 *ret_int = 0;
625 }
626 else {
627 *ret_int = ldum;
628 }
629 break;
630
631 case EX_INQ_INFO:
632 /* returns the number of information records */
633 if (ex__get_dimension(rootid, DIM_NUM_INFO, "info records", &ldum, &dimid, NULL) != NC_NOERR) {
634 *ret_int = 0;
635 }
636 else {
637 *ret_int = ldum;
638 }
639 break;
640
641 case EX_INQ_TIME:
642 /* returns the number of time steps stored in the database */
643 if (ex__get_dimension(exoid, DIM_TIME, "time dimension", &ldum, &dimid, __func__) != NC_NOERR) {
644 return (EX_FATAL);
645 }
646 *ret_int = ldum;
647 break;
648
649 case EX_INQ_EB_PROP:
650 /* returns the number of element block properties */
651 *ret_int = ex_get_num_props(exoid, EX_ELEM_BLOCK);
652 break;
653
654 case EX_INQ_NS_PROP:
655 /* returns the number of node set properties */
656 *ret_int = ex_get_num_props(exoid, EX_NODE_SET);
657 break;
658
659 case EX_INQ_SS_PROP:
660 /* returns the number of side set properties */
661 *ret_int = ex_get_num_props(exoid, EX_SIDE_SET);
662 break;
663
664 case EX_INQ_ELEM_MAP:
665 /* returns the number of element maps */
666 if (ex__get_dimension(exoid, DIM_NUM_EM, "element maps", &ldum, &dimid, NULL) != NC_NOERR) {
667 *ret_int = 0;
668 }
669 else {
670 *ret_int = ldum;
671 }
672 break;
673
674 case EX_INQ_EM_PROP:
675 /* returns the number of element map properties */
676 *ret_int = ex_get_num_props(exoid, EX_ELEM_MAP);
677 break;
678
679 case EX_INQ_NODE_MAP:
680 /* returns the number of node maps */
681 if (ex__get_dimension(exoid, DIM_NUM_NM, "node maps", &ldum, &dimid, NULL) != NC_NOERR) {
682 *ret_int = 0;
683 }
684 else {
685 *ret_int = ldum;
686 }
687 break;
688
689 case EX_INQ_NM_PROP:
690 /* returns the number of node map properties */
691 *ret_int = ex_get_num_props(exoid, EX_NODE_MAP);
692 break;
693
694 case EX_INQ_EDGE:
695 /* returns the number of edges (defined across all edge blocks). */
696 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_EDGE, 1) != EX_NOERR) {
697 return (EX_FATAL);
698 }
699 break;
700
701 case EX_INQ_EDGE_BLK:
702 /* returns the number of edge blocks. */
703 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_ED_BLK, 1) != EX_NOERR) {
704 return (EX_FATAL);
705 }
706 break;
707
708 case EX_INQ_EDGE_SETS:
709 /* returns the number of edge sets. */
710 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_ES, 1) != EX_NOERR) {
711 return (EX_FATAL);
712 }
713 break;
714
715 case EX_INQ_ES_LEN:
716 /* returns the length of the concatenated edge set edge list. */
717 ex_get_concat_set_len(exoid, ret_int, "edge", DIM_NUM_ES, VAR_ES_STAT, "num_edge_es", 0);
718 break;
719
720 case EX_INQ_ES_DF_LEN:
721 /* returns the length of the concatenated edge set distribution factor list.
722 */
723 ex_get_concat_set_len(exoid, ret_int, "edge", DIM_NUM_ES, VAR_ES_STAT, "num_df_es", 1);
724 break;
725
726 case EX_INQ_EDGE_PROP:
727 /* returns the number of integer properties stored for each edge block. This
728 * includes the "ID" property. */
729 *ret_int = ex_get_num_props(exoid, EX_EDGE_BLOCK);
730 break;
731
732 case EX_INQ_ES_PROP:
733 /* returns the number of integer properties stored for each edge set.. This
734 * includes the "ID" property */
735 *ret_int = ex_get_num_props(exoid, EX_EDGE_SET);
736 break;
737
738 case EX_INQ_FACE:
739 /* returns the number of faces (defined across all face blocks). */
740 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_FACE, 1) != EX_NOERR) {
741 return (EX_FATAL);
742 }
743 break;
744
745 case EX_INQ_FACE_BLK:
746 /* returns the number of face blocks. */
747 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_FA_BLK, 1) != EX_NOERR) {
748 return (EX_FATAL);
749 }
750 break;
751
752 case EX_INQ_FACE_SETS:
753 /* returns the number of face sets. */
754 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_FS, 1) != EX_NOERR) {
755 return (EX_FATAL);
756 }
757 break;
758
759 case EX_INQ_FS_LEN:
760 /* returns the length of the concatenated edge set edge list. */
761 ex_get_concat_set_len(exoid, ret_int, "face", DIM_NUM_FS, VAR_FS_STAT, "num_face_fs", 0);
762 break;
763
764 case EX_INQ_FS_DF_LEN:
765 /* returns the length of the concatenated edge set distribution factor list.
766 */
767 ex_get_concat_set_len(exoid, ret_int, "face", DIM_NUM_FS, VAR_FS_STAT, "num_df_fs", 1);
768 break;
769
770 case EX_INQ_FACE_PROP:
771 /* returns the number of integer properties stored for each edge block. This
772 * includes the "ID" property. */
773 *ret_int = ex_get_num_props(exoid, EX_FACE_BLOCK);
774 break;
775
776 case EX_INQ_FS_PROP:
777 /* returns the number of integer properties stored for each edge set.. This
778 * includes the "ID" property */
779 *ret_int = ex_get_num_props(exoid, EX_FACE_SET);
780 break;
781
782 case EX_INQ_ELEM_SETS:
783 /* returns the number of element sets. */
784 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_ELS, 1) != EX_NOERR) {
785 return (EX_FATAL);
786 }
787 break;
788
789 case EX_INQ_ELS_LEN:
790 /* returns the length of the concatenated element set element list. */
791 ex_get_concat_set_len(exoid, ret_int, "element", DIM_NUM_ELS, VAR_ELS_STAT, "num_ele_els", 0);
792 break;
793
794 case EX_INQ_ELS_DF_LEN:
795 /* returns the length of the concatenated element set distribution factor
796 * list. */
797 ex_get_concat_set_len(exoid, ret_int, "element", DIM_NUM_ELS, VAR_ELS_STAT, "num_df_els", 1);
798 break;
799
800 case EX_INQ_ELS_PROP:
801 /* returns the number of integer properties stored for each element set. */
802 *ret_int = ex_get_num_props(exoid, EX_ELEM_SET);
803 break;
804
805 case EX_INQ_EDGE_MAP:
806 /* returns the number of edge maps. */
807 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_EDM, 1) != EX_NOERR) {
808 return (EX_FATAL);
809 }
810 break;
811
812 case EX_INQ_FACE_MAP:
813 /* returns the number of face maps. */
814 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_FAM, 1) != EX_NOERR) {
815 return (EX_FATAL);
816 }
817 break;
818
819 case EX_INQ_NUM_NODE_VAR:
820 if (ex_get_variable_param(exoid, EX_NODAL, &num_var) != EX_NOERR) {
821 return (EX_FATAL);
822 }
823 *ret_int = num_var;
824 break;
825
826 case EX_INQ_NUM_EDGE_BLOCK_VAR:
827 if (ex_get_variable_param(exoid, EX_EDGE_BLOCK, &num_var) != EX_NOERR) {
828 return (EX_FATAL);
829 }
830 *ret_int = num_var;
831 break;
832
833 case EX_INQ_NUM_FACE_BLOCK_VAR:
834 if (ex_get_variable_param(exoid, EX_FACE_BLOCK, &num_var) != EX_NOERR) {
835 return (EX_FATAL);
836 }
837 *ret_int = num_var;
838 break;
839
840 case EX_INQ_NUM_ELEM_BLOCK_VAR:
841 if (ex_get_variable_param(exoid, EX_ELEM_BLOCK, &num_var) != EX_NOERR) {
842 return (EX_FATAL);
843 }
844 *ret_int = num_var;
845 break;
846
847 case EX_INQ_NUM_NODE_SET_VAR:
848 if (ex_get_variable_param(exoid, EX_NODE_SET, &num_var) != EX_NOERR) {
849 return (EX_FATAL);
850 }
851 *ret_int = num_var;
852 break;
853
854 case EX_INQ_NUM_EDGE_SET_VAR:
855 if (ex_get_variable_param(exoid, EX_EDGE_SET, &num_var) != EX_NOERR) {
856 return (EX_FATAL);
857 }
858 *ret_int = num_var;
859 break;
860
861 case EX_INQ_NUM_FACE_SET_VAR:
862 if (ex_get_variable_param(exoid, EX_FACE_SET, &num_var) != EX_NOERR) {
863 return (EX_FATAL);
864 }
865 *ret_int = num_var;
866 break;
867
868 case EX_INQ_NUM_ELEM_SET_VAR:
869 if (ex_get_variable_param(exoid, EX_ELEM_SET, &num_var) != EX_NOERR) {
870 return (EX_FATAL);
871 }
872 *ret_int = num_var;
873 break;
874
875 case EX_INQ_NUM_SIDE_SET_VAR:
876 if (ex_get_variable_param(exoid, EX_SIDE_SET, &num_var) != EX_NOERR) {
877 return (EX_FATAL);
878 }
879 *ret_int = num_var;
880 break;
881
882 case EX_INQ_NUM_GLOBAL_VAR:
883 if (ex_get_variable_param(exoid, EX_GLOBAL, &num_var) != EX_NOERR) {
884 return (EX_FATAL);
885 }
886 *ret_int = num_var;
887 break;
888
889 case EX_INQ_COORD_FRAMES:
890 /* return the number of coordinate frames */
891 if (ex__get_dimension_value(exoid, ret_int, 0, DIM_NUM_CFRAMES, 1) != EX_NOERR) {
892 return (EX_FATAL);
893 }
894 break;
895
896 case EX_INQ_NUM_CHILD_GROUPS: {
897 /* return number of groups contained in this (exoid) group */
898 int tmp_num = 0;
899 #if NC_HAS_HDF5
900 nc_inq_grps(exoid, &tmp_num, NULL);
901 #endif
902 *ret_int = tmp_num;
903 } break;
904
905 case EX_INQ_GROUP_PARENT: {
906 /* return id of parent of this (exoid) group; returns exoid if at root */
907 #if NC_HAS_HDF5
908 int tmp_num = exoid;
909 nc_inq_grp_parent(exoid, &tmp_num);
910 *ret_int = tmp_num;
911 #else
912 *ret_int = exoid;
913 #endif
914 } break;
915
916 case EX_INQ_GROUP_ROOT:
917 /* return id of root group "/" of this (exoid) group; returns exoid if at
918 * root */
919 *ret_int = (unsigned)exoid & EX_FILE_ID_MASK;
920 break;
921
922 case EX_INQ_GROUP_NAME_LEN: {
923 size_t len_name = 0;
924 #if NC_HAS_HDF5
925 /* return name length of group exoid */
926 nc_inq_grpname_len(exoid, &len_name);
927 #endif
928 *ret_int = (int)len_name;
929 } break;
930
931 case EX_INQ_GROUP_NAME:
932 /* return name of group exoid. "/" returned for root group */
933 /* Assumes that ret_char is large enough to hold name. */
934 if (!ret_char) {
935 snprintf(errmsg, MAX_ERR_LENGTH,
936 "ERROR: Requested group name, but character pointer was "
937 "null for file id %d",
938 exoid);
939 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
940 return (EX_FATAL);
941 }
942 #if NC_HAS_HDF5
943 nc_inq_grpname(exoid, ret_char);
944 #endif
945 break;
946
947 case EX_INQ_FULL_GROUP_NAME_LEN: {
948 size_t len_name = 0;
949 #if NC_HAS_HDF5
950 /* return length of full group name which is the "/" separated path from
951 * root
952 * For example "/group1/subgroup1/subsubgroup1"
953 * length does not include the NULL terminator byte.
954 */
955 nc_inq_grpname_full(exoid, &len_name, NULL);
956 #endif
957 *ret_int = (int)len_name;
958 } break;
959
960 case EX_INQ_FULL_GROUP_NAME:
961 /* return full path name of group exoid which is the "/" separated path from
962 * root
963 * For example "/group1/subgroup1/subsubgroup1"
964 * Assumes that ret_char is large enough to hold full path name.
965 */
966 if (!ret_char) {
967 snprintf(errmsg, MAX_ERR_LENGTH,
968 "ERROR: Requested group name, but character pointer was "
969 "null for file id %d",
970 exoid);
971 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
972 return (EX_FATAL);
973 }
974 #if NC_HAS_HDF5
975 nc_inq_grpname_full(exoid, NULL, ret_char);
976 #endif
977 break;
978
979 case EX_INQ_THREADSAFE:
980 /* Return 1 if the library was compiled in thread-safe mode.
981 * Return 0 otherwise
982 */
983 #if defined(EXODUS_THREADSAFE)
984 *ret_int = 1;
985 #else
986 *ret_int = 0;
987 #endif
988 break;
989
990 default:
991 *ret_int = 0;
992 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: invalid inquiry %d", req_info);
993 ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
994 return (EX_FATAL);
995 }
996 return (EX_NOERR);
997 }
998
999 /*!
1000 \ingroup Utilities
1001
1002 A variant of ex_inquire() which queries integer-valued information only. \see
1003 ex_inquire().
1004 \param[in] exoid exodus file ID returned from a previous call to
1005 ex_create() or ex_open().
1006 \param[in] req_info A flag of type #ex_inquiry which designates what information is requested.
1007 (See ex_inquire() documentation)
1008 \return result of inquiry.
1009
1010 As an example, the following will return the number of nodes,
1011 elements, and element blocks stored in the exodus file :
1012
1013 ~~~{.c}
1014 #include "exodusII.h"
1015 int exoid;
1016 int num_nodes = ex_inquire_int(exoid, EX_INQ_NODES);
1017 int num_elems = ex_inquire_int(exoid, EX_INQ_ELEM);
1018 int num_block = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
1019 ~~~
1020
1021 */
ex_inquire_int(int exoid,ex_inquiry req_info)1022 int64_t ex_inquire_int(int exoid, ex_inquiry req_info)
1023 {
1024 char * cdummy = NULL; /* Needed just for function call, unused. */
1025 float fdummy = 0; /* Needed just for function call, unused. */
1026 int64_t ret_val = 0;
1027 int error;
1028 EX_FUNC_ENTER();
1029 error = ex_inquire_internal(exoid, req_info, &ret_val, &fdummy, cdummy);
1030 if (error < 0) {
1031 ret_val = error;
1032 }
1033 EX_FUNC_LEAVE(ret_val);
1034 }
1035
1036 /*!
1037 \ingroup Utilities
1038
1039 The function ex_inquire() is used to inquire values of certain
1040 data entities in an exodus file. Memory must be allocated for the
1041 returned values before this function is invoked.query database.
1042
1043 \sa ex_inquire_int(), ex_inquiry.
1044
1045 \return In case of an error, ex_inquire() returns a negative
1046 number; a warning will return a positive number.
1047 Possible causes of errors include:
1048 - data file not properly opened with call to ex_create() or ex_open().
1049 - requested information not stored in the file.
1050 - invalid request flag.
1051
1052 \param[in] exoid exodus file ID returned from a previous call to ex_create()
1053 or ex_open().
1054 \param[in] req_info A flag of type #ex_inquiry which designates what information is requested. It
1055 must be one of the following constants in the table below.
1056
1057 \param[out] ret_int Returned integer, if an integer value is requested
1058 (according to req_info); otherwise, supply a dummy argument.
1059
1060 \param[out] ret_float Returned float, if a float value is requested
1061 (according to req_info); otherwise, supply a dummy
1062 argument. This argument is always a float even if the
1063 database IO and/or CPU word size is a double.
1064
1065 \param[out] ret_char Returned character string, if a character value is
1066 requested (according to req_info);
1067 otherwise, supply a dummy argument.
1068
1069 As an example, the following will return the number of element
1070 block properties stored in the exodus file :
1071
1072 ~~~{.c}
1073 #include "exodusII.h"
1074 int error, exoid, num_props;
1075 float fdum;
1076 char *cdum;
1077
1078 \comment{determine the number of element block properties}
1079 error = ex_inquire (exoid, EX_INQ_EB_PROP, &num_props,
1080 &fdum, cdum);
1081
1082 \comment{...Another way to get the same information}
1083 num_props = ex_inquire_int(exoid, EX_INQ_EB_PROP);
1084 ~~~
1085
1086 */
1087
ex_inquire(int exoid,ex_inquiry req_info,void_int * ret_int,float * ret_float,char * ret_char)1088 int ex_inquire(int exoid, ex_inquiry req_info, void_int *ret_int, float *ret_float, char *ret_char)
1089 {
1090 int ierr;
1091 if (ex_int64_status(exoid) & EX_INQ_INT64_API) {
1092 EX_FUNC_ENTER();
1093 ierr = ex_inquire_internal(exoid, req_info, ret_int, ret_float, ret_char);
1094 EX_FUNC_LEAVE(ierr);
1095 }
1096 /* ret_int is a 32-bit int */
1097 int64_t tmp_int;
1098 int * return_int = ret_int;
1099
1100 EX_FUNC_ENTER();
1101 ierr = ex_inquire_internal(exoid, req_info, &tmp_int, ret_float, ret_char);
1102 *return_int = (int)tmp_int;
1103 EX_FUNC_LEAVE(ierr);
1104 }
1105