24 #define EXO_MAX_STR_LENGTH 33
25 #define EXO_MAX_LINE_LENGTH 81
26 #define EXO_API_VERSION 8.03f
27 #define EXO_DB_VERSION 8.03f
28 #define EXO_FILE_SIZE 1
31 #define MAX_ELEM_BLOCKS 64
53 static const ElemTypeMap elem_type_table[] = {
101 {911,
"BAR2"}, {912,
"BAR2"}, {913,
"BAR2"}, {914,
"BAR2"}, {915,
"BAR2"}, {916,
"BAR2"},
102 {921,
"BAR2"}, {922,
"BAR2"}, {923,
"BAR2"}, {924,
"BAR2"}, {925,
"BAR2"}, {926,
"BAR2"},
103 {931,
"BAR2"}, {932,
"BAR2"}, {933,
"BAR2"}, {934,
"BAR2"}, {935,
"BAR2"}, {936,
"BAR2"},
104 {941,
"BAR2"}, {942,
"BAR2"}, {943,
"BAR2"}, {944,
"BAR2"}, {945,
"BAR2"}, {946,
"BAR2"},
105 {951,
"BAR2"}, {952,
"BAR2"}, {953,
"BAR2"}, {954,
"BAR2"}, {955,
"BAR2"}, {956,
"BAR2"},
106 {961,
"BAR2"}, {962,
"BAR2"}, {963,
"BAR2"}, {964,
"BAR2"}, {965,
"BAR2"}, {966,
"BAR2"},
119 #define NCERR(e) do { \
120 if ((e) != NC_NOERR) { \
121 fprintf(stderr, "NetCDF error at %s:%d: %s\n", \
122 __FILE__, __LINE__, nc_strerror(e)); \
130 static const ElemTypeMap* get_elem_type_map(
int hecmw_type)
133 for (i = 0; elem_type_table[i].exo_name !=
NULL; i++) {
134 if (elem_type_table[i].hecmw_type == hecmw_type)
135 return &elem_type_table[i];
143 static int get_node_shift(
int hecmw_type)
145 switch (hecmw_type) {
162 return jE - jS - shift;
170 const char *exo_name;
179 static void pad_string(
char *buf,
int len,
const char *str)
181 int slen = (int)strlen(str);
183 if (slen > len) slen = len;
184 for (i = 0; i < slen; i++) buf[i] = str[i];
185 for (i = slen; i < len; i++) buf[i] =
'\0';
199 static const char *comp_suffix_1[] = {
""};
200 static const char *comp_suffix_2[] = {
"_X",
"_Y"};
201 static const char *comp_suffix_3[] = {
"_X",
"_Y",
"_Z"};
202 static const char *comp_suffix_3_principal[] = {
"_1st",
"_2nd",
"_3rd"};
203 static const char *comp_suffix_6[] = {
"_XX",
"_YY",
"_ZZ",
"_XY",
"_YZ",
"_ZX"};
204 static const char *comp_suffix_7[] = {
"_XX",
"_YY",
"_ZZ",
"_XY",
"_YZ",
"_ZX",
"_MISES"};
206 static int label_is_principal(
const char *label)
211 return (strstr(label,
"Principal") !=
NULL);
214 static const char** get_comp_suffixes(
int ndof,
const char *label)
217 case 1:
return comp_suffix_1;
218 case 2:
return comp_suffix_2;
219 case 3:
return label_is_principal(label) ? comp_suffix_3_principal
221 case 6:
return comp_suffix_6;
222 case 7:
return comp_suffix_7;
223 default:
return NULL;
244 char *outfile,
char *outfile1,
251 int n_node, n_elem, shift;
252 int data_tot_n, data_tot_e;
253 int table342[10] = {0, 1, 2, 3, 6, 4, 5, 7, 8, 9};
258 static int time_step_count = 0;
274 ElemBlockInfo blocks[MAX_ELEM_BLOCKS];
277 int total_nod_var = 0;
278 int total_elem_var = 0;
286 for (i = 0; i <
data->nn_component; i++)
287 data_tot_n +=
data->nn_dof[i];
290 for (i = 0; i <
data->ne_component; i++)
291 data_tot_e +=
data->ne_dof[i];
294 for (i = 0; i <
data->nn_component; i++)
295 total_nod_var +=
data->nn_dof[i];
296 for (i = 0; i <
data->ne_component; i++)
297 total_elem_var +=
data->ne_dof[i];
300 if (time_step_count == 0) {
311 p = strrchr(dir_exo,
'.');
312 if (p !=
NULL) *p =
'\0';
319 p = strrchr(basename_exo,
'/');
321 memmove(basename_exo, p + 1, strlen(p + 1) + 1);
323 p = strrchr(basename_exo,
'.');
324 if (p !=
NULL) *p =
'\0';
335 dir_exo, basename_exo, time_step_count);
338 dir_exo, basename_exo, time_step_count, petot,
myrank);
346 if (time_step_count == 0) {
349 dir_exo, basename_exo);
352 dir_exo, basename_exo, petot,
myrank);
359 if (time_step_count == 0 || per_step) {
368 memset(blocks, 0,
sizeof(blocks));
369 for (i = 0; i < n_elem; i++) {
372 for (j = 0; j < num_blocks; j++) {
373 if (blocks[j].hecmw_type == etype) {
374 blocks[j].num_elem++;
380 if (num_blocks >= MAX_ELEM_BLOCKS) {
383 const ElemTypeMap *map = get_elem_type_map(etype);
385 fprintf(stderr,
"WARNING: Unknown element type %d, skipping\n", etype);
388 blocks[num_blocks].hecmw_type = etype;
389 blocks[num_blocks].exo_name = map->exo_name;
391 blocks[num_blocks].nod_per_elem = get_effective_n_nodes(mesh, i);
392 blocks[num_blocks].num_elem = 1;
398 for (j = 0; j < num_blocks; j++) {
399 blocks[j].elem_indices = (
int *)
HECMW_malloc(
sizeof(
int) * blocks[j].num_elem);
400 if (blocks[j].elem_indices ==
NULL)
402 blocks[j].num_elem = 0;
404 for (i = 0; i < n_elem; i++) {
406 for (j = 0; j < num_blocks; j++) {
407 if (blocks[j].hecmw_type == etype) {
408 blocks[j].elem_indices[blocks[j].num_elem] = i;
409 blocks[j].num_elem++;
421 if (per_step || time_step_count == 0) {
425 stat = nc_create(file_exo, NC_CLOBBER | NC_64BIT_OFFSET, &ncid);
427 stat = nc_set_fill(ncid, NC_NOFILL, &old_fill_mode);
434 float api_ver = EXO_API_VERSION;
435 float db_ver = EXO_DB_VERSION;
436 int word_sz = (int)
sizeof(
double);
437 int file_sz = EXO_FILE_SIZE;
438 char title[] =
"FrontISTR Exodus output";
440 stat = nc_put_att_float(ncid, NC_GLOBAL,
"api_version", NC_FLOAT, 1, &api_ver);
442 stat = nc_put_att_float(ncid, NC_GLOBAL,
"version", NC_FLOAT, 1, &db_ver);
444 stat = nc_put_att_int(ncid, NC_GLOBAL,
"floating_point_word_size", NC_INT, 1, &word_sz);
446 stat = nc_put_att_int(ncid, NC_GLOBAL,
"file_size", NC_INT, 1, &file_sz);
448 stat = nc_put_att_text(ncid, NC_GLOBAL,
"title", strlen(
title),
title);
455 int dim_len_string, dim_len_name, dim_len_line, dim_four;
456 int dim_time_step, dim_num_dim, dim_num_nodes, dim_num_elem;
460 stat = nc_def_dim(ncid,
"len_string", EXO_MAX_STR_LENGTH, &dim_len_string);
462 stat = nc_def_dim(ncid,
"len_name", EXO_MAX_STR_LENGTH, &dim_len_name);
464 stat = nc_def_dim(ncid,
"len_line", EXO_MAX_LINE_LENGTH, &dim_len_line);
466 stat = nc_def_dim(ncid,
"four", 4, &dim_four);
468 stat = nc_def_dim(ncid,
"time_step", NC_UNLIMITED, &dim_time_step);
470 stat = nc_def_dim(ncid,
"num_dim", 3, &dim_num_dim);
472 stat = nc_def_dim(ncid,
"num_nodes", (
size_t)n_node, &dim_num_nodes);
474 stat = nc_def_dim(ncid,
"num_elem", (
size_t)n_elem, &dim_num_elem);
476 stat = nc_def_dim(ncid,
"num_el_blk", (
size_t)num_blocks, &dim_num_el_blk);
480 stat = nc_def_dim(ncid,
"num_qa_rec", 1, &dim_num_qa_rec);
484 int dim_el_in_blk[MAX_ELEM_BLOCKS];
485 int dim_nod_per_el[MAX_ELEM_BLOCKS];
486 for (j = 0; j < num_blocks; j++) {
487 char dname[EXO_MAX_STR_LENGTH];
488 snprintf(dname, EXO_MAX_STR_LENGTH,
"num_el_in_blk%d", j + 1);
489 stat = nc_def_dim(ncid, dname, (
size_t)blocks[j].num_elem, &dim_el_in_blk[j]);
491 snprintf(dname, EXO_MAX_STR_LENGTH,
"num_nod_per_el%d", j + 1);
492 stat = nc_def_dim(ncid, dname, (
size_t)blocks[j].nod_per_elem, &dim_nod_per_el[j]);
497 int dim_num_nod_var = -1, dim_num_elem_var = -1;
498 if (total_nod_var > 0) {
499 stat = nc_def_dim(ncid,
"num_nod_var", (
size_t)total_nod_var, &dim_num_nod_var);
502 if (total_elem_var > 0) {
503 stat = nc_def_dim(ncid,
"num_elem_var", (
size_t)total_elem_var, &dim_num_elem_var);
511 stat = nc_def_var(ncid,
"time_whole", NC_DOUBLE, 1, &dim_time_step, &var_time_whole);
517 int var_coordx, var_coordy, var_coordz;
518 stat = nc_def_var(ncid,
"coordx", NC_DOUBLE, 1, &dim_num_nodes, &var_coordx);
520 stat = nc_def_var(ncid,
"coordy", NC_DOUBLE, 1, &dim_num_nodes, &var_coordy);
522 stat = nc_def_var(ncid,
"coordz", NC_DOUBLE, 1, &dim_num_nodes, &var_coordz);
528 int dims2[2] = {dim_num_dim, dim_len_name};
529 stat = nc_def_var(ncid,
"coor_names", NC_CHAR, 2, dims2, &var_coor_names);
536 int var_eb_status, var_eb_prop1;
537 stat = nc_def_var(ncid,
"eb_status", NC_INT, 1, &dim_num_el_blk, &var_eb_status);
539 stat = nc_def_var(ncid,
"eb_prop1", NC_INT, 1, &dim_num_el_blk, &var_eb_prop1);
541 stat = nc_put_att_text(ncid, var_eb_prop1,
"name", 2,
"ID");
547 int dims2[2] = {dim_num_el_blk, dim_len_name};
548 stat = nc_def_var(ncid,
"eb_names", NC_CHAR, 2, dims2, &var_eb_names);
553 int var_connect[MAX_ELEM_BLOCKS];
554 for (j = 0; j < num_blocks; j++) {
555 char vname[EXO_MAX_STR_LENGTH];
556 snprintf(vname, EXO_MAX_STR_LENGTH,
"connect%d", j + 1);
557 int dims2[2] = {dim_el_in_blk[j], dim_nod_per_el[j]};
558 stat = nc_def_var(ncid, vname, NC_INT, 2, dims2, &var_connect[j]);
560 stat = nc_put_att_text(ncid, var_connect[j],
"elem_type",
561 strlen(blocks[j].exo_name), blocks[j].exo_name);
570 int dims3[3] = {dim_num_qa_rec, dim_four, dim_len_string};
571 stat = nc_def_var(ncid,
"qa_records", NC_CHAR, 3, dims3, &var_qa_records);
578 int var_node_num_map, var_elem_num_map;
579 stat = nc_def_var(ncid,
"node_num_map", NC_INT, 1, &dim_num_nodes, &var_node_num_map);
581 stat = nc_def_var(ncid,
"elem_num_map", NC_INT, 1, &dim_num_elem, &var_elem_num_map);
587 int var_name_nod_var = -1;
588 int var_vals_nod[512];
589 if (total_nod_var > 0) {
590 int dims2[2] = {dim_num_nod_var, dim_len_name};
591 stat = nc_def_var(ncid,
"name_nod_var", NC_CHAR, 2, dims2, &var_name_nod_var);
594 for (i = 0; i < total_nod_var; i++) {
595 char vname[EXO_MAX_STR_LENGTH];
596 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_nod_var%d", i + 1);
597 int dims_ts_nn[2] = {dim_time_step, dim_num_nodes};
598 stat = nc_def_var(ncid, vname, NC_DOUBLE, 2, dims_ts_nn, &var_vals_nod[i]);
606 int var_name_elem_var = -1;
607 int var_vals_elem[512];
608 int var_elem_var_tab = -1;
609 if (total_elem_var > 0) {
610 int dims2[2] = {dim_num_elem_var, dim_len_name};
611 stat = nc_def_var(ncid,
"name_elem_var", NC_CHAR, 2, dims2, &var_name_elem_var);
616 int dims_tt[2] = {dim_num_el_blk, dim_num_elem_var};
617 stat = nc_def_var(ncid,
"elem_var_tab", NC_INT, 2, dims_tt, &var_elem_var_tab);
622 for (i = 0; i < total_elem_var; i++) {
623 for (j = 0; j < num_blocks; j++) {
624 char vname[EXO_MAX_STR_LENGTH];
625 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_elem_var%deb%d", i + 1, j + 1);
626 int dims_ts_eb[2] = {dim_time_step, dim_el_in_blk[j]};
627 stat = nc_def_var(ncid, vname, NC_DOUBLE, 2, dims_ts_eb,
628 &var_vals_elem[i * num_blocks + j]);
637 stat = nc_enddef(ncid);
647 double *cx = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
648 double *cy = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
649 double *cz = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
654 for (i = 0; i < n_node; i++) {
659 stat = nc_put_var_double(ncid, var_coordx, cx); NCERR(stat);
660 stat = nc_put_var_double(ncid, var_coordy, cy); NCERR(stat);
661 stat = nc_put_var_double(ncid, var_coordz, cz); NCERR(stat);
667 char names[3][EXO_MAX_STR_LENGTH];
668 pad_string(names[0], EXO_MAX_STR_LENGTH,
"x");
669 pad_string(names[1], EXO_MAX_STR_LENGTH,
"y");
670 pad_string(names[2], EXO_MAX_STR_LENGTH,
"z");
671 stat = nc_put_var_text(ncid, var_coor_names, &names[0][0]);
677 int *eb_stat = (
int *)
HECMW_malloc(
sizeof(
int) * num_blocks);
678 int *eb_ids = (
int *)
HECMW_malloc(
sizeof(
int) * num_blocks);
679 if (eb_stat ==
NULL || eb_ids ==
NULL) {
683 for (j = 0; j < num_blocks; j++) {
687 stat = nc_put_var_int(ncid, var_eb_status, eb_stat); NCERR(stat);
688 stat = nc_put_var_int(ncid, var_eb_prop1, eb_ids); NCERR(stat);
694 char *names_buf = (
char *)
HECMW_malloc(num_blocks * EXO_MAX_STR_LENGTH);
695 if (names_buf ==
NULL)
697 for (j = 0; j < num_blocks; j++) {
698 char label[EXO_MAX_STR_LENGTH];
699 snprintf(label, EXO_MAX_STR_LENGTH,
"block_%d_%s", j + 1, blocks[j].exo_name);
700 pad_string(&names_buf[j * EXO_MAX_STR_LENGTH], EXO_MAX_STR_LENGTH, label);
702 stat = nc_put_var_text(ncid, var_eb_names, names_buf);
708 for (j = 0; j < num_blocks; j++) {
709 int ne = blocks[j].num_elem;
710 int nn = blocks[j].nod_per_elem;
711 int etype = blocks[j].hecmw_type;
712 int node_shift = get_node_shift(etype);
717 for (i = 0; i < ne; i++) {
718 int ei = blocks[j].elem_indices[i];
724 for (k = 0; k < nn; k++) {
729 for (k = 0; k < nn; k++) {
734 stat = nc_put_var_int(ncid, var_connect[j], conn);
741 char qa_data[1][4][EXO_MAX_STR_LENGTH];
742 time_t now = time(
NULL);
743 struct tm *t = localtime(&now);
744 char datestr[32], timestr[32];
745 strftime(datestr,
sizeof(datestr),
"%Y%m%d", t);
746 strftime(timestr,
sizeof(timestr),
"%H:%M:%S", t);
748 pad_string(qa_data[0][0], EXO_MAX_STR_LENGTH,
"FrontISTR");
749 pad_string(qa_data[0][1], EXO_MAX_STR_LENGTH,
"1.0");
750 pad_string(qa_data[0][2], EXO_MAX_STR_LENGTH, datestr);
751 pad_string(qa_data[0][3], EXO_MAX_STR_LENGTH, timestr);
752 stat = nc_put_var_text(ncid, var_qa_records, &qa_data[0][0][0]);
768 for (i = 0; i < n_node; i++) nmap[i] = i + 1;
773 for (i = 0; i < n_elem; i++) emap[i] = i + 1;
775 stat = nc_put_var_int(ncid, var_node_num_map, nmap); NCERR(stat);
776 stat = nc_put_var_int(ncid, var_elem_num_map, emap); NCERR(stat);
781 if (total_nod_var > 0) {
782 char *name_buf = (
char *)
HECMW_malloc(total_nod_var * EXO_MAX_STR_LENGTH);
783 if (name_buf ==
NULL)
786 for (i = 0; i <
data->nn_component; i++) {
787 const char **suffixes = get_comp_suffixes(
data->nn_dof[i],
data->node_label[i]);
788 for (k = 0; k <
data->nn_dof[i]; k++) {
789 char vname[EXO_MAX_STR_LENGTH];
790 if (suffixes !=
NULL) {
791 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s%s",
792 data->node_label[i], suffixes[k]);
794 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s_%d",
795 data->node_label[i], k + 1);
797 pad_string(&name_buf[vi * EXO_MAX_STR_LENGTH], EXO_MAX_STR_LENGTH, vname);
801 stat = nc_put_var_text(ncid, var_name_nod_var, name_buf);
807 if (total_elem_var > 0) {
808 char *name_buf = (
char *)
HECMW_malloc(total_elem_var * EXO_MAX_STR_LENGTH);
809 if (name_buf ==
NULL)
812 for (i = 0; i <
data->ne_component; i++) {
813 const char **suffixes = get_comp_suffixes(
data->ne_dof[i],
data->elem_label[i]);
814 for (k = 0; k <
data->ne_dof[i]; k++) {
815 char vname[EXO_MAX_STR_LENGTH];
816 if (suffixes !=
NULL) {
817 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s%s",
818 data->elem_label[i], suffixes[k]);
820 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s_%d",
821 data->elem_label[i], k + 1);
823 pad_string(&name_buf[vi * EXO_MAX_STR_LENGTH], EXO_MAX_STR_LENGTH, vname);
827 stat = nc_put_var_text(ncid, var_name_elem_var, name_buf);
833 if (total_elem_var > 0) {
834 int *tab = (
int *)
HECMW_malloc(
sizeof(
int) * num_blocks * total_elem_var);
837 for (i = 0; i < num_blocks * total_elem_var; i++) tab[i] = 1;
838 stat = nc_put_var_int(ncid, var_elem_var_tab, tab);
847 stat = nc_open(file_exo, NC_WRITE, &ncid);
856 double time_value = 0.0;
859 for (i = 0; i <
data->ng_component; i++) {
860 if (strcmp(
data->global_label[i],
"TOTALTIME") == 0) {
861 time_value =
data->global_val_item[gshift];
864 gshift +=
data->ng_dof[i];
873 size_t ts_idx = per_step ? 0 : (size_t)time_step_count;
874 stat = nc_inq_varid(ncid,
"time_whole", &varid); NCERR(stat);
875 stat = nc_put_var1_double(ncid, varid, &ts_idx, &time_value); NCERR(stat);
879 size_t ts_idx = per_step ? 0 : (size_t)time_step_count;
882 if (total_nod_var > 0) {
885 for (i = 0; i <
data->nn_component; i++) {
886 for (k = 0; k <
data->nn_dof[i]; k++) {
887 char vname[EXO_MAX_STR_LENGTH];
888 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_nod_var%d", vi + 1);
890 stat = nc_inq_varid(ncid, vname, &varid); NCERR(stat);
892 double *vals = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
895 for (j = 0; j < n_node; j++) {
896 vals[j] =
data->node_val_item[j * data_tot_n + comp_shift + k];
898 size_t start[2] = {ts_idx, 0};
899 size_t count[2] = {1, (size_t)n_node};
900 stat = nc_put_vara_double(ncid, varid, start, count, vals);
905 comp_shift +=
data->nn_dof[i];
910 if (total_elem_var > 0) {
913 for (i = 0; i <
data->ne_component; i++) {
914 for (k = 0; k <
data->ne_dof[i]; k++) {
916 for (j = 0; j < num_blocks; j++) {
917 char vname[EXO_MAX_STR_LENGTH];
918 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_elem_var%deb%d", vi + 1, j + 1);
920 stat = nc_inq_varid(ncid, vname, &varid); NCERR(stat);
922 int ne = blocks[j].num_elem;
923 double *vals = (
double *)
HECMW_malloc(
sizeof(
double) * ne);
927 for (ei_idx = 0; ei_idx < ne; ei_idx++) {
928 int ei = blocks[j].elem_indices[ei_idx];
929 vals[ei_idx] =
data->elem_val_item[ei * data_tot_e + comp_shift + k];
931 size_t start[2] = {ts_idx, 0};
932 size_t count[2] = {1, (size_t)ne};
933 stat = nc_put_vara_double(ncid, varid, start, count, vals);
939 comp_shift +=
data->ne_dof[i];
946 stat = nc_close(ncid);
950 for (j = 0; j < num_blocks; j++) {
964 char *outfile,
char *outfile1,
967 exodus_output(mesh,
data, outfile, outfile1, VIS_COMM, 0);
973 char *outfile,
char *outfile1,
976 exodus_output(mesh,
data, outfile, outfile1, VIS_COMM, 1);
988 static void exodus_stub_warning(
HECMW_Comm VIS_COMM)
994 "WARNING: output_type=EXODUS requested but FrontISTR was not\n"
995 " compiled with NetCDF support.\n"
996 " Rebuild with -DWITH_NETCDF=ON (CMake) or\n"
997 " --with-netcdf (Makefile) to enable Exodus output.\n");
1003 char *outfile,
char *outfile1,
1006 exodus_stub_warning(VIS_COMM);
1007 (void)
mesh; (void)
data; (void)outfile; (void)outfile1;
1012 char *outfile,
char *outfile1,
1015 exodus_stub_warning(VIS_COMM);
1016 (void)
mesh; (void)
data; (void)outfile; (void)outfile1;
int HECMW_Comm_rank(HECMW_Comm comm, int *rank)
int HECMW_Comm_size(HECMW_Comm comm, int *size)
#define HECMW_FILENAME_LEN
int HECMW_ctrl_make_subdir(char *filename)
struct hecmwST_local_mesh * mesh
void HECMW_exodus_output(struct hecmwST_local_mesh *mesh, struct hecmwST_result_data *data, char *outfile, char *outfile1, HECMW_Comm VIS_COMM)
void HECMW_exodus_step_output(struct hecmwST_local_mesh *mesh, struct hecmwST_result_data *data, char *outfile, char *outfile1, HECMW_Comm VIS_COMM)
#define HECMW_malloc(size)
void HECMW_vis_print_exit(char *var)
integer(kind=kint) myrank
PARALLEL EXECUTION.
long long * elem_node_index