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 blocks[j].num_elem = 0;
402 for (i = 0; i < n_elem; i++) {
404 for (j = 0; j < num_blocks; j++) {
405 if (blocks[j].hecmw_type == etype) {
406 blocks[j].elem_indices[blocks[j].num_elem] = i;
407 blocks[j].num_elem++;
419 if (per_step || time_step_count == 0) {
423 stat = nc_create(file_exo, NC_CLOBBER | NC_64BIT_OFFSET, &ncid);
425 stat = nc_set_fill(ncid, NC_NOFILL, &old_fill_mode);
432 float api_ver = EXO_API_VERSION;
433 float db_ver = EXO_DB_VERSION;
434 int word_sz = (int)
sizeof(
double);
435 int file_sz = EXO_FILE_SIZE;
436 char title[] =
"FrontISTR Exodus output";
438 stat = nc_put_att_float(ncid, NC_GLOBAL,
"api_version", NC_FLOAT, 1, &api_ver);
440 stat = nc_put_att_float(ncid, NC_GLOBAL,
"version", NC_FLOAT, 1, &db_ver);
442 stat = nc_put_att_int(ncid, NC_GLOBAL,
"floating_point_word_size", NC_INT, 1, &word_sz);
444 stat = nc_put_att_int(ncid, NC_GLOBAL,
"file_size", NC_INT, 1, &file_sz);
446 stat = nc_put_att_text(ncid, NC_GLOBAL,
"title", strlen(
title),
title);
453 int dim_len_string, dim_len_name, dim_len_line, dim_four;
454 int dim_time_step, dim_num_dim, dim_num_nodes, dim_num_elem;
458 stat = nc_def_dim(ncid,
"len_string", EXO_MAX_STR_LENGTH, &dim_len_string);
460 stat = nc_def_dim(ncid,
"len_name", EXO_MAX_STR_LENGTH, &dim_len_name);
462 stat = nc_def_dim(ncid,
"len_line", EXO_MAX_LINE_LENGTH, &dim_len_line);
464 stat = nc_def_dim(ncid,
"four", 4, &dim_four);
466 stat = nc_def_dim(ncid,
"time_step", NC_UNLIMITED, &dim_time_step);
468 stat = nc_def_dim(ncid,
"num_dim", 3, &dim_num_dim);
470 stat = nc_def_dim(ncid,
"num_nodes", (
size_t)n_node, &dim_num_nodes);
472 stat = nc_def_dim(ncid,
"num_elem", (
size_t)n_elem, &dim_num_elem);
474 stat = nc_def_dim(ncid,
"num_el_blk", (
size_t)num_blocks, &dim_num_el_blk);
478 stat = nc_def_dim(ncid,
"num_qa_rec", 1, &dim_num_qa_rec);
482 int dim_el_in_blk[MAX_ELEM_BLOCKS];
483 int dim_nod_per_el[MAX_ELEM_BLOCKS];
484 for (j = 0; j < num_blocks; j++) {
485 char dname[EXO_MAX_STR_LENGTH];
486 snprintf(dname, EXO_MAX_STR_LENGTH,
"num_el_in_blk%d", j + 1);
487 stat = nc_def_dim(ncid, dname, (
size_t)blocks[j].num_elem, &dim_el_in_blk[j]);
489 snprintf(dname, EXO_MAX_STR_LENGTH,
"num_nod_per_el%d", j + 1);
490 stat = nc_def_dim(ncid, dname, (
size_t)blocks[j].nod_per_elem, &dim_nod_per_el[j]);
495 int dim_num_nod_var = -1, dim_num_elem_var = -1;
496 if (total_nod_var > 0) {
497 stat = nc_def_dim(ncid,
"num_nod_var", (
size_t)total_nod_var, &dim_num_nod_var);
500 if (total_elem_var > 0) {
501 stat = nc_def_dim(ncid,
"num_elem_var", (
size_t)total_elem_var, &dim_num_elem_var);
509 stat = nc_def_var(ncid,
"time_whole", NC_DOUBLE, 1, &dim_time_step, &var_time_whole);
515 int var_coordx, var_coordy, var_coordz;
516 stat = nc_def_var(ncid,
"coordx", NC_DOUBLE, 1, &dim_num_nodes, &var_coordx);
518 stat = nc_def_var(ncid,
"coordy", NC_DOUBLE, 1, &dim_num_nodes, &var_coordy);
520 stat = nc_def_var(ncid,
"coordz", NC_DOUBLE, 1, &dim_num_nodes, &var_coordz);
526 int dims2[2] = {dim_num_dim, dim_len_name};
527 stat = nc_def_var(ncid,
"coor_names", NC_CHAR, 2, dims2, &var_coor_names);
534 int var_eb_status, var_eb_prop1;
535 stat = nc_def_var(ncid,
"eb_status", NC_INT, 1, &dim_num_el_blk, &var_eb_status);
537 stat = nc_def_var(ncid,
"eb_prop1", NC_INT, 1, &dim_num_el_blk, &var_eb_prop1);
539 stat = nc_put_att_text(ncid, var_eb_prop1,
"name", 2,
"ID");
545 int dims2[2] = {dim_num_el_blk, dim_len_name};
546 stat = nc_def_var(ncid,
"eb_names", NC_CHAR, 2, dims2, &var_eb_names);
551 int var_connect[MAX_ELEM_BLOCKS];
552 for (j = 0; j < num_blocks; j++) {
553 char vname[EXO_MAX_STR_LENGTH];
554 snprintf(vname, EXO_MAX_STR_LENGTH,
"connect%d", j + 1);
555 int dims2[2] = {dim_el_in_blk[j], dim_nod_per_el[j]};
556 stat = nc_def_var(ncid, vname, NC_INT, 2, dims2, &var_connect[j]);
558 stat = nc_put_att_text(ncid, var_connect[j],
"elem_type",
559 strlen(blocks[j].exo_name), blocks[j].exo_name);
568 int dims3[3] = {dim_num_qa_rec, dim_four, dim_len_string};
569 stat = nc_def_var(ncid,
"qa_records", NC_CHAR, 3, dims3, &var_qa_records);
576 int var_node_num_map, var_elem_num_map;
577 stat = nc_def_var(ncid,
"node_num_map", NC_INT, 1, &dim_num_nodes, &var_node_num_map);
579 stat = nc_def_var(ncid,
"elem_num_map", NC_INT, 1, &dim_num_elem, &var_elem_num_map);
585 int var_name_nod_var = -1;
586 int var_vals_nod[512];
587 if (total_nod_var > 0) {
588 int dims2[2] = {dim_num_nod_var, dim_len_name};
589 stat = nc_def_var(ncid,
"name_nod_var", NC_CHAR, 2, dims2, &var_name_nod_var);
592 for (i = 0; i < total_nod_var; i++) {
593 char vname[EXO_MAX_STR_LENGTH];
594 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_nod_var%d", i + 1);
595 int dims_ts_nn[2] = {dim_time_step, dim_num_nodes};
596 stat = nc_def_var(ncid, vname, NC_DOUBLE, 2, dims_ts_nn, &var_vals_nod[i]);
604 int var_name_elem_var = -1;
605 int var_vals_elem[512];
606 int var_elem_var_tab = -1;
607 if (total_elem_var > 0) {
608 int dims2[2] = {dim_num_elem_var, dim_len_name};
609 stat = nc_def_var(ncid,
"name_elem_var", NC_CHAR, 2, dims2, &var_name_elem_var);
614 int dims_tt[2] = {dim_num_el_blk, dim_num_elem_var};
615 stat = nc_def_var(ncid,
"elem_var_tab", NC_INT, 2, dims_tt, &var_elem_var_tab);
620 for (i = 0; i < total_elem_var; i++) {
621 for (j = 0; j < num_blocks; j++) {
622 char vname[EXO_MAX_STR_LENGTH];
623 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_elem_var%deb%d", i + 1, j + 1);
624 int dims_ts_eb[2] = {dim_time_step, dim_el_in_blk[j]};
625 stat = nc_def_var(ncid, vname, NC_DOUBLE, 2, dims_ts_eb,
626 &var_vals_elem[i * num_blocks + j]);
635 stat = nc_enddef(ncid);
645 double *cx = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
646 double *cy = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
647 double *cz = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
648 for (i = 0; i < n_node; i++) {
653 stat = nc_put_var_double(ncid, var_coordx, cx); NCERR(stat);
654 stat = nc_put_var_double(ncid, var_coordy, cy); NCERR(stat);
655 stat = nc_put_var_double(ncid, var_coordz, cz); NCERR(stat);
661 char names[3][EXO_MAX_STR_LENGTH];
662 pad_string(names[0], EXO_MAX_STR_LENGTH,
"x");
663 pad_string(names[1], EXO_MAX_STR_LENGTH,
"y");
664 pad_string(names[2], EXO_MAX_STR_LENGTH,
"z");
665 stat = nc_put_var_text(ncid, var_coor_names, &names[0][0]);
671 int *eb_stat = (
int *)
HECMW_malloc(
sizeof(
int) * num_blocks);
672 int *eb_ids = (
int *)
HECMW_malloc(
sizeof(
int) * num_blocks);
673 for (j = 0; j < num_blocks; j++) {
677 stat = nc_put_var_int(ncid, var_eb_status, eb_stat); NCERR(stat);
678 stat = nc_put_var_int(ncid, var_eb_prop1, eb_ids); NCERR(stat);
684 char *names_buf = (
char *)
HECMW_malloc(num_blocks * EXO_MAX_STR_LENGTH);
685 for (j = 0; j < num_blocks; j++) {
686 char label[EXO_MAX_STR_LENGTH];
687 snprintf(label, EXO_MAX_STR_LENGTH,
"block_%d_%s", j + 1, blocks[j].exo_name);
688 pad_string(&names_buf[j * EXO_MAX_STR_LENGTH], EXO_MAX_STR_LENGTH, label);
690 stat = nc_put_var_text(ncid, var_eb_names, names_buf);
696 for (j = 0; j < num_blocks; j++) {
697 int ne = blocks[j].num_elem;
698 int nn = blocks[j].nod_per_elem;
699 int etype = blocks[j].hecmw_type;
700 int node_shift = get_node_shift(etype);
703 for (i = 0; i < ne; i++) {
704 int ei = blocks[j].elem_indices[i];
710 for (k = 0; k < nn; k++) {
715 for (k = 0; k < nn; k++) {
720 stat = nc_put_var_int(ncid, var_connect[j], conn);
727 char qa_data[1][4][EXO_MAX_STR_LENGTH];
728 time_t now = time(
NULL);
729 struct tm *t = localtime(&now);
730 char datestr[32], timestr[32];
731 strftime(datestr,
sizeof(datestr),
"%Y%m%d", t);
732 strftime(timestr,
sizeof(timestr),
"%H:%M:%S", t);
734 pad_string(qa_data[0][0], EXO_MAX_STR_LENGTH,
"FrontISTR");
735 pad_string(qa_data[0][1], EXO_MAX_STR_LENGTH,
"1.0");
736 pad_string(qa_data[0][2], EXO_MAX_STR_LENGTH, datestr);
737 pad_string(qa_data[0][3], EXO_MAX_STR_LENGTH, timestr);
738 stat = nc_put_var_text(ncid, var_qa_records, &qa_data[0][0][0]);
750 for (i = 0; i < n_node; i++) nmap[i] = i + 1;
755 for (i = 0; i < n_elem; i++) emap[i] = i + 1;
757 stat = nc_put_var_int(ncid, var_node_num_map, nmap); NCERR(stat);
758 stat = nc_put_var_int(ncid, var_elem_num_map, emap); NCERR(stat);
763 if (total_nod_var > 0) {
764 char *name_buf = (
char *)
HECMW_malloc(total_nod_var * EXO_MAX_STR_LENGTH);
766 for (i = 0; i <
data->nn_component; i++) {
767 const char **suffixes = get_comp_suffixes(
data->nn_dof[i],
data->node_label[i]);
768 for (k = 0; k <
data->nn_dof[i]; k++) {
769 char vname[EXO_MAX_STR_LENGTH];
770 if (suffixes !=
NULL) {
771 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s%s",
772 data->node_label[i], suffixes[k]);
774 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s_%d",
775 data->node_label[i], k + 1);
777 pad_string(&name_buf[vi * EXO_MAX_STR_LENGTH], EXO_MAX_STR_LENGTH, vname);
781 stat = nc_put_var_text(ncid, var_name_nod_var, name_buf);
787 if (total_elem_var > 0) {
788 char *name_buf = (
char *)
HECMW_malloc(total_elem_var * EXO_MAX_STR_LENGTH);
790 for (i = 0; i <
data->ne_component; i++) {
791 const char **suffixes = get_comp_suffixes(
data->ne_dof[i],
data->elem_label[i]);
792 for (k = 0; k <
data->ne_dof[i]; k++) {
793 char vname[EXO_MAX_STR_LENGTH];
794 if (suffixes !=
NULL) {
795 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s%s",
796 data->elem_label[i], suffixes[k]);
798 snprintf(vname, EXO_MAX_STR_LENGTH,
"%s_%d",
799 data->elem_label[i], k + 1);
801 pad_string(&name_buf[vi * EXO_MAX_STR_LENGTH], EXO_MAX_STR_LENGTH, vname);
805 stat = nc_put_var_text(ncid, var_name_elem_var, name_buf);
811 if (total_elem_var > 0) {
812 int *tab = (
int *)
HECMW_malloc(
sizeof(
int) * num_blocks * total_elem_var);
813 for (i = 0; i < num_blocks * total_elem_var; i++) tab[i] = 1;
814 stat = nc_put_var_int(ncid, var_elem_var_tab, tab);
823 stat = nc_open(file_exo, NC_WRITE, &ncid);
832 double time_value = 0.0;
835 for (i = 0; i <
data->ng_component; i++) {
836 if (strcmp(
data->global_label[i],
"TOTALTIME") == 0) {
837 time_value =
data->global_val_item[gshift];
840 gshift +=
data->ng_dof[i];
849 size_t ts_idx = per_step ? 0 : (size_t)time_step_count;
850 stat = nc_inq_varid(ncid,
"time_whole", &varid); NCERR(stat);
851 stat = nc_put_var1_double(ncid, varid, &ts_idx, &time_value); NCERR(stat);
855 size_t ts_idx = per_step ? 0 : (size_t)time_step_count;
858 if (total_nod_var > 0) {
861 for (i = 0; i <
data->nn_component; i++) {
862 for (k = 0; k <
data->nn_dof[i]; k++) {
863 char vname[EXO_MAX_STR_LENGTH];
864 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_nod_var%d", vi + 1);
866 stat = nc_inq_varid(ncid, vname, &varid); NCERR(stat);
868 double *vals = (
double *)
HECMW_malloc(
sizeof(
double) * n_node);
869 for (j = 0; j < n_node; j++) {
870 vals[j] =
data->node_val_item[j * data_tot_n + comp_shift + k];
872 size_t start[2] = {ts_idx, 0};
873 size_t count[2] = {1, (size_t)n_node};
874 stat = nc_put_vara_double(ncid, varid, start, count, vals);
879 comp_shift +=
data->nn_dof[i];
884 if (total_elem_var > 0) {
887 for (i = 0; i <
data->ne_component; i++) {
888 for (k = 0; k <
data->ne_dof[i]; k++) {
890 for (j = 0; j < num_blocks; j++) {
891 char vname[EXO_MAX_STR_LENGTH];
892 snprintf(vname, EXO_MAX_STR_LENGTH,
"vals_elem_var%deb%d", vi + 1, j + 1);
894 stat = nc_inq_varid(ncid, vname, &varid); NCERR(stat);
896 int ne = blocks[j].num_elem;
897 double *vals = (
double *)
HECMW_malloc(
sizeof(
double) * ne);
899 for (ei_idx = 0; ei_idx < ne; ei_idx++) {
900 int ei = blocks[j].elem_indices[ei_idx];
901 vals[ei_idx] =
data->elem_val_item[ei * data_tot_e + comp_shift + k];
903 size_t start[2] = {ts_idx, 0};
904 size_t count[2] = {1, (size_t)ne};
905 stat = nc_put_vara_double(ncid, varid, start, count, vals);
911 comp_shift +=
data->ne_dof[i];
918 stat = nc_close(ncid);
922 for (j = 0; j < num_blocks; j++) {
936 char *outfile,
char *outfile1,
939 exodus_output(mesh,
data, outfile, outfile1, VIS_COMM, 0);
945 char *outfile,
char *outfile1,
948 exodus_output(mesh,
data, outfile, outfile1, VIS_COMM, 1);
960 static void exodus_stub_warning(
HECMW_Comm VIS_COMM)
966 "WARNING: output_type=EXODUS requested but FrontISTR was not\n"
967 " compiled with NetCDF support.\n"
968 " Rebuild with -DWITH_NETCDF=ON (CMake) or\n"
969 " --with-netcdf (Makefile) to enable Exodus output.\n");
975 char *outfile,
char *outfile1,
978 exodus_stub_warning(VIS_COMM);
979 (void)
mesh; (void)
data; (void)outfile; (void)outfile1;
984 char *outfile,
char *outfile1,
987 exodus_stub_warning(VIS_COMM);
988 (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