1 /*
2 * Copyright (c) 2005-2017 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 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * * Neither the name of NTESS nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
35 /*****************************************************************************
36 *
37 * exgsnl - ex_get_side_set_node_list_len
38 *
39 * entry conditions -
40 * input parameters:
41 * int exoid exodus file id
42 * int side_set_id side set id
43 *
44 * exit conditions -
45 * int *side_set_node_list_len length of node list
46 *
47 * revision history -
48 *
49 *
50 *****************************************************************************/
51
52 #include "exodusII.h" // for ex_err, etc
53 #include "exodusII_int.h" // for elem_blk_parm, EX_FATAL, etc
54 #include "vtk_netcdf.h" // for NC_NOERR
55 #include <ctype.h> // for toupper
56 #include <inttypes.h> // for PRId64
57 #include <stddef.h> // for size_t
58 #include <stdio.h>
59 #include <stdlib.h> // for malloc, NULL, free
60 #include <string.h> // for strncmp, strlen
61 #include <sys/types.h> // for int64_t
62
63 /*!
64 * This routine is designed to read the Exodus II V 2.0 side set side
65 * definition and return the length of a ExodusI style side set node list.
66 * \param exoid exodus file id
67 * \param side_set_id side set id
68 * \param[out] *side_set_node_list_len length of node list
69 */
70
ex_get_side_set_node_list_len(int exoid,ex_entity_id side_set_id,void_int * side_set_node_list_len)71 int ex_get_side_set_node_list_len(int exoid, ex_entity_id side_set_id,
72 void_int *side_set_node_list_len)
73 {
74 size_t ii, i, j;
75 int64_t num_side_sets, num_elem_blks, num_df, ndim;
76 size_t list_len = 0;
77 int64_t tot_num_elem = 0, tot_num_ss_elem = 0;
78 void_int *elem_blk_ids = NULL;
79 int * ss_elem_ndx = NULL;
80 int64_t * ss_elem_ndx_64 = NULL;
81
82 void_int *side_set_elem_list = NULL;
83 void_int *side_set_side_list = NULL;
84 size_t elem_ctr;
85
86 int err_stat = EX_NOERR;
87 int status;
88
89 struct elem_blk_parm *elem_blk_parms = NULL;
90
91 char errmsg[MAX_ERR_LENGTH];
92
93 EX_FUNC_ENTER();
94 ex_check_valid_file_id(exoid, __func__);
95
96 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
97 *(int64_t *)side_set_node_list_len = 0; /* default value */
98 }
99 else {
100 *(int *)side_set_node_list_len = 0; /* default value */
101 }
102
103 /* first check if any side sets are specified */
104 /* inquire how many side sets have been stored */
105
106 /* get the dimensionality of the coordinates; this is necessary to
107 distinguish between 2d TRIs and 3d TRIs */
108
109 ndim = ex_inquire_int(exoid, EX_INQ_DIM);
110 if (ndim < 0) {
111 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get dimensionality in file id %d", exoid);
112 ex_err(__func__, errmsg, EX_LASTERR);
113 EX_FUNC_LEAVE(EX_FATAL);
114 }
115
116 tot_num_elem = ex_inquire_int(exoid, EX_INQ_ELEM);
117 if (tot_num_elem < 0) {
118 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get total number of elements in file id %d",
119 exoid);
120 ex_err(__func__, errmsg, EX_LASTERR);
121 EX_FUNC_LEAVE(EX_FATAL);
122 }
123
124 num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
125 if (num_elem_blks < 0) {
126 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of element blocks in file id %d",
127 exoid);
128 ex_err(__func__, errmsg, EX_LASTERR);
129 EX_FUNC_LEAVE(EX_FATAL);
130 }
131
132 num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
133 if (num_side_sets < 0) {
134 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
135 exoid);
136 ex_err(__func__, errmsg, EX_LASTERR);
137 EX_FUNC_LEAVE(EX_FATAL);
138 }
139
140 if (num_side_sets == 0) {
141 snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no side sets defined in file id %d", exoid);
142 ex_err(__func__, errmsg, EX_WARN);
143 EX_FUNC_LEAVE(EX_WARN);
144 }
145
146 /* First determine the # of elements in the side set*/
147 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
148 status = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &tot_num_ss_elem, &num_df);
149 }
150 else {
151 int tot;
152 int df;
153 status = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &tot, &df);
154 tot_num_ss_elem = tot;
155 num_df = df;
156 }
157
158 if (status != NC_NOERR) {
159 snprintf(errmsg, MAX_ERR_LENGTH,
160 "ERROR: failed to get number of elements in side set %" PRId64 " in file id %d",
161 side_set_id, exoid);
162 ex_err(__func__, errmsg, EX_LASTERR);
163 EX_FUNC_LEAVE(EX_FATAL);
164 }
165
166 if (tot_num_ss_elem == 0) { /* NULL side set? */
167 EX_FUNC_LEAVE(EX_NOERR);
168 }
169
170 /* Allocate space for the side set element list */
171 {
172 int int_size = sizeof(int);
173 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
174 int_size = sizeof(int64_t);
175 }
176 if (!(side_set_elem_list = malloc(tot_num_ss_elem * int_size))) {
177 snprintf(errmsg, MAX_ERR_LENGTH,
178 "ERROR: failed to allocate space for side set element "
179 "list for file id %d",
180 exoid);
181 ex_err(__func__, errmsg, EX_MEMFAIL);
182 EX_FUNC_LEAVE(EX_FATAL);
183 }
184
185 /* Allocate space for the side set side list */
186 if (!(side_set_side_list = malloc(tot_num_ss_elem * int_size))) {
187 snprintf(errmsg, MAX_ERR_LENGTH,
188 "ERROR: failed to allocate space for side set side list "
189 "for file id %d",
190 exoid);
191 ex_err(__func__, errmsg, EX_MEMFAIL);
192 err_stat = EX_FATAL;
193 goto cleanup;
194 }
195
196 if (ex_get_set(exoid, EX_SIDE_SET, side_set_id, side_set_elem_list, side_set_side_list) !=
197 NC_NOERR) {
198 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get side set %" PRId64 " in file id %d",
199 side_set_id, exoid);
200 ex_err(__func__, errmsg, EX_LASTERR);
201 err_stat = EX_FATAL;
202 goto cleanup;
203 }
204
205 /* Allocate space for the ss element index array */
206 if (int_size == sizeof(int64_t)) {
207 ss_elem_ndx_64 = malloc(tot_num_ss_elem * int_size);
208 }
209 else {
210 ss_elem_ndx = malloc(tot_num_ss_elem * int_size);
211 }
212
213 if (ss_elem_ndx_64 == NULL && ss_elem_ndx == NULL) {
214 snprintf(errmsg, MAX_ERR_LENGTH,
215 "ERROR: failed to allocate space for side set elem sort "
216 "array for file id %d",
217 exoid);
218 ex_err(__func__, errmsg, EX_MEMFAIL);
219 err_stat = EX_FATAL;
220 goto cleanup;
221 }
222 }
223
224 /* Sort side set element list into index array - non-destructive */
225 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
226 for (i = 0; i < tot_num_ss_elem; i++) {
227 ss_elem_ndx_64[i] = i; /* init index array to current position */
228 }
229 ex_iqsort64(side_set_elem_list, ss_elem_ndx_64, tot_num_ss_elem);
230 }
231 else {
232 for (i = 0; i < tot_num_ss_elem; i++) {
233 ss_elem_ndx[i] = i; /* init index array to current position */
234 }
235 ex_iqsort(side_set_elem_list, ss_elem_ndx, tot_num_ss_elem);
236 }
237
238 /* Allocate space for the element block ids */
239 {
240 int int_size = sizeof(int);
241 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
242 int_size = sizeof(int64_t);
243 }
244
245 if (!(elem_blk_ids = malloc(num_elem_blks * int_size))) {
246 snprintf(errmsg, MAX_ERR_LENGTH,
247 "ERROR: failed to allocate space for element block ids "
248 "for file id %d",
249 exoid);
250 ex_err(__func__, errmsg, EX_MEMFAIL);
251 err_stat = EX_FATAL;
252 goto cleanup;
253 }
254 }
255
256 if (ex_get_ids(exoid, EX_ELEM_BLOCK, elem_blk_ids)) {
257 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get element block ids in file id %d", exoid);
258 ex_err(__func__, errmsg, EX_MSG);
259 err_stat = EX_FATAL;
260 goto cleanup;
261 }
262
263 /* Allocate space for the element block params */
264 if (!(elem_blk_parms = malloc(num_elem_blks * sizeof(struct elem_blk_parm)))) {
265 snprintf(errmsg, MAX_ERR_LENGTH,
266 "ERROR: failed to allocate space for element block params "
267 "for file id %d",
268 exoid);
269 ex_err(__func__, errmsg, EX_MEMFAIL);
270 err_stat = EX_FATAL;
271 goto cleanup;
272 }
273
274 elem_ctr = 0;
275 for (i = 0; i < num_elem_blks; i++) {
276 ex_entity_id id;
277 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
278 id = ((int64_t *)elem_blk_ids)[i];
279 }
280 else {
281 id = ((int *)elem_blk_ids)[i];
282 }
283
284 err_stat = ex_int_get_block_param(exoid, id, ndim, &elem_blk_parms[i]);
285 if (err_stat != EX_NOERR) {
286 goto cleanup;
287 }
288
289 elem_ctr += elem_blk_parms[i].num_elem_in_blk;
290 elem_blk_parms[i].elem_ctr = elem_ctr; /* save elem number max */
291 }
292
293 /* Walk through element list and keep a running count of the node length */
294
295 list_len = 0;
296 j = 0; /* The current element block... */
297 for (ii = 0; ii < tot_num_ss_elem; ii++) {
298 size_t elem;
299 size_t side;
300 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
301 i = ss_elem_ndx_64[ii];
302 elem = ((int64_t *)side_set_elem_list)[i];
303 side = ((int64_t *)side_set_side_list)[i];
304 }
305 else {
306 i = ss_elem_ndx[ii];
307 elem = ((int *)side_set_elem_list)[i];
308 side = ((int *)side_set_side_list)[i];
309 }
310
311 /*
312 * Since the elements are being accessed in sorted, order, the
313 * block that contains the elements must progress sequentially
314 * from block 0 to block[num_elem_blks-1]. Once we find an element
315 * not in this block, find a following block that contains it...
316 */
317 for (; j < num_elem_blks; j++) {
318 if (elem_blk_parms[j].elem_type_val != EX_EL_NULL_ELEMENT) {
319 if (elem <= elem_blk_parms[j].elem_ctr) {
320 break;
321 }
322 }
323 }
324
325 if (j >= num_elem_blks) {
326 snprintf(errmsg, MAX_ERR_LENGTH,
327 "ERROR: Invalid element number %" ST_ZU " found in side set %" PRId64 " in file %d",
328 elem, side_set_id, exoid);
329 ex_err(__func__, errmsg, EX_BADPARAM);
330 err_stat = EX_FATAL;
331 goto cleanup;
332 }
333 list_len += elem_blk_parms[j].num_nodes_per_side[side - 1];
334 }
335
336 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
337 *(int64_t *)side_set_node_list_len = list_len;
338 }
339 else {
340 *(int *)side_set_node_list_len = list_len;
341 }
342
343 if (num_df > 0 && num_df != tot_num_ss_elem) {
344 if (list_len != num_df) {
345 snprintf(errmsg, MAX_ERR_LENGTH,
346 "Warning: In side set %" PRId64 " the distribution factor count (%" PRId64
347 ") does not match the side set node list length (%" ST_ZU
348 "). These should match and this may indicate a corrupt database in file %d",
349 side_set_id, num_df, list_len, exoid);
350 ex_err(__func__, errmsg, EX_MSG);
351 err_stat = EX_WARN;
352 goto cleanup;
353 }
354 }
355
356 /* All done: release element block ids array,
357 element block parameters array, and side set element index array */
358 cleanup:
359 free(elem_blk_ids);
360 free(elem_blk_parms);
361 free(ss_elem_ndx);
362 free(ss_elem_ndx_64);
363 free(side_set_side_list);
364 free(side_set_elem_list);
365
366 EX_FUNC_LEAVE(err_stat);
367 }
368