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 * exgssc - ex_get_side_set_node_count
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_cnt_list returned array of number of nodes for
46 * side or face
47 * revision history -
48 *
49 *****************************************************************************/
50
51 #include "exodusII.h" // for ex_err, ex_block, etc
52 #include "exodusII_int.h" // for elem_blk_parm, EX_FATAL, etc
53 #include <assert.h> // for assert
54 #include <ctype.h> // for toupper
55 #include <inttypes.h> // for PRId64
56 #include <stddef.h> // for size_t
57 #include <stdio.h>
58 #include <stdlib.h> // for free, malloc
59 #include <string.h> // for strncmp, strlen
60 #include <sys/types.h> // for int64_t
61
ex_get_side_set_node_count(int exoid,ex_entity_id side_set_id,int * side_set_node_cnt_list)62 int ex_get_side_set_node_count(int exoid, ex_entity_id side_set_id, int *side_set_node_cnt_list)
63 {
64 int status;
65 size_t ii, i, j;
66 int num_side_sets, num_elem_blks, ndim;
67 size_t tot_num_ss_elem = 0;
68 int64_t side, elem;
69 void_int *elem_blk_ids = NULL;
70 void_int *ss_elem_ndx = NULL;
71 void_int *side_set_elem_list = NULL;
72 void_int *side_set_side_list = NULL;
73 size_t elem_ctr;
74
75 struct elem_blk_parm *elem_blk_parms = NULL;
76
77 char errmsg[MAX_ERR_LENGTH];
78 int err_stat = EX_NOERR;
79
80 EX_FUNC_ENTER();
81 ex_check_valid_file_id(exoid, __func__);
82
83 /* first check if any side sets are specified */
84 /* inquire how many side sets have been stored */
85 num_side_sets = ex_inquire_int(exoid, EX_INQ_SIDE_SETS);
86 if (num_side_sets < 0) {
87 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of side sets in file id %d",
88 exoid);
89 ex_err(__func__, errmsg, EX_LASTERR);
90 EX_FUNC_LEAVE(EX_FATAL);
91 }
92
93 if (num_side_sets == 0) {
94 snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no side sets defined in file id %d", exoid);
95 ex_err(__func__, errmsg, EX_WARN);
96 EX_FUNC_LEAVE(EX_WARN);
97 }
98
99 /* Lookup index of side set id in VAR_SS_IDS array */
100 if (ex_id_lkup(exoid, EX_SIDE_SET, side_set_id) <= 0) {
101 ;
102 }
103 ex_get_err(NULL, NULL, &status);
104
105 if (status != 0) {
106 if (status == EX_NULLENTITY) {
107 snprintf(errmsg, MAX_ERR_LENGTH, "Warning: side set %" PRId64 " is NULL in file id %d",
108 side_set_id, exoid);
109 ex_err(__func__, errmsg, EX_NULLENTITY);
110 EX_FUNC_LEAVE(EX_WARN);
111 }
112
113 snprintf(errmsg, MAX_ERR_LENGTH,
114 "ERROR: failed to locate side set %" PRId64 " in VAR_SS_IDS array in file id %d",
115 side_set_id, exoid);
116 ex_err(__func__, errmsg, status);
117 EX_FUNC_LEAVE(EX_FATAL);
118 }
119
120 num_elem_blks = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
121 if (num_elem_blks < 0) {
122 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get number of element blocks in file id %d",
123 exoid);
124 ex_err(__func__, errmsg, EX_LASTERR);
125 EX_FUNC_LEAVE(EX_FATAL);
126 }
127
128 /* get the dimensionality of the coordinates; this is necessary to
129 distinguish between 2d TRIs and 3d TRIs */
130 ndim = ex_inquire_int(exoid, EX_INQ_DIM);
131 if (ndim < 0) {
132 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get dimensionality in file id %d", exoid);
133 ex_err(__func__, errmsg, EX_LASTERR);
134 EX_FUNC_LEAVE(EX_FATAL);
135 }
136
137 int int_size = sizeof(int);
138 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
139 int_size = sizeof(int64_t);
140 }
141
142 /* First determine the # of elements in the side set*/
143 int err;
144 if (int_size == sizeof(int64_t)) {
145 int64_t ss_elem = 0;
146 int64_t ss_df = 0;
147 err = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &ss_elem, &ss_df);
148 tot_num_ss_elem = ss_elem;
149 }
150 else {
151 int ss_elem = 0;
152 int ss_df = 0;
153 err = ex_get_set_param(exoid, EX_SIDE_SET, side_set_id, &ss_elem, &ss_df);
154 tot_num_ss_elem = ss_elem;
155 }
156
157 if (err == -1) {
158 snprintf(errmsg, MAX_ERR_LENGTH,
159 "ERROR: failed to get number of elements in side set %" PRId64 " in file id %d",
160 side_set_id, exoid);
161 ex_err(__func__, errmsg, EX_LASTERR);
162 EX_FUNC_LEAVE(EX_FATAL);
163 }
164
165 /* Allocate space for the side set element list */
166 {
167 if (!(side_set_elem_list = malloc(tot_num_ss_elem * int_size))) {
168 snprintf(errmsg, MAX_ERR_LENGTH,
169 "ERROR: failed to allocate space for side set element "
170 "list for file id %d",
171 exoid);
172 ex_err(__func__, errmsg, EX_MEMFAIL);
173 EX_FUNC_LEAVE(EX_FATAL);
174 }
175
176 /* Allocate space for the side set side list */
177 if (!(side_set_side_list = malloc(tot_num_ss_elem * int_size))) {
178 snprintf(errmsg, MAX_ERR_LENGTH,
179 "ERROR: failed to allocate space for side set side list "
180 "for file id %d",
181 exoid);
182 ex_err(__func__, errmsg, EX_MEMFAIL);
183 err_stat = EX_FATAL;
184 goto cleanup;
185 }
186
187 if (ex_get_set(exoid, EX_SIDE_SET, side_set_id, side_set_elem_list, side_set_side_list) == -1) {
188 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get side set %" PRId64 " in file id %d",
189 side_set_id, exoid);
190 ex_err(__func__, errmsg, EX_LASTERR);
191 err_stat = EX_FATAL;
192 goto cleanup;
193 }
194
195 /* Allocate space for the ss element index array */
196 if (!(ss_elem_ndx = malloc(tot_num_ss_elem * int_size))) {
197 snprintf(errmsg, MAX_ERR_LENGTH,
198 "ERROR: failed to allocate space for side set elem sort "
199 "array for file id %d",
200 exoid);
201 ex_err(__func__, errmsg, EX_MEMFAIL);
202 err_stat = EX_FATAL;
203 goto cleanup;
204 }
205
206 if (int_size == sizeof(int64_t)) {
207 /* Sort side set element list into index array - non-destructive */
208 int64_t *elems = (int64_t *)ss_elem_ndx;
209 for (i = 0; i < tot_num_ss_elem; i++) {
210 elems[i] = i; /* init index array to current position */
211 }
212 ex_iqsort64(side_set_elem_list, elems, tot_num_ss_elem);
213 }
214 else {
215 /* Sort side set element list into index array - non-destructive */
216 int *elems = (int *)ss_elem_ndx;
217 for (i = 0; i < tot_num_ss_elem; i++) {
218 elems[i] = i; /* init index array to current position */
219 }
220 ex_iqsort(side_set_elem_list, elems, tot_num_ss_elem);
221 }
222 }
223
224 /* Allocate space for the element block ids */
225 {
226 int_size = sizeof(int);
227 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
228 int_size = sizeof(int64_t);
229 }
230
231 if (!(elem_blk_ids = malloc(num_elem_blks * int_size))) {
232 snprintf(errmsg, MAX_ERR_LENGTH,
233 "ERROR: failed to allocate space for element block ids "
234 "for file id %d",
235 exoid);
236 ex_err(__func__, errmsg, EX_MEMFAIL);
237 err_stat = EX_FATAL;
238 goto cleanup;
239 }
240
241 if (ex_get_ids(exoid, EX_ELEM_BLOCK, elem_blk_ids) == -1) {
242 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get element block ids in file id %d",
243 exoid);
244 ex_err(__func__, errmsg, EX_MSG);
245 err_stat = EX_FATAL;
246 goto cleanup;
247 }
248 }
249
250 /* Allocate space for the element block params */
251 if (!(elem_blk_parms = malloc(num_elem_blks * sizeof(struct elem_blk_parm)))) {
252 snprintf(errmsg, MAX_ERR_LENGTH,
253 "ERROR: failed to allocate space for element block params "
254 "for file id %d",
255 exoid);
256 ex_err(__func__, errmsg, EX_MEMFAIL);
257 err_stat = EX_FATAL;
258 goto cleanup;
259 }
260
261 elem_ctr = 0;
262 for (i = 0; i < num_elem_blks; i++) {
263 ex_entity_id id;
264 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
265 id = ((int64_t *)elem_blk_ids)[i];
266 }
267 else {
268 id = ((int *)elem_blk_ids)[i];
269 }
270
271 err_stat = ex_int_get_block_param(exoid, id, ndim, &elem_blk_parms[i]);
272 if (err_stat != EX_NOERR) {
273 goto cleanup;
274 }
275
276 elem_ctr += elem_blk_parms[i].num_elem_in_blk;
277 elem_blk_parms[i].elem_ctr = elem_ctr; /* save elem number max */
278 }
279
280 /* Finally... Create the list of node counts for each face in the
281 * side set.
282 */
283
284 j = 0; /* The current element block... */
285 for (ii = 0; ii < tot_num_ss_elem; ii++) {
286
287 if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
288 i = ((int64_t *)ss_elem_ndx)[ii];
289 elem = ((int64_t *)side_set_elem_list)[i];
290 side = ((int64_t *)side_set_side_list)[i] - 1; /* Convert to 0-based sides */
291 }
292 else {
293 i = ((int *)ss_elem_ndx)[ii];
294 elem = ((int *)side_set_elem_list)[i];
295 side = ((int *)side_set_side_list)[i] - 1; /* Convert to 0-based sides */
296 }
297
298 /*
299 * Since the elements are being accessed in sorted, order, the
300 * block that contains the elements must progress sequentially
301 * from block 0 to block[num_elem_blks-1]. Once we find an element
302 * not in this block, find a following block that contains it...
303 */
304 for (; j < num_elem_blks; j++) {
305 if (elem <= elem_blk_parms[j].elem_ctr) {
306 break;
307 }
308 }
309
310 if (j < num_elem_blks) {
311 assert(side < elem_blk_parms[j].num_sides);
312 side_set_node_cnt_list[i] = elem_blk_parms[j].num_nodes_per_side[side];
313 }
314 else {
315 snprintf(errmsg, MAX_ERR_LENGTH,
316 "ERROR: Invalid element number %" PRId64 " found in side set %" PRId64 " in file %d",
317 elem, side_set_id, exoid);
318 ex_err(__func__, errmsg, EX_BADPARAM);
319 err_stat = EX_FATAL;
320 goto cleanup;
321 }
322 }
323
324 /* All done: release connectivity array space, element block ids
325 * array, element block parameters array, and side set element index
326 * array
327 */
328 cleanup:
329 free(elem_blk_ids);
330 free(elem_blk_parms);
331 free(ss_elem_ndx);
332 free(side_set_side_list);
333 free(side_set_elem_list);
334
335 EX_FUNC_LEAVE(err_stat);
336 }
337