Example #1
0
int ex_set_max_name_length(int exoid, int length)
{
  char errmsg[MAX_ERR_LENGTH];
  if (length <= 0) {
    exerrval = NC_EMAXNAME;
    snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: Max name length must be positive.");
    ex_err("ex_set_max_name_length", errmsg, exerrval);
    return (EX_FATAL);
  }
  if (length > NC_MAX_NAME) {
    exerrval = NC_EMAXNAME;
    snprintf(errmsg, MAX_ERR_LENGTH,
             "ERROR: Max name length (%d) exceeds netcdf max name size (%d).", length, NC_MAX_NAME);
    ex_err("ex_set_max_name_length", errmsg, exerrval);
    return (EX_FATAL);
  }
  else {
    ex_set_option(exoid, EX_OPT_MAX_NAME_LENGTH, length);
  }
  return EX_NOERR;
}
Example #2
0
int main (int argc, char **argv)
{
   int exoid, num_dim, num_nodes, num_elem, num_elem_blk;
   int num_elem_in_block[10], num_nodes_per_elem[10];
   int num_face_in_sset[10], num_nodes_in_nset[10];
   int num_node_sets, num_side_sets, error;
   int i, j, k, m, *elem_map, *connect;
   int node_list[100],elem_list[100],side_list[100];
   int ebids[10], ssids[10], nsids[10];
   int  num_qa_rec, num_info;
   int num_glo_vars, num_nod_vars, num_ele_vars, num_sset_vars, num_nset_vars;
   int *truth_tab;
   int whole_time_step, num_time_steps;
   int CPU_word_size,IO_word_size;
   int prop_array[2];

   float *glob_var_vals, *nodal_var_vals, *elem_var_vals;
   float *sset_var_vals, *nset_var_vals;
   float time_value;
   float x[100], y[100], z[100];
   float attrib[1], dist_fact[100];
   char *coord_names[3], *qa_record[2][4], *info[3], *variable_names[3];
   char *block_names[10], *nset_names[10], *sset_names[10];
   char *prop_names[2], *attrib_names[2];
   char *title = "This is a test";
   ex_opts (EX_VERBOSE | EX_ABORT );

/* Specify compute and i/o word size */

   CPU_word_size = 0;                   /* sizeof(float) */
   IO_word_size = 4;                    /* (4 bytes) */

/* create EXODUS II file */

   
   exoid = ex_create ("test.exo",       /* filename path */
                       EX_CLOBBER,      /* create mode */
                       &CPU_word_size,  /* CPU float word size in bytes */
                       &IO_word_size);  /* I/O float word size in bytes */
   printf ("after ex_create for test.exo, exoid = %d\n", exoid);
   printf (" cpu word size: %d io word size: %d\n",CPU_word_size,IO_word_size);

   ex_set_option(exoid, EX_OPT_MAX_NAME_LENGTH, 127); /* Using long names */

   /* initialize file with parameters */

   num_dim = 3;
   num_nodes = 33;
   num_elem = 7;
   num_elem_blk = 7;
   num_node_sets = 2;
   num_side_sets = 5;

   
   error = ex_put_init (exoid, title, num_dim, num_nodes, num_elem,
                        num_elem_blk, num_node_sets, num_side_sets);

   printf ("after ex_put_init, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

/* write nodal coordinates values and names to database */

/* Quad #1 */
   x[0] = 0.0; y[0] = 0.0; z[0] = 0.0;
   x[1] = 1.0; y[1] = 0.0; z[1] = 0.0;
   x[2] = 1.0; y[2] = 1.0; z[2] = 0.0;
   x[3] = 0.0; y[3] = 1.0; z[3] = 0.0;

/* Quad #2 */
   x[4]  =  1.0; y[4]  =  0.0; z[4]  =  0.0;
   x[5]  =  2.0; y[5]  =  0.0; z[5]  =  0.0;
   x[6]  =  2.0; y[6]  =  1.0; z[6]  =  0.0;
   x[7]  =  1.0; y[7]  =  1.0; z[7]  =  0.0;

/* Hex #1 */
   x[8]  =  0.0; y[8]  =  0.0; z[8]  =  0.0;
   x[9]  = 10.0; y[9]  =  0.0; z[9]  =  0.0;
   x[10] = 10.0; y[10] =  0.0; z[10] =-10.0;
   x[11] =  1.0; y[11] =  0.0; z[11] =-10.0;
   x[12] =  1.0; y[12] = 10.0; z[12] =  0.0;
   x[13] = 10.0; y[13] = 10.0; z[13] =  0.0;
   x[14] = 10.0; y[14] = 10.0; z[14] =-10.0;
   x[15] =  1.0; y[15] = 10.0; z[15] =-10.0;

/* Tetra #1 */
   x[16] =  0.0; y[16] =  0.0; z[16] =  0.0;
   x[17] =  1.0; y[17] =  0.0; z[17] =  5.0;
   x[18] = 10.0; y[18] =  0.0; z[18] =  2.0;
   x[19] =  7.0; y[19] =  5.0; z[19] =  3.0;

/* Wedge #1 */
   x[20] =  3.0; y[20] =  0.0; z[20] =  6.0;
   x[21] =  6.0; y[21] =  0.0; z[21] =  0.0;
   x[22] =  0.0; y[22] =  0.0; z[22] =  0.0;
   x[23] =  3.0; y[23] =  2.0; z[23] =  6.0;
   x[24] =  6.0; y[24] =  2.0; z[24] =  2.0;
   x[25] =  0.0; y[25] =  2.0; z[25] =  0.0;

/* Tetra #2 */
   x[26] =  2.7; y[26] =  1.7; z[26] =  2.7;
   x[27] =  6.0; y[27] =  1.7; z[27] =  3.3;
   x[28] =  5.7; y[28] =  1.7; z[28] =  1.7;
   x[29] =  3.7; y[29] =  0.0; z[29] =  2.3;

/* 3d Tri */
   x[30] =  0.0; y[30] =  0.0; z[30] =  0.0;
   x[31] = 10.0; y[31] =  0.0; z[31] =  0.0;
   x[32] = 10.0; y[32] = 10.0; z[32] = 10.0;

   error = ex_put_coord (exoid, x, y, z);
   printf ("after ex_put_coord, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   /*                0        1         2         3         4         5         6     */
   /*                1234567890123456789012345678901234567890123456789012345678901234 */
   coord_names[0] = "X coordinate name that is padded to be longer than 32 characters";
   coord_names[1] = "Y coordinate name that is padded to be longer than 32 characters";
   coord_names[2] = "Z coordinate name that is padded to be longer than 32 characters";

   error = ex_put_coord_names (exoid, coord_names);
   printf ("after ex_put_coord_names, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   /* Add nodal attributes */
   error = ex_put_attr_param(exoid, EX_NODAL, 0, 2);
   printf ("after ex_put_attr_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   error = ex_put_one_attr(exoid, EX_NODAL, 0, 1, x);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   error = ex_put_one_attr(exoid, EX_NODAL, 0, 2, y);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   {
     attrib_names[0] = "Node_attr_1";
     attrib_names[1] = "Node_attr_2";
     error = ex_put_attr_names (exoid, EX_NODAL, 0, attrib_names);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
   }

/* write element order map */

   elem_map = (int *) calloc(num_elem, sizeof(int));

   for (i=1; i<=num_elem; i++)
   {
      elem_map[i-1] = i;
   }

   error = ex_put_map (exoid, elem_map);
   printf ("after ex_put_map, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   free (elem_map);


/* write element block parameters */

   /*                0        1         2         3         4         5         6     */
   /*                1234567890123456789012345678901234567890123456789012345678901234 */
   block_names[0] = "Very long name for block_1 that exceeds 32 characters";
   block_names[1] = "Very long name for block_2 that exceeds 32 characters";
   block_names[2] = "Very long name for block_3 that exceeds 32 characters";
   block_names[3] = "Very long name for block_4 that exceeds 32 characters";
   block_names[4] = "Very long name for block_5 that exceeds 32 characters";
   block_names[5] = "Very long name for block_6 that exceeds 32 characters";
   block_names[6] = "Very long name for block_7 that exceeds 32 characters";
   num_elem_in_block[0] = 1;
   num_elem_in_block[1] = 1;
   num_elem_in_block[2] = 1;
   num_elem_in_block[3] = 1;
   num_elem_in_block[4] = 1;
   num_elem_in_block[5] = 1;
   num_elem_in_block[6] = 1;

   num_nodes_per_elem[0] = 4; /* elements in block #1 are 4-node quads  */
   num_nodes_per_elem[1] = 4; /* elements in block #2 are 4-node quads  */
   num_nodes_per_elem[2] = 8; /* elements in block #3 are 8-node hexes  */
   num_nodes_per_elem[3] = 4; /* elements in block #4 are 4-node tetras */
   num_nodes_per_elem[4] = 6; /* elements in block #5 are 6-node wedges */
   num_nodes_per_elem[5] = 8; /* elements in block #6 are 8-node tetras */
   num_nodes_per_elem[6] = 3; /* elements in block #7 are 3-node tris   */

   ebids[0] = 10;
   ebids[1] = 11;
   ebids[2] = 12;
   ebids[3] = 13;
   ebids[4] = 14;
   ebids[5] = 15;
   ebids[6] = 16;

   error = ex_put_elem_block (exoid, ebids[0], "quad", num_elem_in_block[0],
                              num_nodes_per_elem[0], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_block (exoid, ebids[1], "quad", num_elem_in_block[1],
                               num_nodes_per_elem[1], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_block (exoid, ebids[2], "hex", num_elem_in_block[2],
                               num_nodes_per_elem[2], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_block (exoid, ebids[3], "tetra", num_elem_in_block[3],
                               num_nodes_per_elem[3], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_block (exoid, ebids[4], "wedge", num_elem_in_block[4],
                               num_nodes_per_elem[4], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_block (exoid, ebids[5], "tetra", num_elem_in_block[5],
                               num_nodes_per_elem[5], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_block (exoid, ebids[6], "tri", num_elem_in_block[6],
                               num_nodes_per_elem[6], 1);
   printf ("after ex_put_elem_block, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   /* Write element block names */
   error = ex_put_names(exoid, EX_ELEM_BLOCK, block_names);
   printf ("after ex_put_names, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
/* write element block properties */

   /*               0        1         2         3         4         5         6     */
   /*               1234567890123456789012345678901234567890123456789012345678901234 */
   prop_names[0] = "MATERIAL_PROPERTY_LONG_NAME_32CH";
   prop_names[1] = "DENSITY";
   error = ex_put_prop_names(exoid,EX_ELEM_BLOCK,2,prop_names);
   printf ("after ex_put_prop_names, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[0], prop_names[0], 10);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[1], prop_names[0], 20);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[2], prop_names[0], 30);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[3], prop_names[0], 40);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[4], prop_names[0], 50);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[5], prop_names[0], 60);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_ELEM_BLOCK, ebids[6], prop_names[0], 70);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }


/* write element connectivity */

   connect = (int *) calloc(8, sizeof(int));
   connect[0] = 1; connect[1] = 2; connect[2] = 3; connect[3] = 4;

   error = ex_put_elem_conn (exoid, ebids[0], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   connect[0] = 5; connect[1] = 6; connect[2] = 7; connect[3] = 8;

   error = ex_put_elem_conn (exoid, ebids[1], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   connect[0] = 9; connect[1] = 10; connect[2] = 11; connect[3] = 12;
   connect[4] = 13; connect[5] = 14; connect[6] = 15; connect[7] = 16;

   error = ex_put_elem_conn (exoid, ebids[2], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   connect[0] = 17; connect[1] = 18; connect[2] = 19; connect[3] = 20;

   error = ex_put_elem_conn (exoid, ebids[3], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   connect[0] = 21; connect[1] = 22; connect[2] = 23;
   connect[3] = 24; connect[4] = 25; connect[5] = 26;

   error = ex_put_elem_conn (exoid, ebids[4], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   connect[0] = 17; connect[1] = 18; connect[2] = 19; connect[3] = 20;
   connect[4] = 27; connect[5] = 28; connect[6] = 30; connect[7] = 29;

   error = ex_put_elem_conn (exoid, ebids[5], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   connect[0] = 31; connect[1] = 32; connect[2] = 33;

   error = ex_put_elem_conn (exoid, ebids[6], connect);
   printf ("after ex_put_elem_conn, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   free (connect);


/* write element block attributes */

   attrib[0] = 3.14159;
   error = ex_put_elem_attr (exoid, ebids[0], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_attr (exoid, ebids[0], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   attrib[0] = 6.14159;
   error = ex_put_elem_attr (exoid, ebids[1], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_attr (exoid, ebids[2], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_attr (exoid, ebids[3], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_attr (exoid, ebids[4], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_attr (exoid, ebids[5], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_elem_attr (exoid, ebids[6], attrib);
   printf ("after ex_put_elem_attr, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   /*                 0        1         2         3         4         5         6     */
   /*                 1234567890123456789012345678901234567890123456789012345678901234 */
   attrib_names[0] = "The name for the attribute representing the shell thickness";
   for (i=0; i < 7; i++) {
     error = ex_put_elem_attr_names (exoid, ebids[i], attrib_names);
     printf ("after ex_put_elem_attr_names, error = %d\n", error);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
   }

/* write individual node sets */


   num_nodes_in_nset[0] = 5;
   num_nodes_in_nset[1] = 3;

   nsids[0] = 20;
   nsids[1] = 21;

   error = ex_put_node_set_param (exoid, nsids[0], 5, 5);
   printf ("after ex_put_node_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   node_list[0] = 10; node_list[1] = 11; node_list[2] = 12; 
   node_list[3] = 13; node_list[4] = 14; 

   dist_fact[0] = 1.0; dist_fact[1] = 2.0; dist_fact[2] = 3.0;
   dist_fact[3] = 4.0; dist_fact[4] = 5.0;

   error = ex_put_node_set (exoid, nsids[0], node_list);
   printf ("after ex_put_node_set, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_node_set_dist_fact (exoid, nsids[0], dist_fact);
   printf ("after ex_put_node_set_dist_fact, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   error = ex_put_node_set_param (exoid, nsids[1], 3, 3);
   printf ("after ex_put_node_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   node_list[0] = 20; node_list[1] = 21; node_list[2] = 22; 

   dist_fact[0] = 1.1; dist_fact[1] = 2.1; dist_fact[2] = 3.1;

   error = ex_put_node_set (exoid, nsids[1], node_list);
   printf ("after ex_put_node_set, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_node_set_dist_fact (exoid, nsids[1], dist_fact);
   printf ("after ex_put_node_set_dist_fact, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   /* Write node set names */
   nset_names[0] = "nset_1";
   nset_names[1] = "nset_2";

   error = ex_put_names(exoid, EX_NODE_SET, nset_names);
   printf ("after ex_put_names, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   error = ex_put_prop(exoid, EX_NODE_SET, nsids[0], "FACE", 4);
   printf ("after ex_put_prop, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_NODE_SET, nsids[1], "FACE", 5);
   printf ("after ex_put_prop, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   prop_array[0] = 1000;
   prop_array[1] = 2000;

   error = ex_put_prop_array(exoid, EX_NODE_SET, "VELOCITY", prop_array);
   printf ("after ex_put_prop_array, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   /* Add nodeset attributes */
   error = ex_put_attr_param(exoid, EX_NODE_SET, nsids[0], 1);
   printf ("after ex_put_attr_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   error = ex_put_attr(exoid, EX_NODE_SET, nsids[0], x);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   {
     attrib_names[0] = "Nodeset_attribute";
     error = ex_put_attr_names (exoid, EX_NODE_SET, nsids[0], attrib_names);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
   }

/* write individual side sets */
   num_face_in_sset[0] =  2;
   num_face_in_sset[1] =  2;
   num_face_in_sset[2] =  7;
   num_face_in_sset[3] =  8;
   num_face_in_sset[4] = 10;
   
   ssids[0] = 30;
   ssids[1] = 31;
   ssids[2] = 32;
   ssids[3] = 33;
   ssids[4] = 34;

   /* side set #1  - quad */

   error = ex_put_side_set_param (exoid, ssids[0], 2, 4);
   printf ("after ex_put_side_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   elem_list[0] = 2; elem_list[1] = 2;

   side_list[0] = 4; side_list[1] = 2;

   dist_fact[0] = 30.0; dist_fact[1] = 30.1; dist_fact[2] = 30.2;
   dist_fact[3] = 30.3;

   error = ex_put_side_set (exoid, 30, elem_list, side_list);
   printf ("after ex_put_side_set, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_side_set_dist_fact (exoid, 30, dist_fact);
   printf ("after ex_put_side_set_dist_fact, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   /* side set #2  - quad, spanning 2 elements  */

   error = ex_put_side_set_param (exoid, 31, 2, 4);
   printf ("after ex_put_side_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   elem_list[0] = 1; elem_list[1] = 2;

   side_list[0] = 2; side_list[1] = 3;

   dist_fact[0] = 31.0; dist_fact[1] = 31.1; dist_fact[2] = 31.2;
   dist_fact[3] = 31.3;

   error = ex_put_side_set (exoid, 31, elem_list, side_list);
   printf ("after ex_put_side_set, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_side_set_dist_fact (exoid, 31, dist_fact);
   printf ("after ex_put_side_set_dist_fact, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   /* side set #3  - hex */

   error = ex_put_side_set_param (exoid, 32, 7, 0);
   printf ("after ex_put_side_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   elem_list[0] = 3; elem_list[1] = 3;
   elem_list[2] = 3; elem_list[3] = 3;
   elem_list[4] = 3; elem_list[5] = 3;
   elem_list[6] = 3;

   side_list[0] = 5; side_list[1] = 3;
   side_list[2] = 3; side_list[3] = 2;
   side_list[4] = 4; side_list[5] = 1;
   side_list[6] = 6;

   error = ex_put_side_set (exoid, 32, elem_list, side_list);
   printf ("after ex_put_side_set, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   /* side set #4  - tetras */

   error = ex_put_side_set_param (exoid, 33, 8, 0);
   printf ("after ex_put_side_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   elem_list[0] = 4; elem_list[1] = 4;
   elem_list[2] = 4; elem_list[3] = 4;
   elem_list[4] = 6; elem_list[5] = 6;
   elem_list[6] = 6; elem_list[7] = 6;

   side_list[0] = 1; side_list[1] = 2;
   side_list[2] = 3; side_list[3] = 4;
   side_list[4] = 1; side_list[5] = 2;
   side_list[6] = 3; side_list[7] = 4;

   error = ex_put_side_set (exoid, 33, elem_list, side_list);
   printf ("after ex_put_side_set, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   /* side set #5  - wedges and tris */

   error = ex_put_side_set_param (exoid, 34, 10, 0);
   printf ("after ex_put_side_set_param, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   elem_list[0] = 5; elem_list[1] = 5;
   elem_list[2] = 5; elem_list[3] = 5;
   elem_list[4] = 5; elem_list[5] = 7;
   elem_list[6] = 7; elem_list[7] = 7;
   elem_list[8] = 7; elem_list[9] = 7;

   side_list[0] = 1; side_list[1] = 2;
   side_list[2] = 3; side_list[3] = 4;
   side_list[4] = 5; side_list[5] = 1;
   side_list[6] = 2; side_list[7] = 3;
   side_list[8] = 4; side_list[9] = 5;

   error = ex_put_side_set (exoid, 34, elem_list, side_list);
   printf ("after ex_put_side_set, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   /* Write side set names */
   sset_names[0] = "sset_1";
   sset_names[1] = "sset_2";
   sset_names[2] = "sset_3";
   sset_names[3] = "sset_4";
   sset_names[4] = "sset_5";

   error = ex_put_names(exoid, EX_SIDE_SET, sset_names);
   printf ("after ex_put_names, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   
   error = ex_put_prop(exoid, EX_SIDE_SET, 30, "COLOR", 100);
   printf ("after ex_put_prop, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_prop(exoid, EX_SIDE_SET, 31, "COLOR", 101);
   printf ("after ex_put_prop, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }


/* write QA records; test empty and just blank-filled records */

   num_qa_rec = 2;


   qa_record[0][0] = "TESTWT";
   qa_record[0][1] = "testwt";
   qa_record[0][2] = "07/07/93";
   qa_record[0][3] = "15:41:33";
   qa_record[1][0] = "";
   qa_record[1][1] = "                            ";
   qa_record[1][2] = "";
   qa_record[1][3] = "                        ";

   error = ex_put_qa (exoid, num_qa_rec, qa_record);
   printf ("after ex_put_qa, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }


/* write information records; test empty and just blank-filled records */

   num_info = 3;


   info[0] = "This is the first information record.";
   info[1] = "";
   info[2] = "                                     ";

   error = ex_put_info (exoid, num_info, info);
   printf ("after ex_put_info, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }



/* write results variables parameters and names */

   num_glo_vars = 1;

   variable_names[0] = "glo_vars";

   error = ex_put_variable_param (exoid, EX_GLOBAL, num_glo_vars);
   printf ("after ex_put_variable_param, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_variable_names (exoid, EX_GLOBAL, num_glo_vars, variable_names);
   printf ("after ex_put_variable_names, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }



   num_nod_vars = 2;
   /*              0        1         2         3         4         5         6     */
   /*              1234567890123456789012345678901234567890123456789012345678901234 */
   variable_names[0] = "node_variable_a_somewhat_long_name_0";
   variable_names[1] = "node_variable_a_much_longer_name_that_is_not_too_long_name";

   error = ex_put_variable_param (exoid, EX_NODAL, num_nod_vars);
   printf ("after ex_put_variable_param, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_variable_names (exoid, EX_NODAL, num_nod_vars, variable_names);
   printf ("after ex_put_variable_names, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }


   num_ele_vars = 3;

   /*              0        1         2         3         4         5         6     */
   /*              1234567890123456789012345678901234567890123456789012345678901234 */
   variable_names[0] = "the_stress_on_the_elements_in_this_block_that_are_active_now";
   variable_names[1] = "ele_var1";
   variable_names[2] = "ele_var2";

   error = ex_put_variable_param (exoid, EX_ELEM_BLOCK, num_ele_vars);
   printf ("after ex_put_variable_param, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   error = ex_put_variable_names (exoid, EX_ELEM_BLOCK, num_ele_vars, variable_names);
   printf ("after ex_put_variable_names, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   {
     num_nset_vars = 3;
     
     variable_names[0] = "ns_var0";
     variable_names[1] = "ns_var1";
     variable_names[2] = "ns_var2";
     
     error = ex_put_variable_param (exoid, EX_NODE_SET, num_nset_vars);
     printf ("after ex_put_variable_param, error = %d\n", error);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
     
     error = ex_put_variable_names (exoid, EX_NODE_SET, num_nset_vars, variable_names);
     printf ("after ex_put_variable_names, error = %d\n", error);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
   }
   
   {
     num_sset_vars = 3;

     variable_names[0] = "ss_var0";
     variable_names[1] = "ss_var1";
     variable_names[2] = "ss_var2";
     
     error = ex_put_variable_param (exoid, EX_SIDE_SET, num_sset_vars);
     printf ("after ex_put_variable_param, error = %d\n", error);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
     
     error = ex_put_variable_names (exoid, EX_SIDE_SET, num_sset_vars, variable_names);
     printf ("after ex_put_variable_names, error = %d\n", error);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
   }



/* write element variable truth table */

   truth_tab = (int *) calloc ((num_elem_blk*num_ele_vars), sizeof(int));

   k = 0;
   for (i=0; i<num_elem_blk; i++)
   {
      for (j=0; j<num_ele_vars; j++)
      {
         truth_tab[k++] = 1;
      }
   }

   error = ex_put_elem_var_tab (exoid, num_elem_blk, num_ele_vars, truth_tab);
   printf ("after ex_put_elem_var_tab, error = %d\n", error);

   if (error) {
     ex_close (exoid);
     exit(-1);
   }

   free (truth_tab);


/* for each time step, write the analysis results;
 * the code below fills the arrays glob_var_vals, 
 * nodal_var_vals, and elem_var_vals with values for debugging purposes;
 * obviously the analysis code will populate these arrays
 */

   whole_time_step = 1;
   num_time_steps = 10;

   glob_var_vals = (float *) calloc (num_glo_vars, CPU_word_size);
   nodal_var_vals = (float *) calloc (num_nodes, CPU_word_size);
   elem_var_vals = (float *) calloc (4, CPU_word_size);
   sset_var_vals = (float *) calloc (10, CPU_word_size);
   nset_var_vals = (float *) calloc (10, CPU_word_size);
   
   for (i=0; i<num_time_steps; i++)
   {
     time_value = (float)(i+1)/100.;

/* write time value */

     error = ex_put_time (exoid, whole_time_step, &time_value);
     printf ("after ex_put_time, error = %d\n", error);

     if (error) {
       ex_close (exoid);
       exit(-1);
     }

/* write global variables */

     for (j=0; j<num_glo_vars; j++)
     {
       glob_var_vals[j] = (float)(j+2) * time_value;
     }

     error = ex_put_glob_vars (exoid, whole_time_step, num_glo_vars, 
                               glob_var_vals);
     printf ("after ex_put_glob_vars, error = %d\n", error);

     if (error) {
       ex_close (exoid);
       exit(-1);
     }

/* write nodal variables */

     for (k=1; k<=num_nod_vars; k++)
     {
       for (j=0; j<num_nodes; j++)
       {
         nodal_var_vals[j] = (float)k + ((float)(j+1) * time_value);
       }

       error = ex_put_nodal_var (exoid, whole_time_step, k, num_nodes,
                                 nodal_var_vals);
       printf ("after ex_put_nodal_var, error = %d\n", error);
       if (error) {
         ex_close (exoid);
         exit(-1);
       }

     }

/* write element variables */

     for (k=1; k<=num_ele_vars; k++)
     {
       for (j=0; j<num_elem_blk; j++)
       {
         for (m=0; m<num_elem_in_block[j]; m++)
         {
           elem_var_vals[m] = (float)(k+1) + (float)(j+2) + 
                              ((float)(m+1)*time_value);
           /* printf("elem_var_vals[%d]: %f\n",m,elem_var_vals[m]); */
         }
         error = ex_put_elem_var (exoid, whole_time_step, k, ebids[j],
                                  num_elem_in_block[j], elem_var_vals);
         printf ("after ex_put_elem_var, error = %d\n", error);
         if (error) {
           ex_close (exoid);
           exit(-1);
         }
       }
     }

/* write sideset variables */

     for (k=1; k<=num_sset_vars; k++)
     {
       for (j=0; j<num_side_sets; j++)
       {
         for (m=0; m<num_face_in_sset[j]; m++)
         {
           sset_var_vals[m] = (float)(k+2) + (float)(j+3) + 
                              ((float)(m+1)*time_value);
           /* printf("sset_var_vals[%d]: %f\n",m,sset_var_vals[m]); */
         }
         error = ex_put_sset_var (exoid, whole_time_step, k, ssids[j],
                                  num_face_in_sset[j], sset_var_vals);
         printf ("after ex_put_sset_var, error = %d\n", error);
         if (error) {
           ex_close (exoid);
           exit(-1);
         }
       }
     }

/* write nodeset variables */

     for (k=1; k<=num_nset_vars; k++)
     {
       for (j=0; j<num_node_sets; j++)
       {
         for (m=0; m<num_nodes_in_nset[j]; m++)
         {
           nset_var_vals[m] = (float)(k+3) + (float)(j+4) + 
                              ((float)(m+1)*time_value);
           /* printf("nset_var_vals[%d]: %f\n",m,nset_var_vals[m]); */
         }
         error = ex_put_nset_var (exoid, whole_time_step, k, nsids[j],
                                  num_nodes_in_nset[j], nset_var_vals);
         printf ("after ex_put_nset_var, error = %d\n", error);
         if (error) {
           ex_close (exoid);
           exit(-1);
         }
       }
     }

     whole_time_step++;

/* update the data file; this should be done at the end of every time step
 * to ensure that no data is lost if the analysis dies
 */
     error = ex_update (exoid);
     printf ("after ex_update, error = %d\n", error);
     if (error) {
       ex_close (exoid);
       exit(-1);
     }
   }
   free(glob_var_vals);
   free(nodal_var_vals);
   free(elem_var_vals);
   free(sset_var_vals);
   free(nset_var_vals);


/* close the EXODUS files
 */
   error = ex_close (exoid);
   printf ("after ex_close, error = %d\n", error);
   if (error) {
     ex_close (exoid);
     exit(-1);
   }
   return 0;
}
int write_nemesis(std::string &nemI_out_file,
                  Machine_Description* machine,
                  Problem_Description* problem,
                  Mesh_Description<INT>* mesh,
                  LB_Description<INT>* lb,
                  Sphere_Info* sphere)
{
  int     exoid;
  char    title[MAX_LINE_LENGTH+1], method1[MAX_LINE_LENGTH+1];
  char    method2[MAX_LINE_LENGTH+1];

  int cpu_ws = sizeof(float);
  int io_ws  = sizeof(float);

  printf("Outputting load balance to file %s\n", nemI_out_file.c_str());

  /* Create the load balance file */
  /* Attempt to create a netcdf4-format file; if it fails, then assume
     that the netcdf library does not support that mode and fall back
     to classic netcdf3 format.  If that fails, issue an error and
     return failure.
  */
  int mode3 = EX_CLOBBER;
  int mode4 = mode3|EX_NETCDF4|EX_NOCLASSIC|problem->int64db|problem->int64api;

  ex_opts(EX_DEFAULT); // Eliminate misleading error if the first ex_create fails, but the second succeeds.
  if((exoid=ex_create(nemI_out_file.c_str(), mode4, &cpu_ws, &io_ws)) < 0) {
    /* If int64api or int64db non-zero, then netcdf-4 format is required, so
       fail now...
    */
    if (problem->int64db|problem->int64api) {
      Gen_Error(0, "fatal: failed to create Nemesis netcdf-4 file");
      return 0;
    }
    if((exoid=ex_create(nemI_out_file.c_str(), mode3, &cpu_ws, &io_ws)) < 0) {
      Gen_Error(0, "fatal: failed to create Nemesis file");
      return 0;
    }
  }
  ON_BLOCK_EXIT(ex_close, exoid);
  
  /* Set the error reporting value */
  if (error_lev > 1)
    ex_opts(EX_VERBOSE | EX_DEBUG);
  else
    ex_opts(EX_VERBOSE);

  /* Enable compression (if netcdf-4) */
  ex_set_option(exoid, EX_OPT_COMPRESSION_LEVEL, 1);
  ex_set_option(exoid, EX_OPT_COMPRESSION_SHUFFLE, 1);

  /* Create the title */
  if(problem->type == NODAL)
    strcpy(method1, "nodal");
  else
    strcpy(method1, "elemental");

  sprintf(title, "nem_slice %s load balance file", method1);

  strcpy(method1, "method1: ");
  strcpy(method2, "method2: ");

  switch(lb->type)
    {
    case MULTIKL:
      strcat(method1, "Multilevel-KL decomposition");
      strcat(method2, "With Kernighan-Lin refinement");
      break;
    case SPECTRAL:
      strcat(method1, "Spectral decomposition");
      break;
    case INERTIAL:
      strcat(method1, "Inertial decomposition");
      break;
    case ZPINCH:
      strcat(method1, "ZPINCH decomposition");
      break;
    case BRICK:
      strcat(method1, "BRICK decomposition");
      break;
    case ZOLTAN_RCB:
      strcat(method1, "RCB decomposition");
      break;
    case ZOLTAN_RIB:
      strcat(method1, "RIB decomposition");
      break;
    case ZOLTAN_HSFC:
      strcat(method1, "HSFC decomposition");
      break;
    case LINEAR:
      strcat(method1, "Linear decomposition");
      break;
    case RANDOM:
      strcat(method1, "Random decomposition");
      break;
    case SCATTERED:
      strcat(method1, "Scattered decomposition");
      break;
    }

  if(lb->refine == KL_REFINE && lb->type != MULTIKL)
    strcat(method2, "with Kernighan-Lin refinement");
  else if(lb->type != MULTIKL)
    strcat(method2, "no refinement");

  switch(lb->num_sects)
    {
    case 1:
      strcat(method1, " via bisection");
      break;
    case 2:
      strcat(method1, " via quadrasection");
      break;
    case 3:
      strcat(method1, " via octasection");
      break;
    }

  /* Do some sorting */
  for(int proc=0; proc < machine->num_procs; proc++) {

    /* Sort node maps */
    gds_qsort(TOPTR(lb->int_nodes[proc]), lb->int_nodes[proc].size());
    if(problem->type == NODAL) {
      sort2(lb->ext_nodes[proc].size(), TOPTR(lb->ext_nodes[proc]),
	    TOPTR(lb->ext_procs[proc]));
    }

    /* Sort element maps */
    gds_qsort(TOPTR(lb->int_elems[proc]), lb->int_elems[proc].size());
  }

  /* Output the info records */
  char *info[3];
  info[0] = title;
  info[1] = method1;
  info[2] = method2;

  if(ex_put_info(exoid, 3, info) < 0)
    Gen_Error(0, "warning: output of info records failed");

  /* Generate a QA record for the utility */
  time_t time_val = time(nullptr);
  char *ct_ptr   = asctime(localtime(&time_val));
  char tm_date[30];
  strcpy(tm_date, ct_ptr);

  /* Break string with null characters */
  tm_date[3]  = '\0';
  tm_date[7]  = '\0';
  tm_date[10] = '\0';
  tm_date[19] = '\0';

  char    qa_date[15], qa_time[10], qa_name[MAX_STR_LENGTH];
  char    qa_vers[10];

  sprintf(qa_date, "%s %s %s", &tm_date[8], &tm_date[4], &tm_date[20]);
  sprintf(qa_time, "%s", &tm_date[11]);
  strcpy(qa_name, UTIL_NAME);
  strcpy(qa_vers, ELB_VERSION);

  if(qa_date[strlen(qa_date)-1] == '\n')
    qa_date[strlen(qa_date)-1] = '\0';

  char **lqa_record = (char **)array_alloc(1, 4, sizeof(char *));
  for(int i2=0; i2 < 4; i2++)
    lqa_record[i2] = (char *)array_alloc(1, MAX_STR_LENGTH+1, sizeof(char));

  strcpy(lqa_record[0], qa_name);
  strcpy(lqa_record[1], qa_vers);
  strcpy(lqa_record[2], qa_date);
  strcpy(lqa_record[3], qa_time);

  printf("QA Record:\n");
  for(int i2=0; i2 < 4; i2++) {
    printf("\t%s\n", lqa_record[i2]);
  }

  if(ex_put_qa(exoid, 1, (char *(*)[4]) &lqa_record[0]) < 0) {
    Gen_Error(0, "fatal: unable to output QA records");
    return 0;
  }

  /* free up memory */
  for(int i2=0; i2 < 4; i2++)
    free(lqa_record[i2]);

  free(lqa_record);

  /* Output the the initial Nemesis global information */
  if(ex_put_init_global(exoid, mesh->num_nodes, mesh->num_elems,
                        mesh->num_el_blks, 0, 0) < 0) {
    Gen_Error(0, "fatal: failed to output initial Nemesis parameters");
    return 0;
  }
  
  /* Set up dummy arrays for ouput */
  std::vector<INT> num_nmap_cnts(machine->num_procs);
  std::vector<INT> num_emap_cnts(machine->num_procs);
  
  if(problem->type == NODAL) {
    /* need to check and make sure that there really are comm maps */
    for(int cnt=0; cnt < machine->num_procs; cnt++) {
      if (!lb->bor_nodes[cnt].empty())
	num_nmap_cnts[cnt] = 1;
    }
  }
  else {	/* Elemental load balance */
    if(((problem->num_vertices)-(sphere->num)) > 0) {
      /* need to check and make sure that there really are comm maps */
      for(int cnt=0; cnt < machine->num_procs; cnt++) {
        if (!lb->bor_nodes[cnt].empty()) num_nmap_cnts[cnt] = 1;
      }
      for(int cnt=0; cnt < machine->num_procs; cnt++) {
        if (!lb->bor_elems[cnt].empty()) num_emap_cnts[cnt] = 1;
      }
    }
  }

  if(ex_put_init_info(exoid, machine->num_procs, machine->num_procs, (char*)"s") < 0) {
    Gen_Error(0, "fatal: unable to output init info");
    return 0;
  }

  // Need to create 5 arrays with the sizes of lb->int_nodes[i].size()...
  {
    std::vector<INT> ins(machine->num_procs);
    std::vector<INT> bns(machine->num_procs);
    std::vector<INT> ens(machine->num_procs);
    std::vector<INT> ies(machine->num_procs);
    std::vector<INT> bes(machine->num_procs);

    for (int iproc = 0; iproc < machine->num_procs; iproc++) {
      ins[iproc] = lb->int_nodes[iproc].size();
      bns[iproc] = lb->bor_nodes[iproc].size();
      ens[iproc] = lb->ext_nodes[iproc].size();
      ies[iproc] = lb->int_elems[iproc].size();
      bes[iproc] = lb->bor_elems[iproc].size();
    }

    if(ex_put_loadbal_param_cc(exoid,
			       TOPTR(ins), TOPTR(bns), TOPTR(ens),
			       TOPTR(ies), TOPTR(bes), TOPTR(num_nmap_cnts),
			       TOPTR(num_emap_cnts)) < 0)
      {
	Gen_Error(0, "fatal: unable to output load-balance parameters");
	return 0;
      }
  }

  if(problem->type == NODAL)		/* Nodal load balance output */
    {
      /* Set up for the concatenated communication map parameters */
      std::vector<INT> node_proc_ptr(machine->num_procs+1);
      std::vector<INT> node_cmap_ids_cc(machine->num_procs);
      std::vector<INT> node_cmap_cnts_cc(machine->num_procs);

      node_proc_ptr[0] = 0;
      for(int proc=0; proc < machine->num_procs; proc++) {
	node_proc_ptr[proc+1]   = node_proc_ptr[proc] + 1;
	node_cmap_cnts_cc[proc] = lb->ext_nodes[proc].size();
	node_cmap_ids_cc[proc]  = 1;
      }

      /* Output the communication map parameters */
      if(ex_put_cmap_params_cc(exoid, TOPTR(node_cmap_ids_cc),
			       TOPTR(node_cmap_cnts_cc),
			       TOPTR(node_proc_ptr), nullptr, nullptr, nullptr) < 0)
	{
	  Gen_Error(0, "fatal: unable to output communication map parameters");
	  return 0;
	}

      /* Output the node and element maps */
      for(int proc=0; proc < machine->num_procs; proc++) {
	/* Output the nodal map */
	if(ex_put_processor_node_maps(exoid,
				      TOPTR(lb->int_nodes[proc]),
				      TOPTR(lb->bor_nodes[proc]),
				      TOPTR(lb->ext_nodes[proc]), proc) < 0)
	  {
	    Gen_Error(0, "fatal: failed to output node map");
	    return 0;
	  }

	/* Output the elemental map */
	if(ex_put_processor_elem_maps(exoid, TOPTR(lb->int_elems[proc]), nullptr, proc) < 0)
	  {
	    Gen_Error(0, "fatal: failed to output element map");
	    return 0;
	  }

	/*
	 * Reorder the nodal communication maps so that they are ordered
	 * by processor and then by global ID.
	 */

	/* This is a 2-key sort */
	qsort2(TOPTR(lb->ext_procs[proc]), TOPTR(lb->ext_nodes[proc]), lb->ext_nodes[proc].size());

	/* Output the nodal communication map */
	if(ex_put_node_cmap(exoid, 1,
			    TOPTR(lb->ext_nodes[proc]),
			    TOPTR(lb->ext_procs[proc]), proc) < 0)
	  {
	    Gen_Error(0, "fatal: failed to output nodal communication map");
	    return 0;
	  }

      } /* End "for(proc=0; proc < machine->num_procs; proc++)" */
    }
  else if(problem->type == ELEMENTAL)	/* Elemental load balance output */
    {
      std::vector<INT> node_proc_ptr(machine->num_procs+1);
      std::vector<INT> node_cmap_ids_cc(machine->num_procs);
      std::vector<INT> node_cmap_cnts_cc(machine->num_procs);

      node_proc_ptr[0] = 0;
      for(int proc=0; proc < machine->num_procs; proc++) {
	node_proc_ptr[proc+1]   = node_proc_ptr[proc] + 1;

	node_cmap_cnts_cc[proc] = 0;
	for(size_t cnt=0; cnt < lb->bor_nodes[proc].size(); cnt++)
	  node_cmap_cnts_cc[proc] += lb->born_procs[proc][cnt].size();

	node_cmap_ids_cc[proc]  = 1;
      }

      std::vector<INT> elem_proc_ptr(machine->num_procs+1);
      std::vector<INT> elem_cmap_ids_cc(machine->num_procs);
      std::vector<INT> elem_cmap_cnts_cc(machine->num_procs);

      elem_proc_ptr[0] = 0;
      for(int proc=0; proc < machine->num_procs; proc++) {
	elem_proc_ptr[proc+1]   = elem_proc_ptr[proc] + 1;
	elem_cmap_cnts_cc[proc] = lb->e_cmap_elems[proc].size();
	elem_cmap_ids_cc[proc]  = 1;
      }

      /* Output the communication map parameters */
      if(ex_put_cmap_params_cc(exoid, TOPTR(node_cmap_ids_cc), TOPTR(node_cmap_cnts_cc),
			       TOPTR(node_proc_ptr), TOPTR(elem_cmap_ids_cc),
			       TOPTR(elem_cmap_cnts_cc), TOPTR(elem_proc_ptr)) < 0)
	{
	  Gen_Error(0, "fatal: unable to output communication map parameters");
	  return 0;
	}

      /* Output the node and element maps */
      for(int proc=0; proc < machine->num_procs; proc++)
	{
	  /* Output the nodal map */
	  if(ex_put_processor_node_maps(exoid,
					TOPTR(lb->int_nodes[proc]),
					TOPTR(lb->bor_nodes[proc]),
					nullptr, proc) < 0)
	    {
	      Gen_Error(0, "fatal: failed to output node map");
	      return 0;
	    }

	  /* Output the elemental map */
	  if(ex_put_processor_elem_maps(exoid,
					TOPTR(lb->int_elems[proc]),
					TOPTR(lb->bor_elems[proc]),
					proc) < 0)
	    {
	      Gen_Error(0, "fatal: failed to output element map");
	      return 0;
	    }

	  /*
	   * Build a nodal communication map from the list of border nodes
	   * and their associated processors and side IDs.
	   */
	  size_t nsize = 0;
	  for(size_t cnt=0; cnt < lb->bor_nodes[proc].size(); cnt++)
	    nsize += lb->born_procs[proc][cnt].size();

	  if (nsize > 0) {
	    std::vector<INT> n_cmap_nodes(nsize);
	    std::vector<INT> n_cmap_procs(nsize);

	    size_t cnt3 = 0;
	    for(size_t cnt=0; cnt < lb->bor_nodes[proc].size(); cnt++) {
	      for(size_t cnt2=0; cnt2 < lb->born_procs[proc][cnt].size(); cnt2++) {
		n_cmap_nodes[cnt3]   = lb->bor_nodes[proc][cnt];
		n_cmap_procs[cnt3++] = lb->born_procs[proc][cnt][cnt2];
	      }
	    }

	    /*
	     * Reorder the nodal communication maps so that they are ordered
	     * by processor and then by global ID.
	     */
	    /* This is a 2-key sort */
	    qsort2(TOPTR(n_cmap_procs), TOPTR(n_cmap_nodes), cnt3);

	    /* Output the nodal communication map */
	    if(ex_put_node_cmap(exoid, 1, TOPTR(n_cmap_nodes), TOPTR(n_cmap_procs), proc) < 0) {
	      Gen_Error(0, "fatal: unable to output nodal communication map");
	      return 0;
	    }
	  } /* End "if (nsize > 0)" */

	    /* Output the elemental communication map */
	  if(!lb->e_cmap_elems[proc].empty()) {
	    if(ex_put_elem_cmap(exoid, 1,
				TOPTR(lb->e_cmap_elems[proc]),
				TOPTR(lb->e_cmap_sides[proc]),
				TOPTR(lb->e_cmap_procs[proc]), proc) < 0)
	      {
		Gen_Error(0, "fatal: unable to output elemental communication map");
		return 0;
	      }
	  }

	} /* End "for(proc=0; proc < machine->num_procs; proc++)" */

    }
  return 1;
} /*------------------------End write_nemesis()------------------------------*/
Example #4
0
void write_exo_mesh(int debug, char *file_name, INT map_origin, INT num_nodes, INT num_elements,
                    INT num_domains, INT num_nodal_fields, INT num_global_fields,
                    INT num_element_fields, INT num_timesteps, realtyp *x, realtyp *y, realtyp *z,
                    INT *connect, int compression_level, int shuffle, int int64bit)
{
  int  CPU_word_size = sizeof(realtyp);
  int  IO_word_size  = sizeof(realtyp);
  int  exoid, err, num_dim, num_elem_blk, num_node_sets, num_side_sets;
  INT  i, j, t, index, loc_num_elements, loc_num_nodes, len_connect;
  INT *elem_map = NULL, *node_map = NULL, *domain_connect = NULL, *loc_connect = NULL;
  int *elem_var_tab;
  INT  accum_num_elements = 0;
  INT  loc_node_size      = -1;

  realtyp *loc_xcoords = NULL;
  realtyp *loc_ycoords = NULL;
  realtyp *loc_zcoords = NULL;
  realtyp *globals     = NULL;

  char   temporary_name[MAX_STRING_LEN];
  char **var_name;

  accum_num_elements = 0;
  for (i = 0; i < num_domains; i++) {
    int mymode = EX_MAPS_INT64_API | EX_BULK_INT64_API | EX_IDS_INT64_API;
    if (int64bit) {
      mymode |= EX_MAPS_INT64_DB | EX_BULK_INT64_DB | EX_IDS_INT64_DB;
    }

    /* create the EXODUSII file */
    get_file_name(file_name, "e", i, num_domains, NULL, temporary_name);

    exoid = ex_create(temporary_name, EX_CLOBBER | mymode, &CPU_word_size, &IO_word_size);

    if (exoid < 0) {
      fprintf(stderr, "after ex_create, error = %d\n", exoid);
      exit(-1);
    }

    ex_set_option(exoid, EX_OPT_COMPRESSION_LEVEL, compression_level);
    ex_set_option(exoid, EX_OPT_COMPRESSION_SHUFFLE, shuffle);

    if (num_domains > 1) {
      /* Determine local number of elements */
      if (num_elements < num_domains) {
        fprintf(stderr, "number of elements is less than number of domains.\n");
        if (i < num_elements)
          loc_num_elements = 1;
        else
          loc_num_elements = 0;
      }
      else {
        loc_num_elements = num_elements / num_domains;
        if (i < (num_elements % num_domains))
          loc_num_elements++;
      }

      len_connect = NUM_NODES_PER_ELEM * loc_num_elements;

      /* malloc things we need */

      if (i == 0) { /* first time through; max size arrays occur on
                       first iteration */
        elem_map       = malloc(loc_num_elements * sizeof(INT));
        domain_connect = malloc(len_connect * sizeof(INT));
        loc_connect    = malloc(len_connect * sizeof(INT));
        node_map       = malloc(num_nodes * sizeof(INT));
      }

      /* Create element local/global map */
      create_elem_map(loc_num_elements, accum_num_elements, elem_map, map_origin);

      /* Extract current domain's connectivity, referencing global node ids */
      extract_connect(accum_num_elements, loc_num_elements, elem_map, connect, domain_connect,
                      map_origin);

      accum_num_elements += loc_num_elements;

      /* The local/global node map is just the current domain's connectivity,
         sorted with duplicate entries removed */
      create_node_map(num_nodes, len_connect, domain_connect, node_map, &loc_num_nodes, map_origin);

      /* Using local/global node map, convert the domain connectivity
         (referencing global node ids) to local connectivity (referencing
         local node ids) */

      create_local_connect(node_map, loc_num_nodes, len_connect, domain_connect, loc_connect,
                           map_origin);
    }
    else {
      loc_num_elements = num_elements;
      loc_num_nodes    = num_nodes;
    }

    if (debug) {
      fprintf(stderr, "\n\n\n");

      fprintf(stderr, "\n domain: %" PRId64 "\n", i);
      fprintf(stderr, "\n loc_num_elements: %" PRId64 "\n", loc_num_elements);
      fprintf(stderr, "\n loc_num_nodes: %" PRId64 "\n", loc_num_nodes);
    }

    num_dim       = 3;
    num_elem_blk  = 1;
    num_node_sets = 0;
    num_side_sets = 0;

    err = ex_put_init(exoid, "This is an EXODUSII performance test.", num_dim, loc_num_nodes,
                      loc_num_elements, num_elem_blk, num_node_sets, num_side_sets);

    if (err) {
      fprintf(stderr, "after ex_put_init, error = %d\n", err);
      ex_close(exoid);
      exit(-1);
    }

    /* Extract the local x and y coordinates */
    if (num_domains > 1) {
      if (loc_num_nodes > loc_node_size) {
        loc_xcoords   = realloc(loc_xcoords, loc_num_nodes * sizeof(realtyp));
        loc_ycoords   = realloc(loc_ycoords, loc_num_nodes * sizeof(realtyp));
        loc_zcoords   = realloc(loc_zcoords, loc_num_nodes * sizeof(realtyp));
        loc_node_size = loc_num_nodes;
      }

      for (j = 0; j < loc_num_nodes; j++) {
        index          = node_map[j] - map_origin;
        loc_xcoords[j] = x[index];
        loc_ycoords[j] = y[index];
        loc_zcoords[j] = z[index];
      }

      err = ex_put_coord(exoid, loc_xcoords, loc_ycoords, loc_zcoords);
    }
    else {
      err = ex_put_coord(exoid, x, y, z);
    }
    if (err) {
      fprintf(stderr, "after ex_put_coord, error = %d\n", err);
      ex_close(exoid);
      exit(-1);
    }
    if (debug) {
      fprintf(stderr, "\tCoordinates output.\n");
    }
#if 1
    {
      INT   ids[1] = {EBLK_ID};
      INT   num_elem_per_block[1];
      char *names[1] = {"hex"};
      INT   num_node_per_elem[1];
      INT   num_attr_per_block[1];
      int   write_map       = num_domains > 1 ? EX_TRUE : EX_FALSE;
      num_elem_per_block[0] = loc_num_elements;
      num_node_per_elem[0]  = NUM_NODES_PER_ELEM;
      num_attr_per_block[0] = 0;
      err = ex_put_concat_elem_block(exoid, ids, names, num_elem_per_block, num_node_per_elem,
                                     num_attr_per_block, write_map);
    }
#else
    err = ex_put_elem_block(exoid, 10000000000, "hex", loc_num_elements, NUM_NODES_PER_ELEM, 0);
#endif

    if (err) {
      fprintf(stderr, "after ex_put_elem_block, error = %d\n", err);
      ex_close(exoid);
      exit(-1);
    }

    if (num_domains > 1) {
      err = ex_put_elem_conn(exoid, EBLK_ID, loc_connect);
    }
    else {
      err = ex_put_elem_conn(exoid, EBLK_ID, connect);
    }

    if (err) {
      fprintf(stderr, "after ex_put_elem_conn, error = %d\n", err);
      ex_close(exoid);
      exit(-1);
    }

    if (debug) {
      fprintf(stderr, "\tConnectivity output.\n");
    }
    /* write out element and node maps */

    if (num_domains > 1) {
      err = ex_put_id_map(exoid, EX_NODE_MAP, node_map);

      if (err) {
        fprintf(stderr, "after ex_put_id_map, error = %d\n", err);
        ex_close(exoid);
        exit(-1);
      }

      err = ex_put_id_map(exoid, EX_ELEM_MAP, elem_map);

      if (err) {
        fprintf(stderr, "after ex_put_id_map, error = %d\n", err);
        ex_close(exoid);
        exit(-1);
      }

      if (debug) {
        fprintf(stderr, "\tMaps output.\n");
      }
    }

    /* write out simulated results fields;
       we'll just write out the x coordinate field 'num_nodal_fields' times */
    if (loc_num_nodes < loc_num_elements) {
      fprintf(stderr, "INTERNAL ERROR: Programmer assumed number of nodes > number of elements, "
                      "but that is not true.\n");
      ex_close(exoid);
      exit(-1);
    }

    if (num_element_fields > 0) {
      elem_var_tab = malloc(num_element_fields * sizeof(int));
      for (j            = 0; j < num_element_fields; j++)
        elem_var_tab[j] = 1;
    }
    else {
      elem_var_tab = 0;
    }
    err = ex_put_all_var_param(exoid, num_global_fields, num_nodal_fields, num_element_fields,
                               elem_var_tab, 0, 0, 0, 0);
    if (err) {
      fprintf(stderr, "after ex_put_all_var_param, error = %d\n", err);
      ex_close(exoid);
      exit(-1);
    }

    if (num_nodal_fields > 0) {

      var_name = malloc(num_nodal_fields * sizeof(char *));
      for (j = 0; j < num_nodal_fields; j++) {
        var_name[j] = malloc((MAX_STRING_LEN + 1) * sizeof(char));
        sprintf(var_name[j], "node_field_%" PRId64, j + 1);
      }
      err = ex_put_variable_names(exoid, EX_NODAL, num_nodal_fields, var_name);
      for (j = 0; j < num_nodal_fields; j++) {
        free(var_name[j]);
      }
      free(var_name);
    }

    if (num_global_fields > 0) {
      globals  = malloc(num_global_fields * sizeof(realtyp));
      var_name = malloc(num_global_fields * sizeof(char *));
      for (j = 0; j < num_global_fields; j++) {
        var_name[j] = malloc((MAX_STRING_LEN + 1) * sizeof(char));
        sprintf(var_name[j], "global_field_%" PRId64, j + 1);
        globals[j] = j;
      }
      err = ex_put_variable_names(exoid, EX_GLOBAL, num_global_fields, var_name);
      for (j = 0; j < num_global_fields; j++) {
        free(var_name[j]);
      }
      free(var_name);
    }

    if (num_element_fields > 0) {
      free(elem_var_tab);
      var_name = malloc(num_element_fields * sizeof(char *));
      for (j = 0; j < num_element_fields; j++) {
        var_name[j] = malloc((MAX_STRING_LEN + 1) * sizeof(char));
        sprintf(var_name[j], "element_field_%" PRId64, j + 1);
      }
      err = ex_put_variable_names(exoid, EX_ELEM_BLOCK, num_element_fields, var_name);
      for (j = 0; j < num_element_fields; j++) {
        free(var_name[j]);
      }
      free(var_name);
    }

    if (num_nodal_fields + num_global_fields + num_element_fields > 0) {
      fprintf(stderr, "Domain %" PRId64 "/%" PRId64 ", Writing Timestep: ", i + 1, num_domains);
      for (t = 0; t < num_timesteps; t++) {
        realtyp time = t;
        ex_put_time(exoid, t + 1, &time);
        fprintf(stderr, "%" PRId64 ", ", t + 1);
        if (num_global_fields > 0) {
          err = ex_put_var(exoid, t + 1, EX_GLOBAL, 1, 0, num_global_fields, globals);
          if (err) {
            fprintf(stderr, "after ex_put_global_var, error = %d\n", err);
            ex_close(exoid);
            exit(-1);
          }
        }
        for (j = 0; j < num_nodal_fields; j++) {
          err = ex_put_var(exoid, t + 1, EX_NODAL, j + 1, 0, loc_num_nodes, x);
          if (err) {
            fprintf(stderr, "after ex_put_nodal_var, error = %d\n", err);
            ex_close(exoid);
            exit(-1);
          }
        }
        for (j = 0; j < num_element_fields; j++) {
          err = ex_put_var(exoid, t + 1, EX_ELEM_BLOCK, j + 1, EBLK_ID, loc_num_elements, x);
          if (err) {
            fprintf(stderr, "after ex_put_element_var, error = %d\n", err);
            ex_close(exoid);
            exit(-1);
          }
        }
      }
      fprintf(stderr, "\n");
    }

    err = ex_close(exoid);

    if (err) {
      fprintf(stderr, "after ex_close, error = %d\n", err);
      exit(-1);
    }
    if (debug) {
      fprintf(stderr, "\tFile written.\n");
    }
  }

  /*
   * Free Memory
   */

  if (num_domains > 1) {
    free(domain_connect);
    free(elem_map);
    free(loc_connect);
    free(loc_xcoords);
    free(loc_ycoords);
    free(loc_zcoords);
    free(node_map);
  }
  if (num_global_fields > 0)
    free(globals);
}
bool Excn::ExodusFile::create_output(const SystemInterface& si, int cycle)
  // Create output file...
{
  std::string curdir = si.cwd();
  std::string file_prefix = si.basename();
  std::string output_suffix = si.output_suffix();

  outputFilename_ = file_prefix;
  if (!output_suffix.empty()) {
    outputFilename_ += "." + output_suffix;
  }

  if(curdir.length() && outputFilename_[0] != '/') {
    outputFilename_ = curdir + "/" + outputFilename_;
  }

  if (si.subcycle() > 1) {
    Excn::ParallelDisks::Create_IO_Filename(outputFilename_,
					    cycle, si.subcycle());
  }

  // See if output file should be opened in netcdf4 format...
  // Did user specify it via -netcdf4 or -large_model argument...
  int mode = 0;
  
  if (si.use_netcdf4()) {
    mode |= EX_NETCDF4;
  } else if (ex_large_model(fileids_[0]) == 1) {
    mode |= EX_LARGE_MODEL;
  }
  
  mode |= mode64bit_;
  
  if (si.int64()) {
    mode |= EX_ALL_INT64_DB;
    mode |= EX_ALL_INT64_API;
  }

  if (si.append()) {
    std::cout << "Output:   '" << outputFilename_ << "' (appending)" << std::endl;
    float version = 0.0;
    mode |= EX_WRITE;
    outputId_ = ex_open(outputFilename_.c_str(), mode, 
			&cpuWordSize_, &ioWordSize_, &version);
  } else {
    mode |= EX_CLOBBER;
    if (si.compress_data() > 0) {
      // Force netcdf-4 if compression is specified...
      mode |= EX_NETCDF4;
    }
    std::cout << "Output:   '" << outputFilename_ << "'" << std::endl;
    outputId_ = ex_create(outputFilename_.c_str(), mode,
			  &cpuWordSize_, &ioWordSize_);
  }
  if (outputId_ < 0) {
    std::cerr << "Cannot open file '" << outputFilename_ << "'" << std::endl;
    return false;
  }

  if (si.compress_data() > 0) {
    ex_set_option(outputId_, EX_OPT_COMPRESSION_LEVEL, si.compress_data());
    ex_set_option(outputId_, EX_OPT_COMPRESSION_SHUFFLE, 1);
  }

  // EPU Can add a name of "processor_id_epu" which is 16 characters long.
  // Make sure maximumNameLength_ is at least that long...
  
  if (maximumNameLength_ < 16)
    maximumNameLength_ = 16;
  ex_set_option(outputId_, EX_OPT_MAX_NAME_LENGTH, maximumNameLength_);

  int int_size = si.int64() ? 8 : 4;
  std::cout << "IO Word sizes: "
	    << ioWordSize_ << " bytes floating point and "
	    << int_size << " bytes integer.\n";
  return true;
}