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 * exutils - utility routines
38 *
39 *****************************************************************************/
40
41 #if defined(DEBUG_QSORT)
42 #include <assert.h>
43 #endif
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <unistd.h>
50
51 #include "exodusII.h"
52 #include "exodusII_int.h"
53
54 struct obj_stats* exoII_eb = 0;
55 struct obj_stats* exoII_ed = 0;
56 struct obj_stats* exoII_fa = 0;
57 struct obj_stats* exoII_ns = 0;
58 struct obj_stats* exoII_es = 0;
59 struct obj_stats* exoII_fs = 0;
60 struct obj_stats* exoII_ss = 0;
61 struct obj_stats* exoII_els = 0;
62 struct obj_stats* exoII_em = 0;
63 struct obj_stats* exoII_edm = 0;
64 struct obj_stats* exoII_fam = 0;
65 struct obj_stats* exoII_nm = 0;
66
67
68 /*****************************************************************************
69 *
70 * utility routines for string conversions
71 * ex_catstr - concatenate string/number (where number is converted to ASCII)
72 * ex_catstr2 - concatenate string1/number1/string2/number2 "
73 *
74 * NOTE: these routines reuse the same storage over and over to build
75 * concatenated strings, because the strings are just passed to netCDF
76 * routines as names used to look up variables. if the strings returned
77 * by these routines are needed for any other purpose, they should
78 * immediately be copied into other storage.
79 *****************************************************************************/
80
81 static char ret_string[10*(MAX_VAR_NAME_LENGTH+1)];
82 static char* cur_string = &ret_string[0];
83
ex_check_file_type(const char * path,int * type)84 int ex_check_file_type(const char *path, int *type)
85 {
86 /* Based on (stolen from?) NC_check_file_type from netcdf sources.
87
88 Type is set to:
89 1 if this is a netcdf classic file,
90 2 if this is a netcdf 64-bit offset file,
91 5 if this is an hdf5 file
92 */
93
94 #define MAGIC_NUMBER_LEN 4
95
96 char magic[MAGIC_NUMBER_LEN];
97
98 *type = 0;
99
100 /* Get the 4-byte magic from the beginning of the file. */
101 {
102 FILE *fp;
103 int i;
104
105 if (!(fp = fopen(path, "r")))
106 return errno;
107 i = fread(magic, MAGIC_NUMBER_LEN, 1, fp);
108 fclose(fp);
109 if(i != 1)
110 return errno;
111 }
112
113 /* Ignore the first byte for HDF */
114 if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
115 *type = 5;
116 else if (magic[0] == 'C' && magic[1] == 'D' && magic[2] == 'F')
117 {
118 if (magic[3] == '\001')
119 *type = 1;
120 else if(magic[3] == '\002')
121 *type = 2;
122 }
123 return EX_NOERR;
124 }
125
ex_set_max_name_length(int exoid,int length)126 int ex_set_max_name_length(int exoid, int length)
127 {
128 char errmsg[MAX_ERR_LENGTH];
129 if (length <= 0) {
130 exerrval = NC_EMAXNAME;
131 sprintf(errmsg, "Error: Max name length must be positive.");
132 ex_err("ex_set_max_name_length",errmsg,exerrval);
133 return (EX_FATAL);
134 }
135 else if (length > NC_MAX_NAME) {
136 exerrval = NC_EMAXNAME;
137 sprintf(errmsg, "Error: Max name length (%d) exceeds netcdf max name size (%d).",
138 length, NC_MAX_NAME);
139 ex_err("ex_set_max_name_length",errmsg,exerrval);
140 return (EX_FATAL);
141 }
142 else {
143 ex_set_option(exoid, EX_OPT_MAX_NAME_LENGTH, length);
144 }
145 return EX_NOERR;
146 }
147
ex_update_max_name_length(int exoid,int length)148 void ex_update_max_name_length(int exoid, int length)
149 {
150 int status;
151 int db_length = 0;
152 /* Get current value of the maximum_name_length attribute... */
153 if ((status = nc_get_att_int(exoid, NC_GLOBAL, ATT_MAX_NAME_LENGTH, &db_length)) != NC_NOERR) {
154 char errmsg[MAX_ERR_LENGTH];
155 exerrval = status;
156 sprintf(errmsg,
157 "Error: failed to update 'max_name_length' attribute in file id %d",
158 exoid);
159 ex_err("ex_update_max_name_length",errmsg,exerrval);
160 }
161
162 if (length > db_length) {
163 /* Update with new value... */
164 nc_put_att_int(exoid, NC_GLOBAL, ATT_MAX_NAME_LENGTH, NC_INT, 1, &length);
165 }
166 }
167
ex_put_names_internal(int exoid,int varid,size_t num_entity,char ** names,ex_entity_type obj_type,const char * subtype,const char * routine)168 int ex_put_names_internal(int exoid, int varid, size_t num_entity, char **names,
169 ex_entity_type obj_type, const char *subtype, const char *routine)
170 {
171 size_t i;
172 int status;
173 size_t start[2], count[2];
174 char errmsg[MAX_ERR_LENGTH];
175 int max_name_len = 0;
176 size_t name_length;
177
178 /* inquire previously defined dimensions */
179 name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH)+1;
180
181 for (i=0; i<num_entity; i++) {
182 if (names[i] != '\0') {
183 int too_long = 0;
184 start[0] = i;
185 start[1] = 0;
186
187 count[0] = 1;
188 count[1] = strlen(names[i]) + 1;
189
190 if (count[1] > name_length) {
191 fprintf(stderr,
192 "Warning: The %s %s name '%s' is too long.\n\tIt will be truncated from %d to %d characters\n",
193 ex_name_of_object(obj_type), subtype, names[i], (int)strlen(names[i]), (int)name_length-1);
194 count[1] = name_length;
195 too_long = 1;
196 }
197
198 if (count[1] > max_name_len)
199 max_name_len = count[1];
200
201 if ((status = nc_put_vara_text(exoid, varid, start, count, names[i])) != NC_NOERR) {
202 exerrval = status;
203 sprintf(errmsg,
204 "Error: failed to store %s names in file id %d",
205 ex_name_of_object(obj_type), exoid);
206 ex_err(routine,errmsg,exerrval);
207 return (EX_FATAL);
208 }
209
210 /* Add the trailing null if the variable name was too long */
211 if (too_long) {
212 start[1] = name_length-1;
213 nc_put_var1_text(exoid, varid, start, "\0");
214 }
215 }
216 }
217
218 /* Update the maximum_name_length attribute on the file. */
219 ex_update_max_name_length(exoid, max_name_len-1);
220
221 return (EX_NOERR);
222 }
223
ex_put_name_internal(int exoid,int varid,size_t index,const char * name,ex_entity_type obj_type,const char * subtype,const char * routine)224 int ex_put_name_internal(int exoid, int varid, size_t index, const char *name,
225 ex_entity_type obj_type, const char *subtype, const char *routine)
226 {
227 int status;
228 size_t start[2], count[2];
229 char errmsg[MAX_ERR_LENGTH];
230 size_t name_length;
231
232 /* inquire previously defined dimensions */
233 name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH)+1;
234
235 if (name != '\0') {
236 int too_long = 0;
237 start[0] = index;
238 start[1] = 0;
239
240 count[0] = 1;
241 count[1] = strlen(name) + 1;
242
243 if (count[1] > name_length) {
244 fprintf(stderr,
245 "Warning: The %s %s name '%s' is too long.\n\tIt will be truncated from %d to %d characters\n",
246 ex_name_of_object(obj_type), subtype, name, (int)strlen(name), (int)name_length-1);
247 count[1] = name_length;
248 too_long = 1;
249 }
250
251 if ((status = nc_put_vara_text(exoid, varid, start, count, name)) != NC_NOERR) {
252 exerrval = status;
253 sprintf(errmsg,
254 "Error: failed to store %s name in file id %d",
255 ex_name_of_object(obj_type), exoid);
256 ex_err(routine,errmsg,exerrval);
257 return (EX_FATAL);
258 }
259
260 /* Add the trailing null if the variable name was too long */
261 if (too_long) {
262 start[1] = name_length-1;
263 nc_put_var1_text(exoid, varid, start, "\0");
264 }
265
266 /* Update the maximum_name_length attribute on the file. */
267 ex_update_max_name_length(exoid, count[1]-1);
268 }
269
270 return (EX_NOERR);
271 }
272
ex_get_names_internal(int exoid,int varid,size_t num_entity,char ** names,ex_entity_type obj_type,const char * routine)273 int ex_get_names_internal(int exoid, int varid, size_t num_entity, char **names,
274 ex_entity_type obj_type, const char *routine)
275 {
276 size_t i;
277 int status;
278
279 /* Query size of names on file
280 * Use the smaller of the size on file or user-specified length
281 */
282 int db_name_size = ex_inquire_int(exoid, EX_INQ_DB_MAX_ALLOWED_NAME_LENGTH);
283 int api_name_size = ex_inquire_int(exoid, EX_INQ_MAX_READ_NAME_LENGTH);
284 int name_size = db_name_size < api_name_size ? db_name_size : api_name_size;
285
286 for (i=0; i<num_entity; i++) {
287 status = ex_get_name_internal(exoid, varid, i, names[i], name_size, obj_type, routine);
288 if (status != NC_NOERR)
289 return status;
290 }
291 return EX_NOERR;
292 }
293
ex_get_name_internal(int exoid,int varid,size_t index,char * name,int name_size,ex_entity_type obj_type,const char * routine)294 int ex_get_name_internal(int exoid, int varid, size_t index, char *name, int name_size,
295 ex_entity_type obj_type, const char *routine)
296 {
297 size_t start[2], count[2];
298 int status;
299 char errmsg[MAX_ERR_LENGTH];
300 int api_name_size = ex_inquire_int(exoid, EX_INQ_MAX_READ_NAME_LENGTH);
301
302 /* read the name */
303 start[0] = index; count[0] = 1;
304 start[1] = 0; count[1] = name_size+1;
305
306 status = nc_get_vara_text(exoid, varid, start, count, name);
307 if (status != NC_NOERR) {
308 exerrval = status;
309 sprintf(errmsg, "Error: failed to get %s name at index %d from file id %d",
310 ex_name_of_object(obj_type), (int)index, exoid);
311 ex_err(routine,errmsg,exerrval);
312 return (EX_FATAL);
313 }
314
315 name[api_name_size] = '\0';
316
317 ex_trim_internal(name);
318 return EX_NOERR;
319 }
320
ex_trim_internal(char * name)321 void ex_trim_internal(char *name)
322 {
323 /* Trim trailing spaces... */
324 size_t size;
325 char *end;
326
327 if (name == NULL)
328 return;
329
330 size = strlen(name);
331 if (size==0)
332 return;
333
334 end = name + size - 1;
335 while (end >= name && isspace(*end))
336 end--;
337
338 *(end+1) = '\0';
339 }
340
341 /** ex_catstr - concatenate string/number (where number is converted to ASCII) */
ex_catstr(const char * string,int num)342 char *ex_catstr (const char *string,
343 int num)
344 {
345 char* tmp_string = cur_string;
346 cur_string += sprintf (cur_string, "%s%d", string, num) + 1;
347 if ( cur_string - ret_string > 9*(MAX_VAR_NAME_LENGTH+1) )
348 cur_string = ret_string;
349 return (tmp_string);
350 }
351
352
353 /** ex_catstr2 - concatenate string1num1string2num2 */
ex_catstr2(const char * string1,int num1,const char * string2,int num2)354 char *ex_catstr2 (const char *string1,
355 int num1,
356 const char *string2,
357 int num2)
358 {
359 char* tmp_string = cur_string;
360 cur_string += sprintf (cur_string, "%s%d%s%d", string1, num1, string2, num2) + 1;
361 if ( cur_string - ret_string > 9*(MAX_VAR_NAME_LENGTH+1) )
362 cur_string = ret_string;
363 return (tmp_string);
364 }
365
ex_name_of_object(ex_entity_type obj_type)366 char* ex_name_of_object(ex_entity_type obj_type)
367 {
368 switch (obj_type) {
369 case EX_COORDINATE: /* kluge so some wrapper functions work */
370 return "coordinate";
371 case EX_NODAL:
372 return "nodal";
373 case EX_EDGE_BLOCK:
374 return "edge block";
375 case EX_FACE_BLOCK:
376 return "face block";
377 case EX_ELEM_BLOCK:
378 return "element block";
379 case EX_NODE_SET:
380 return "node set";
381 case EX_EDGE_SET:
382 return "edge set";
383 case EX_FACE_SET:
384 return "face set";
385 case EX_SIDE_SET:
386 return "side set";
387 case EX_ELEM_SET:
388 return "element set";
389 case EX_ELEM_MAP:
390 return "element map";
391 case EX_NODE_MAP:
392 return "node map";
393 case EX_EDGE_MAP:
394 return "edge map";
395 case EX_FACE_MAP:
396 return "face map";
397 case EX_GLOBAL:
398 return "global";
399 default:
400 return "invalid type";
401 }
402 }
403
ex_var_type_to_ex_entity_type(char var_type)404 ex_entity_type ex_var_type_to_ex_entity_type(char var_type)
405 {
406 char var_lower = tolower(var_type);
407 if (var_lower == 'n')
408 return EX_NODAL;
409 else if (var_lower == 'l')
410 return EX_EDGE_BLOCK;
411 else if (var_lower == 'f')
412 return EX_FACE_BLOCK;
413 else if (var_lower == 'e')
414 return EX_ELEM_BLOCK;
415 else if (var_lower == 'm')
416 return EX_NODE_SET;
417 else if (var_lower == 'd')
418 return EX_EDGE_SET;
419 else if (var_lower == 'a')
420 return EX_FACE_SET;
421 else if (var_lower == 's')
422 return EX_SIDE_SET;
423 else if (var_lower == 't')
424 return EX_ELEM_SET;
425 else if (var_lower == 'g')
426 return EX_GLOBAL;
427 else
428 return EX_INVALID;
429 }
430
ex_dim_num_objects(ex_entity_type obj_type)431 char* ex_dim_num_objects(ex_entity_type obj_type)
432 {
433 exerrval = 0; /* clear error code */
434 switch (obj_type)
435 {
436 case EX_NODAL:
437 return DIM_NUM_NODES;
438 case EX_ELEM_BLOCK:
439 return DIM_NUM_EL_BLK;
440 case EX_EDGE_BLOCK:
441 return DIM_NUM_ED_BLK;
442 case EX_FACE_BLOCK:
443 return DIM_NUM_FA_BLK;
444 case EX_NODE_SET:
445 return DIM_NUM_NS;
446 case EX_EDGE_SET:
447 return DIM_NUM_ES;
448 case EX_FACE_SET:
449 return DIM_NUM_FS;
450 case EX_ELEM_SET:
451 return DIM_NUM_ELS;
452 case EX_SIDE_SET:
453 return DIM_NUM_SS;
454 case EX_ELEM_MAP:
455 return DIM_NUM_EM;
456 case EX_FACE_MAP:
457 return DIM_NUM_FAM;
458 case EX_EDGE_MAP:
459 return DIM_NUM_EDM;
460 case EX_NODE_MAP:
461 return DIM_NUM_NM;
462 default:
463 {
464 char errmsg[MAX_ERR_LENGTH];
465 exerrval = EX_BADPARAM;
466 sprintf(errmsg, "Error: object type %d not supported in call to ex_dim_num_objects",
467 obj_type);
468 ex_err("ex_dim_num_objects",errmsg,exerrval);
469 return (NULL);
470 }
471 }
472 }
473
ex_dim_num_entries_in_object(ex_entity_type obj_type,int idx)474 char* ex_dim_num_entries_in_object( ex_entity_type obj_type,
475 int idx )
476 {
477 switch (obj_type) {
478 case EX_NODAL:
479 return DIM_NUM_NODES;
480 case EX_EDGE_BLOCK:
481 return DIM_NUM_ED_IN_EBLK(idx);
482 case EX_FACE_BLOCK:
483 return DIM_NUM_FA_IN_FBLK(idx);
484 case EX_ELEM_BLOCK:
485 return DIM_NUM_EL_IN_BLK(idx);
486 case EX_NODE_SET:
487 return DIM_NUM_NOD_NS(idx);
488 case EX_EDGE_SET:
489 return DIM_NUM_EDGE_ES(idx);
490 case EX_FACE_SET:
491 return DIM_NUM_FACE_FS(idx);
492 case EX_SIDE_SET:
493 return DIM_NUM_SIDE_SS(idx);
494 case EX_ELEM_SET:
495 return DIM_NUM_ELE_ELS(idx);
496 default:
497 return 0;
498 }
499 }
500
ex_name_var_of_object(ex_entity_type obj_type,int i,int j)501 char* ex_name_var_of_object(ex_entity_type obj_type,
502 int i, int j)
503 {
504 switch (obj_type) {
505 case EX_EDGE_BLOCK:
506 return VAR_EDGE_VAR(i,j);
507 case EX_FACE_BLOCK:
508 return VAR_FACE_VAR(i,j);
509 case EX_ELEM_BLOCK:
510 return VAR_ELEM_VAR(i,j);
511 case EX_NODE_SET:
512 return VAR_NS_VAR(i,j);
513 case EX_EDGE_SET:
514 return VAR_ES_VAR(i,j);
515 case EX_FACE_SET:
516 return VAR_FS_VAR(i,j);
517 case EX_SIDE_SET:
518 return VAR_SS_VAR(i,j);
519 case EX_ELEM_SET:
520 return VAR_ELS_VAR(i,j);
521 default:
522 return 0;
523 }
524 }
525
ex_name_of_map(ex_entity_type map_type,int map_index)526 char* ex_name_of_map(ex_entity_type map_type, int map_index)
527 {
528 switch (map_type) {
529 case EX_NODE_MAP:
530 return VAR_NODE_MAP(map_index);
531 case EX_EDGE_MAP:
532 return VAR_EDGE_MAP(map_index);
533 case EX_FACE_MAP:
534 return VAR_FACE_MAP(map_index);
535 case EX_ELEM_MAP:
536 return VAR_ELEM_MAP(map_index);
537 default:
538 return 0;
539 }
540 }
541
542 /*****************************************************************************
543 *
544 * ex_id_lkup - look up id
545 *
546 * entry conditions -
547 * input parameters:
548 * int exoid exodus file id
549 * ex_entity_type id_type id type name:
550 * elem_ss
551 * node_ns
552 * side_ss
553 * int num id value
554 *
555 * exit conditions -
556 * int return index into table (1-based)
557 *
558 *****************************************************************************/
559
ex_id_lkup(int exoid,ex_entity_type id_type,ex_entity_id num)560 int ex_id_lkup( int exoid,
561 ex_entity_type id_type,
562 ex_entity_id num)
563 {
564
565 char id_table[MAX_VAR_NAME_LENGTH+1];
566 char id_dim[MAX_VAR_NAME_LENGTH+1];
567 char stat_table[MAX_VAR_NAME_LENGTH+1];
568 int varid, dimid;
569 size_t dim_len, i;
570 int64_t *id_vals=NULL;
571 int *stat_vals=NULL;
572
573 static int filled=FALSE;
574 struct obj_stats *tmp_stats;
575 int status;
576 char errmsg[MAX_ERR_LENGTH];
577
578 exerrval = 0; /* clear error code */
579
580 switch(id_type) {
581 case EX_NODAL:
582 return 0;
583 case EX_GLOBAL:
584 return 0;
585 case EX_ELEM_BLOCK:
586 strcpy(id_table, VAR_ID_EL_BLK); /* id array name */
587 strcpy(id_dim, DIM_NUM_EL_BLK); /* id array dimension name*/
588 strcpy(stat_table, VAR_STAT_EL_BLK); /* id status array name */
589 tmp_stats = ex_get_stat_ptr (exoid, &exoII_eb);
590 break;
591 case EX_NODE_SET:
592 strcpy(id_table, VAR_NS_IDS);
593 strcpy(id_dim, DIM_NUM_NS);
594 strcpy(stat_table, VAR_NS_STAT);
595 tmp_stats = ex_get_stat_ptr (exoid, &exoII_ns);
596 break;
597 case EX_SIDE_SET:
598 strcpy(id_table, VAR_SS_IDS);
599 strcpy(id_dim, DIM_NUM_SS);
600 strcpy(stat_table, VAR_SS_STAT);
601 tmp_stats = ex_get_stat_ptr (exoid, &exoII_ss);
602 break;
603 case EX_ELEM_MAP:
604 strcpy(id_table, VAR_EM_PROP(1));
605 strcpy(id_dim, DIM_NUM_EM);
606 strcpy(stat_table, "");
607 tmp_stats = ex_get_stat_ptr (exoid, &exoII_em);
608 break;
609 case EX_NODE_MAP:
610 strcpy(id_table, VAR_NM_PROP(1));
611 strcpy(id_dim, DIM_NUM_NM);
612 strcpy(stat_table, "");
613 tmp_stats = ex_get_stat_ptr (exoid, &exoII_nm);
614 break;
615 case EX_EDGE_BLOCK:
616 strcpy(id_table, VAR_ID_ED_BLK);
617 strcpy(id_dim, DIM_NUM_ED_BLK);
618 strcpy(stat_table, VAR_STAT_ED_BLK);
619 tmp_stats = ex_get_stat_ptr (exoid, &exoII_ed);
620 break;
621 case EX_FACE_BLOCK:
622 strcpy(id_table, VAR_ID_FA_BLK);
623 strcpy(id_dim, DIM_NUM_FA_BLK);
624 strcpy(stat_table, VAR_STAT_FA_BLK);
625 tmp_stats = ex_get_stat_ptr (exoid, &exoII_fa);
626 break;
627 case EX_EDGE_SET:
628 strcpy(id_table, VAR_ES_IDS);
629 strcpy(id_dim, DIM_NUM_ES);
630 strcpy(stat_table, VAR_ES_STAT);
631 tmp_stats = ex_get_stat_ptr (exoid, &exoII_es);
632 break;
633 case EX_FACE_SET:
634 strcpy(id_table, VAR_FS_IDS);
635 strcpy(id_dim, DIM_NUM_FS);
636 strcpy(stat_table, VAR_FS_STAT);
637 tmp_stats = ex_get_stat_ptr (exoid, &exoII_fs);
638 break;
639 case EX_ELEM_SET:
640 strcpy(id_table, VAR_ELS_IDS);
641 strcpy(id_dim, DIM_NUM_ELS);
642 strcpy(stat_table, VAR_ELS_STAT);
643 tmp_stats = ex_get_stat_ptr (exoid, &exoII_els);
644 break;
645 case EX_EDGE_MAP:
646 strcpy(id_table, VAR_EDM_PROP(1));
647 strcpy(id_dim, DIM_NUM_EDM);
648 strcpy(stat_table, "");
649 tmp_stats = ex_get_stat_ptr (exoid, &exoII_edm);
650 break;
651 case EX_FACE_MAP:
652 strcpy(id_table, VAR_FAM_PROP(1));
653 strcpy(id_dim, DIM_NUM_FAM);
654 strcpy(stat_table, "");
655 tmp_stats = ex_get_stat_ptr (exoid, &exoII_fam);
656 break;
657 default:
658 exerrval = EX_BADPARAM;
659 sprintf(errmsg,
660 "Error: unsupported id array type %d for file id %d",
661 id_type, exoid);
662 ex_err("ex_id_lkup",errmsg,exerrval);
663 return (EX_FATAL);
664 }
665
666 if ( (tmp_stats->id_vals == NULL) || (!(tmp_stats->valid_ids)) ) {
667
668 /* first time thru or id arrays haven't been completely filled yet */
669
670 /* get size of id array */
671
672 /* First get dimension id of id array */
673 if ((status = nc_inq_dimid(exoid,id_dim,&dimid)) != NC_NOERR) {
674 exerrval = status;
675 sprintf(errmsg,
676 "Error: failed to locate id array dimension in file id %d",
677 exoid);
678 ex_err("ex_id_lkup",errmsg,exerrval);
679 return (EX_FATAL);
680 }
681
682
683 /* Next get value of dimension */
684 if ((status = nc_inq_dimlen(exoid,dimid,&dim_len)) != NC_NOERR) {
685 exerrval = status;
686 sprintf(errmsg,
687 "Error: failed to locate %s array length in file id %d",
688 id_table,exoid);
689 ex_err("ex_id_lkup",errmsg,exerrval);
690 return (EX_FATAL);
691 }
692
693 /* get variable id of id array */
694 if ((status = nc_inq_varid (exoid, id_table, &varid)) != NC_NOERR) {
695 exerrval = status;
696 sprintf(errmsg,
697 "Error: failed to locate %s array in file id %d",
698 id_table, exoid);
699 ex_err("ex_id_lkup",errmsg,exerrval);
700 return (EX_FATAL);
701 }
702
703 /* allocate space for id array and initialize to zero to ensure
704 that the higher bits don't contain garbage while copy from ints */
705 if (!(id_vals = calloc(dim_len,sizeof(int64_t)))) {
706 exerrval = EX_MEMFAIL;
707 sprintf(errmsg,
708 "Error: failed to allocate memory for %s array for file id %d",
709 id_table,exoid);
710 ex_err("ex_id_lkup",errmsg,exerrval);
711 return (EX_FATAL);
712 }
713
714 if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
715 status = nc_get_var_longlong (exoid, varid, (long long*)id_vals);
716 }
717 else {
718 int *id_vals_int;
719 if (!(id_vals_int = malloc(dim_len*sizeof(int)))) {
720 exerrval = EX_MEMFAIL;
721 sprintf(errmsg,
722 "Error: failed to allocate memory for temporary array id_vals_int for file id %d",
723 exoid);
724 ex_err("ex_id_lkup",errmsg,exerrval);
725 return (EX_FATAL);
726 }
727 status = nc_get_var_int(exoid, varid, (int *)id_vals_int);
728 if (status == NC_NOERR) {
729 for (i=0;i<dim_len;i++)
730 id_vals[i] = (int64_t) id_vals_int[i];
731 }
732 free(id_vals_int);
733 }
734
735 if (status != NC_NOERR) {
736 exerrval = status;
737 sprintf(errmsg,
738 "Error: failed to get %s array from file id %d",
739 id_table,exoid);
740 ex_err("ex_id_lkup",errmsg,exerrval);
741 free(id_vals);
742 return (EX_FATAL);
743 }
744
745 /* check if values in stored arrays are filled with non-zeroes */
746 filled = TRUE;
747 for (i=0;i<dim_len;i++) {
748 if (id_vals[i] == EX_INVALID_ID || id_vals[i] == NC_FILL_INT) {
749 filled = FALSE;
750 break; /* id array hasn't been completely filled with valid ids yet */
751 }
752 }
753
754 if (filled) {
755 tmp_stats->valid_ids = TRUE;
756 tmp_stats->num = dim_len;
757 tmp_stats->id_vals = id_vals;
758 }
759
760 } else {
761 id_vals = tmp_stats->id_vals;
762 dim_len = tmp_stats->num;
763 }
764
765 /* Do a linear search through the id array to find the array value
766 corresponding to the passed index number */
767
768 for (i=0;i<dim_len;i++) {
769 if (id_vals[i] == num)
770 break; /* found the id requested */
771 }
772 if (i >= dim_len) /* failed to find id number */
773 {
774 if ( !(tmp_stats->valid_ids) ) {
775 free (id_vals);
776 }
777 exerrval = EX_LOOKUPFAIL;
778 return(EX_LOOKUPFAIL); /*if we got here, the id array value doesn't exist */
779 }
780
781 /* Now check status array to see if object is null */
782
783 /* get variable id of status array */
784 if (nc_inq_varid (exoid, stat_table, &varid) == NC_NOERR) {
785 /* if status array exists, use it, otherwise assume object exists
786 to be backward compatible */
787
788 if ( (tmp_stats->stat_vals == NULL) || (!(tmp_stats->valid_stat)) ) {
789 /* first time thru or status arrays haven't been filled yet */
790
791 /* allocate space for new status array */
792
793 if (!(stat_vals = malloc((int)dim_len*sizeof(int)))) {
794 exerrval = EX_MEMFAIL;
795 sprintf(errmsg,
796 "Error: failed to allocate memory for %s array for file id %d",
797 id_table,exoid);
798 ex_err("ex_id_lkup",errmsg,exerrval);
799 return (EX_FATAL);
800 }
801
802 if ((status = nc_get_var_int (exoid, varid, stat_vals)) != NC_NOERR) {
803 exerrval = status;
804 free(stat_vals);
805 sprintf(errmsg,
806 "Error: failed to get %s array from file id %d",
807 stat_table,exoid);
808 ex_err("ex_id_lkup",errmsg,exerrval);
809 return (EX_FATAL);
810 }
811
812 if (tmp_stats->valid_ids) {
813 /* status array is valid only if ids are valid */
814 tmp_stats->valid_stat = TRUE;
815 tmp_stats->stat_vals = stat_vals;
816 }
817
818 } else {
819 stat_vals = tmp_stats->stat_vals;
820 }
821
822 if (stat_vals[i] == 0) /* is this object null? */ {
823 exerrval = EX_NULLENTITY;
824 if ( !(tmp_stats->valid_stat) ) {
825 free (stat_vals);
826 }
827 if ( !(tmp_stats->valid_ids) ) {
828 if (id_vals) free (id_vals);
829 }
830 return(-((int)i+1)); /* return index into id array (1-based) */
831 }
832 }
833 if ( !(tmp_stats->valid_ids) ) {
834 if (id_vals) free (id_vals);
835 if (stat_vals) free (stat_vals);
836 }
837 return(i+1); /* return index into id array (1-based) */
838 }
839
840 /******************************************************************************
841 *
842 * ex_get_stat_ptr - returns a pointer to a structure of object ids
843 *
844 *****************************************************************************/
845
846 /*! this routine returns a pointer to a structure containing the ids of
847 * element blocks, node sets, or side sets according to exoid; if there
848 * is not a structure that matches the exoid, one is created
849 */
850
ex_get_stat_ptr(int exoid,struct obj_stats ** obj_ptr)851 struct obj_stats *ex_get_stat_ptr (int exoid, struct obj_stats **obj_ptr)
852
853 {
854 struct obj_stats *tmp_ptr;
855
856 tmp_ptr = *obj_ptr;
857
858 while (tmp_ptr) {
859 if ( (tmp_ptr)->exoid == exoid) {
860 break;
861 }
862 tmp_ptr = (tmp_ptr)->next;
863 }
864
865 if (!tmp_ptr) { /* exoid not found */
866 tmp_ptr = (struct obj_stats *) calloc (1, sizeof(struct obj_stats));
867 tmp_ptr->exoid = exoid;
868 tmp_ptr->next = *obj_ptr;
869 tmp_ptr->id_vals = 0;
870 tmp_ptr->stat_vals = 0;
871 tmp_ptr->num = 0;
872 tmp_ptr->valid_ids = 0;
873 tmp_ptr->valid_stat = 0;
874 *obj_ptr = tmp_ptr;
875 }
876
877 return (tmp_ptr);
878 }
879
880 /******************************************************************************
881 *
882 * ex_rm_stat_ptr - removes a pointer to a structure of object ids
883 *
884 *****************************************************************************/
885
886 /*! this routine removes a pointer to a structure containing the ids of
887 * element blocks, node sets, or side sets according to exoid; this
888 * is necessary to clean up because netCDF reuses file ids; should be
889 * called from ex_close
890 */
891
ex_rm_stat_ptr(int exoid,struct obj_stats ** obj_ptr)892 void ex_rm_stat_ptr (int exoid, struct obj_stats **obj_ptr)
893
894 {
895 struct obj_stats *last_head_list_ptr, *tmp_ptr;
896
897 tmp_ptr = *obj_ptr;
898 last_head_list_ptr = *obj_ptr; /* save last head pointer */
899
900 while (tmp_ptr ) /* Walk linked list of file ids/vals */
901 {
902 if (exoid == tmp_ptr->exoid ) /* linear search for exodus file id */
903 {
904 if (tmp_ptr == *obj_ptr) /* Are we at the head of the list? */
905 *obj_ptr = (*obj_ptr)->next; /* yes, reset ptr to head of list */
906 else /* no, remove this record from chain*/
907 last_head_list_ptr->next=tmp_ptr->next;
908 if (tmp_ptr->id_vals != NULL)
909 free(tmp_ptr->id_vals); /* free up memory */
910 if (tmp_ptr->stat_vals != NULL)
911 free(tmp_ptr->stat_vals);
912 free(tmp_ptr);
913 break; /* Quit if found */
914 }
915 last_head_list_ptr = tmp_ptr; /* save last head pointer */
916 tmp_ptr = tmp_ptr->next; /* Loop back if not */
917 }
918 }
919
920 /* structures to hold number of blocks of that type for each file id */
921 static struct list_item* ed_ctr_list = 0; /* edge blocks */
922 static struct list_item* fa_ctr_list = 0; /* face blocks */
923 static struct list_item* eb_ctr_list = 0; /* element blocks */
924 /* structures to hold number of sets of that type for each file id */
925 static struct list_item* ns_ctr_list = 0; /* node sets */
926 static struct list_item* es_ctr_list = 0; /* edge sets */
927 static struct list_item* fs_ctr_list = 0; /* face sets */
928 static struct list_item* ss_ctr_list = 0; /* side sets */
929 static struct list_item* els_ctr_list = 0; /* element sets */
930 /* structures to hold number of maps of that type for each file id */
931 static struct list_item* nm_ctr_list = 0; /* node maps */
932 static struct list_item* edm_ctr_list = 0; /* edge maps */
933 static struct list_item* fam_ctr_list = 0; /* face maps */
934 static struct list_item* em_ctr_list = 0; /* element maps */
935
ex_get_counter_list(ex_entity_type obj_type)936 struct list_item** ex_get_counter_list(ex_entity_type obj_type)
937 {
938 switch(obj_type) {
939 case EX_ELEM_BLOCK:
940 return &eb_ctr_list;
941 case EX_NODE_SET:
942 return &ns_ctr_list;
943 case EX_SIDE_SET:
944 return &ss_ctr_list;
945 case EX_ELEM_MAP:
946 return &em_ctr_list;
947 case EX_NODE_MAP:
948 return &nm_ctr_list;
949 case EX_EDGE_BLOCK:
950 return &ed_ctr_list;
951 case EX_FACE_BLOCK:
952 return &fa_ctr_list;
953 case EX_EDGE_SET:
954 return &es_ctr_list;
955 case EX_FACE_SET:
956 return &fs_ctr_list;
957 case EX_ELEM_SET:
958 return &els_ctr_list;
959 case EX_EDGE_MAP:
960 return &edm_ctr_list;
961 case EX_FACE_MAP:
962 return &fam_ctr_list;
963 default:
964 return (NULL);
965 }
966 }
967
968 /******************************************************************************
969 *
970 * ex_inc_file_item - increment file item
971 *
972 *****************************************************************************/
973
974
975 /*! this routine sets up a structure to track and increment a counter for
976 * each open exodus file. it is designed to be used by the routines
977 * ex_put_elem_block() and ex_put_set_param(),
978 * to keep track of the number of element blocks, and each type of set,
979 * respectively, for each open exodus II file.
980 *
981 * The list structure is used as follows:
982 *
983 * ptr -----------> list item structure
984 * -------------------
985 * exodus file id
986 * item value (int)
987 * ptr to next (NULL if last)
988 *
989 *
990 * NOTE: since netCDF reuses its file ids, and a user may open and close any
991 * number of files in one application, items must be taken out of the
992 * linked lists in each of the above routines. these should be called
993 * after ncclose().
994 */
995
ex_inc_file_item(int exoid,struct list_item ** list_ptr)996 int ex_inc_file_item( int exoid, /* file id */
997 struct list_item **list_ptr)/* ptr to ptr to list_item */
998
999 {
1000 struct list_item* tlist_ptr;
1001
1002
1003 /* printf("[f] list: %ld, *list: %ld \n", list_ptr, *list_ptr); */
1004 tlist_ptr = *list_ptr; /* use temp list ptr to walk linked list */
1005
1006 while (tlist_ptr ) /* Walk linked list of file ids/vals */
1007 {
1008 if (exoid == tlist_ptr->exo_id ) /* linear search for exodus file id */
1009 break; /* Quit if found */
1010 tlist_ptr = tlist_ptr->next; /* Loop back if not */
1011 }
1012
1013 if (!tlist_ptr ) /* ptr NULL? */
1014 { /* yes, new file id */
1015 /* allocate space for new structure record */
1016 tlist_ptr = (struct list_item*) calloc(1,sizeof(struct list_item));
1017 tlist_ptr->exo_id = exoid; /* insert file id */
1018 tlist_ptr->next = *list_ptr; /* insert into head of list */
1019 *list_ptr = tlist_ptr; /* fix up new head of list */
1020 }
1021
1022 /* printf("[f] tlist: %ld *tlist: %ld **tlist: %ld\n",
1023 tlist_ptr,*tlist_ptr,(*tlist_ptr)->value, (*tlist_ptr)->next); */
1024
1025
1026 return(tlist_ptr->value++);
1027
1028 }
1029
1030 /*****************************************************************************
1031 *
1032 * ex_get_file_item - increment file item
1033 *
1034 *****************************************************************************/
1035
1036
1037 /*! this routine accesses a structure to track and increment a counter for
1038 * each open exodus file. it is designed to be used by the routines
1039 * ex_put_elem_block(), and ex_put_set_param(),
1040 * to get the number of element blocks, or a type of set,
1041 * respectively, for an open exodus II file.
1042 *
1043 * The list structure is used as follows:
1044 *
1045 * ptr -----------> list item structure
1046 * -------------------
1047 * exodus file id
1048 * item value (int)
1049 * ptr to next (NULL if last)
1050 *
1051 *
1052 * NOTE: since netCDF reuses its file ids, and a user may open and close any
1053 * number of files in one application, items must be taken out of the
1054 * linked lists in each of the above routines. these should be called
1055 * after ncclose().
1056 */
1057
ex_get_file_item(int exoid,struct list_item ** list_ptr)1058 int ex_get_file_item( int exoid, /* file id */
1059 struct list_item **list_ptr)/* ptr to ptr to list_item */
1060
1061 {
1062 struct list_item* tlist_ptr;
1063
1064 /* printf("[f] list: %ld, *list: %ld \n", list_ptr, *list_ptr); */
1065 tlist_ptr = *list_ptr; /* use temp list ptr to walk linked list */
1066
1067
1068 while (tlist_ptr ) /* Walk linked list of file ids/vals */
1069 {
1070 if (exoid == tlist_ptr->exo_id ) /* linear search for exodus file id */
1071 break; /* Quit if found */
1072 tlist_ptr = tlist_ptr->next; /* Loop back if not */
1073 }
1074
1075 if (!tlist_ptr ) /* ptr NULL? */
1076 { /* yes, Error: file id not found*/
1077 return(-1);
1078 }
1079
1080 /* printf("[f] list: %ld *list: %ld **list: %ld\n",
1081 list_ptr,*list_ptr,(*list_ptr)->value, (*list_ptr)->next); */
1082
1083 return(tlist_ptr->value);
1084 }
1085
1086 /*****************************************************************************
1087 *
1088 * ex_rm_file_item - remove file item
1089 *
1090 *****************************************************************************/
1091
1092
1093 /*! this routine removes a structure to track and increment a counter for
1094 * each open exodus file.
1095 *
1096 * The list structure is used as follows:
1097 *
1098 * ptr -----------> list item structure
1099 * -------------------
1100 * exodus file id
1101 * item value (int)
1102 * ptr to next (NULL if last)
1103 *
1104 *
1105 * NOTE: since netCDF reuses its file ids, and a user may open and close any
1106 * number of files in one application, items must be taken out of the
1107 * linked lists in each of the above routines. these should be called
1108 * after ncclose().
1109 */
1110
ex_rm_file_item(int exoid,struct list_item ** list_ptr)1111 void ex_rm_file_item( int exoid, /* file id */
1112 struct list_item **list_ptr)/* ptr to ptr to list_item */
1113
1114 {
1115 struct list_item *last_head_list_ptr, *tlist_ptr;
1116
1117 /* printf("[f] list: %ld, *list: %ld \n", list_ptr, *list_ptr); */
1118 tlist_ptr = *list_ptr;
1119 last_head_list_ptr = *list_ptr; /* save last head pointer */
1120 /* printf("[f] last head list: %ld\n",last_head_list_ptr); */
1121
1122 while (tlist_ptr ) /* Walk linked list of file ids/vals */
1123 {
1124 if (exoid == tlist_ptr->exo_id ) /* linear search for exodus file id */
1125 {
1126 if (tlist_ptr == *list_ptr) /* Are we at the head of the list? */
1127 *list_ptr = (*list_ptr)->next; /* yes, reset ptr to head of list */
1128 else /* no, remove this record from chain*/
1129 last_head_list_ptr->next=tlist_ptr->next;
1130 free(tlist_ptr); /* free up memory */
1131 break; /* Quit if found */
1132 }
1133 last_head_list_ptr = tlist_ptr; /* save last head pointer */
1134 tlist_ptr = tlist_ptr->next; /* Loop back if not */
1135 }
1136
1137 /* printf("[f] list: %ld *list: %ld **list: %ld\n",
1138 list_ptr,*list_ptr,(*list_ptr)->value, (*list_ptr)->next); */
1139
1140 }
1141
1142 /*****************************************************************************
1143 *
1144 * ex_get_num_props - get number of properties
1145 *
1146 *****************************************************************************/
ex_get_num_props(int exoid,ex_entity_type obj_type)1147 int ex_get_num_props (int exoid, ex_entity_type obj_type)
1148 {
1149 int cntr, varid;
1150 char var_name[MAX_VAR_NAME_LENGTH+1];
1151 char errmsg[MAX_ERR_LENGTH];
1152
1153 cntr = 0;
1154
1155 /* loop until there is not a property variable defined; the name of */
1156 /* the variables begin with an increment of 1 ("xx_prop1") so use cntr+1 */
1157
1158 while (TRUE)
1159 {
1160 switch (obj_type)
1161 {
1162 case EX_ELEM_BLOCK:
1163 strcpy (var_name, VAR_EB_PROP(cntr+1));
1164 break;
1165 case EX_EDGE_BLOCK:
1166 strcpy (var_name, VAR_ED_PROP(cntr+1));
1167 break;
1168 case EX_FACE_BLOCK:
1169 strcpy (var_name, VAR_FA_PROP(cntr+1));
1170 break;
1171 case EX_NODE_SET:
1172 strcpy (var_name, VAR_NS_PROP(cntr+1));
1173 break;
1174 case EX_EDGE_SET:
1175 strcpy (var_name, VAR_ES_PROP(cntr+1));
1176 break;
1177 case EX_FACE_SET:
1178 strcpy (var_name, VAR_FS_PROP(cntr+1));
1179 break;
1180 case EX_SIDE_SET:
1181 strcpy (var_name, VAR_SS_PROP(cntr+1));
1182 break;
1183 case EX_ELEM_SET:
1184 strcpy (var_name, VAR_ELS_PROP(cntr+1));
1185 break;
1186 case EX_ELEM_MAP:
1187 strcpy (var_name, VAR_EM_PROP(cntr+1));
1188 break;
1189 case EX_FACE_MAP:
1190 strcpy (var_name, VAR_FAM_PROP(cntr+1));
1191 break;
1192 case EX_EDGE_MAP:
1193 strcpy (var_name, VAR_EDM_PROP(cntr+1));
1194 break;
1195 case EX_NODE_MAP:
1196 strcpy (var_name, VAR_NM_PROP(cntr+1));
1197 break;
1198 default:
1199 exerrval = EX_BADPARAM;
1200 sprintf(errmsg, "Error: object type %d not supported; file id %d",
1201 obj_type, exoid);
1202 ex_err("ex_get_prop_names",errmsg,exerrval);
1203 return(EX_FATAL);
1204 }
1205
1206 if (nc_inq_varid (exoid, var_name, &varid) != NC_NOERR) {
1207 /* no variable with this name; return cntr which is now the number of */
1208 /* properties for this type of entity */
1209 return (cntr);
1210 }
1211 cntr++;
1212 }
1213 }
1214
ex_get_cpu_ws(void)1215 int ex_get_cpu_ws(void)
1216 {
1217 return(sizeof(float));
1218 }
1219
1220
1221 /* swap - interchange v[i] and v[j] */
ex_swap(int v[],int i,int j)1222 static void ex_swap (int v[], int i, int j)
1223 {
1224 int temp;
1225
1226 temp = v[i];
1227 v[i] = v[j];
1228 v[j] = temp;
1229 }
1230
ex_swap64(int64_t v[],int64_t i,int64_t j)1231 static void ex_swap64 (int64_t v[], int64_t i, int64_t j)
1232 {
1233 int64_t temp;
1234
1235 temp = v[i];
1236 v[i] = v[j];
1237 v[j] = temp;
1238 }
1239
1240 /*!
1241 * The following 'indexed qsort' routine is modified from Sedgewicks
1242 * algorithm It selects the pivot based on the median of the left,
1243 * right, and center values to try to avoid degenerate cases ocurring
1244 * when a single value is chosen. It performs a quicksort on
1245 * intervals down to the EX_QSORT_CUTOFF size and then performs a final
1246 * insertion sort on the almost sorted final array. Based on data in
1247 * Sedgewick, the EX_QSORT_CUTOFF value should be between 5 and 20.
1248 *
1249 * See Sedgewick for further details
1250 * Define DEBUG_QSORT at the top of this file and recompile to compile
1251 * in code that verifies that the array is sorted.
1252 */
1253
1254 #define EX_QSORT_CUTOFF 12
1255
ex_int_median3(int v[],int iv[],int left,int right)1256 static int ex_int_median3(int v[], int iv[], int left, int right)
1257 {
1258 ssize_t center;
1259 center = ((ssize_t)left + (ssize_t)right) / 2;
1260
1261 if (v[iv[left]] > v[iv[center]])
1262 ex_swap(iv, left, center);
1263 if (v[iv[left]] > v[iv[right]])
1264 ex_swap(iv, left, right);
1265 if (v[iv[center]] > v[iv[right]])
1266 ex_swap(iv, center, right);
1267
1268 ex_swap(iv, center, right-1);
1269 return iv[right-1];
1270 }
1271
ex_int_median3_64(int64_t v[],int64_t iv[],int64_t left,int64_t right)1272 static int64_t ex_int_median3_64(int64_t v[], int64_t iv[], int64_t left, int64_t right)
1273 {
1274 int64_t center;
1275 center = (left + right) / 2;
1276
1277 if (v[iv[left]] > v[iv[center]])
1278 ex_swap64(iv, left, center);
1279 if (v[iv[left]] > v[iv[right]])
1280 ex_swap64(iv, left, right);
1281 if (v[iv[center]] > v[iv[right]])
1282 ex_swap64(iv, center, right);
1283
1284 ex_swap64(iv, center, right-1);
1285 return iv[right-1];
1286 }
1287
ex_int_iqsort(int v[],int iv[],int left,int right)1288 static void ex_int_iqsort(int v[], int iv[], int left, int right)
1289 {
1290 int pivot;
1291 int i, j;
1292
1293 if (left + EX_QSORT_CUTOFF <= right) {
1294 pivot = ex_int_median3(v, iv, left, right);
1295 i = left;
1296 j = right - 1;
1297
1298 for ( ; ; ) {
1299 while (v[iv[++i]] < v[pivot]);
1300 while (v[iv[--j]] > v[pivot]);
1301 if (i < j) {
1302 ex_swap(iv, i, j);
1303 } else {
1304 break;
1305 }
1306 }
1307
1308 ex_swap(iv, i, right-1);
1309 ex_int_iqsort(v, iv, left, i-1);
1310 ex_int_iqsort(v, iv, i+1, right);
1311 }
1312 }
1313
ex_int_iqsort64(int64_t v[],int64_t iv[],int64_t left,int64_t right)1314 static void ex_int_iqsort64(int64_t v[], int64_t iv[], int64_t left, int64_t right)
1315 {
1316 int64_t pivot;
1317 int64_t i, j;
1318
1319 if (left + EX_QSORT_CUTOFF <= right) {
1320 pivot = ex_int_median3_64(v, iv, left, right);
1321 i = left;
1322 j = right - 1;
1323
1324 for ( ; ; ) {
1325 while (v[iv[++i]] < v[pivot]);
1326 while (v[iv[--j]] > v[pivot]);
1327 if (i < j) {
1328 ex_swap64(iv, i, j);
1329 } else {
1330 break;
1331 }
1332 }
1333
1334 ex_swap64(iv, i, right-1);
1335 ex_int_iqsort64(v, iv, left, i-1);
1336 ex_int_iqsort64(v, iv, i+1, right);
1337 }
1338 }
1339
ex_int_iisort(int v[],int iv[],int N)1340 static void ex_int_iisort(int v[], int iv[], int N)
1341 {
1342 int i,j;
1343 int ndx = 0;
1344 int small;
1345 int tmp;
1346
1347 small = v[iv[0]];
1348 for (i = 1; i < N; i++) {
1349 if (v[iv[i]] < small) {
1350 small = v[iv[i]];
1351 ndx = i;
1352 }
1353 }
1354 /* Put smallest value in slot 0 */
1355 ex_swap(iv, 0, ndx);
1356
1357 for (i=1; i <N; i++) {
1358 tmp = iv[i];
1359 for (j=i; v[tmp] < v[iv[j-1]]; j--) {
1360 iv[j] = iv[j-1];
1361 }
1362 iv[j] = tmp;
1363 }
1364 }
1365
ex_int_iisort64(int64_t v[],int64_t iv[],int64_t N)1366 static void ex_int_iisort64(int64_t v[], int64_t iv[], int64_t N)
1367 {
1368 int64_t i,j;
1369 int64_t ndx = 0;
1370 int64_t small;
1371 int64_t tmp;
1372
1373 small = v[iv[0]];
1374 for (i = 1; i < N; i++) {
1375 if (v[iv[i]] < small) {
1376 small = v[iv[i]];
1377 ndx = i;
1378 }
1379 }
1380 /* Put smallest value in slot 0 */
1381 ex_swap64(iv, 0, ndx);
1382
1383 for (i=1; i <N; i++) {
1384 tmp = iv[i];
1385 for (j=i; v[tmp] < v[iv[j-1]]; j--) {
1386 iv[j] = iv[j-1];
1387 }
1388 iv[j] = tmp;
1389 }
1390 }
1391
ex_iqsort(int v[],int iv[],int N)1392 void ex_iqsort(int v[], int iv[], int N)
1393 {
1394 ex_int_iqsort(v, iv, 0, N-1);
1395 ex_int_iisort(v, iv, N);
1396
1397 #if defined(DEBUG_QSORT)
1398 fprintf(stderr, "Checking sort of %d values\n", N+1);
1399 int i;
1400 for (i=1; i < N; i++) {
1401 assert(v[iv[i-1]] <= v[iv[i]]);
1402 }
1403 #endif
1404 }
1405
ex_iqsort64(int64_t v[],int64_t iv[],int64_t N)1406 void ex_iqsort64(int64_t v[], int64_t iv[], int64_t N)
1407 {
1408 ex_int_iqsort64(v, iv, 0, N-1);
1409 ex_int_iisort64(v, iv, N);
1410
1411 #if defined(DEBUG_QSORT)
1412 fprintf(stderr, "Checking sort of %d values\n", N+1);
1413 int i;
1414 for (i=1; i < N; i++) {
1415 assert(v[iv[i-1]] <= v[iv[i]]);
1416 }
1417 #endif
1418 }
1419
1420 /*!
1421 * Determine whether the new large model storage is being used in this
1422 * file, or old method. Basically, the difference is whether the
1423 * coordinates and nodal variables are stored in a blob (xyz
1424 * components together) or as a variable per component per
1425 * nodal_variable.
1426 */
ex_large_model(int exoid)1427 int ex_large_model(int exoid)
1428 {
1429 static int message_output = FALSE;
1430 if (exoid < 0) {
1431 /* If exoid not specified, then query is to see if user specified
1432 * the large model via an environment variable
1433 */
1434 char *option = getenv("EXODUS_LARGE_MODEL");
1435 if (option != NULL) {
1436 if (option[0] == 'n' || option[0] == 'N') {
1437 if (!message_output) {
1438 fprintf(stderr,
1439 "EXODUSII: Small model size selected via EXODUS_LARGE_MODEL environment variable\n");
1440 message_output = TRUE;
1441 }
1442 return 0;
1443 } else {
1444 if (!message_output) {
1445 fprintf(stderr,
1446 "EXODUSII: Large model size selected via EXODUS_LARGE_MODEL environment variable\n");
1447 message_output = TRUE;
1448 }
1449 return 1;
1450 }
1451 } else {
1452 return EXODUS_DEFAULT_SIZE; /* Specified in exodusII_int.h */
1453 }
1454
1455 } else {
1456 /* See if the ATT_FILESIZE attribute is defined in the file */
1457 int file_size = 0;
1458 if (nc_get_att_int(exoid, NC_GLOBAL, ATT_FILESIZE, &file_size) != NC_NOERR) {
1459 /* Variable not found; default is 0 */
1460 file_size = 0;
1461 }
1462 return file_size;
1463 }
1464 }
1465
ex_get_dimension(int exoid,const char * DIMENSION,const char * label,size_t * count,int * dimid,const char * routine)1466 int ex_get_dimension(int exoid, const char* DIMENSION, const char *label,
1467 size_t *count, int *dimid, const char *routine)
1468 {
1469 char errmsg[MAX_ERR_LENGTH];
1470 int status;
1471
1472 *count = 0;
1473 *dimid = -1;
1474
1475 if ((status = nc_inq_dimid(exoid, DIMENSION, dimid)) != NC_NOERR) {
1476 exerrval = status;
1477 if (routine != NULL) {
1478 if (status == NC_EBADDIM) {
1479 sprintf(errmsg,
1480 "Warning: no %s defined in file id %d",
1481 label, exoid);
1482 ex_err(routine, errmsg,exerrval);
1483
1484 } else {
1485 sprintf(errmsg,
1486 "Error: failed to locate number of %s in file id %d",
1487 label, exoid);
1488 ex_err(routine,errmsg,exerrval);
1489 }
1490 }
1491 return status;
1492 }
1493
1494 if ((status = nc_inq_dimlen (exoid, *dimid, count)) != NC_NOERR) {
1495 exerrval = status;
1496 if (routine != NULL) {
1497 sprintf(errmsg,
1498 "Error: failed to get number of %s in file id %d",
1499 label, exoid);
1500 ex_err(routine,errmsg,exerrval);
1501 return -1;
1502 }
1503 }
1504 return status;
1505 }
1506
1507 /* Deprecated. do not use */
ex_header_size(int exoid)1508 size_t ex_header_size(int exoid)
1509 {
1510 return 0;
1511 }
1512
1513 /* type = 1 for integer, 2 for real, 3 for character */
ex_compress_variable(int exoid,int varid,int type)1514 void ex_compress_variable(int exoid, int varid, int type)
1515 {
1516 #if !defined(NOT_NETCDF4)
1517
1518 struct file_item* file = ex_find_file_item(exoid);
1519
1520 if (!file ) {
1521 char errmsg[MAX_ERR_LENGTH];
1522 exerrval = EX_BADFILEID;
1523 sprintf(errmsg,"Error: unknown file id %d for ex_compress_variable().",exoid);
1524 ex_err("ex_compress_variable",errmsg,exerrval);
1525 }
1526 else {
1527 int deflate_level = file->compression_level;
1528 int compress = 1;
1529 int shuffle = file->shuffle;
1530 #if 0
1531 if (type == 2)
1532 shuffle = 0;
1533 #endif
1534 if (deflate_level > 0 && (file->file_type == 2 || file->file_type == 3)) {
1535 nc_def_var_deflate(exoid, varid, shuffle, compress, deflate_level);
1536 }
1537 }
1538 #endif
1539 }
1540