Example #1
0
int read_exoII_file(int Proc,
                    int Num_Proc,
                    PROB_INFO_PTR prob,
                    PARIO_INFO_PTR pio_info,
                    MESH_INFO_PTR mesh)
{
#ifndef ZOLTAN_NEMESIS
  Gen_Error(0, "Fatal:  Nemesis requested but not linked with driver.");
  return 0;

#else /* ZOLTAN_NEMESIS */
  /* Local declarations. */
  char  *yo = "read_exoII_mesh";
  char   par_nem_fname[FILENAME_MAX+1], title[MAX_LINE_LENGTH+1];
  char   cmesg[256];

  float  ver;

  int    i, pexoid, cpu_ws = 0, io_ws = 0;
  int   *nnodes = NULL, *etypes = NULL;
#ifdef DEBUG_EXO
  int    j, k, elem;
#endif
  FILE  *fdtmp;

/***************************** BEGIN EXECUTION ******************************/

  DEBUG_TRACE_START(Proc, yo);

  /* since this is a test driver, set error reporting in exodus */
  ex_opts(EX_VERBOSE | EX_DEBUG);

  /* generate the parallel filename for this processor */
  gen_par_filename(pio_info->pexo_fname, par_nem_fname, pio_info, Proc,
                   Num_Proc);

  /* 
   * check whether parallel file exists.  do the check with fopen 
   * as ex_open coredumps on the paragon when files do not exist.
   */

  if ((fdtmp = fopen(par_nem_fname, "r")) == NULL) {
    sprintf(cmesg,"fatal: parallel Exodus II file %s does not exist",
            par_nem_fname);
    Gen_Error(0, cmesg);
    return 0;
  }
  else
    fclose(fdtmp);

  /*
   * now open the existing parallel file using Exodus calls.
   */

  if ((pexoid = ex_open(par_nem_fname, EX_READ, &cpu_ws, &io_ws,
                        &ver)) < 0) {
    sprintf(cmesg,"fatal: could not open parallel Exodus II file %s",
            par_nem_fname);
    Gen_Error(0, cmesg);
    return 0;
  }

  /* and get initial information */
  if (ex_get_init(pexoid, title, &(mesh->num_dims),
                  &(mesh->num_nodes), &(mesh->num_elems),
                  &(mesh->num_el_blks), &(mesh->num_node_sets),
                  &(mesh->num_side_sets)) < 0) {
    Gen_Error(0, "fatal: Error returned from ex_get_init");
    return 0;
  }


  /* alocate some memory for the element blocks */
  mesh->data_type = MESH;
  mesh->vwgt_dim = 1;  /* One weight for now. */
  mesh->ewgt_dim = 1;  /* One weight for now. */
  mesh->eb_etypes = (int *) malloc (5 * mesh->num_el_blks * sizeof(int));
  if (!mesh->eb_etypes) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  mesh->eb_ids = mesh->eb_etypes + mesh->num_el_blks;
  mesh->eb_cnts = mesh->eb_ids + mesh->num_el_blks;
  mesh->eb_nnodes = mesh->eb_cnts + mesh->num_el_blks;
  mesh->eb_nattrs = mesh->eb_nnodes + mesh->num_el_blks;

  mesh->eb_names = (char **) malloc (mesh->num_el_blks * sizeof(char *));
  if (!mesh->eb_names) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }

  mesh->hindex = (int *) malloc(sizeof(int));
  mesh->hindex[0] = 0;

  if (ex_get_elem_blk_ids(pexoid, mesh->eb_ids) < 0) {
    Gen_Error(0, "fatal: Error returned from ex_get_elem_blk_ids");
    return 0;
  }

  /* allocate temporary storage for items needing global reduction.   */
  /* nemesis does not store most element block info about blocks for  */
  /* which the processor owns no elements.                            */
  /* we, however, use this information in migration, so we need to    */
  /* accumulate it for all element blocks.    kdd 2/2001              */

  if (mesh->num_el_blks > 0) {
    nnodes = (int *) malloc(2 * mesh->num_el_blks * sizeof(int));
    if (!nnodes) {
      Gen_Error(0, "fatal: insufficient memory");
      return 0;
    }
    etypes = nnodes + mesh->num_el_blks;
  }

  /* get the element block information */
  for (i = 0; i < mesh->num_el_blks; i++) {

    /* allocate space for name */
    mesh->eb_names[i] = (char *) malloc((MAX_STR_LENGTH+1) * sizeof(char));
    if (!mesh->eb_names[i]) {
      Gen_Error(0, "fatal: insufficient memory");
      return 0;
    }

    if (ex_get_elem_block(pexoid, mesh->eb_ids[i], mesh->eb_names[i],
                          &(mesh->eb_cnts[i]), &(nnodes[i]),
                          &(mesh->eb_nattrs[i])) < 0) {
      Gen_Error(0, "fatal: Error returned from ex_get_elem_block");
      return 0;
    }

    if (mesh->eb_cnts[i] > 0) {
      if ((etypes[i] =  (int) get_elem_type(mesh->eb_names[i],
                                            nnodes[i],
                                            mesh->num_dims)) == E_TYPE_ERROR) {
        Gen_Error(0, "fatal: could not get element type");
        return 0;
      }
    }
    else etypes[i] = (int) NULL_EL;
  }

  /* Perform reduction on necessary fields of element blocks.  kdd 2/2001 */
  MPI_Allreduce(nnodes, mesh->eb_nnodes, mesh->num_el_blks, MPI_INT, MPI_MAX, 
                MPI_COMM_WORLD);
  MPI_Allreduce(etypes, mesh->eb_etypes, mesh->num_el_blks, MPI_INT, MPI_MIN, 
                MPI_COMM_WORLD);
  for (i = 0; i < mesh->num_el_blks; i++) {
    strcpy(mesh->eb_names[i], get_elem_name(mesh->eb_etypes[i]));
  }
  free(nnodes);

  /*
   * allocate memory for the elements
   * allocate a little extra for element migration latter
   */
  mesh->elem_array_len = mesh->num_elems + 5;
  mesh->elements = (ELEM_INFO_PTR) malloc (mesh->elem_array_len 
                                         * sizeof(ELEM_INFO));
  if (!(mesh->elements)) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }

  /*
   * intialize all of the element structs as unused by
   * setting the globalID to -1
   */
  for (i = 0; i < mesh->elem_array_len; i++) 
    initialize_element(&(mesh->elements[i]));

  /* read the information for the individual elements */
  if (!read_elem_info(pexoid, Proc, prob, mesh)) {
    Gen_Error(0, "fatal: Error returned from read_elem_info");
    return 0;
  }

  /* read the communication information */
  if (!read_comm_map_info(pexoid, Proc, prob, mesh)) {
    Gen_Error(0, "fatal: Error returned from read_comm_map_info");
    return 0;
  }

  /* Close the parallel file */
  if(ex_close (pexoid) < 0) {
    Gen_Error(0, "fatal: Error returned from ex_close");
    return 0;
  }

  /* print out the distributed mesh */
  if (Debug_Driver > 3)
    print_distributed_mesh(Proc, Num_Proc, mesh);

  DEBUG_TRACE_END(Proc, yo);
  return 1;

