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 #include "exodusII.h"
37 #include "exodusII_int.h"
38 #include <string.h>
39
40 /*!
41
42 The function ex_put_prop() stores an integer object property value to
43 a single element block, node set, or side set. Although it is not
44 necessary to invoke ex_put_prop_names(), since ex_put_prop() will
45 allocate space within the data file if it hasn't been previously
46 allocated, it is more efficient to use ex_put_prop_names() if there is
47 more than one property to store. \see Efficiency for a discussion of
48 efficiency issues.
49
50 It should be noted that the interpretation of the values of the
51 integers stored as properties is left to the application code. In
52 general, a zero (0) means the object does not have the specified
53 property (or is not in the specified group); a nonzero value means the
54 object does have the specified property. When space is allocated for
55 the properties using ex_put_prop_names() or ex_put_prop(), the
56 properties are initialized to zero (0).
57
58 Because the ID of an element block, node set, or side set is just
59 another property (named \b ID), this routine can be used to change
60 the value of an ID. This feature must be used with caution, though,
61 because changing the ID of an object to the ID of another object of
62 the same type (element block, node set, or side set) would cause two
63 objects to have the same ID, and thus only the first would be
64 accessible. Therefore, ex_put_prop() issues a warning if a user
65 attempts to give two objects the same ID.
66
67 \return In case of an error, ex_put_prop() returns a negative number;
68 a warning will return a positive number. Possible causes of errors
69 include:
70 - data file not properly opened with call to ex_create() or ex_open()
71 - data file opened for read only.
72 - data file not initialized properly with call to ex_put_init().
73 - invalid object type specified.
74 - a warning is issued if a user attempts to change the ID of an
75 object to the ID of an existing object of the same type.
76
77 \param[in] exoid exodus file ID returned from a previous call to ex_create() or ex_open().
78 \param[in] obj_type Type of object; use one of the options in the table below.
79 \param[in] obj_id The element block, node set, or side set ID.
80 \param[in] prop_name The name of the property for which the value will be stored.
81 Maximum length of this string is \p MAX_STR_LENGTH .
82 \param[in] value The value of the property.
83
84 <table>
85 <tr><td> \c EX_NODE_SET </td><td> Node Set entity type </td></tr>
86 <tr><td> \c EX_EDGE_BLOCK </td><td> Edge Block entity type </td></tr>
87 <tr><td> \c EX_EDGE_SET </td><td> Edge Set entity type </td></tr>
88 <tr><td> \c EX_FACE_BLOCK </td><td> Face Block entity type </td></tr>
89 <tr><td> \c EX_FACE_SET </td><td> Face Set entity type </td></tr>
90 <tr><td> \c EX_ELEM_BLOCK </td><td> Element Block entity type</td></tr>
91 <tr><td> \c EX_ELEM_SET </td><td> Element Set entity type </td></tr>
92 <tr><td> \c EX_SIDE_SET </td><td> Side Set entity type </td></tr>
93 <tr><td> \c EX_ELEM_MAP </td><td> Element Map entity type </td></tr>
94 <tr><td> \c EX_NODE_MAP </td><td> Node Map entity type </td></tr>
95 <tr><td> \c EX_EDGE_MAP </td><td> Edge Map entity type </td></tr>
96 <tr><td> \c EX_FACE_MAP </td><td> Face Map entity type </td></tr>
97 </table>
98
99 For an example of code to write out an object property, refer to the
100 description for ex_put_prop_names().
101 */
102
ex_put_prop(int exoid,ex_entity_type obj_type,int obj_id,const char * prop_name,int value)103 int ex_put_prop (int exoid,
104 ex_entity_type obj_type,
105 int obj_id,
106 const char *prop_name,
107 int value)
108 {
109 int status;
110 int oldfill, temp;
111 int found = FALSE;
112 int num_props, i, dimid, propid, dims[1];
113 size_t start[1];
114 size_t prop_name_len, name_length;
115 int ldum;
116 char name[MAX_VAR_NAME_LENGTH+1];
117 char tmpstr[MAX_STR_LENGTH+1];
118 char dim_name[MAX_VAR_NAME_LENGTH+1];
119 int vals[1];
120
121 char errmsg[MAX_ERR_LENGTH];
122
123 exerrval = 0; /* clear error code */
124
125 /* check if property has already been created */
126
127 num_props = ex_get_num_props(exoid, obj_type);
128
129 if (num_props > 1) { /* any properties other than the default 1? */
130
131 for (i=1; i<=num_props; i++) {
132 switch (obj_type) {
133 case EX_ELEM_BLOCK:
134 strcpy (name, VAR_EB_PROP(i));
135 break;
136 case EX_EDGE_BLOCK:
137 strcpy (name, VAR_ED_PROP(i));
138 break;
139 case EX_FACE_BLOCK:
140 strcpy (name, VAR_FA_PROP(i));
141 break;
142 case EX_NODE_SET:
143 strcpy (name, VAR_NS_PROP(i));
144 break;
145 case EX_EDGE_SET:
146 strcpy (name, VAR_ES_PROP(i));
147 break;
148 case EX_FACE_SET:
149 strcpy (name, VAR_FS_PROP(i));
150 break;
151 case EX_ELEM_SET:
152 strcpy (name, VAR_ELS_PROP(i));
153 break;
154 case EX_SIDE_SET:
155 strcpy (name, VAR_SS_PROP(i));
156 break;
157 case EX_ELEM_MAP:
158 strcpy (name, VAR_EM_PROP(i));
159 break;
160 case EX_FACE_MAP:
161 strcpy (name, VAR_FAM_PROP(i));
162 break;
163 case EX_EDGE_MAP:
164 strcpy (name, VAR_EDM_PROP(i));
165 break;
166 case EX_NODE_MAP:
167 strcpy (name, VAR_NM_PROP(i));
168 break;
169 default:
170 exerrval = EX_BADPARAM;
171 sprintf(errmsg, "Error: object type %d not supported; file id %d",
172 obj_type, exoid);
173 ex_err("ex_put_prop",errmsg,exerrval);
174 return(EX_FATAL);
175 }
176
177 if ((status = nc_inq_varid(exoid, name, &propid)) != NC_NOERR) {
178 exerrval = status;
179 sprintf(errmsg,
180 "Error: failed to get property array id in file id %d",
181 exoid);
182 ex_err("ex_put_prop",errmsg,exerrval);
183 return (EX_FATAL);
184 }
185
186 /* compare stored attribute name with passed property name */
187 memset(tmpstr, 0, MAX_STR_LENGTH+1);
188 if ((status = nc_get_att_text(exoid, propid, ATT_PROP_NAME, tmpstr)) != NC_NOERR) {
189 exerrval = status;
190 sprintf(errmsg,
191 "Error: failed to get property name in file id %d", exoid);
192 ex_err("ex_put_prop",errmsg,exerrval);
193 return (EX_FATAL);
194 }
195
196 if (strcmp(tmpstr, prop_name) == 0) {
197 found = TRUE;
198 break;
199 }
200 }
201 }
202
203 /* if property array has not been created, create it */
204 if (!found) {
205
206 name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH)+1;
207
208 /* put netcdf file into define mode */
209 if ((status = nc_redef (exoid)) != NC_NOERR) {
210 exerrval = status;
211 sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid);
212 ex_err("ex_put_prop",errmsg,exerrval);
213 return (EX_FATAL);
214 }
215
216 /* create a variable with a name xx_prop#, where # is the new number */
217 /* of the property */
218
219 switch (obj_type){
220 case EX_ELEM_BLOCK:
221 strcpy (name, VAR_EB_PROP(num_props+1));
222 strcpy (dim_name, DIM_NUM_EL_BLK);
223 break;
224 case EX_FACE_BLOCK:
225 strcpy (name, VAR_FA_PROP(num_props+1));
226 strcpy (dim_name, DIM_NUM_FA_BLK);
227 break;
228 case EX_EDGE_BLOCK:
229 strcpy (name, VAR_ED_PROP(num_props+1));
230 strcpy (dim_name, DIM_NUM_ED_BLK);
231 break;
232 case EX_NODE_SET:
233 strcpy (name, VAR_NS_PROP(num_props+1));
234 strcpy (dim_name, DIM_NUM_NS);
235 break;
236 case EX_EDGE_SET:
237 strcpy (name, VAR_ES_PROP(num_props+1));
238 strcpy (dim_name, DIM_NUM_ES);
239 break;
240 case EX_FACE_SET:
241 strcpy (name, VAR_FS_PROP(num_props+1));
242 strcpy (dim_name, DIM_NUM_FS);
243 break;
244 case EX_ELEM_SET:
245 strcpy (name, VAR_ELS_PROP(num_props+1));
246 strcpy (dim_name, DIM_NUM_ELS);
247 break;
248 case EX_SIDE_SET:
249 strcpy (name, VAR_SS_PROP(num_props+1));
250 strcpy (dim_name, DIM_NUM_SS);
251 break;
252 case EX_ELEM_MAP:
253 strcpy (name, VAR_EM_PROP(num_props+1));
254 strcpy (dim_name, DIM_NUM_EM);
255 break;
256 case EX_FACE_MAP:
257 strcpy (name, VAR_FAM_PROP(num_props+1));
258 strcpy (dim_name, DIM_NUM_FAM);
259 break;
260 case EX_EDGE_MAP:
261 strcpy (name, VAR_EDM_PROP(num_props+1));
262 strcpy (dim_name, DIM_NUM_EDM);
263 break;
264 case EX_NODE_MAP:
265 strcpy (name, VAR_NM_PROP(num_props+1));
266 strcpy (dim_name, DIM_NUM_NM);
267 break;
268 default:
269 exerrval = EX_BADPARAM;
270 sprintf(errmsg, "Error: object type %d not supported; file id %d",
271 obj_type, exoid);
272 ex_err("ex_put_prop",errmsg,exerrval);
273 goto error_ret; /* Exit define mode and return */
274 }
275
276 /* inquire id of previously defined dimension (number of objects) */
277 if ((status = nc_inq_dimid(exoid, dim_name, &dimid)) != NC_NOERR) {
278 exerrval = status;
279 sprintf(errmsg,
280 "Error: failed to locate number of objects in file id %d",
281 exoid);
282 ex_err("ex_put_prop",errmsg, exerrval);
283 goto error_ret; /* Exit define mode and return */
284 }
285
286 dims[0] = dimid;
287 nc_set_fill(exoid, NC_FILL, &oldfill); /* fill with zeros per routine spec */
288
289 if ((status = nc_def_var(exoid, name, NC_INT, 1, dims, &propid)) != NC_NOERR) {
290 exerrval = status;
291 sprintf(errmsg,
292 "Error: failed to create property array variable in file id %d",
293 exoid);
294 ex_err("ex_put_prop",errmsg,exerrval);
295 goto error_ret; /* Exit define mode and return */
296 }
297
298 vals[0] = 0; /* fill value */
299 /* create attribute to cause variable to fill with zeros per routine spec */
300 if ((status = nc_put_att_int(exoid, propid, _FillValue, NC_INT, 1, vals)) != NC_NOERR) {
301 exerrval = status;
302 sprintf(errmsg,
303 "Error: failed to create property name fill attribute in file id %d",
304 exoid);
305 ex_err("ex_put_prop",errmsg,exerrval);
306 goto error_ret; /* Exit define mode and return */
307 }
308
309 /* Check that the property name length is less than MAX_NAME_LENGTH */
310 prop_name_len = strlen(prop_name)+1;
311 if (prop_name_len > name_length) {
312 fprintf(stderr,
313 "Warning: The property name '%s' is too long.\n\tIt will be truncated from %d to %d characters\n",
314 prop_name, (int)prop_name_len-1, (int)name_length-1);
315 prop_name_len = name_length;
316 }
317
318 /* store property name as attribute of property array variable */
319 if ((status = nc_put_att_text(exoid, propid, ATT_PROP_NAME,
320 prop_name_len, (void*)prop_name)) != NC_NOERR) {
321 exerrval = status;
322 sprintf(errmsg,
323 "Error: failed to store property name %s in file id %d",
324 prop_name,exoid);
325 ex_err("ex_put_prop",errmsg,exerrval);
326 goto error_ret; /* Exit define mode and return */
327 }
328
329 ex_update_max_name_length(exoid, prop_name_len-1);
330
331 /* leave define mode */
332 if ((status = nc_enddef (exoid)) != NC_NOERR) {
333 exerrval = status;
334 sprintf(errmsg,
335 "Error: failed to leave define mode in file id %d",
336 exoid);
337 ex_err("ex_put_prop",errmsg,exerrval);
338 return (EX_FATAL);
339 }
340
341 nc_set_fill(exoid, oldfill, &temp); /* default: nofill */
342 }
343
344 /* find index into property array using obj_id; put value in property */
345 /* array at proper index; ex_id_lkup returns an index that is 1-based,*/
346 /* but netcdf expects 0-based arrays so subtract 1 */
347
348 /* special case: property name ID - check for duplicate ID assignment */
349 if (strcmp("ID",prop_name) == 0) {
350 start[0] = ex_id_lkup (exoid, obj_type, value);
351 if (exerrval != EX_LOOKUPFAIL) /* found the id */
352 {
353 exerrval = EX_BADPARAM;
354 sprintf(errmsg,
355 "Warning: attempt to assign duplicate %s ID %d in file id %d",
356 ex_name_of_object(obj_type), value, exoid);
357 ex_err("ex_put_prop",errmsg,exerrval);
358 return (EX_WARN);
359 }
360 }
361
362 start[0] = ex_id_lkup (exoid, obj_type, obj_id);
363 if (exerrval != 0) {
364 if (exerrval == EX_NULLENTITY) {
365 sprintf(errmsg,
366 "Warning: no properties allowed for NULL %s id %d in file id %d",
367 ex_name_of_object(obj_type), obj_id,exoid);
368 ex_err("ex_put_prop",errmsg,EX_MSG);
369 return (EX_WARN);
370 } else {
371 sprintf(errmsg,
372 "Error: failed to find value %d in %s property array in file id %d",
373 obj_id, ex_name_of_object(obj_type), exoid);
374 ex_err("ex_put_prop",errmsg,exerrval);
375 return (EX_FATAL);
376 }
377 }
378
379 start[0] = start[0] - 1;
380
381 ldum = (int)value;
382 if ((status = nc_put_var1_int(exoid, propid, start, &ldum)) != NC_NOERR) {
383 exerrval = status;
384 sprintf(errmsg,
385 "Error: failed to store property value in file id %d",
386 exoid);
387 ex_err("ex_put_prop",errmsg,exerrval);
388 return (EX_FATAL);
389 }
390
391 return (EX_NOERR);
392
393 /* Fatal error: exit definition mode and return */
394 error_ret:
395 nc_set_fill(exoid, oldfill, &temp); /* default: nofill */
396
397 if (nc_enddef (exoid) != NC_NOERR) { /* exit define mode */
398 sprintf(errmsg,
399 "Error: failed to complete definition for file id %d",
400 exoid);
401 ex_err("ex_put_prop",errmsg,exerrval);
402 }
403 return (EX_FATAL);
404 }
405