1 /*
2  * Copyright (c) 2005-2017 National Technology & Engineering Solutions
3  * of Sandia, LLC (NTESS).  Under the terms of Contract DE-NA0003525 with
4  * NTESS, the U.S. Government 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 NTESS 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 /*****************************************************************************/
38 /*****************************************************************************/
39 /* Function(s) contained in this file:
40  *
41  *     ex_leavedef()
42  *     ne_id_lkup()
43  *     ex_get_file_type()
44  *     ex_put_nemesis_version()
45  *     ne_check_file_version()
46  *     ex_get_idx()
47  *
48  *****************************************************************************
49  * Much of this code is a modified version of what is found in NemesisI.
50  */
51 /*****************************************************************************/
52 /*****************************************************************************/
53 /*****************************************************************************/
54 
55 #include <exodusII.h>     // for ex_err, etc
56 #include <exodusII_int.h> // for EX_FATAL, EX_NOERR, etc
57 #include <vtk_netcdf.h>       // for NC_NOERR, nc_inq_varid, etc
58 #include <stddef.h>       // for size_t
59 #include <stdio.h>
60 #include <stdlib.h>    // for malloc
61 #include <string.h>    // for strcpy, strlen
62 #include <sys/types.h> // for int64_t
63 
64 /* Global variables */
65 char *ne_ret_string;
66 
ex_leavedef(int exoid,const char * call_rout)67 int ex_leavedef(int exoid, const char *call_rout)
68 {
69   char errmsg[MAX_ERR_LENGTH];
70   int  status;
71 
72   if ((status = nc_enddef(exoid)) != NC_NOERR) {
73     snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to end define mode for file id %d", exoid);
74     ex_err(call_rout, errmsg, status);
75 
76     return (EX_FATAL);
77   }
78   return (EX_NOERR);
79 }
80 
81 /*****************************************************************************/
82 /*****************************************************************************/
83 /*****************************************************************************/
84 /* Note: This function assumes a 1-d vector of data for "ne_var_name".
85  */
86 /*****************************************************************************/
ne_id_lkup(int exoid,const char * ne_var_name,int64_t * idx,ex_entity_id ne_var_id)87 int ne_id_lkup(int exoid, const char *ne_var_name, int64_t *idx, ex_entity_id ne_var_id)
88 {
89   int       status;
90   int       varid, ndims, dimid[1], ret = -1;
91   nc_type   var_type;
92   size_t    length, start[1];
93   int64_t   my_index, begin, end;
94   long long id_val;
95 
96   char errmsg[MAX_ERR_LENGTH];
97 
98   if ((status = nc_inq_varid(exoid, ne_var_name, &varid)) != NC_NOERR) {
99     snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to find variable ID for \"%s\" in file ID %d",
100              ne_var_name, exoid);
101     ex_err(__func__, errmsg, status);
102     return (EX_FATAL);
103   }
104 
105   /* check if I need the length for this variable */
106   if (idx[1] == -1) {
107     /* Get the dimension IDs for this variable */
108     if ((status = nc_inq_var(exoid, varid, (char *)0, &var_type, &ndims, dimid, (int *)0)) !=
109         NC_NOERR) {
110       snprintf(errmsg, MAX_ERR_LENGTH,
111                "ERROR: failed to find dimension ID for variable \"%s\" "
112                "in file ID %d",
113                ne_var_name, exoid);
114       ex_err(__func__, errmsg, status);
115       return (-1);
116     }
117 
118     /* Get the length of this variable */
119     if ((status = nc_inq_dimlen(exoid, dimid[0], &length)) != NC_NOERR) {
120       snprintf(errmsg, MAX_ERR_LENGTH,
121                "ERROR: failed to find dimension for variable \"%s\" in file ID %d", ne_var_name,
122                exoid);
123       ex_err(__func__, errmsg, status);
124       return (-1);
125     }
126 
127     idx[1] = length;
128   } /* End "if (idx[1] == -1)" */
129 
130   begin = idx[0];
131   end   = idx[1];
132 
133   /* Find the index by looping over each entry */
134   for (my_index = begin; my_index < end; my_index++) {
135     start[0] = my_index;
136     status   = nc_get_var1_longlong(exoid, varid, start, &id_val);
137 
138     if (status != NC_NOERR) {
139       snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to find variable \"%s\" in file ID %d",
140                ne_var_name, exoid);
141       ex_err(__func__, errmsg, status);
142       return (-1);
143     }
144 
145     if (id_val == ne_var_id) {
146       ret = (int)my_index;
147       break;
148     }
149   }
150   return (ret);
151 }
152 
153 /*****************************************************************************/
154 /*****************************************************************************/
155 /*****************************************************************************/
156 /* This function retrieves the file type from a Nemesis file.
157  */
158 /*****************************************************************************/
ex_get_file_type(int exoid,char * ftype)159 int ex_get_file_type(int exoid, char *ftype)
160 {
161   int status;
162   int varid;
163   int lftype;
164 
165   char errmsg[MAX_ERR_LENGTH];
166 
167   EX_FUNC_ENTER();
168 
169   if ((status = nc_inq_varid(exoid, VAR_FILE_TYPE, &varid)) != NC_NOERR) {
170 
171     /* If no file type is found, assume parallel */
172     ftype[0] = 'p';
173     ftype[1] = '\0';
174 
175     EX_FUNC_LEAVE(EX_NOERR);
176   }
177 
178   if ((status = nc_get_var1_int(exoid, varid, NULL, &lftype)) != NC_NOERR) {
179     snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get variable \"%s\" from file ID %d",
180              VAR_FILE_TYPE, exoid);
181     ex_err(__func__, errmsg, status);
182     EX_FUNC_LEAVE(EX_FATAL);
183   }
184 
185   /* Set the appropriate character */
186   if (lftype == 0) {
187     strcpy(ftype, "p");
188   }
189   else if (lftype == 1) {
190     strcpy(ftype, "s");
191   }
192 
193   EX_FUNC_LEAVE(EX_NOERR);
194 }
195 
196 /*****************************************************************************/
197 /*****************************************************************************/
198 /*****************************************************************************/
199 /* This function outputs the Nemesis version information to the file.
200  */
201 /*****************************************************************************/
ex_put_nemesis_version(int exoid)202 int ex_put_nemesis_version(int exoid)
203 {
204   int   status;
205   float file_ver, api_ver;
206 
207   char errmsg[MAX_ERR_LENGTH];
208 
209   EX_FUNC_ENTER();
210 
211   file_ver = NEMESIS_FILE_VERSION;
212   api_ver  = NEMESIS_API_VERSION;
213 
214   /* Check to see if the nemesis file version is already in the file */
215   if (nc_get_att_float(exoid, NC_GLOBAL, "nemesis_file_version", &file_ver) != NC_NOERR) {
216 
217     /* Output the Nemesis file version */
218     if ((status = nc_put_att_float(exoid, NC_GLOBAL, "nemesis_file_version", NC_FLOAT, 1,
219                                    &file_ver)) != NC_NOERR) {
220       snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to output nemesis file version in file ID %d",
221                exoid);
222       ex_err(__func__, errmsg, status);
223       EX_FUNC_LEAVE(EX_FATAL);
224     }
225 
226     /* Output the Nemesis API version */
227     if ((status = nc_put_att_float(exoid, NC_GLOBAL, "nemesis_api_version", NC_FLOAT, 1,
228                                    &api_ver)) != NC_NOERR) {
229       snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to output nemesis api version in file ID %d",
230                exoid);
231       ex_err(__func__, errmsg, status);
232       EX_FUNC_LEAVE(EX_FATAL);
233     }
234   }
235   EX_FUNC_LEAVE(EX_NOERR);
236 }
237 
238 /*****************************************************************************/
239 /*****************************************************************************/
240 /*****************************************************************************/
241 /* This function checks that the version info is correct.
242  */
243 /*****************************************************************************/
ne_check_file_version(int exoid)244 int ne_check_file_version(int exoid)
245 {
246 #if 0
247   float  file_ver;
248 
249   int    status;
250   char   errmsg[MAX_ERR_LENGTH];
251 
252   EX_FUNC_ENTER();
253 
254   /* Get the file version */
255   if ((status = nc_get_att_float(exoid, NC_GLOBAL, "nemesis_file_version", &file_ver)) != NC_NOERR) {
256     snprintf(errmsg, MAX_ERR_LENGTH,
257             "ERROR: failed to get the nemesis file version from file ID %d",
258             exoid);
259     ex_err(__func__, errmsg, status);
260     EX_FUNC_LEAVE(EX_FATAL);
261   }
262 
263   if (fabs(NEMESIS_FILE_VERSION-file_ver) > 0.001) {
264     snprintf(errmsg, MAX_ERR_LENGTH,
265             "ERROR: Nemesis version mismatch in file ID %d!\n", exoid);
266     ex_err(__func__, errmsg, EX_MSG);
267     EX_FUNC_LEAVE(EX_FATAL);
268   }
269   EX_FUNC_LEAVE(EX_NOERR);
270 #else
271   return EX_NOERR;
272 #endif
273 }
274 
275 /*****************************************************************************/
276 /*****************************************************************************/
277 /*****************************************************************************/
278 /* This function gets the index for the given variable at the
279  * position given.
280  */
281 /*****************************************************************************/
ex_get_idx(int exoid,const char * ne_var_name,int64_t * my_index,int pos)282 int ex_get_idx(int exoid, const char *ne_var_name, int64_t *my_index, int pos)
283 {
284   int    status;
285   int    varid;
286   size_t start[1], count[1];
287 #if NC_HAS_HDF5
288   long long varidx[2];
289 #else
290   int varidx[2];
291 #endif
292   char errmsg[MAX_ERR_LENGTH];
293   /*-----------------------------Execution begins-----------------------------*/
294   EX_FUNC_ENTER();
295 
296   /* set default values for idx */
297   my_index[0] = 0;
298   my_index[1] = -1;
299 
300   /*
301    * assume that if there is an error returned, that this
302    * means that this is a parallel file, and the index does
303    * not exists. This is not an error
304    */
305   if ((status = nc_inq_varid(exoid, ne_var_name, &varid)) == NC_NOERR) {
306     /* check if we are at the beginning of the index vector */
307     if (pos == 0) {
308       start[0] = pos;
309       count[0] = 1;
310     }
311     else {
312       start[0] = pos - 1;
313       count[0] = 2;
314     }
315 
316 #if NC_HAS_HDF5
317     status = nc_get_vara_longlong(exoid, varid, start, count, varidx);
318 #else
319     status = nc_get_vara_int(exoid, varid, start, count, varidx);
320 #endif
321     if (status != NC_NOERR) {
322       snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to find variable \"%s\" in file ID %d",
323                ne_var_name, exoid);
324       ex_err(__func__, errmsg, status);
325       EX_FUNC_LEAVE(-1);
326     }
327 
328     if (pos == 0) {
329       my_index[0] = 0;
330       my_index[1] = varidx[0];
331     }
332     else {
333       my_index[0] = varidx[0];
334       my_index[1] = varidx[1];
335     }
336   }
337   EX_FUNC_LEAVE(1);
338 }
339