1 /*
2 * Copyright (c) 2005 Sandia Corporation. Under the terms of Contract
3 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement
4 * 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 Sandia Corporation 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 * expclb - ex_put_concat_elem_block: write element block parameters
38 *
39 * entry conditions -
40 * input parameters:
41 * int idexo exodus file id
42 * char** elem_type element type string
43 * int* num_elem_this_blk number of elements in the element blk
44 * int* num_nodes_per_elem number of nodes per element block
45 * int* num_attr_this_blk number of attributes
46 * int define_maps if != 0, write maps, else don't
47 *
48 *****************************************************************************/
49
50 #include <stdlib.h>
51 #include "exodusII.h"
52 #include "exodusII_int.h"
53 #include <string.h>
54
55 /*!
56 * writes the parameters used to describe an element block
57 * \param exoid exodus file id
58 * \param elem_blk_id element block id
59 * \param elem_type element type string
60 * \param num_elem_this_blk number of elements in the element blk
61 * \param num_nodes_per_elem number of nodes per element block
62 * \param num_attr_this_blk number of attributes
63 * \param define_maps if != 0, write maps, else don't
64 */
ex_put_concat_elem_block(int exoid,const void_int * elem_blk_id,char * elem_type[],const void_int * num_elem_this_blk,const void_int * num_nodes_per_elem,const void_int * num_attr_this_blk,int define_maps)65 int ex_put_concat_elem_block (int exoid,
66 const void_int* elem_blk_id,
67 char *elem_type[],
68 const void_int* num_elem_this_blk,
69 const void_int* num_nodes_per_elem,
70 const void_int* num_attr_this_blk,
71 int define_maps)
72 {
73 int i, varid, dimid, dims[2], strdim, *eb_array;
74 int temp;
75 int iblk;
76 int status;
77 int num_elem_blk;
78 int map_int_type, conn_int_type;
79 size_t length;
80 int cur_num_elem_blk, nelnoddim, numelbdim, numattrdim, connid, numelemdim, numnodedim;
81 char errmsg[MAX_ERR_LENGTH];
82
83 exerrval = 0; /* clear error code */
84
85 /* first check if any element blocks are specified
86 * OK if zero...
87 */
88 if (nc_inq_dimid(exoid, DIM_NUM_EL_BLK, &dimid) != NC_NOERR) {
89 return (EX_NOERR);
90 }
91
92 /* Get number of element blocks defined for this file */
93 if ((status = nc_inq_dimlen(exoid,dimid,&length)) != NC_NOERR) {
94 exerrval = status;
95 sprintf(errmsg,
96 "Error: failed to get number of element blocks in file id %d",
97 exoid);
98 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
99 return (EX_FATAL);
100 }
101 num_elem_blk = length;
102
103 /* Fill out the element block status array */
104 if (!(eb_array = malloc(num_elem_blk*sizeof(int)))) {
105 exerrval = EX_MEMFAIL;
106 sprintf(errmsg,
107 "Error: failed to allocate space for element block status array in file id %d",
108 exoid);
109 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
110 return (EX_FATAL);
111 }
112
113 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
114 for (i=0;i<num_elem_blk;i++) {
115 eb_array[i] = (((int64_t*)num_elem_this_blk)[i] == 0) ? 0 : 1;
116 }
117 } else {
118 for (i=0;i<num_elem_blk;i++) {
119 eb_array[i] = (((int*)num_elem_this_blk)[i] == 0) ? 0 : 1;
120 }
121 }
122
123 /* Next, get variable id of status array */
124 if ((status = nc_inq_varid(exoid, VAR_STAT_EL_BLK, &varid)) != NC_NOERR) {
125 exerrval = status;
126 sprintf(errmsg,
127 "Error: failed to locate element block status in file id %d",
128 exoid);
129 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
130 return (EX_FATAL);
131 }
132
133 status = nc_put_var_int(exoid, varid, eb_array);
134
135 if (status != NC_NOERR) {
136 exerrval = status;
137 sprintf(errmsg,
138 "Error: failed to store element block status array to file id %d",
139 exoid);
140 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
141 return (EX_FATAL);
142 }
143
144 /* Next, fill out ids array */
145 /* first get id of ids array variable */
146 if ((status = nc_inq_varid(exoid, VAR_ID_EL_BLK, &varid)) != NC_NOERR) {
147 exerrval = status;
148 sprintf(errmsg,
149 "Error: failed to locate element block ids array in file id %d",
150 exoid);
151 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
152 return (EX_FATAL);
153 }
154
155 /* then, write out id list */
156 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
157 status = nc_put_var_longlong(exoid, varid, elem_blk_id);
158 } else {
159 status = nc_put_var_int(exoid, varid, elem_blk_id);
160 }
161
162 if (status != NC_NOERR) {
163 exerrval = status;
164 sprintf(errmsg,
165 "Error: failed to store element block id array in file id %d",
166 exoid);
167 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
168 return (EX_FATAL);
169 }
170
171 /* inquire previously defined dimensions */
172 if ((status = nc_inq_dimid(exoid, DIM_STR_NAME, &strdim)) != NC_NOERR) {
173 exerrval = status;
174 sprintf(errmsg,
175 "Error: failed to get string length in file id %d",exoid);
176 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
177 return (EX_FATAL);
178 }
179
180 /* put netcdf file into define mode */
181 if ((status = nc_redef (exoid)) != NC_NOERR) {
182 exerrval = status;
183 sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid);
184 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
185 return (EX_FATAL);
186 }
187
188 conn_int_type = NC_INT;
189 if (ex_int64_status(exoid) & EX_BULK_INT64_DB) {
190 conn_int_type = NC_INT64;
191 }
192
193 map_int_type = NC_INT;
194 if (ex_int64_status(exoid) & EX_MAPS_INT64_DB) {
195 map_int_type = NC_INT64;
196 }
197
198 /* Iterate over element blocks ... */
199 for (iblk = 0; iblk < num_elem_blk; iblk++) {
200 ex_entity_id eb_id;
201 size_t num_elem;
202 size_t num_npe;
203 size_t num_attr;
204 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
205 eb_id = ((int64_t*)elem_blk_id)[iblk];
206 num_elem = ((int64_t*)num_elem_this_blk)[iblk];
207 num_npe = ((int64_t*)num_nodes_per_elem)[iblk];
208 num_attr = ((int64_t*)num_attr_this_blk)[iblk];
209 } else {
210 eb_id = ((int*)elem_blk_id)[iblk];
211 num_elem = ((int*)num_elem_this_blk)[iblk];
212 num_npe = ((int*)num_nodes_per_elem)[iblk];
213 num_attr = ((int*)num_attr_this_blk)[iblk];
214 }
215
216 cur_num_elem_blk=ex_get_file_item(exoid, ex_get_counter_list(EX_ELEM_BLOCK));
217 if (cur_num_elem_blk >= num_elem_blk) {
218 exerrval = EX_FATAL;
219 sprintf(errmsg,
220 "Error: exceeded number of element blocks (%d) defined in file id %d",
221 num_elem_blk,exoid);
222 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
223 goto error_ret;
224 }
225
226 /* NOTE: ex_inc_file_item is used to find the number of element blocks
227 for a specific file and returns that value incremented. */
228 cur_num_elem_blk=ex_inc_file_item(exoid, ex_get_counter_list(EX_ELEM_BLOCK));
229
230 if (eb_array[iblk] == 0) /* Is this a NULL element block? */
231 continue;
232
233 /* define some dimensions and variables*/
234 if ((status = nc_def_dim(exoid,
235 DIM_NUM_EL_IN_BLK(cur_num_elem_blk+1),
236 num_elem, &numelbdim)) != NC_NOERR) {
237 exerrval = status;
238 if (status == NC_ENAMEINUSE) { /* duplicate entry */
239 sprintf(errmsg,
240 "Error: element block %"PRId64" already defined in file id %d",
241 eb_id,exoid);
242 } else {
243 sprintf(errmsg,
244 "Error: failed to define number of elements/block for block %"PRId64" file id %d",
245 eb_id,exoid);
246 }
247 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
248 goto error_ret; /* exit define mode and return */
249 }
250
251 if ((status = nc_def_dim(exoid,
252 DIM_NUM_NOD_PER_EL(cur_num_elem_blk+1),
253 num_npe, &nelnoddim)) != NC_NOERR) {
254 exerrval = status;
255 sprintf(errmsg,
256 "Error: failed to define number of nodes/element for block %"PRId64" in file id %d",
257 eb_id,exoid);
258 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
259 goto error_ret; /* exit define mode and return */
260 }
261
262 /* element connectivity array */
263 dims[0] = numelbdim;
264 dims[1] = nelnoddim;
265
266 if ((status = nc_def_var (exoid, VAR_CONN(cur_num_elem_blk+1),
267 conn_int_type, 2, dims, &connid)) != NC_NOERR) {
268 exerrval = status;
269 sprintf(errmsg,
270 "Error: failed to create connectivity array for block %"PRId64" in file id %d",
271 eb_id,exoid);
272 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
273 goto error_ret; /* exit define mode and return */
274 }
275 ex_compress_variable(exoid, connid, 1);
276
277 /* store element type as attribute of connectivity variable */
278 if ((status = nc_put_att_text(exoid, connid, ATT_NAME_ELB, strlen(elem_type[iblk])+1,
279 (void*)elem_type[iblk])) != NC_NOERR) {
280 exerrval = status;
281 sprintf(errmsg,
282 "Error: failed to store element type name %s in file id %d",
283 elem_type[iblk],exoid);
284 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
285 goto error_ret; /* exit define mode and return */
286 }
287
288 /* element attribute array */
289 if (num_attr > 0) {
290 if ((status = nc_def_dim (exoid,
291 DIM_NUM_ATT_IN_BLK(cur_num_elem_blk+1),
292 num_attr, &numattrdim)) != NC_NOERR) {
293 exerrval = status;
294 sprintf(errmsg,
295 "Error: failed to define number of attributes in block %"PRId64" in file id %d",
296 eb_id,exoid);
297 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
298 goto error_ret; /* exit define mode and return */
299 }
300
301 /* Attribute names... */
302 dims[0] = numattrdim;
303 dims[1] = strdim;
304
305 if ((status = nc_def_var(exoid, VAR_NAME_ATTRIB(cur_num_elem_blk+1),
306 NC_CHAR, 2, dims, &temp)) != NC_NOERR) {
307 exerrval = status;
308 sprintf(errmsg,
309 "Error: failed to define element attribute name array in file id %d",exoid);
310 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
311 goto error_ret; /* exit define mode and return */
312 }
313 eb_array[iblk] = temp;
314
315 dims[0] = numelbdim;
316 dims[1] = numattrdim;
317
318 if ((status = nc_def_var(exoid, VAR_ATTRIB(cur_num_elem_blk+1),
319 nc_flt_code(exoid), 2, dims, &temp)) != NC_NOERR) {
320 exerrval = status;
321 sprintf(errmsg,
322 "Error: failed to define attributes for element block %"PRId64" in file id %d",
323 eb_id,exoid);
324 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
325 goto error_ret; /* exit define mode and return */
326 }
327
328 }
329
330 }
331
332 /* Define the element map here to avoid a later redefine call */
333 if (define_maps != 0) {
334 if (nc_inq_varid(exoid, VAR_ELEM_NUM_MAP, &temp) != NC_NOERR) {
335 /* Map does not exist */
336 /* Possible to have zero elements but >0 element blocks.
337 * Only define map if there are nonzero elements
338 */
339 if (nc_inq_dimid(exoid, DIM_NUM_ELEM, &numelemdim) == NC_NOERR) {
340 dims[0] = numelemdim;
341
342 if ((status = nc_def_var(exoid, VAR_ELEM_NUM_MAP, map_int_type, 1, dims, &temp)) != NC_NOERR) {
343 exerrval = status;
344 if (status == NC_ENAMEINUSE) {
345 sprintf(errmsg,
346 "Error: element numbering map already exists in file id %d",
347 exoid);
348 } else {
349 sprintf(errmsg,
350 "Error: failed to create element numbering map in file id %d",
351 exoid);
352 }
353 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
354 goto error_ret; /* exit define mode and return */
355 }
356 ex_compress_variable(exoid, temp, 1);
357 }
358 }
359
360 /* Do the same for the node numbering map */
361 if (nc_inq_varid(exoid, VAR_NODE_NUM_MAP, &temp) != NC_NOERR) {
362 /* Map does not exist */
363 if ((nc_inq_dimid(exoid, DIM_NUM_NODES, &numnodedim)) == NC_NOERR) {
364 dims[0] = numnodedim;
365 if ((status = nc_def_var(exoid, VAR_NODE_NUM_MAP, map_int_type, 1, dims, &temp)) != NC_NOERR) {
366 exerrval = status;
367 if (status == NC_ENAMEINUSE) {
368 sprintf(errmsg,
369 "Error: node numbering map already exists in file id %d",
370 exoid);
371 } else {
372 sprintf(errmsg,
373 "Error: failed to create node numbering map array in file id %d",
374 exoid);
375 }
376 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
377 goto error_ret; /* exit define mode and return */
378 }
379 ex_compress_variable(exoid, temp, 1);
380 }
381 }
382 }
383
384 /* leave define mode */
385 if ((status = nc_enddef(exoid)) != NC_NOERR) {
386 exerrval = status;
387 sprintf(errmsg,
388 "Error: failed to complete element block definition in file id %d",
389 exoid);
390 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
391 return (EX_FATAL);
392 }
393
394 {
395 /* Write dummy attribute name. Without this we get corruption in the
396 * attribute name.
397 */
398 size_t start[2], count[2];
399 char *text = "";
400 count[0] = 1;
401 start[1] = 0;
402 count[1] = strlen(text)+1;
403
404 for (iblk = 0; iblk < num_elem_blk; iblk++) {
405 size_t num_attr;
406 if (eb_array[iblk] == 0) /* Is this a NULL element block? */
407 continue;
408 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
409 num_attr = ((int64_t*)num_attr_this_blk)[iblk];
410 } else {
411 num_attr = ((int*)num_attr_this_blk)[iblk];
412 }
413 for (i = 0; i < num_attr; i++) {
414 start[0] = i;
415 nc_put_vara_text(exoid, eb_array[iblk], start, count, text);
416 }
417 }
418 }
419 free(eb_array);
420
421 return (EX_NOERR);
422
423 /* Fatal error: exit definition mode and return */
424 error_ret:
425 if (nc_enddef (exoid) != NC_NOERR) { /* exit define mode */
426 sprintf(errmsg,
427 "Error: failed to complete definition for file id %d",
428 exoid);
429 ex_err("ex_put_concat_elem_block",errmsg,exerrval);
430 }
431 return (EX_FATAL);
432 }
433
434