#endif /* ZOLTAN_NEMESIS */
}
Example #2
0
void exodus_file_write_mesh(exodus_file_t* file,
                            fe_mesh_t* mesh)
{
  ASSERT(file->writing);

  // See whether we have polyhedral blocks, and whether the non-polyhedral
  // blocks have supported element types.
  int num_blocks = fe_mesh_num_blocks(mesh);
  bool is_polyhedral = false;
  int pos = 0;
  char* block_name;
  fe_block_t* block;
  while (fe_mesh_next_block(mesh, &pos, &block_name, &block))
  {
    fe_mesh_element_t elem_type = fe_block_element_type(block);
    if (elem_type == FE_POLYHEDRON)
    {
      is_polyhedral = true;
      break;
    }
    else if (elem_type != FE_INVALID)
    {
      // Check the number of nodes for the element.
      if (!element_is_supported(elem_type, fe_block_num_element_nodes(block, 0)))
        polymec_error("exodus_file_write_mesh: Element type in block %s has invalid number of nodes.", block_name);
    }
    else
      polymec_error("exodus_file_write_mesh: Invalid element type for block %s.", block_name);
  }

  // Write out information about elements, faces, edges, nodes.
  file->num_nodes = fe_mesh_num_nodes(mesh);
  ex_init_params params;
  strcpy(params.title, file->title);
  params.num_dim = 3;
  params.num_nodes = file->num_nodes;
  int num_edges = fe_mesh_num_edges(mesh);
  params.num_edge = num_edges;
  params.num_edge_blk = 0;
  int num_faces = fe_mesh_num_faces(mesh);
  params.num_face = num_faces;
  params.num_face_blk = (is_polyhedral) ? 1 : 0;
  int num_elem = fe_mesh_num_elements(mesh);
  params.num_elem = num_elem;
  params.num_elem_blk = num_blocks;
  params.num_elem_sets = file->num_elem_sets = fe_mesh_num_element_sets(mesh);
  params.num_face_sets = file->num_face_sets = fe_mesh_num_face_sets(mesh);
  params.num_edge_sets = file->num_edge_sets = fe_mesh_num_edge_sets(mesh);
  params.num_node_sets = file->num_node_sets = fe_mesh_num_node_sets(mesh);
  params.num_side_sets = file->num_side_sets = fe_mesh_num_side_sets(mesh);
  params.num_elem_maps = 0;
  params.num_face_maps = 0;
  params.num_edge_maps = 0;
  params.num_node_maps = 0;
  ex_put_init_ext(file->ex_id, &params);

  // If we have any polyhedral element blocks, we write out a single face 
  // block that incorporates all of the polyhedral elements.
  if (is_polyhedral)
  {
    // Generate face->node connectivity information.
    int num_pfaces = fe_mesh_num_faces(mesh);
    int face_node_size = 0;
    int num_face_nodes[num_pfaces];
    for (int f = 0; f < num_pfaces; ++f)
    {
      int num_nodes = fe_mesh_num_face_nodes(mesh, f);
      num_face_nodes[f] = num_nodes;
      face_node_size += num_nodes;
    }
    int* face_nodes = polymec_malloc(sizeof(int) * face_node_size);
    int offset = 0;
    for (int f = 0; f < num_pfaces; ++f)
    {
      fe_mesh_get_face_nodes(mesh, f, &face_nodes[offset]);
      offset += num_face_nodes[f];
    }
    for (int i = 0; i < face_node_size; ++i)
      face_nodes[i] += 1;

    // Write an "nsided" face block.
    ex_put_block(file->ex_id, EX_FACE_BLOCK, 1, "nsided",
                 num_pfaces, face_node_size, 0, 0, 0);
    ex_put_name(file->ex_id, EX_FACE_BLOCK, 1, "face_block");
    ex_put_conn(file->ex_id, EX_FACE_BLOCK, 1, face_nodes, NULL, NULL);

    // Clean up.
    polymec_free(face_nodes);

    // Number of nodes per face.
    ex_put_entity_count_per_polyhedra(file->ex_id, EX_FACE_BLOCK, 
                                      1, num_face_nodes); 
  }

  // Go over the element blocks and write out the data.
  pos = 0;
  while (fe_mesh_next_block(mesh, &pos, &block_name, &block))
  {
    int elem_block = pos;
    int num_e = fe_block_num_elements(block);
    fe_mesh_element_t elem_type = fe_block_element_type(block);
    if (elem_type == FE_POLYHEDRON)
    {
      // Count up the faces in the block and write the block information.
      int tot_num_elem_faces = 0;
      int faces_per_elem[num_e];
      for (int i = 0; i < num_e; ++i)
      {
        faces_per_elem[i] = fe_block_num_element_faces(block, i);
        tot_num_elem_faces += faces_per_elem[i];
      }
      ex_put_block(file->ex_id, EX_ELEM_BLOCK, elem_block, "nfaced", 
                   num_e, 0, 0, tot_num_elem_faces, 0);

      // Write elem->face connectivity information.
      int elem_faces[tot_num_elem_faces], offset = 0;
      for (int i = 0; i < num_e; ++i)
      {
        fe_block_get_element_faces(block, i, &elem_faces[offset]);
        offset += faces_per_elem[i];
      }
      for (int i = 0; i < tot_num_elem_faces; ++i)
        elem_faces[i] += 1;
      ex_put_conn(file->ex_id, EX_ELEM_BLOCK, elem_block, NULL, NULL, elem_faces);
      ex_put_entity_count_per_polyhedra(file->ex_id, EX_ELEM_BLOCK, elem_block, faces_per_elem); 
    }
    else if (elem_type != FE_INVALID)
    {
      // Get element information.
      char elem_type_name[MAX_NAME_LENGTH+1];
      get_elem_name(elem_type, elem_type_name);
      int num_nodes_per_elem = fe_block_num_element_nodes(block, 0);

      // Write the block.
      ex_put_block(file->ex_id, EX_ELEM_BLOCK, elem_block, elem_type_name, 
                   num_e, num_nodes_per_elem, 0, 0, 0);

      // Write the elem->node connectivity.
      int elem_nodes[num_e* num_nodes_per_elem], offset = 0;
      for (int i = 0; i < num_e; ++i)
      {
        fe_block_get_element_nodes(block, i, &elem_nodes[offset]);
        offset += num_nodes_per_elem;
      }
      for (int i = 0; i < num_e* num_nodes_per_elem; ++i)
        elem_nodes[i] += 1;
      ex_put_conn(file->ex_id, EX_ELEM_BLOCK, elem_block, elem_nodes, NULL, NULL);
    }

    // Set the element block name.
    ex_put_name(file->ex_id, EX_ELEM_BLOCK, elem_block, block_name);
  }

  // Set node positions.
  real_t x[file->num_nodes], y[file->num_nodes], z[file->num_nodes];
  point_t* X = fe_mesh_node_positions(mesh);
  for (int n = 0; n < file->num_nodes; ++n)
  {
    x[n] = X[n].x;
    y[n] = X[n].y;
    z[n] = X[n].z;
  }
  ex_put_coord(file->ex_id, x, y, z);
  char* coord_names[3] = {"x", "y", "z"};
  ex_put_coord_names(file->ex_id, coord_names);

  // Write sets of entities.
  int *set, set_id = 0;
  size_t set_size;
  char* set_name;
  pos = set_id = 0;
  while (fe_mesh_next_element_set(mesh, &pos, &set_name, &set, &set_size))
    write_set(file, EX_ELEM_SET, ++set_id, set_name, set, set_size);
  pos = set_id = 0;
  while (fe_mesh_next_face_set(mesh, &pos, &set_name, &set, &set_size))
    write_set(file, EX_FACE_SET, ++set_id, set_name, set, set_size);
  pos = set_id = 0;
  while (fe_mesh_next_edge_set(mesh, &pos, &set_name, &set, &set_size))
    write_set(file, EX_EDGE_SET, ++set_id, set_name, set, set_size);
  pos = set_id = 0;
  while (fe_mesh_next_node_set(mesh, &pos, &set_name, &set, &set_size))
    write_set(file, EX_NODE_SET, ++set_id, set_name, set, set_size);
  pos = set_id = 0;
  while (fe_mesh_next_side_set(mesh, &pos, &set_name, &set, &set_size))
    write_set(file, EX_SIDE_SET, ++set_id, set_name, set, set_size);
}