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 * expblk - ex_put_block: write edge, face, or element block parameters
38 *
39 * entry conditions -
40 *   input parameters:
41 *       int     idexo                   exodus file id
42 *       int     blk_type                type of block (edge, face, or element)
43 *       int     blk_id                  block identifer
44 *       char*   entry_descrip           string describing shape of entries in the block
45 *       int     num_entries_this_blk    number of entries(records) in the block
46 *       int     num_nodes_per_entry     number of nodes per block entry
47 *       int     num_edges_per_entry     number of edges per block entry
48 *       int     num_faces_per_entry     number of faces per block entry
49 *       int     num_attr_per_entry      number of attributes per block entry
50 *
51 * exit conditions -
52 *
53 *
54 *****************************************************************************/
55 
56 #include "exodusII.h"
57 #include "exodusII_int.h"
58 #include <string.h>
59 
60 /*!
61  * writes the parameters used to describe an element block
62  * \param   exoid                   exodus file id
63  * \param   blk_type                type of block (edge, face, or element)
64  * \param   blk_id                  block identifer
65  * \param   entry_descrip           string describing shape of entries in the block
66  * \param   num_entries_this_blk    number of entries(records) in the block
67  * \param   num_nodes_per_entry     number of nodes per block entry
68  * \param   num_edges_per_entry     number of edges per block entry
69  * \param   num_faces_per_entry     number of faces per block entry
70  * \param   num_attr_per_entry      number of attributes per block entry
71  */
72 
ex_put_block(int exoid,ex_entity_type blk_type,int blk_id,const char * entry_descrip,int num_entries_this_blk,int num_nodes_per_entry,int num_edges_per_entry,int num_faces_per_entry,int num_attr_per_entry)73 int ex_put_block( int         exoid,
74                   ex_entity_type blk_type,
75                   int         blk_id,
76                   const char* entry_descrip,
77                   int         num_entries_this_blk,
78                   int         num_nodes_per_entry,
79                   int         num_edges_per_entry,
80                   int         num_faces_per_entry,
81                   int         num_attr_per_entry )
82 {
83   int status;
84   int arbitrary_polyhedra = 0; /* 1 if block is arbitrary 2d polyhedra type; 2 if 3d polyhedra */
85   int att_name_varid, varid, dimid, dims[2], blk_id_ndx, blk_stat, strdim;
86   size_t start[2];
87   int num_blk;
88   size_t temp;
89   int cur_num_blk, numblkdim, numattrdim;
90   int nnodperentdim, nedgperentdim, nfacperentdim;
91   int connid;
92   int npeid;
93   char errmsg[MAX_ERR_LENGTH];
94   char entity_type1[5];
95   char entity_type2[5];
96   const char* dnumblk = NULL;
97   const char* vblkids = NULL;
98   const char* vblksta = NULL;
99   const char* vnodcon = NULL;
100   const char* vnpecnt = NULL;
101   const char* vedgcon = NULL;
102   const char* vfaccon = NULL;
103   const char* vconn   = NULL;
104   const char* vattnam = NULL;
105   const char* vblkatt = NULL;
106   const char* dneblk  = NULL;
107   const char* dnape   = NULL;
108   const char* dnnpe   = NULL;
109   const char* dnepe   = NULL;
110   const char* dnfpe   = NULL;
111 
112   exerrval  = 0; /* clear error code */
113 
114   switch (blk_type) {
115   case EX_EDGE_BLOCK:
116     dnumblk = DIM_NUM_ED_BLK;
117     vblkids = VAR_ID_ED_BLK;
118     vblksta = VAR_STAT_ED_BLK;
119     break;
120   case EX_FACE_BLOCK:
121     dnumblk = DIM_NUM_FA_BLK;
122     vblkids = VAR_ID_FA_BLK;
123     vblksta = VAR_STAT_FA_BLK;
124     break;
125   case EX_ELEM_BLOCK:
126     dnumblk = DIM_NUM_EL_BLK;
127     vblkids = VAR_ID_EL_BLK;
128     vblksta = VAR_STAT_EL_BLK;
129     break;
130   default:
131     exerrval = EX_BADPARAM;
132     sprintf( errmsg, "Error: Bad block type (%d) specified for file id %d",
133 	     blk_type, exoid );
134     ex_err( "ex_put_block", errmsg, exerrval );
135     return (EX_FATAL);
136   }
137 
138   /* first check if any element blocks are specified */
139 
140   if ((status = ex_get_dimension(exoid, dnumblk, ex_name_of_object(blk_type),
141 				 &temp, &dimid, "ex_put_block")) != NC_NOERR) {
142     return EX_FATAL;
143   }
144   num_blk = temp;
145 
146   /* Next: Make sure that this is not a duplicate element block id by
147      searching the vblkids array.
148      WARNING: This must be done outside of define mode because id_lkup accesses
149      the database to determine the position
150   */
151 
152   if ((status = nc_inq_varid(exoid, vblkids, &varid)) != NC_NOERR) {
153     exerrval = status;
154     sprintf(errmsg,
155             "Error: failed to locate %s ids in file id %d",
156 	    ex_name_of_object(blk_type), exoid);
157     ex_err("ex_put_block",errmsg,exerrval);
158   }
159 
160   blk_id_ndx = ex_id_lkup(exoid,blk_type,blk_id);
161   if (exerrval != EX_LOOKUPFAIL) {   /* found the element block id */
162     exerrval = EX_FATAL;
163     sprintf(errmsg,
164             "Error: %s id %d already exists in file id %d",
165 	    ex_name_of_object(blk_type), blk_id,exoid);
166     ex_err("ex_put_block",errmsg,exerrval);
167     return (EX_FATAL);
168   }
169 
170   /* Keep track of the total number of element blocks defined using a counter
171      stored in a linked list keyed by exoid.
172      NOTE: ex_get_file_item  is a function that finds the number of element
173      blocks for a specific file and returns that value incremented.
174   */
175   cur_num_blk=ex_get_file_item(exoid, ex_get_counter_list(blk_type));
176   if (cur_num_blk >= num_blk) {
177     exerrval = EX_FATAL;
178     sprintf(errmsg,
179 	    "Error: exceeded number of %ss (%d) defined in file id %d",
180 	    ex_name_of_object(blk_type), num_blk,exoid);
181     ex_err("ex_put_block",errmsg,exerrval);
182     return (EX_FATAL);
183   }
184 
185 
186   /*   NOTE: ex_get_file_item  is a function that finds the number of element
187        blocks for a specific file and returns that value incremented. */
188   cur_num_blk=ex_inc_file_item(exoid, ex_get_counter_list(blk_type));
189   start[0] = cur_num_blk;
190 
191   /* write out element block id to previously defined id array variable*/
192   if ((status = nc_put_var1_int(exoid, varid, start, &blk_id)) != NC_NOERR) {
193     exerrval = status;
194     sprintf(errmsg,
195 	    "Error: failed to store %s id to file id %d",
196 	    ex_name_of_object(blk_type), exoid);
197     ex_err("ex_put_block",errmsg,exerrval);
198     return (EX_FATAL);
199   }
200 
201   blk_id_ndx = start[0]+1; /* element id index into vblkids array*/
202 
203   if (num_entries_this_blk == 0) /* Is this a NULL element block? */
204     blk_stat = 0; /* change element block status to NULL */
205   else
206     blk_stat = 1; /* change element block status to TRUE */
207 
208   if ((status = nc_inq_varid (exoid, vblksta, &varid)) != NC_NOERR) {
209     exerrval = status;
210     sprintf(errmsg,
211 	    "Error: failed to locate %s status in file id %d",
212 	    ex_name_of_object(blk_type), exoid);
213     ex_err("ex_put_block",errmsg,exerrval);
214     return (EX_FATAL);
215   }
216 
217   if ((status = nc_put_var1_int(exoid, varid, start, &blk_stat)) != NC_NOERR) {
218     exerrval = status;
219     sprintf(errmsg,
220 	    "Error: failed to store %s id %d status to file id %d",
221 	    ex_name_of_object(blk_type), blk_id, exoid);
222     ex_err("ex_put_block",errmsg,exerrval);
223     return (EX_FATAL);
224   }
225 
226   if (num_entries_this_blk == 0) {/* Is this a NULL element block? */
227     return(EX_NOERR);
228   }
229 
230 
231   /* put netcdf file into define mode  */
232   if ((status=nc_redef (exoid)) != NC_NOERR) {
233     exerrval = status;
234     sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid);
235     ex_err("ex_put_block",errmsg,exerrval);
236     return (EX_FATAL);
237   }
238 
239   switch (blk_type) {
240   case EX_EDGE_BLOCK:
241     dneblk = DIM_NUM_ED_IN_EBLK(blk_id_ndx);
242     dnnpe = DIM_NUM_NOD_PER_ED(blk_id_ndx);
243     dnepe = 0;
244     dnfpe = 0;
245     dnape = DIM_NUM_ATT_IN_EBLK(blk_id_ndx);
246     vblkatt = VAR_EATTRIB(blk_id_ndx);
247     vattnam = VAR_NAME_EATTRIB(blk_id_ndx);
248     vnodcon = VAR_EBCONN(blk_id_ndx);
249     vedgcon = 0;
250     vfaccon = 0;
251     break;
252   case EX_FACE_BLOCK:
253     dneblk = DIM_NUM_FA_IN_FBLK(blk_id_ndx);
254     dnnpe = DIM_NUM_NOD_PER_FA(blk_id_ndx);
255     dnepe = 0;
256     dnfpe = 0;
257     dnape = DIM_NUM_ATT_IN_FBLK(blk_id_ndx);
258     vblkatt = VAR_FATTRIB(blk_id_ndx);
259     vattnam = VAR_NAME_FATTRIB(blk_id_ndx);
260     vnodcon = VAR_FBCONN(blk_id_ndx);
261     vnpecnt = VAR_FBEPEC(blk_id_ndx);
262     vedgcon = 0;
263     vfaccon = 0;
264     break;
265   case EX_ELEM_BLOCK:
266     dneblk = DIM_NUM_EL_IN_BLK(blk_id_ndx);
267     dnnpe = DIM_NUM_NOD_PER_EL(blk_id_ndx);
268     dnepe = DIM_NUM_EDG_PER_EL(blk_id_ndx);
269     dnfpe = DIM_NUM_FAC_PER_EL(blk_id_ndx);
270     dnape = DIM_NUM_ATT_IN_BLK(blk_id_ndx);
271     vblkatt = VAR_ATTRIB(blk_id_ndx);
272     vattnam = VAR_NAME_ATTRIB(blk_id_ndx);
273     vnodcon = VAR_CONN(blk_id_ndx);
274     vnpecnt = VAR_EBEPEC(blk_id_ndx);
275     vedgcon = VAR_ECONN(blk_id_ndx);
276     vfaccon = VAR_FCONN(blk_id_ndx);
277     break;
278   default:
279     exerrval = 1005;
280     sprintf(errmsg,
281 	    "Internal Error: unrecognized block type in switch: %d in file id %d",
282 	    blk_type,exoid);
283     ex_err("ex_put_block",errmsg,EX_MSG);
284     return (EX_FATAL);              /* number of attributes not defined */
285   }
286   /* define some dimensions and variables*/
287 
288   if ((status = nc_def_dim(exoid,dneblk,num_entries_this_blk, &numblkdim )) != NC_NOERR) {
289     if (status == NC_ENAMEINUSE) {        /* duplicate entry */
290       exerrval = status;
291       sprintf(errmsg,
292 	      "Error: %s %d already defined in file id %d",
293 	      ex_name_of_object(blk_type), blk_id,exoid);
294       ex_err("ex_put_block",errmsg,exerrval);
295     } else {
296       exerrval = status;
297       sprintf(errmsg,
298 	      "Error: failed to define number of entities/block for %s %d file id %d",
299 	      ex_name_of_object(blk_type), blk_id,exoid);
300       ex_err("ex_put_block",errmsg,exerrval);
301     }
302     goto error_ret;         /* exit define mode and return */
303   }
304 
305   if ( dnnpe && num_nodes_per_entry > 0) {
306     /* A nfaced block would not have any nodes defined... */
307     if ((status = nc_def_dim(exoid,dnnpe,num_nodes_per_entry, &nnodperentdim)) != NC_NOERR) {
308       exerrval = status;
309       sprintf(errmsg,
310 	      "Error: failed to define number of nodes/entity for %s %d in file id %d",
311 	      ex_name_of_object(blk_type), blk_id,exoid);
312       ex_err("ex_put_block",errmsg,exerrval);
313       goto error_ret;         /* exit define mode and return */
314     }
315   }
316 
317   if (dnepe && num_edges_per_entry > 0 ) {
318     if ((status = nc_def_dim (exoid,dnepe,num_edges_per_entry, &nedgperentdim)) != NC_NOERR) {
319       exerrval = status;
320       sprintf(errmsg,
321 	      "Error: failed to define number of edges/entity for %s %d in file id %d",
322 	      ex_name_of_object(blk_type), blk_id,exoid);
323       ex_err("ex_put_block",errmsg,exerrval);
324       goto error_ret;         /* exit define mode and return */
325     }
326   }
327 
328   if ( dnfpe && num_faces_per_entry > 0 ) {
329     if ((status = nc_def_dim(exoid,dnfpe,num_faces_per_entry, &nfacperentdim)) != NC_NOERR) {
330       exerrval = status;
331       sprintf(errmsg,
332 	      "Error: failed to define number of faces/entity for %s %d in file id %d",
333 	      ex_name_of_object(blk_type), blk_id,exoid);
334       ex_err("ex_put_block",errmsg,exerrval);
335       goto error_ret;         /* exit define mode and return */
336     }
337   }
338 
339   /* element attribute array */
340   if (num_attr_per_entry > 0) {
341 
342     if ((status = nc_def_dim(exoid, dnape, num_attr_per_entry, &numattrdim)) != NC_NOERR) {
343       exerrval = status;
344       sprintf(errmsg,
345 	      "Error: failed to define number of attributes in %s %d in file id %d",
346 	      ex_name_of_object(blk_type), blk_id,exoid);
347       ex_err("ex_put_block",errmsg,exerrval);
348       goto error_ret;         /* exit define mode and return */
349     }
350 
351     dims[0] = numblkdim;
352     dims[1] = numattrdim;
353 
354     if ((status = nc_def_var(exoid, vblkatt, nc_flt_code(exoid), 2, dims, &varid)) != NC_NOERR) {
355       exerrval = status;
356       sprintf(errmsg,
357 	      "Error:  failed to define attributes for %s %d in file id %d",
358 	      ex_name_of_object(blk_type), blk_id,exoid);
359       ex_err("ex_put_block",errmsg,exerrval);
360       goto error_ret;         /* exit define mode and return */
361     }
362 
363     /* inquire previously defined dimensions  */
364     if ((status = nc_inq_dimid(exoid, DIM_STR_NAME, &strdim)) != NC_NOERR) {
365       exerrval = status;
366       sprintf(errmsg,
367 	      "Error: failed to get string length in file id %d",exoid);
368       ex_err("ex_put_block",errmsg,exerrval);
369       return (EX_FATAL);
370     }
371 
372     /* Attribute names... */
373     dims[0] = numattrdim;
374     dims[1] = strdim;
375 
376     if ((status = nc_def_var(exoid, vattnam, NC_CHAR, 2, dims, &att_name_varid)) != NC_NOERR) {
377       exerrval = status;
378       sprintf(errmsg,
379 	      "Error: failed to define %s attribute name array in file id %d",
380 	      ex_name_of_object(blk_type), exoid);
381       ex_err("ex_put_block",errmsg,exerrval);
382       goto error_ret;         /* exit define mode and return */
383     }
384   }
385 
386   /* See if storing an 'nsided' element block (arbitrary 2d polyhedra or super element) */
387   if (strlen(entry_descrip) >= 3) {
388     if ((entry_descrip[0] == 'n' || entry_descrip[0] == 'N') &&
389 	(entry_descrip[1] == 's' || entry_descrip[1] == 'S') &&
390 	(entry_descrip[2] == 'i' || entry_descrip[2] == 'I'))
391       arbitrary_polyhedra = 1;
392     else if ((entry_descrip[0] == 'n' || entry_descrip[0] == 'N') &&
393 	     (entry_descrip[1] == 'f' || entry_descrip[1] == 'F') &&
394 	     (entry_descrip[2] == 'a' || entry_descrip[2] == 'A'))
395       /* If a FACE_BLOCK, then we are dealing with the faces of the nfaced block. */
396       arbitrary_polyhedra = blk_type == EX_FACE_BLOCK ? 1 : 2;
397   }
398 
399   /* element connectivity array */
400   if (arbitrary_polyhedra > 0) {
401     if (blk_type != EX_FACE_BLOCK && blk_type != EX_ELEM_BLOCK) {
402       exerrval = EX_BADPARAM;
403       sprintf( errmsg, "Error: Bad block type (%d) for nsided/nfaced block in file id %d",
404 	       blk_type, exoid );
405       ex_err( "ex_put_block", errmsg, exerrval );
406       return (EX_FATAL);
407     }
408 
409     if (arbitrary_polyhedra == 1) {
410       dims[0] = nnodperentdim;
411       vconn = vnodcon;
412 
413       /* store entity types as attribute of npeid variable -- node/elem, node/face, face/elem*/
414       strcpy(entity_type1, "NODE");
415       if (blk_type == EX_ELEM_BLOCK)
416 	strcpy(entity_type2, "ELEM");
417       else
418 	strcpy(entity_type2, "FACE");
419     } else if (arbitrary_polyhedra == 2) {
420       dims[0] = nfacperentdim;
421       vconn = vfaccon;
422 
423       /* store entity types as attribute of npeid variable -- node/elem, node/face, face/elem*/
424       strcpy(entity_type1, "FACE");
425       strcpy(entity_type2, "ELEM");
426     }
427 
428     if ((status = nc_def_var(exoid, vconn, NC_INT, 1, dims, &connid)) != NC_NOERR) {
429       exerrval = status;
430       sprintf(errmsg,
431 	      "Error: failed to create connectivity array for %s %d in file id %d",
432 	      ex_name_of_object(blk_type), blk_id,exoid);
433       ex_err("ex_put_block",errmsg,exerrval);
434       goto error_ret;         /* exit define mode and return */
435     }
436 
437     /* element face-per-element or node-per-element count array */
438     dims[0] = numblkdim;
439 
440     if ((status = nc_def_var(exoid, vnpecnt, NC_INT, 1, dims, &npeid)) != NC_NOERR) {
441       exerrval = status;
442       sprintf(errmsg,
443 	      "Error: failed to create face- or node- per-entity count array for %s %d in file id %d",
444 	      ex_name_of_object(blk_type), blk_id, exoid);
445       ex_err("ex_put_block",errmsg,exerrval);
446       goto error_ret;         /* exit define mode and return */
447     }
448 
449     if ((status = nc_put_att_text(exoid, npeid, "entity_type1", strlen(entity_type1)+1,
450 				  entity_type1)) != NC_NOERR) {
451       exerrval = status;
452       sprintf(errmsg,
453 	      "Error: failed to store entity type attribute text for %s %d in file id %d",
454 	      ex_name_of_object(blk_type), blk_id, exoid);
455       ex_err("ex_put_block",errmsg,exerrval);
456       goto error_ret;         /* exit define mode and return */
457     }
458     if ((status = nc_put_att_text(exoid, npeid, "entity_type2", strlen(entity_type2)+1,
459 				  entity_type2)) != NC_NOERR) {
460       exerrval = status;
461       sprintf(errmsg,
462 	      "Error: failed to store entity type attribute text for %s %d in file id %d",
463 	      ex_name_of_object(blk_type), blk_id, exoid);
464       ex_err("ex_put_block",errmsg,exerrval);
465       goto error_ret;         /* exit define mode and return */
466     }
467   } else {
468     /* "Normal" (non-polyhedra) element block type */
469     dims[0] = numblkdim;
470     dims[1] = nnodperentdim;
471 
472     if ((status = nc_def_var(exoid, vnodcon, NC_INT, 2, dims, &connid)) != NC_NOERR) {
473       exerrval = status;
474       sprintf(errmsg,
475 	      "Error: failed to create connectivity array for %s %d in file id %d",
476 	      ex_name_of_object(blk_type), blk_id,exoid);
477       ex_err("ex_put_block",errmsg,exerrval);
478       goto error_ret;         /* exit define mode and return */
479     }
480   }
481   /* store element type as attribute of connectivity variable */
482   if ((status = nc_put_att_text(exoid, connid, ATT_NAME_ELB, strlen(entry_descrip)+1,
483 				entry_descrip)) != NC_NOERR) {
484     exerrval = status;
485     sprintf(errmsg,
486 	    "Error: failed to store %s type name %s in file id %d",
487 	    ex_name_of_object(blk_type), entry_descrip,exoid);
488     ex_err("ex_put_block",errmsg,exerrval);
489     goto error_ret;         /* exit define mode and return */
490   }
491 
492   if (arbitrary_polyhedra == 0) {
493     if (vedgcon && num_edges_per_entry ) {
494       dims[0] = numblkdim;
495       dims[1] = nedgperentdim;
496 
497       if ((status = nc_def_var(exoid, vedgcon, NC_INT, 2, dims, &varid)) != NC_NOERR) {
498 	exerrval = status;
499 	sprintf(errmsg,
500 		"Error: failed to create edge connectivity array for %s %d in file id %d",
501 		ex_name_of_object(blk_type), blk_id,exoid);
502 	ex_err("ex_put_block",errmsg,exerrval);
503 	goto error_ret;         /* exit define mode and return */
504       }
505     }
506 
507     if ( vfaccon && num_faces_per_entry ) {
508       dims[0] = numblkdim;
509       dims[1] = nfacperentdim;
510 
511       if ((status = nc_def_var(exoid, vfaccon, NC_INT, 2, dims, &varid)) != NC_NOERR) {
512 	exerrval = status;
513 	sprintf(errmsg,
514 		"Error: failed to create face connectivity array for %s %d in file id %d",
515 		ex_name_of_object(blk_type), blk_id,exoid);
516 	ex_err("ex_put_block",errmsg,exerrval);
517 	goto error_ret;         /* exit define mode and return */
518       }
519     }
520   }
521   /* leave define mode  */
522 
523   if ((exerrval=nc_enddef (exoid)) != NC_NOERR) {
524     sprintf(errmsg,
525 	    "Error: failed to complete %s definition in file id %d",
526 	    ex_name_of_object(blk_type), exoid);
527     ex_err("ex_put_block",errmsg,exerrval);
528     return (EX_FATAL);
529   }
530 
531   /* Output a dummy empty attribute name in case client code doesn't
532      write anything; avoids corruption in some cases.
533   */
534   if (num_attr_per_entry > 0) {
535     size_t  count[2];
536     char *text = "";
537     size_t i;
538 
539     count[0] = 1;
540     start[1] = 0;
541     count[1] = strlen(text)+1;
542 
543     for (i = 0; i < num_attr_per_entry; i++) {
544       start[0] = i;
545       nc_put_vara_text(exoid, att_name_varid, start, count, text);
546     }
547   }
548 
549   return (EX_NOERR);
550 
551   /* Fatal error: exit definition mode and return */
552  error_ret:
553   if (nc_enddef (exoid) != NC_NOERR) {    /* exit define mode */
554     sprintf(errmsg,
555 	    "Error: failed to complete definition for file id %d",
556 	    exoid);
557     ex_err("ex_put_block",errmsg,exerrval);
558   }
559   return (EX_FATAL);
560 }
561 
562