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 * expvtt - ex_put_truth_table
38 *
39 * entry conditions -
40 * input parameters:
41 * int exoid exodus file id
42 * int obj_type object type
43 * int num_blk number of blocks
44 * int num_var number of variables
45 * int* variable_table variable truth table array
46 *
47 * exit conditions -
48 *
49 * revision history -
50 *
51 *
52 *****************************************************************************/
53
54 #include "exodusII.h" // for ex_err, etc
55 #include "exodusII_int.h" // for ex_get_dimension, EX_FATAL, etc
56 #include "vtk_netcdf.h" // for nc_inq_varid, NC_NOERR, etc
57 #include <stddef.h> // for size_t
58 #include <stdio.h>
59 #include <stdlib.h> // for free, NULL, malloc
60
61 /*!
62 \ingroup ResultsData
63
64 * writes the EXODUS variable truth table to the database; also,
65 * creates netCDF variables in which to store EXODUS variable
66 * values; although this table isn't required (because the netCDF
67 * variables can also be created in ex_put_var()), this call will save
68 * tremendous time because all of the variables are defined at once
69 * while the file is in define mode, rather than going in and out of
70 * define mode (causing the entire file to be copied over and over)
71 * which is what occurs when the variables are defined in ex_put_var()
72 * \param exoid exodus file id
73 * \param obj_type object type
74 * \param num_blk number of blocks or sets
75 * \param num_var number of variables
76 * \param *var_tab variable truth table array
77 *
78 The following coding will create, populate, and write an element
79 variable truth table to an opened exodus file (NOTE: all element
80 variables are valid for all element blocks in this example.):
81
82 ~~~{.c}
83 int *truth_tab, num_elem_blk, num_ele_vars, error, exoid;
84
85 \comment{write element variable truth table}
86 truth_tab = (int *)calloc((num_elem_blk*num_ele_vars), sizeof(int));
87
88 for (i=0, k=0; i < num_elem_blk; i++) {
89 for (j=0; j < num_ele_vars; j++) {
90 truth_tab[k++] = 1;
91 }
92 }
93 error = ex_put_truth_table(exoid, EX_ELEM_BLOCK, num_elem_blk, num_ele_vars,
94 truth_tab);
95 ~~~
96 */
97
ex_put_truth_table(int exoid,ex_entity_type obj_type,int num_blk,int num_var,int * var_tab)98 int ex_put_truth_table(int exoid, ex_entity_type obj_type, int num_blk, int num_var, int *var_tab)
99 {
100 int numelblkdim, numelvardim, timedim, dims[2], varid;
101 char * sta_type, *tab_type;
102 size_t num_entity = 0;
103 size_t num_var_db = 0;
104 int * stat_vals;
105 int i, j, k;
106 int status;
107 char errmsg[MAX_ERR_LENGTH];
108
109 /*
110 * The ent_type and the var_name are used to build the netcdf
111 * variables name. Normally this is done via a macro defined in
112 * exodusII_int.h
113 */
114 const char *ent_type = NULL;
115 const char *var_name = NULL;
116 const char *ent_size = NULL;
117
118 EX_FUNC_ENTER();
119
120 ex_check_valid_file_id(exoid, __func__);
121
122 ex_get_dimension(exoid, ex_dim_num_objects(obj_type), ex_name_of_object(obj_type), &num_entity,
123 &numelblkdim, __func__);
124
125 if (obj_type == EX_ELEM_BLOCK) {
126 ex_get_dimension(exoid, DIM_NUM_ELE_VAR, "element variables", &num_var_db, &numelvardim,
127 __func__);
128 var_name = "vals_elem_var";
129 ent_type = "eb";
130 ent_size = "num_el_in_blk";
131 sta_type = VAR_STAT_EL_BLK;
132 tab_type = VAR_ELEM_TAB;
133 }
134 else if (obj_type == EX_EDGE_BLOCK) {
135 ex_get_dimension(exoid, DIM_NUM_EDG_VAR, "edge block variables", &num_var_db, &numelvardim,
136 __func__);
137 var_name = "vals_edge_var";
138 ent_type = "eb";
139 ent_size = "num_ed_in_blk";
140 sta_type = VAR_STAT_ED_BLK;
141 tab_type = VAR_EBLK_TAB;
142 }
143 else if (obj_type == EX_FACE_BLOCK) {
144 ex_get_dimension(exoid, DIM_NUM_FAC_VAR, "face block variables", &num_var_db, &numelvardim,
145 __func__);
146 var_name = "vals_face_var";
147 ent_type = "fb";
148 ent_size = "num_fa_in_blk";
149 sta_type = VAR_STAT_FA_BLK;
150 tab_type = VAR_FBLK_TAB;
151 }
152 else if (obj_type == EX_SIDE_SET) {
153 ex_get_dimension(exoid, DIM_NUM_SSET_VAR, "sideset variables", &num_var_db, &numelvardim,
154 __func__);
155 var_name = "vals_sset_var";
156 ent_type = "ss";
157 ent_size = "num_side_ss";
158 sta_type = VAR_SS_STAT;
159 tab_type = VAR_SSET_TAB;
160 }
161 else if (obj_type == EX_NODE_SET) {
162 ex_get_dimension(exoid, DIM_NUM_NSET_VAR, "nodeset variables", &num_var_db, &numelvardim,
163 __func__);
164 var_name = "vals_nset_var";
165 ent_type = "ns";
166 ent_size = "num_nod_ns";
167 sta_type = VAR_NS_STAT;
168 tab_type = VAR_NSET_TAB;
169 }
170 else if (obj_type == EX_EDGE_SET) {
171 ex_get_dimension(exoid, DIM_NUM_ESET_VAR, "edge set variables", &num_var_db, &numelvardim,
172 __func__);
173 var_name = "vals_eset_var";
174 ent_type = "es";
175 ent_size = "num_edge_es";
176 sta_type = VAR_ES_STAT;
177 tab_type = VAR_ESET_TAB;
178 }
179 else if (obj_type == EX_FACE_SET) {
180 ex_get_dimension(exoid, DIM_NUM_FSET_VAR, "face set variables", &num_var_db, &numelvardim,
181 __func__);
182 var_name = "vals_fset_var";
183 ent_type = "fs";
184 ent_size = "num_face_fs";
185 sta_type = VAR_FS_STAT;
186 tab_type = VAR_FSET_TAB;
187 }
188 else if (obj_type == EX_ELEM_SET) {
189 ex_get_dimension(exoid, DIM_NUM_ELSET_VAR, "element set variables", &num_var_db, &numelvardim,
190 __func__);
191 var_name = "vals_elset_var";
192 ent_type = "es";
193 ent_size = "num_ele_els";
194 sta_type = VAR_ELS_STAT;
195 tab_type = VAR_ELSET_TAB;
196 }
197
198 else { /* invalid variable type */
199 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Invalid variable type %d specified in file id %d",
200 obj_type, exoid);
201 ex_err(__func__, errmsg, EX_BADPARAM);
202 EX_FUNC_LEAVE(EX_WARN);
203 }
204
205 if ((int)num_entity != num_blk) {
206 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: # of %s doesn't match those defined in file id %d",
207 ex_name_of_object(obj_type), exoid);
208 ex_err(__func__, errmsg, EX_BADPARAM);
209 EX_FUNC_LEAVE(EX_FATAL);
210 }
211
212 if ((int)num_var_db != num_var) {
213 snprintf(errmsg, MAX_ERR_LENGTH,
214 "ERROR: # of %s variables doesn't match those defined in file id %d",
215 ex_name_of_object(obj_type), exoid);
216 ex_err(__func__, errmsg, EX_BADPARAM);
217 EX_FUNC_LEAVE(EX_FATAL);
218 }
219
220 /* Get status array for later use */
221 if (!(stat_vals = malloc(num_blk * sizeof(int)))) {
222 snprintf(errmsg, MAX_ERR_LENGTH,
223 "ERROR: failed to allocate memory for %s status array for file id %d",
224 ex_name_of_object(obj_type), exoid);
225 ex_err(__func__, errmsg, EX_MEMFAIL);
226 EX_FUNC_LEAVE(EX_FATAL);
227 }
228
229 status = nc_inq_varid(exoid, sta_type, &varid);
230
231 /* get variable id of status array */
232 if (status == NC_NOERR) {
233 /* if status array exists (V 2.01+), use it, otherwise assume
234 object exists to be backward compatible */
235
236 if ((status = nc_get_var_int(exoid, varid, stat_vals)) != NC_NOERR) {
237 free(stat_vals);
238 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get %s status array from file id %d",
239 ex_name_of_object(obj_type), exoid);
240 ex_err(__func__, errmsg, status);
241 EX_FUNC_LEAVE(EX_FATAL);
242 }
243 }
244 else {
245 /* status array doesn't exist (V2.00), dummy one up for later checking */
246 for (i = 0; i < num_blk; i++) {
247 stat_vals[i] = 1;
248 }
249 }
250
251 /* put netcdf file into define mode */
252 if ((status = nc_redef(exoid)) != NC_NOERR) {
253 free(stat_vals);
254 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to put file id %d into define mode", exoid);
255 ex_err(__func__, errmsg, status);
256 EX_FUNC_LEAVE(EX_FATAL);
257 }
258
259 /* inquire previously defined dimensions */
260 if ((status = nc_inq_dimid(exoid, DIM_TIME, &timedim)) != NC_NOERR) {
261 free(stat_vals);
262 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate time variable in file id %d", exoid);
263 ex_err(__func__, errmsg, status);
264 goto error_ret; /* exit define mode and return */
265 }
266
267 /* define netCDF variables in which to store EXODUS element
268 * variable values
269 */
270
271 k = 0;
272 for (i = 0; i < num_blk; i++) {
273 for (j = 1; j <= num_var; j++) {
274
275 /* check if variables are to be put out for this entity */
276 if (var_tab[k] != 0) {
277 if (stat_vals[i] != 0) { /* check for NULL entity */
278 /* NOTE: This code used to zero out the var_tab entry
279 if the stat_vals[i] value was zero. However, in some
280 cases it is good to know that a variable was assigned to
281 an entity even if that entity is empty. The code was
282 changed to not modify the truth table.
283 */
284 dims[0] = timedim;
285
286 /* Determine number of entities in block */
287 if ((status = nc_inq_dimid(exoid, ex_catstr(ent_size, (i + 1)), &dims[1])) != NC_NOERR) {
288 free(stat_vals);
289 snprintf(errmsg, MAX_ERR_LENGTH,
290 "ERROR: failed to locate number of entities in "
291 "%d'th %s in file id %d",
292 i + 1, ex_name_of_object(obj_type), exoid);
293 ex_err(__func__, errmsg, status);
294 goto error_ret; /* exit define mode and return */
295 }
296
297 /* define netCDF variable to store variable values; the j
298 * index cycles from 1 through the number of variables so
299 * that the index of the EXODUS variable (which is part
300 * of the name of the netCDF variable) will begin at 1
301 * instead of 0
302 */
303
304 if ((status = nc_def_var(exoid, ex_catstr2(var_name, j, ent_type, i + 1),
305 nc_flt_code(exoid), 2, dims, &varid)) != NC_NOERR) {
306 if (status != NC_ENAMEINUSE) {
307 free(stat_vals);
308 snprintf(errmsg, MAX_ERR_LENGTH,
309 "ERROR: failed to define variable for %d'th %s in file id %d", i + 1,
310 ex_name_of_object(obj_type), exoid);
311 ex_err(__func__, errmsg, status);
312 goto error_ret; /* exit define mode and return */
313 }
314 ex_compress_variable(exoid, varid, 2);
315 }
316 }
317 } /* if */
318 k++; /* increment element truth table pointer */
319 } /* for j */
320 } /* for i */
321
322 free(stat_vals);
323
324 /* create a variable array in which to store the truth table
325 */
326
327 dims[0] = numelblkdim;
328 dims[1] = numelvardim;
329 status = nc_def_var(exoid, tab_type, NC_INT, 2, dims, &varid);
330
331 if (status != NC_NOERR) {
332 snprintf(errmsg, MAX_ERR_LENGTH,
333 "ERROR: failed to define %s variable truth table in file id %d",
334 ex_name_of_object(obj_type), exoid);
335 ex_err(__func__, errmsg, status);
336 goto error_ret; /* exit define mode and return */
337 }
338
339 /* leave define mode */
340 if ((status = nc_enddef(exoid)) != NC_NOERR) {
341 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to complete definitions in file id %d", exoid);
342 ex_err(__func__, errmsg, status);
343 EX_FUNC_LEAVE(EX_FATAL);
344 }
345
346 /* write out the element variable truth table */
347 status = nc_put_var_int(exoid, varid, var_tab);
348
349 if (status != NC_NOERR) {
350 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to store variable truth table in file id %d",
351 exoid);
352 ex_err(__func__, errmsg, status);
353 EX_FUNC_LEAVE(EX_FATAL);
354 }
355
356 EX_FUNC_LEAVE(EX_NOERR);
357
358 /* Fatal error: exit definition mode and return */
359 error_ret:
360 if ((status = nc_enddef(exoid)) != NC_NOERR) /* exit define mode */
361 {
362 snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to complete definition for file id %d", exoid);
363 ex_err(__func__, errmsg, status);
364 }
365 EX_FUNC_LEAVE(EX_FATAL);
366 }
367