1 /*
2  * Copyright (c) 2006 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_all_blocks: write elem, edge, & face block parameters
38 *
39 * entry conditions -
40 *   input parameters:
41 *       int                    exoid          exodus file id
42 *       const ex_block_params* bparam         block parameters structure
43 *
44 *****************************************************************************/
45 
46 #include <stdlib.h>
47 #include "exodusII.h"
48 #include "exodusII_int.h"
49 #include <string.h>
50 
51 
52 /*!
53  * writes the parameters used to describe all element, edge, and face blocks
54  * \param     exoid          exodus file id
55  * \param     param         block parameters structure
56  */
ex_put_concat_all_blocks(int exoid,const ex_block_params * param)57 int ex_put_concat_all_blocks (int    exoid,
58                               const ex_block_params *param)
59 {
60   int varid, dimid, dims[2], strdim, *eb_stat, *ed_stat, *fa_stat;
61   int temp;
62   size_t iblk;
63   int status;
64   size_t num_elem_blk, num_edge_blk, num_face_blk, i;
65   int cur_num_elem_blk, nelnoddim, numelbdim, numattrdim, connid=-1;
66   int cur_num_edge_blk, numedbdim, nednoddim, cur_num_face_blk, numfabdim, nfanoddim;
67   int neledgdim=-1, nelfacdim=-1;
68   char errmsg[MAX_ERR_LENGTH];
69   int elem_work = 0; /* is DIM_NUM_EL_BLK defined? If so, there's work to do */
70   int edge_work = 0; /* is DIM_NUM_ED_BLK defined? If so, there's work to do */
71   int face_work = 0; /* is DIM_NUM_FA_BLK defined? If so, there's work to do */
72   static const char* dim_num_maps[] = {
73     DIM_NUM_NM,
74     DIM_NUM_EDM,
75     DIM_NUM_FAM,
76     DIM_NUM_EM,
77   };
78   static const char* dim_size_maps[] = {
79     DIM_NUM_NODES,
80     DIM_NUM_EDGE,
81     DIM_NUM_FACE,
82     DIM_NUM_ELEM,
83   };
84   static const ex_entity_type map_enums[] = {
85     EX_NODE_MAP,
86     EX_EDGE_MAP,
87     EX_FACE_MAP,
88     EX_ELEM_MAP
89   };
90   /* If param->define_maps is true, we must fill these with values from ex_put_init_ext
91      before entering define mode */
92   size_t num_maps[sizeof(dim_num_maps)/sizeof(dim_num_maps[0])];
93   size_t num_map_dims = sizeof(dim_num_maps)/sizeof(dim_num_maps[0]);
94 
95   exerrval  = 0; /* clear error code */
96 
97   /* inquire previously defined dimensions  */
98   if ((status = nc_inq_dimid(exoid, DIM_STR_NAME, &strdim)) != NC_NOERR) {
99     exerrval = status;
100     sprintf(errmsg,
101             "Error: failed to get string length in file id %d",exoid);
102     ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
103     return (EX_FATAL);
104   }
105 
106   if ( param->define_maps ) {
107     for ( i = 0; i < num_map_dims; ++i ) {
108       if ((status = nc_inq_dimid(exoid, dim_num_maps[i], &dimid)) != NC_NOERR) {
109         exerrval = status;
110         sprintf( errmsg, "Error: failed to find node map size of file id %d", exoid );
111         ex_err( "ex_put_concat_all_blocks", errmsg, exerrval );
112         return (EX_FATAL);
113       }
114       if ((status = nc_inq_dimlen(exoid, dimid, num_maps+i)) != NC_NOERR) {
115 	exerrval = status;
116 	sprintf( errmsg, "Error: failed to retrieve node map size of file id %d", exoid );
117 	ex_err( "ex_put_concat_all_blocks", errmsg, exerrval );
118 	return (EX_FATAL);
119       }
120     }
121   }
122 
123 #define EX_PREPARE_BLOCK(TNAME,WNAME,DNUMNAME,VSTATNAME,VIDNAME,LNUMNAME,SNUMNAME,SIDNAME,GSTAT) \
124   /* first check if any TNAME blocks are specified			\
125    * OK if zero...							\
126    */									\
127     if ((status = (nc_inq_dimid(exoid, DNUMNAME, &dimid))) == NC_NOERR) { \
128       WNAME = 1;							\
129 									\
130       /* Get number of TNAME blocks defined for this file */		\
131       if ((status = nc_inq_dimlen(exoid,dimid,&LNUMNAME)) != NC_NOERR) { \
132 	exerrval = status;						\
133 	sprintf(errmsg,							\
134 		"Error: failed to get number of " TNAME " blocks in file id %d", \
135 		exoid);							\
136 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
137 	return (EX_FATAL);						\
138       }									\
139 									\
140       /* Fill out the TNAME block status array */			\
141       if (!(GSTAT = malloc(LNUMNAME*sizeof(int)))) {			\
142 	exerrval = EX_MEMFAIL;						\
143 	sprintf(errmsg,							\
144 		"Error: failed to allocate space for " TNAME " block status array in file id %d", \
145 		exoid);							\
146 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
147 	return (EX_FATAL);						\
148       }									\
149 									\
150       for (i=0;i<LNUMNAME;i++) {					\
151 	if (SNUMNAME[i] == 0) /* Is this a NULL TNAME block? */		\
152 	  GSTAT[i] = 0; /* change TNAME block status to NULL */		\
153 	else								\
154 	  GSTAT[i] = 1; /* change TNAME block status to TRUE */		\
155       }									\
156 									\
157       /* Next, get variable id of status array */			\
158       if ((status = nc_inq_varid(exoid, VSTATNAME, &varid)) != NC_NOERR) { \
159 	exerrval = status;						\
160 	sprintf(errmsg,							\
161 		"Error: failed to locate " TNAME " block status in file id %d", \
162 		exoid);							\
163 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
164 	return (EX_FATAL);						\
165       }									\
166 									\
167       status = nc_put_var_int(exoid, varid, GSTAT);			\
168 									\
169       if (status != NC_NOERR) {						\
170 	exerrval = status;						\
171 	sprintf(errmsg,							\
172 		"Error: failed to store " TNAME " block status array to file id %d", \
173 		exoid);							\
174 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
175 	return (EX_FATAL);						\
176       }									\
177 									\
178       free(GSTAT);							\
179 									\
180       /* Next, fill out ids array */					\
181       /* first get id of ids array variable */				\
182       if ((status = nc_inq_varid(exoid, VIDNAME, &varid)) != NC_NOERR) { \
183 	exerrval = status;						\
184 	sprintf(errmsg,							\
185 		"Error: failed to locate " TNAME " block ids array in file id %d", \
186 		exoid);							\
187 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
188 	return (EX_FATAL);						\
189       }									\
190 									\
191       /* then, write out id list */					\
192       status = nc_put_var_int(exoid, varid, SIDNAME);			\
193 									\
194       if (status != NC_NOERR) {						\
195 	exerrval = status;						\
196 	sprintf(errmsg,							\
197 		"Error: failed to store " TNAME " block id array in file id %d", \
198 		exoid);							\
199 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
200 	return (EX_FATAL);						\
201       }									\
202     }
203 
204   EX_PREPARE_BLOCK("element",elem_work,DIM_NUM_EL_BLK,VAR_STAT_EL_BLK,VAR_ID_EL_BLK,
205 		   num_elem_blk,param->num_elem_this_blk,param->elem_blk_id,eb_stat);
206   EX_PREPARE_BLOCK(   "edge",edge_work,DIM_NUM_ED_BLK,VAR_STAT_ED_BLK,VAR_ID_ED_BLK,
207 		      num_edge_blk,param->num_edge_this_blk,param->edge_blk_id,ed_stat);
208   EX_PREPARE_BLOCK(   "face",face_work,DIM_NUM_FA_BLK,VAR_STAT_FA_BLK,VAR_ID_FA_BLK,
209 		      num_face_blk,param->num_face_this_blk,param->face_blk_id,fa_stat);
210 
211   if ( elem_work == 0 && edge_work == 0 && face_work == 0 && param->define_maps == 0 ) {
212     /* Nothing to do. This is not an error, but we can save
213      * ourselves from entering define mode by returning here.
214      */
215     return (EX_NOERR);
216   }
217   /* put netcdf file into define mode  */
218   if ((status = nc_redef(exoid)) != NC_NOERR)  {
219     exerrval = status;
220     sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid);
221     ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
222     return (EX_FATAL);
223   }
224 
225 #define EX_PREPARE_ATTRIB_ARRAY(TNAME,CURBLK,DNAME,DVAL,ID,VANAME,VADIM0,VADIM1,VANNAME) \
226   if (DVAL[iblk] > 0) {							\
227     if ((status = nc_def_dim (exoid,					\
228 			      DNAME(CURBLK+1),				\
229 			      DVAL[iblk], &VADIM1)) != NC_NOERR) { \
230       exerrval = status;						\
231       sprintf(errmsg,							\
232 	      "Error: failed to define number of attributes in " TNAME " block %d in file id %d", \
233 	      ID[iblk],exoid);						\
234       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
235       goto error_ret;         /* exit define mode and return */		\
236     }									\
237 									\
238     dims[0] = VADIM0;							\
239     dims[1] = VADIM1;							\
240 									\
241     if ((status = nc_def_var (exoid, VANAME(CURBLK+1),			\
242 			      nc_flt_code(exoid), 2, dims, &temp)) != NC_NOERR) { \
243       exerrval = status;						\
244       sprintf(errmsg,							\
245 	      "Error:  failed to define attributes for " TNAME " block %d in file id %d", \
246 	      ID[iblk],exoid);						\
247       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
248       goto error_ret;         /* exit define mode and return */		\
249     }									\
250 									\
251     /* Attribute names... */						\
252     dims[0] = VADIM1;							\
253     dims[1] = strdim;							\
254 									\
255     if ((status = nc_def_var(exoid, VANNAME(CURBLK+1), NC_CHAR, 2, dims, &temp)) != NC_NOERR) { \
256       exerrval = status;						\
257       sprintf(errmsg,							\
258 	      "Error: failed to define " TNAME " attribute name array in file id %d",exoid); \
259       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
260       goto error_ret;         /* exit define mode and return */		\
261     }									\
262   }
263 
264 #define EX_PREPARE_CONN(TNAME,BLK,BLKID,BLKSZ,VNAME,DNAME)		\
265   if ( DNAME > 0 ) {							\
266     dims[0] = BLKSZ;							\
267     dims[1] = DNAME;							\
268 									\
269     if ((status = nc_def_var(exoid, VNAME(BLK+1),			\
270 			     NC_INT, 2, dims, &connid)) != NC_NOERR) {	\
271       exerrval = status;						\
272       sprintf(errmsg,							\
273 	      "Error: failed to create " TNAME " connectivity array for block %d in file id %d", \
274 	      BLKID[iblk],exoid);					\
275       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);		\
276       goto error_ret;         /* exit define mode and return */		\
277     }									\
278   }
279 
280 
281   /* Iterate over edge blocks ... */
282   for (iblk = 0; iblk < num_edge_blk; ++iblk) {
283 
284     cur_num_edge_blk=ex_get_file_item(exoid, ex_get_counter_list(EX_EDGE_BLOCK));
285     if (cur_num_edge_blk >= (int)num_edge_blk) {
286       exerrval = EX_FATAL;
287       sprintf(errmsg,
288 	      "Error: exceeded number of edge blocks (%ld) defined in file id %d",
289 	      (long)num_edge_blk,exoid);
290       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
291       goto error_ret;
292     }
293 
294     /* NOTE: ex_inc_file_item  is used to find the number of edge blocks
295        for a specific file and returns that value incremented. */
296     cur_num_edge_blk=ex_inc_file_item(exoid, ex_get_counter_list(EX_EDGE_BLOCK));
297 
298     if (param->num_edge_this_blk[iblk] == 0) /* Is this a NULL edge block? */
299       continue;
300 
301     /* define some dimensions and variables*/
302     if ((status = nc_def_dim(exoid,
303 			     DIM_NUM_ED_IN_EBLK(cur_num_edge_blk+1),
304 			     param->num_edge_this_blk[iblk],&numedbdim)) != NC_NOERR) {
305       exerrval = status;
306       if (status == NC_ENAMEINUSE) {     /* duplicate entry */
307 	sprintf(errmsg,
308 		"Error: edge block %d already defined in file id %d",
309 		param->edge_blk_id[iblk],exoid);
310       } else {
311 	sprintf(errmsg,
312 		"Error: failed to define number of edges/block for block %d file id %d",
313 		param->edge_blk_id[iblk],exoid);
314       }
315       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
316       goto error_ret;         /* exit define mode and return */
317     }
318 
319     if ((status = nc_def_dim(exoid,
320 			     DIM_NUM_NOD_PER_ED(cur_num_edge_blk+1),
321 			     param->num_nodes_per_edge[iblk],&nednoddim)) != NC_NOERR) {
322       exerrval = status;
323       sprintf(errmsg,
324 	      "Error: failed to define number of nodes/edge for block %d in file id %d",
325 	      param->edge_blk_id[iblk],exoid);
326       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
327       goto error_ret;         /* exit define mode and return */
328     }
329 
330     /* edge attribute array */
331     EX_PREPARE_ATTRIB_ARRAY("edge",cur_num_edge_blk,DIM_NUM_ATT_IN_EBLK,param->num_attr_edge,param->edge_blk_id,VAR_EATTRIB,numedbdim,numattrdim,VAR_NAME_EATTRIB);
332 
333     EX_PREPARE_CONN("edge block",cur_num_edge_blk,param->edge_blk_id,numedbdim,VAR_EBCONN,nednoddim);
334 
335     /* store edge type as attribute of connectivity variable */
336     if ((status = nc_put_att_text(exoid, connid, ATT_NAME_ELB, strlen(param->edge_type[iblk])+1,
337 				  (void*)param->edge_type[iblk])) != NC_NOERR) {
338       exerrval = status;
339       sprintf(errmsg,
340 	      "Error: failed to store edge type name %s in file id %d",
341 	      param->edge_type[iblk],exoid);
342       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
343       goto error_ret;         /* exit define mode and return */
344     }
345   }
346 
347   /* Iterate over face blocks ... */
348   for (iblk = 0; iblk < num_face_blk; ++iblk) {
349 
350     cur_num_face_blk=ex_get_file_item(exoid, ex_get_counter_list(EX_FACE_BLOCK));
351     if (cur_num_face_blk >= (int)num_face_blk) {
352       exerrval = EX_FATAL;
353       sprintf(errmsg,
354 	      "Error: exceeded number of face blocks (%ld) defined in file id %d",
355 	      (long)num_face_blk,exoid);
356       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
357       goto error_ret;
358     }
359 
360     /* NOTE: ex_inc_file_item  is used to find the number of edge blocks
361        for a specific file and returns that value incremented. */
362     cur_num_face_blk=ex_inc_file_item(exoid, ex_get_counter_list(EX_FACE_BLOCK));
363 
364     if (param->num_face_this_blk[iblk] == 0) /* Is this a NULL face block? */
365       continue;
366 
367     /* define some dimensions and variables*/
368     if ((status = nc_def_dim (exoid,
369 			      DIM_NUM_FA_IN_FBLK(cur_num_face_blk+1),
370 			      param->num_face_this_blk[iblk],&numfabdim)) != NC_NOERR) {
371       exerrval = status;
372       if (status == NC_ENAMEINUSE) {     /* duplicate entry */
373 	sprintf(errmsg,
374 		"Error: face block %d already defined in file id %d",
375 		param->face_blk_id[iblk],exoid);
376       } else {
377 	sprintf(errmsg,
378 		"Error: failed to define number of faces/block for block %d file id %d",
379 		param->face_blk_id[iblk],exoid);
380       }
381       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
382       goto error_ret;         /* exit define mode and return */
383     }
384 
385     if ((status = nc_def_dim (exoid,
386 			      DIM_NUM_NOD_PER_FA(cur_num_face_blk+1),
387 			      param->num_nodes_per_face[iblk],&nfanoddim)) != NC_NOERR) {
388       exerrval = status;
389       sprintf(errmsg,
390 	      "Error: failed to define number of nodes/face for block %d in file id %d",
391 	      param->face_blk_id[iblk],exoid);
392       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
393       goto error_ret;         /* exit define mode and return */
394     }
395 
396     /* edge attribute array */
397     EX_PREPARE_ATTRIB_ARRAY("face",cur_num_face_blk,DIM_NUM_ATT_IN_FBLK,param->num_attr_face,param->face_blk_id,VAR_FATTRIB,numfabdim,numattrdim,VAR_NAME_FATTRIB);
398 
399     EX_PREPARE_CONN("face block",cur_num_face_blk,param->face_blk_id,numfabdim,VAR_FBCONN,nfanoddim);
400 
401     /* store face type as attribute of connectivity variable */
402     if ((status = nc_put_att_text(exoid, connid, ATT_NAME_ELB, strlen(param->face_type[iblk])+1,
403 				  (void*)param->face_type[iblk])) != NC_NOERR) {
404       exerrval = status;
405       sprintf(errmsg,
406 	      "Error: failed to store face type name %s in file id %d",
407 	      param->face_type[iblk],exoid);
408       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
409       goto error_ret;         /* exit define mode and return */
410     }
411   }
412 
413   /* Iterate over element blocks ... */
414   for (iblk = 0; iblk < num_elem_blk; ++iblk) {
415 
416     cur_num_elem_blk=ex_get_file_item(exoid, ex_get_counter_list(EX_ELEM_BLOCK));
417     if (cur_num_elem_blk >= (int)num_elem_blk) {
418       exerrval = EX_FATAL;
419       sprintf(errmsg,
420 	      "Error: exceeded number of element blocks (%ld) defined in file id %d",
421 	      (long)num_elem_blk,exoid);
422       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
423       goto error_ret;
424     }
425 
426     /* NOTE: ex_inc_file_item  is used to find the number of element blocks
427        for a specific file and returns that value incremented. */
428     cur_num_elem_blk=ex_inc_file_item(exoid, ex_get_counter_list(EX_ELEM_BLOCK));
429 
430     if (param->num_elem_this_blk[iblk] == 0) /* Is this a NULL element block? */
431       continue;
432 
433     /* define some dimensions and variables*/
434     if ((status = nc_def_dim (exoid,
435 			      DIM_NUM_EL_IN_BLK(cur_num_elem_blk+1),
436 			      param->num_elem_this_blk[iblk], &numelbdim)) != NC_NOERR) {
437       exerrval = status;
438       if (status == NC_ENAMEINUSE) {     /* duplicate entry */
439 	sprintf(errmsg,
440 		"Error: element block %d already defined in file id %d",
441 		param->elem_blk_id[iblk],exoid);
442       } else {
443 	sprintf(errmsg,
444 		"Error: failed to define number of elements/block for block %d file id %d",
445 		param->elem_blk_id[iblk],exoid);
446       }
447       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
448       goto error_ret;         /* exit define mode and return */
449     }
450 
451     /* Always define DIM_NUM_NOD_PER_EL, even if zero.
452      * Do not define DIM_NUM_EDG_PER_EL or DIM_NUM_FAC_PER_EL unless > 0.
453      */
454     if ((status = nc_def_dim (exoid,
455 			      DIM_NUM_NOD_PER_EL(cur_num_elem_blk+1),
456 			      param->num_nodes_per_elem[iblk], &nelnoddim)) != NC_NOERR) {
457       exerrval = status;
458       sprintf(errmsg,
459 	      "Error: failed to define number of nodes/element for block %d in file id %d",
460 	      param->elem_blk_id[iblk],exoid);
461       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
462       goto error_ret;         /* exit define mode and return */
463     }
464 
465     if ( param->num_edges_per_elem[iblk] > 0 ) {
466       if ((status = nc_def_dim (exoid,
467 				DIM_NUM_EDG_PER_EL(cur_num_elem_blk+1),
468 				param->num_edges_per_elem[iblk],&neledgdim)) != NC_NOERR) {
469 	exerrval = status;
470 	sprintf(errmsg,
471 		"Error: failed to define number of edges/element for block %d in file id %d",
472 		param->elem_blk_id[iblk],exoid);
473 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
474 	goto error_ret;         /* exit define mode and return */
475       }
476     }
477 
478     if ( param->num_faces_per_elem[iblk] > 0 ) {
479       if ((status = nc_def_dim(exoid,
480 			       DIM_NUM_FAC_PER_EL(cur_num_elem_blk+1),
481 			       param->num_faces_per_elem[iblk],&nelfacdim)) != NC_NOERR) {
482 	exerrval = status;
483 	sprintf(errmsg,
484 		"Error: failed to define number of faces/element for block %d in file id %d",
485 		param->elem_blk_id[iblk],exoid);
486 	ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
487 	goto error_ret;         /* exit define mode and return */
488       }
489     }
490 
491     /* element attribute array */
492     EX_PREPARE_ATTRIB_ARRAY("element",cur_num_elem_blk,DIM_NUM_ATT_IN_BLK,param->num_attr_elem,param->elem_blk_id,VAR_ATTRIB,numelbdim,numattrdim,VAR_NAME_ATTRIB);
493 
494     /* element connectivity array */
495     EX_PREPARE_CONN("nodal",cur_num_elem_blk,param->elem_blk_id,numelbdim,VAR_CONN,nelnoddim);
496 
497     /* store element type as attribute of connectivity variable */
498     if ((status = nc_put_att_text(exoid, connid, ATT_NAME_ELB, strlen(param->elem_type[iblk])+1,
499 				  (void*)param->elem_type[iblk])) != NC_NOERR) {
500       exerrval = status;
501       sprintf(errmsg,
502 	      "Error: failed to store element type name %s in file id %d",
503 	      param->elem_type[iblk],exoid);
504       ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
505       goto error_ret;         /* exit define mode and return */
506     }
507 
508     EX_PREPARE_CONN( "edge",cur_num_elem_blk,param->elem_blk_id,numelbdim,VAR_ECONN,neledgdim);
509     EX_PREPARE_CONN( "face",cur_num_elem_blk,param->elem_blk_id,numelbdim,VAR_FCONN,nelfacdim);
510   }
511 
512   /* Define the element map here to avoid a later redefine call */
513   if ( param->define_maps != 0 ) {
514     size_t map_type;
515     for ( map_type = 0; map_type < num_map_dims; ++map_type ) {
516       if ((status = nc_inq_dimid(exoid, dim_size_maps[map_type], &dims[0])) != NC_NOERR) {
517 	exerrval = status;
518 	sprintf( errmsg,
519 		 "Error: could not find map size dimension %s in file id %d",
520 		 dim_size_maps[map_type], exoid );
521 	ex_err( "ex_put_concat_all_blocks", errmsg, exerrval );
522       }
523       for ( i = 1; i <= num_maps[map_type]; ++i ) {
524 	const char* mapname = ex_name_of_map( map_enums[map_type], i );
525 	if (nc_inq_varid(exoid, mapname, &temp) != NC_NOERR) {
526 	  if ((status = nc_def_var(exoid, mapname, NC_INT, 1, dims, &temp)) != NC_NOERR) {
527 	    exerrval = status;
528 	    if ( status == NC_ENAMEINUSE ) {
529 	      sprintf( errmsg, "Error: number map %s already exists in file id %d", mapname, exoid );
530 	    } else {
531 	      sprintf( errmsg, "Error: failed to create number map array %s in file id %d", mapname, exoid );
532 	    }
533 	    ex_err( "ex_put_concat_all_blocks", errmsg, exerrval );
534 	    goto error_ret; /* exit define mode and return */
535 	  }
536 	}
537       }
538     }
539   }
540 
541   /* leave define mode  */
542   if ((status = nc_enddef (exoid)) != NC_NOERR) {
543     exerrval = status;
544     sprintf(errmsg,
545 	    "Error: failed to complete element block definition in file id %d",
546 	    exoid);
547     ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
548     return (EX_FATAL);
549   }
550 
551   return (EX_NOERR);
552 
553   /* Fatal error: exit definition mode and return */
554  error_ret:
555   if (nc_enddef (exoid) != NC_NOERR) {     /* exit define mode */
556     sprintf(errmsg,
557 	    "Error: failed to complete definition for file id %d",
558 	    exoid);
559     ex_err("ex_put_concat_all_blocks",errmsg,exerrval);
560   }
561   return (EX_FATAL);
562 }
563 
564