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 * expsetp - ex_put_set_param
38 *
39 * entry conditions -
40 *   input parameters:
41 *       int     exoid                   exodus file id
42 *       int     set_type                the type of set
43 *       int     set_id                  set id
44 *       int     num_entries_in_set       number of entries in the set
45 *       int     num_dist_fact_in_set    number of distribution factors in the
46 *                                       set
47 *
48 * exit conditions -
49 *
50 * revision history -
51 *
52 *
53 *****************************************************************************/
54 
55 #include "exodusII.h"
56 #include "exodusII_int.h"
57 
58 /*!
59  * writes the set id and the number of entries which describe a single set
60  * \param  exoid                   exodus file id
61  * \param  set_type                the type of set
62  * \param  set_id                  set id
63  * \param  num_entries_in_set      number of entries in the set
64  * \param  num_dist_fact_in_set    number of distribution factors in the set
65  */
66 
ex_put_set_param(int exoid,ex_entity_type set_type,int set_id,int num_entries_in_set,int num_dist_fact_in_set)67 int ex_put_set_param (int exoid,
68                       ex_entity_type set_type,
69                       int set_id,
70                       int num_entries_in_set,
71                       int num_dist_fact_in_set)
72 {
73   int status;
74   size_t temp;
75   int dimid, varid, set_id_ndx, dims[1];
76   size_t start[1];
77   int num_sets;
78   int ldum;
79   int cur_num_sets, set_stat;
80   char errmsg[MAX_ERR_LENGTH];
81   char* dimptr = NULL;
82   char* idsptr = NULL;
83   char* statptr = NULL;
84   char* numentryptr = NULL;
85   char* numdfptr = NULL;
86   char* factptr = NULL;
87   char* entryptr = NULL;
88   char* extraptr = NULL;
89 
90   exerrval = 0; /* clear error code */
91 
92   /* setup pointers based on set_type
93      NOTE: there is another block that sets more stuff later ... */
94   if (set_type == EX_NODE_SET) {
95     dimptr = DIM_NUM_NS;
96     idsptr = VAR_NS_IDS;
97     statptr = VAR_NS_STAT;
98   }
99   else if (set_type == EX_EDGE_SET) {
100     dimptr = DIM_NUM_ES;
101     idsptr = VAR_ES_IDS;
102     statptr = VAR_ES_STAT;
103   }
104   else if (set_type == EX_FACE_SET) {
105     dimptr = DIM_NUM_FS;
106     idsptr = VAR_FS_IDS;
107     statptr = VAR_FS_STAT;
108   }
109   else if (set_type == EX_SIDE_SET) {
110     dimptr = DIM_NUM_SS;
111     idsptr = VAR_SS_IDS;
112     statptr = VAR_SS_STAT;
113   }
114   else if (set_type == EX_ELEM_SET) {
115     dimptr = DIM_NUM_ELS;
116     idsptr = VAR_ELS_IDS;
117     statptr = VAR_ELS_STAT;
118   }
119   else {
120     exerrval = EX_FATAL;
121     sprintf(errmsg,
122       "Error: invalid set type (%d)", set_type);
123     ex_err("ex_put_set_param",errmsg,exerrval);
124     return (EX_FATAL);
125   }
126 
127   /* first check if any of that set type is specified */
128 
129   if ((status = nc_inq_dimid(exoid, dimptr, &dimid)) != NC_NOERR) {
130     exerrval = status;
131     sprintf(errmsg,
132       "Error: no %ss specified in file id %d", ex_name_of_object(set_type),
133       exoid);
134     ex_err("ex_put_set_param",errmsg,exerrval);
135     return (EX_FATAL);
136   }
137 
138   /* Check for duplicate set id entry */
139   ex_id_lkup(exoid, set_type, set_id);
140   if (exerrval != EX_LOOKUPFAIL) {  /* found the side set id */
141     sprintf(errmsg,
142       "Error: %s %d already defined in file id %d", ex_name_of_object(set_type),
143       set_id,exoid);
144     ex_err("ex_put_set_param",errmsg,exerrval);
145     return(EX_FATAL);
146   }
147 
148   /* Get number of sets specified for this file */
149   if ((status = nc_inq_dimlen(exoid,dimid,&temp)) != NC_NOERR) {
150     exerrval = status;
151     sprintf(errmsg,
152             "Error: failed to get number of %ss in file id %d",
153       ex_name_of_object(set_type), exoid);
154     ex_err("ex_put_set_param",errmsg,exerrval);
155     return (EX_FATAL);
156   }
157   num_sets = temp;
158 
159 
160   /* Keep track of the total number of sets defined using a counter stored
161      in a linked list keyed by exoid.
162      NOTE: ex_get_file_item finds the maximum number of sets defined
163      for a specific file and returns that value.
164   */
165   cur_num_sets=ex_get_file_item(exoid, ex_get_counter_list(set_type));
166   if (cur_num_sets >= num_sets) {
167     exerrval = EX_FATAL;
168     sprintf(errmsg,
169       "Error: exceeded number of %ss (%d) defined in file id %d",
170       ex_name_of_object(set_type), num_sets,exoid);
171     ex_err("ex_put_set_param",errmsg,exerrval);
172     return (EX_FATAL);
173   }
174 
175   /*   NOTE: ex_inc_file_item finds the current number of sets defined
176        for a specific file and returns that value incremented. */
177 
178   cur_num_sets=ex_inc_file_item(exoid, ex_get_counter_list(set_type));
179   set_id_ndx = cur_num_sets + 1;
180 
181   /* setup more pointers based on set_type */
182   if (set_type == EX_NODE_SET) {
183     numentryptr = DIM_NUM_NOD_NS(set_id_ndx);
184     entryptr = VAR_NODE_NS(set_id_ndx);
185     extraptr = NULL;
186     /* note we are using DIM_NUM_NODE_NS instead of DIM_NUM_DF_NS */
187     numdfptr = DIM_NUM_NOD_NS(set_id_ndx);
188     factptr = VAR_FACT_NS(set_id_ndx);
189   }
190   else if (set_type == EX_EDGE_SET) {
191     numentryptr = DIM_NUM_EDGE_ES(set_id_ndx);
192     entryptr = VAR_EDGE_ES(set_id_ndx);
193     extraptr = VAR_ORNT_ES(set_id_ndx);
194     numdfptr = DIM_NUM_DF_ES(set_id_ndx);
195     factptr = VAR_FACT_ES(set_id_ndx);
196   }
197   else if (set_type == EX_FACE_SET) {
198     numentryptr = DIM_NUM_FACE_FS(set_id_ndx);
199     entryptr = VAR_FACE_FS(set_id_ndx);
200     extraptr = VAR_ORNT_FS(set_id_ndx);
201     numdfptr = DIM_NUM_DF_FS(set_id_ndx);
202     factptr = VAR_FACT_FS(set_id_ndx);
203   }
204   else if (set_type == EX_SIDE_SET) {
205     numentryptr = DIM_NUM_SIDE_SS(set_id_ndx);
206     entryptr = VAR_ELEM_SS(set_id_ndx);
207     extraptr = VAR_SIDE_SS(set_id_ndx);
208     numdfptr = DIM_NUM_DF_SS(set_id_ndx);
209     factptr = VAR_FACT_SS(set_id_ndx);
210   }
211   if (set_type == EX_ELEM_SET) {
212     numentryptr = DIM_NUM_ELE_ELS(set_id_ndx);
213     entryptr = VAR_ELEM_ELS(set_id_ndx);
214     extraptr = NULL;
215     numdfptr = DIM_NUM_DF_ELS(set_id_ndx);
216     factptr = VAR_FACT_ELS(set_id_ndx);
217   }
218 
219   /* write out information to previously defined variable */
220 
221   /* first: get id of set id variable */
222   if ((status = nc_inq_varid(exoid, idsptr, &varid)) != NC_NOERR) {
223     exerrval = status;
224     sprintf(errmsg,
225       "Error: failed to locate %s %d in file id %d", ex_name_of_object(set_type),
226       set_id, exoid);
227     ex_err("ex_put_set_param",errmsg,exerrval);
228     return (EX_FATAL);
229   }
230 
231   /* write out set id */
232   start[0] = cur_num_sets;
233 
234   ldum = (int)set_id;
235   if ((status = nc_put_var1_int(exoid, varid, start, &ldum)) != NC_NOERR) {
236     exerrval = status;
237     sprintf(errmsg,
238       "Error: failed to store %s id %d in file id %d", ex_name_of_object(set_type),
239       set_id, exoid);
240     ex_err("ex_put_set_param",errmsg,exerrval);
241     return (EX_FATAL);
242   }
243 
244   if (num_entries_in_set == 0) /* Is this a NULL  set? */
245     set_stat = 0; /* change set status to NULL */
246   else
247     set_stat = 1; /* change set status to TRUE */
248 
249   if ((status = nc_inq_varid(exoid, statptr, &varid)) != NC_NOERR) {
250     exerrval = status;
251     sprintf(errmsg,
252       "Error: failed to locate %s status in file id %d", ex_name_of_object(set_type),
253       exoid);
254     ex_err("ex_put_set_param",errmsg,exerrval);
255     return (EX_FATAL);
256   }
257 
258   ldum = (int)set_stat;
259   if ((status = nc_put_var1_int(exoid, varid, start, &ldum)) != NC_NOERR) {
260     exerrval = status;
261     sprintf(errmsg,
262       "Error: failed to store %s %d status to file id %d", ex_name_of_object(set_type),
263       set_id, exoid);
264     ex_err("ex_put_set_param",errmsg,exerrval);
265     return (EX_FATAL);
266   }
267 
268   if (num_entries_in_set == 0) {/* Is this a NULL set? */
269     return(EX_NOERR);
270   }
271 
272   /* put netcdf file into define mode  */
273   if ((status = nc_redef (exoid)) != NC_NOERR) {
274     exerrval = status;
275     sprintf(errmsg,
276       "Error: failed to put file id %d into define mode",
277       exoid);
278     ex_err("ex_put_set_param",errmsg,exerrval);
279     return (EX_FATAL);
280   }
281 
282 
283   /* define dimensions and variables */
284   if ((status = nc_def_dim(exoid, numentryptr,
285          num_entries_in_set, &dimid)) != NC_NOERR) {
286     exerrval = status;
287     if (status == NC_ENAMEINUSE)
288       {
289   sprintf(errmsg,
290     "Error: %s %d size already defined in file id %d",
291     ex_name_of_object(set_type), set_id,exoid);
292   ex_err("ex_put_set_param",errmsg,exerrval);
293       }
294     else {
295       sprintf(errmsg,
296         "Error: failed to define number of entries in %s %d in file id %d",
297         ex_name_of_object(set_type), set_id,exoid);
298       ex_err("ex_put_set_param",errmsg,exerrval);
299     }
300     goto error_ret;
301   }
302 
303   /* create variable array in which to store the entry lists */
304 
305   dims[0] = dimid;
306   if ((status = nc_def_var(exoid, entryptr, NC_INT, 1, dims, &varid)) != NC_NOERR) {
307     exerrval = status;
308     if (status == NC_ENAMEINUSE) {
309       sprintf(errmsg,
310         "Error: entry list already exists for %s %d in file id %d",
311         ex_name_of_object(set_type), set_id,exoid);
312       ex_err("ex_put_set_param",errmsg,exerrval);
313     } else {
314       sprintf(errmsg,
315         "Error: failed to create entry list for %s %d in file id %d",
316         ex_name_of_object(set_type), set_id,exoid);
317       ex_err("ex_put_set_param",errmsg,exerrval);
318     }
319     goto error_ret;            /* exit define mode and return */
320   }
321 
322   if (extraptr) {
323     if ((status = nc_def_var(exoid, extraptr, NC_INT, 1, dims, &varid)) != NC_NOERR) {
324       exerrval = status;
325       if (status == NC_ENAMEINUSE) {
326   sprintf(errmsg,
327     "Error: extra list already exists for %s %d in file id %d",
328     ex_name_of_object(set_type), set_id, exoid);
329   ex_err("ex_put_set_param",errmsg,exerrval);
330       } else {
331   sprintf(errmsg,
332     "Error: failed to create extra list for %s %d in file id %d",
333     ex_name_of_object(set_type), set_id,exoid);
334   ex_err("ex_put_set_param",errmsg,exerrval);
335       }
336       goto error_ret;         /* exit define mode and return */
337 
338     }
339   }
340 
341   /* Create distribution factors variable if required */
342 
343   if (num_dist_fact_in_set > 0) {
344 
345     if (set_type == EX_NODE_SET) {
346       /* but num_dist_fact_in_set must equal number of nodes */
347       if (num_dist_fact_in_set != num_entries_in_set) {
348   exerrval = EX_FATAL;
349   sprintf(errmsg,
350     "Error: # dist fact (%d) not equal to # nodes (%d) in node  set %d file id %d",
351     num_dist_fact_in_set, num_entries_in_set, set_id, exoid);
352   ex_err("ex_put_set_param",errmsg,exerrval);
353   goto error_ret;    /* exit define mode and return */
354       }
355 
356       /* resuse dimid from entry lists */
357 
358     } else {
359       if ((status = nc_def_dim(exoid, numdfptr,
360              num_dist_fact_in_set, &dimid)) != NC_NOERR) {
361   exerrval = status;
362   sprintf(errmsg,
363     "Error: failed to define number of dist factors in %s %d in file id %d",
364     ex_name_of_object(set_type), set_id,exoid);
365   ex_err("ex_put_set_param",errmsg,exerrval);
366   goto error_ret;          /* exit define mode and return */
367       }
368     }
369 
370     /* create variable array in which to store the set distribution factors
371      */
372     dims[0] = dimid;
373     if ((status = nc_def_var(exoid, factptr, nc_flt_code(exoid), 1, dims, &varid)) != NC_NOERR) {
374       exerrval = status;
375       if (status == NC_ENAMEINUSE) {
376   sprintf(errmsg,
377     "Error: dist factors list already exists for %s %d in file id %d",
378     ex_name_of_object(set_type), set_id,exoid);
379   ex_err("ex_put_set_param",errmsg,exerrval);
380       } else {
381   sprintf(errmsg,
382     "Error: failed to create dist factors list for %s %d in file id %d",
383     ex_name_of_object(set_type), set_id,exoid);
384   ex_err("ex_put_set_param",errmsg,exerrval);
385       }
386       goto error_ret;            /* exit define mode and return */
387     }
388   }
389 
390   /* leave define mode  */
391   if ((status = nc_enddef (exoid)) != NC_NOERR) {
392     exerrval = status;
393     sprintf(errmsg,
394       "Error: failed to complete definition in file id %d", exoid);
395     ex_err("ex_put_set_param",errmsg,exerrval);
396     return (EX_FATAL);
397   }
398 
399   return (EX_NOERR);
400 
401   /* Fatal error: exit definition mode and return */
402  error_ret:
403   if (nc_enddef (exoid) != NC_NOERR) {    /* exit define mode */
404     sprintf(errmsg,
405       "Error: failed to complete definition for file id %d",
406       exoid);
407     ex_err("ex_put_set_param",errmsg,exerrval);
408   }
409   return (EX_FATAL);
410 }
411