예제 #1
0
int write_vis(std::string &nemI_out_file,
	      std::string &exoII_inp_file,
	      Machine_Description* machine,
	      Problem_Description* prob,
	      Mesh_Description<INT>* mesh,
	      LB_Description<INT>* lb)
{
  int    exid_vis, exid_inp;

  char  title[MAX_LINE_LENGTH+1];
  const char   *coord_names[] = {"X", "Y", "Z"};

  /*-----------------------------Execution Begins------------------------------*/

  /* Generate the file name for the visualization file */
  std::string vis_file_name = remove_extension(nemI_out_file);
  vis_file_name += "-vis.exoII";

  /* Generate the title for the file */
  strcpy(title, UTIL_NAME);
  strcat(title, " ");
  strcat(title, ELB_VERSION);
  strcat(title, " load balance visualization file");

  /*
   * If the vis technique is to be by element block then calculate the
   * number of element blocks.
   */
  int    vis_nelem_blks;
  if(prob->type == ELEMENTAL)
    vis_nelem_blks = machine->num_procs;
  else
    vis_nelem_blks = machine->num_procs + 1;

  /* Create the ExodusII file */
  std::cout << "Outputting load balance visualization file " << vis_file_name.c_str() << "\n";
  int cpu_ws = 0;
  int io_ws = 0;
  int mode = EX_CLOBBER;
  if (prob->int64db|prob->int64api) {
    mode |= EX_NETCDF4|EX_NOCLASSIC|prob->int64db|prob->int64api;
  }
  if((exid_vis=ex_create(vis_file_name.c_str(), mode, &cpu_ws, &io_ws)) < 0) {
    Gen_Error(0, "fatal: unable to create visualization output file");
    return 0;
  }
  ON_BLOCK_EXIT(ex_close, exid_vis);

  /*
   * Open the original input ExodusII file, read the values for the
   * element blocks and output them to the visualization file.
   */
  int icpu_ws=0;
  int iio_ws=0;
  float vers=0.0;
  mode = EX_READ | prob->int64api;
  if((exid_inp=ex_open(exoII_inp_file.c_str(), mode, &icpu_ws, &iio_ws, &vers)) < 0) {
    Gen_Error(0, "fatal: unable to open input ExodusII file");
    return 0;
  }
  ON_BLOCK_EXIT(ex_close, exid_inp);
  
  char **elem_type  = (char**)array_alloc(2, mesh->num_el_blks, MAX_STR_LENGTH+1,
					  sizeof(char));
  if(!elem_type) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  ON_BLOCK_EXIT(free, elem_type);

  std::vector<INT> el_blk_ids(mesh->num_el_blks);
  std::vector<INT> el_cnt_blk(mesh->num_el_blks);
  std::vector<INT> node_pel_blk(mesh->num_el_blks);
  std::vector<INT> nattr_el_blk(mesh->num_el_blks);

  if(ex_get_elem_blk_ids(exid_inp, TOPTR(el_blk_ids)) < 0) {
    Gen_Error(0, "fatal: unable to get element block IDs");
    return 0;
  }

  int acc_vis = ELB_TRUE; // Output a different element block per processor
  if (prob->vis_out == 2)
    acc_vis = ELB_FALSE; // Output a nodal/element variable showing processor

  size_t nsize = 0;

  /*
   * Find out if the mesh consists of mixed elements. If not then
   * element blocks will be used to visualize the partitioning. Otherwise
   * nodal/element results will be used.
   */
  for(size_t ecnt=0; ecnt < mesh->num_el_blks; ecnt++) {
    if(ex_get_elem_block(exid_inp, el_blk_ids[ecnt], elem_type[ecnt],
			 &el_cnt_blk[ecnt], &node_pel_blk[ecnt],
			 &nattr_el_blk[ecnt]) < 0) {
      Gen_Error(0, "fatal: unable to get element block parameters");
      return 0;
    }

    nsize += el_cnt_blk[ecnt]*node_pel_blk[ecnt];

    if(strcmp(elem_type[0], elem_type[ecnt]) == 0) {
      if(node_pel_blk[0] != node_pel_blk[ecnt])
	acc_vis = ELB_FALSE;
    }
    else
      acc_vis = ELB_FALSE;
  }

  if(acc_vis == ELB_TRUE) {
    /* Output the initial information */
    if(ex_put_init(exid_vis, title, mesh->num_dims, mesh->num_nodes,
		   mesh->num_elems, vis_nelem_blks, 0, 0) < 0) {
      Gen_Error(0, "fatal: unable to output initial params to vis file");
      return 0;
    }
	
    /* Output the nodal coordinates */
    float *xptr = nullptr;
    float *yptr = nullptr;
    float *zptr = nullptr;
    switch(mesh->num_dims) {
    case 3:
      zptr = (mesh->coords) + 2*mesh->num_nodes;
      /* FALLTHRU */
    case 2:
      yptr = (mesh->coords) + mesh->num_nodes;
      /* FALLTHRU */
    case 1:
      xptr = mesh->coords;
    }
    if(ex_put_coord(exid_vis, xptr, yptr, zptr) < 0) {
      Gen_Error(0, "fatal: unable to output coords to vis file");
      return 0;
    }
	
    if(ex_put_coord_names(exid_vis, (char**)coord_names) < 0) {
      Gen_Error(0, "fatal: unable to output coordinate names");
      return 0;
    }

    std::vector<INT> elem_block(mesh->num_elems);
    std::vector<INT> elem_map(mesh->num_elems);
    std::vector<INT> tmp_connect(nsize);
    for(size_t ecnt=0; ecnt < mesh->num_elems; ecnt++) {
      elem_map[ecnt] = ecnt+1;
      if(prob->type == ELEMENTAL)
	elem_block[ecnt] = lb->vertex2proc[ecnt];
      else {
	int proc   = lb->vertex2proc[mesh->connect[ecnt][0]];
	int nnodes = get_elem_info(NNODES, mesh->elem_type[ecnt]);
	elem_block[ecnt] = proc;
	for(int ncnt=1; ncnt < nnodes; ncnt++) {
	  if(lb->vertex2proc[mesh->connect[ecnt][ncnt]] != proc) {
	    elem_block[ecnt] = machine->num_procs;
	    break;
	  }
	}
      }
    }

    int ccnt = 0;
    std::vector<INT> vis_el_blk_ptr(vis_nelem_blks+1);
    for(INT bcnt=0; bcnt < vis_nelem_blks; bcnt++) {
      vis_el_blk_ptr[bcnt] = ccnt;
      int pos = 0;
      int old_pos = 0;
      INT* el_ptr = TOPTR(elem_block);
      size_t ecnt   = mesh->num_elems;
      while(pos != -1) {
	pos = in_list(bcnt, ecnt, el_ptr);
	if(pos != -1) {
	  old_pos += pos + 1;
	  ecnt     = mesh->num_elems - old_pos;
	  el_ptr   = TOPTR(elem_block) + old_pos;
	  int nnodes = get_elem_info(NNODES, mesh->elem_type[old_pos-1]);
	  for(int ncnt=0; ncnt < nnodes; ncnt++)
	    tmp_connect[ccnt++] = mesh->connect[old_pos-1][ncnt] + 1;
	}
      }
    }
    vis_el_blk_ptr[vis_nelem_blks] = ccnt;
	
    /* Output the element map */
    if(ex_put_map(exid_vis, TOPTR(elem_map)) < 0) {
      Gen_Error(0, "fatal: unable to output element number map");
      return 0;
    }
	
    /* Output the visualization element blocks */
    for(int bcnt=0; bcnt < vis_nelem_blks; bcnt++) {
      /*
       * Note this assumes all the blocks contain the same type
       * element.
       */
      int ecnt = (vis_el_blk_ptr[bcnt+1]-vis_el_blk_ptr[bcnt])/node_pel_blk[0];
      if(ex_put_elem_block(exid_vis, bcnt+1, elem_type[0],
			   ecnt, node_pel_blk[0], 0) < 0) {
	Gen_Error(0, "fatal: unable to output element block params");
	return 0;
      }
	  
      /* Output the connectivity */
      if(ex_put_elem_conn(exid_vis, bcnt+1,
			  &tmp_connect[vis_el_blk_ptr[bcnt]]) < 0) {
	Gen_Error(0, "fatal: unable to output element connectivity");
	return 0;
      }
    }
  }

  else {	/* For nodal/element results visualization of the partioning. */
    // Copy the mesh portion to the vis file.
    ex_copy(exid_inp, exid_vis);

    /* Set up the file for nodal/element results */
    float time_val = 0.0;
    if(ex_put_time(exid_vis, 1, &time_val) < 0) {
      Gen_Error(0, "fatal: unable to output time to vis file");
      return 0;
    }

    const char  *var_names[] = {"proc"};
    if(prob->type == NODAL) {
      /* Allocate memory for the nodal values */
      std::vector<float> proc_vals(mesh->num_nodes);

      if(ex_put_variable_param(exid_vis, EX_NODAL, 1) < 0) {
	Gen_Error(0, "fatal: unable to output var params to vis file");
	return 0;
      }

      if(ex_put_variable_names(exid_vis, EX_NODAL, 1, (char**)var_names) < 0) {
	Gen_Error(0, "fatal: unable to output variable name");
	return 0;
      }

      /* Do some problem specific assignment */
      for(size_t ncnt=0; ncnt < mesh->num_nodes; ncnt++)
	proc_vals[ncnt] = lb->vertex2proc[ncnt];

      for(int pcnt=0; pcnt < machine->num_procs; pcnt++) {
	for(auto & elem : lb->bor_nodes[pcnt])
	  proc_vals[elem] = machine->num_procs + 1;
      }

      /* Output the nodal variables */
      if(ex_put_nodal_var(exid_vis, 1, 1, mesh->num_nodes, TOPTR(proc_vals)) < 0) {
	Gen_Error(0, "fatal: unable to output nodal variables");
	return 0;
      }
    }
    else if(prob->type == ELEMENTAL) {
      /* Allocate memory for the element values */
      std::vector<float> proc_vals(mesh->num_elems);

      if(ex_put_variable_param(exid_vis, EX_ELEM_BLOCK, 1) < 0) {
	Gen_Error(0, "fatal: unable to output var params to vis file");
	return 0;
      }

      if(ex_put_variable_names(exid_vis, EX_ELEM_BLOCK, 1, (char**)var_names) < 0) {
	Gen_Error(0, "fatal: unable to output variable name");
	return 0;
      }

      /* Do some problem specific assignment */
      for(int proc=0; proc < machine->num_procs; proc++) {
	for (size_t e = 0; e < lb->int_elems[proc].size(); e++) {
	  size_t ecnt = lb->int_elems[proc][e];
	  proc_vals[ecnt] = proc;
	}

	for (size_t e = 0; e < lb->bor_elems[proc].size(); e++) {
	  size_t ecnt = lb->bor_elems[proc][e];
	  proc_vals[ecnt] = proc;
	}
      }

      /* Output the element variables */
      size_t offset = 0;
      for (size_t i=0; i < mesh->num_el_blks; i++) {
	if(ex_put_var(exid_vis, 1, EX_ELEM_BLOCK, 1, el_blk_ids[i],
		      el_cnt_blk[i], &proc_vals[offset]) < 0) {
	  Gen_Error(0, "fatal: unable to output nodal variables");
	  return 0;
	}
	offset += el_cnt_blk[i];
      }
    }
  }
  return 1;
} /*---------------------------End write_vis()-------------------------------*/
예제 #2
0
static int find_adjacency(int Proc, MESH_INFO_PTR mesh,
                          int **sur_elem, int *nsurnd, int max_nsur)
{
  /* Local declarations. */
  int     i, iblk, nsides, ielem, nscnt, inode, entry;
  int     side_cnt, nnodes, sid;
  int     side_nodes[MAX_SIDE_NODES], mirror_nodes[MAX_SIDE_NODES];
  int    *hold_elem, *pt_list, nhold, nelem;
  ELEM_INFO_PTR elements = mesh->elements;

  int *eb_etype;
/***************************** BEGIN EXECUTION ******************************/
  /*
   * Use face definition of adjacencies. So, one elements that are
   * connected by an entire face will be considered adjacent. This
   * is temporary, and will be expanded. This will make determining
   * off processor adjacencies much easier.
   *
   * Adjacency info for an element's side i will be stored in the (i-1) entry 
   * of adj array for the element.  Sides without adjacencies will have -1
   * as the adj array entries for those sides.  This system allows easy
   * identification of side ids for recomputing element comm maps after
   * migration.
   */

  eb_etype = mesh->eb_etypes;

  /* allocate space to hold info about surounding elements */
  pt_list = (int *) malloc(2 * max_nsur * sizeof(int));
  if(!pt_list) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  hold_elem = pt_list + max_nsur;

  for (ielem = 0; ielem < mesh->num_elems; ielem++) {

    iblk = elements[ielem].elem_blk;

    /* exclude circle and sphere elements from graph */
    if (mesh->eb_nnodes[iblk] > 1) {

      if ((nsides = get_elem_info(NSIDES, (E_Type) (eb_etype[iblk]), 0)) < 0) {
        Gen_Error(0, "fatal: could not get element information");
        return 0;
      }

      elements[ielem].adj = (int *) malloc(nsides*sizeof(int));
      elements[ielem].adj_proc = (int *) malloc(nsides*sizeof(int));
      elements[ielem].edge_wgt = (float *) malloc(nsides*sizeof(float));
      if(!(elements[ielem].adj) || !(elements[ielem].edge_wgt) ||
         !(elements[ielem].adj_proc)) {
        Gen_Error(0, "fatal: insufficient memory");
        return 0;
      }
      /* NOTE: nadj set in read_elem_info in case graph not generated */
      elements[ielem].adj_len = nsides;

      /* Initialize adjacency entries to -1 for each side. */
      for (nscnt = 0; nscnt < nsides; nscnt++) {
        elements[ielem].adj[nscnt] = -1;
        elements[ielem].adj_proc[nscnt] = -1;
        elements[ielem].edge_wgt[nscnt] = 0;
      }

      /* check each side of this element */
      for (nscnt = 0; nscnt < nsides; nscnt++) {

        /* get the list of nodes on this side set */
        side_cnt = ss_to_node_list((E_Type) (eb_etype[iblk]), 
                                   elements[ielem].connect,
                                   (nscnt+1), side_nodes);

        /*
         * now I need to determine how many side set nodes I
         * need to use to determine if there is an element
         * connected to this side.
         *
         * 2-D - need two nodes, so find one intersection
         * 3-D - need three nodes, so find two intersections
         * NOTE: must check to make sure that this number is not
         *       larger than the number of nodes on the sides (ie - SHELL).
         */
        nnodes = mesh->num_dims;
        if (side_cnt < nnodes)   nnodes = side_cnt;
        nnodes--;      /* decrement to find the number of intersections  */

        nelem = 0;     /* reset this in case no intersections are needed */

        /* copy the first array into temp storage */
        nhold = nsurnd[side_nodes[0]];
        for (i = 0; i < nhold; i++)
          hold_elem[i] = sur_elem[side_nodes[0]][i];

        for (inode = 0; inode < nnodes; inode++) {
          nelem = find_inter(hold_elem, sur_elem[side_nodes[(inode+1)]],
                             nhold, nsurnd[side_nodes[(inode+1)]], 2, pt_list);

          if (nelem < 2) break;
          else {
            nhold = nelem;
            for (i = 0; i < nelem; i++)
              hold_elem[i] = hold_elem[pt_list[i]];
          }
        }

        /*
         * if there is an element on this side of ielem, then there
         * will be at least two elements in the intersection (one
         * will be ielem)
         */
        if (nelem > 1) {

          /*
           * now go through and check each element in the list
           * to see if it is different than ielem.
           */
          for(i=0; i < nelem; i++) {

            entry = hold_elem[i];

            if(entry != ielem) {
              /*
               * get the side id of entry. Make sure that ielem is
               * trying to communicate to a valid side of elem
               */
              side_cnt = get_ss_mirror((E_Type) (eb_etype[iblk]), 
                                       side_nodes, (nscnt+1),
                                       mirror_nodes);

              /*
               * in order to get the correct side order for elem,
               * get the mirror of the side of ielem
               */
              sid = get_side_id((E_Type) (eb_etype[elements[entry].elem_blk]),
                                elements[entry].connect,
                                side_cnt, mirror_nodes);
              if (sid > 0) {
                (elements[ielem].nadj)++;

                /*
                 * store the adjacency info in the entry for this side.
                 */
                elements[ielem].adj[nscnt] = entry;
                elements[ielem].adj_proc[nscnt] = Proc;

                /*
                 * the edge weight is the number of nodes in the
                 * connecting face
                 */
                elements[ielem].edge_wgt[nscnt] = 
                  (float) get_elem_info(NSNODES, (E_Type) (eb_etype[iblk]),
                                       (nscnt+1));

              } /* End: "if (sid > 0)" */
              else if (sid < 0) {
                Gen_Error(0, "fatal: could not find side id");
                return 0;
              }
            } /* End: "if(ielem != entry)" */
          } /* End: "for(i=0; i < nelem; i++)" */
        } /* End: "if (nelem > 1)" */
      } /* End: "for (nscnt = 0; ...)" */
    } /* End: "if (nnode > 1)" */
  } /* End: "for (ielem=0; ...)" */

  free(pt_list);

  return 1;
}
예제 #3
0
static int read_comm_map_info(int pexoid, int Proc, PROB_INFO_PTR prob,
                              MESH_INFO_PTR mesh)
{
  /* Local declarations. */
  char *yo = "read_comm_map_info";
  int  ielem, imap, loc_elem, iblk, max_len, offset, index;
  int  nnodei, nnodeb, nnodee, nelemi, nelemb, nncmap;
  int *int_elem, *bor_elem;
  int *proc_ids;
  int *gids, *my_procs, *recv_procs;
  int  ierr, nrecv;
  int  msg = 200;
  int  sid;
  ELEM_INFO_PTR elements = mesh->elements;
  ZOLTAN_COMM_OBJ *comm_obj;

  E_Type etype;

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

  DEBUG_TRACE_START(Proc, yo);

  if (ne_get_loadbal_param(pexoid, &nnodei, &nnodeb, &nnodee,
                     &nelemi, &nelemb, &nncmap, &(mesh->necmap), Proc) < 0) {
    Gen_Error(0, "fatal: Error returned from ne_get_loadbal_param");
    return 0;
  }

  /*
   * get the list of the border elements in order to set
   * the border flag in the element structures
   */
  int_elem = (int *) malloc ((nelemi + nelemb) * sizeof(int));
  if (!int_elem) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  bor_elem = int_elem + nelemi;

  if (ne_get_elem_map(pexoid, int_elem, bor_elem, Proc) < 0) {
    Gen_Error(0, "fatal: Error returned from ne_get_elem_map");
    return 0;
  }

  for (ielem = 0; ielem < nelemb; ielem++) {
    elements[bor_elem[ielem]-1].border = 1;
  }

  free(int_elem);

  /*
   * For now, only get the elemental communication maps,
   * since, in the driver, elements are only considered
   * adjacent if they share a face (same definition used
   * in element communication maps). Eventually, the ability
   * to consider elements that are connected by any nodes
   * adjacent will have to be added. When that happens,
   * the nodal communication maps will be needed.
   */
  mesh->ecmap_cnt = (int *) malloc (mesh->necmap * sizeof(int));
  mesh->ecmap_id = (int *) malloc(mesh->necmap * sizeof(int));
  if (!mesh->ecmap_cnt || !mesh->ecmap_id) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }

  if (ne_get_cmap_params(pexoid, NULL, NULL, mesh->ecmap_id, 
                         mesh->ecmap_cnt, Proc) < 0) {
    Gen_Error(0, "fatal: Error returned from ne_get_cmap_params");
    return 0;
  }

  max_len = 0;
  for (imap = 0; imap < mesh->necmap; imap++)
    max_len += mesh->ecmap_cnt[imap];

  proc_ids = (int *) malloc(4 * max_len * sizeof(int));
  gids = proc_ids + max_len;
  my_procs = gids + max_len;
  recv_procs = my_procs + max_len;
  mesh->ecmap_elemids = (int *) malloc(max_len * sizeof(int));
  mesh->ecmap_sideids = (int *) malloc(max_len * sizeof(int));
  mesh->ecmap_neighids = (int *) malloc(max_len * sizeof(int));
  if (!mesh->ecmap_elemids || !mesh->ecmap_sideids || !mesh->ecmap_neighids) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }

  offset = 0;
  for (imap = 0; imap < mesh->necmap; imap++) {

    if(ne_get_elem_cmap(pexoid, mesh->ecmap_id[imap],
                        &(mesh->ecmap_elemids[offset]),
                        &(mesh->ecmap_sideids[offset]), 
                        &(proc_ids[offset]), Proc) < 0) {
      Gen_Error(0, "fatal: Error returned from ne_get_elem_cmap");
      return 0;
    }
    offset += mesh->ecmap_cnt[imap];
  } /* End: "for (imap = 0; imap < mesh->necmap; imap++)" */

  /*
   * Decrement the ecmap_elemids by one for zero-based local numbering.
   * Convert the element ids to global ids to send to
   * the neighboring processor.
   */
  for (ielem = 0; ielem < max_len; ielem++) {
    mesh->ecmap_elemids[ielem]--;
    gids[ielem] = elements[mesh->ecmap_elemids[ielem]].globalID;
    my_procs[ielem] = Proc;
  }
  /*
   * Now communicate with other processor to get global IDs
   * for the adjacent elements in this communication map.
   */

  ierr = Zoltan_Comm_Create(&comm_obj, max_len, proc_ids, MPI_COMM_WORLD, 
                            msg, &nrecv);
  if (ierr != ZOLTAN_OK) {
    Gen_Error(0, "fatal: Error returned from Zoltan_Comm_Create");
    return 0;
  }
  if (nrecv != max_len) {
    /* Sanity check; this should never happen. */
    Gen_Error(0, "fatal: Error returned from Zoltan_Comm_Create");
    return 0;
  }

  /* Exchange ids to neighbors.  
   * Assuming messages will be stored in order of processor number in 
   * ecmap_neighids. 
   */
  ierr = Zoltan_Comm_Do(comm_obj, msg+1, (char *) gids, sizeof(int), 
                        (char *) (mesh->ecmap_neighids));

  /* Exchange sanity check information. 
   * Allows to check assumption that messages are stored in order of
   * processor number.
   */
  if (ierr == ZOLTAN_OK)
    ierr = Zoltan_Comm_Do(comm_obj, msg+2, (char *) my_procs, sizeof(int), 
                          (char *) recv_procs);

  if (ierr != ZOLTAN_OK) {
    Gen_Error(0, "fatal: Error returned from Zoltan_Comm_Do");
    return 0;
  }

  ierr = Zoltan_Comm_Destroy(&comm_obj);

  /* Sanity check: messages stored in order of processor number. */
  for (ielem = 0; ielem < max_len; ielem++) {
    if (proc_ids[ielem] != recv_procs[ielem]) {
      Gen_Error(0, "fatal: Sanity check failed; assumption wrong");
      return 0;
    }
  }

  /* now process all of the element ids that have been received */
  offset = 0;
  for (imap = 0; imap < mesh->necmap; imap++) {
    for (ielem = 0; ielem < mesh->ecmap_cnt[imap]; ielem++) {
      index = ielem + offset;
      /* translate from element id in the communication map to local elem id */
      loc_elem = mesh->ecmap_elemids[index];
      iblk = elements[loc_elem].elem_blk;
      etype = (E_Type) (mesh->eb_etypes[iblk]);

      (elements[loc_elem].nadj)++;
      if(elements[loc_elem].nadj > elements[loc_elem].adj_len) {
        /* Shouldn't happen as long as only side adjacencies are used. */
        /* adj_len == number of sides.                                 */
        /* Space should already be allocated for the adjacencies read  */
        /* from the communication maps.                                */
        Gen_Error(0, "fatal: Number of adj greater than adj_len");
        return 0;
      }

      /* Store adjacency info in the adj entry corresponding to this side. */
      sid = mesh->ecmap_sideids[index] - 1;
      elements[loc_elem].adj[sid] = mesh->ecmap_neighids[index];
      elements[loc_elem].adj_proc[sid] = mesh->ecmap_id[imap];
      elements[loc_elem].edge_wgt[sid] =
             (float) get_elem_info(NSNODES, etype, mesh->ecmap_sideids[index]);

    } /* End: "for (ielem = 0; ielem < mesh->ecmap_cnt[imap]; ielem++)" */
    offset += mesh->ecmap_cnt[imap];
  } /* End: "for for (imap = 0; imap < mesh->necmap; imap++)" */
  
  free (proc_ids);

  DEBUG_TRACE_END(Proc, yo);
  return 1;
}
예제 #4
0
/* Function get_side_id() begins:
 *----------------------------------------------------------------------------
 * This function returns the Side ID (as used in ExodusII) given a list of
 * nodes on that side.
 *
 * Changed so that it is now order dependent, but independent of starting
 * node for 3-D sides. On 2-D sides (lines), the starting node is important.
 *
 * Now supoports degenrate faces in HEX elements.
 *****************************************************************************/
int get_side_id(E_Type etype, const int *connect, const int nsnodes,
                int side_nodes[])
{
  const char *func_name="get_side_id";
  char  err_buff[300];

  int nnodes, i, j, num;
  int dup, location = 0;

  /* check if this is a degenerate face */
  dup = 0;
  for (i = 0; i < (nsnodes - 1); i++) {
    for (j = (i + 1); j < nsnodes; j++)
      if (side_nodes[i] == side_nodes[j]) {
        dup = 1;
        location = i; /* location of duplicated node */
        break;
      }
    if (dup) break;
  }

  nnodes = get_elem_info(NNODES, etype, 0);

  /* Find all of the side nodes in the connect table */
  num = 0;
  for(i=0; i < nnodes; i++)
  {
    for(j=0; j < nsnodes; j++)
    {
      if(connect[i] == side_nodes[j])
      {
        num++;
        break;
      }
    }
    if(num == nsnodes)
      break;
  }

  if(num != nsnodes)
  {
    Gen_Error(0, "fatal: not all side nodes in connect table for element");
    return -1;
  }

  /* Find the side ID */
  switch(etype)
  {
  case QUAD1:
  case S_QUAD2:
  case QUAD2:
    /* SIDE 1 */
    if (side_nodes[0] == connect[0] &&
        side_nodes[1] == connect[1]) return 1;

    /* SIDE 2 */
    if (side_nodes[0] == connect[1] &&
        side_nodes[1] == connect[2]) return 2;

    /* SIDE 3 */
    if (side_nodes[0] == connect[2] &&
        side_nodes[1] == connect[3]) return 3;

    /* SIDE 4 */
    if (side_nodes[0] == connect[3] &&
        side_nodes[1] == connect[0]) return 4;

    break;

  case TRI1:
  case TRI2:
    /* SIDE 1 */
    if (side_nodes[0] == connect[0] &&
        side_nodes[1] == connect[1]) return 1;

    /* SIDE 2 */
    if (side_nodes[0] == connect[1] &&
        side_nodes[1] == connect[2]) return 2;

    /* SIDE 3 */
    if (side_nodes[0] == connect[2] &&
        side_nodes[1] == connect[0]) return 3;

    break;

  case TET1:
  case TET2:
    /* SIDE 1 */
    if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 3] == connect[1] &&
          side_nodes[(2 + num) % 3] == connect[3]) return 1;
    }

    /* SIDE 2 */
    if((num = in_list(connect[1], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 3] == connect[2] &&
          side_nodes[(2 + num) % 3] == connect[3]) return 2;
    }

    /* SIDE 3 */
    if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 3] == connect[3] &&
          side_nodes[(2 + num) % 3] == connect[2]) return 3;
    }

    /* SIDE 4 */
    if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 3] == connect[2] &&
          side_nodes[(2 + num) % 3] == connect[1]) return 4;
    }

    break;

  case HEX1:
  case S_HEX2:
  case HEX2:
  case HEXSHELL:  /* this should be the same as a HEX element */
    /* SIDE 1 */
    if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 4] == connect[1] &&
          side_nodes[(2 + num) % 4] == connect[5] &&
          side_nodes[(3 + num) % 4] == connect[4]) return 1;

      /* if this is the duplicated node, then find the next occurence */
      if (dup && connect[0] == side_nodes[location]) {
        num = in_list(connect[0], (nsnodes-num), &(side_nodes[num+1]));
        if (side_nodes[(1 + num) % 4] == connect[1] &&
            side_nodes[(2 + num) % 4] == connect[5] &&
            side_nodes[(3 + num) % 4] == connect[4]) return 1;
      }
    }

    /* SIDE 2 */
    if((num = in_list(connect[1], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 4] == connect[2] &&
          side_nodes[(2 + num) % 4] == connect[6] &&
          side_nodes[(3 + num) % 4] == connect[5]) return 2;

      /* if this is the duplicated node, then find the next occurence */
      if (dup && connect[1] == side_nodes[location]) {
        num = in_list(connect[1], (nsnodes-num), &(side_nodes[num+1]));
        if (side_nodes[(1 + num) % 4] == connect[2] &&
            side_nodes[(2 + num) % 4] == connect[6] &&
            side_nodes[(3 + num) % 4] == connect[5]) return 2;
      }
    }

    /* SIDE 3 */
    if((num = in_list(connect[2], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 4] == connect[3] &&
          side_nodes[(2 + num) % 4] == connect[7] &&
          side_nodes[(3 + num) % 4] == connect[6]) return 3;

      /* if this is the duplicated node, then find the next occurence */
      if (dup && connect[2] == side_nodes[location]) {
        num = in_list(connect[2], (nsnodes-num), &(side_nodes[num+1]));
        if (side_nodes[(1 + num) % 4] == connect[3] &&
            side_nodes[(2 + num) % 4] == connect[7] &&
            side_nodes[(3 + num) % 4] == connect[6]) return 3;
      }
    }

    /* SIDE 4 */
    if((num = in_list(connect[3], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 4] == connect[0] &&
          side_nodes[(2 + num) % 4] == connect[4] &&
          side_nodes[(3 + num) % 4] == connect[7]) return 4;

      /* if this is the duplicated node, then find the next occurence */
      if (dup && connect[3] == side_nodes[location]) {
        num = in_list(connect[3], (nsnodes-num), &(side_nodes[num+1]));
        if (side_nodes[(1 + num) % 4] == connect[0] &&
            side_nodes[(2 + num) % 4] == connect[4] &&
            side_nodes[(3 + num) % 4] == connect[7]) return 4;
      }
    }

    /* SIDE 5 */
    if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 4] == connect[3] &&
          side_nodes[(2 + num) % 4] == connect[2] &&
          side_nodes[(3 + num) % 4] == connect[1]) return 5;

      /* if this is the duplicated node, then find the next occurence */
      if (dup && connect[0] == side_nodes[location]) {
        num = in_list(connect[0], (nsnodes-num), &(side_nodes[num+1]));
        if (side_nodes[(1 + num) % 4] == connect[3] &&
            side_nodes[(2 + num) % 4] == connect[2] &&
            side_nodes[(3 + num) % 4] == connect[1]) return 5;
      }
    }

    /* SIDE 6 */
    if((num = in_list(connect[4], nsnodes, side_nodes)) >= 0) {
      if (side_nodes[(1 + num) % 4] == connect[5] &&
          side_nodes[(2 + num) % 4] == connect[6] &&
          side_nodes[(3 + num) % 4] == connect[7]) return 6;

      /* if this is the duplicated node, then find the next occurence */
      if (dup && connect[4] == side_nodes[location]) {
        num = in_list(connect[4], (nsnodes-num), &(side_nodes[num+1]));
        if (side_nodes[(1 + num) % 4] == connect[5] &&
            side_nodes[(2 + num) % 4] == connect[6] &&
            side_nodes[(3 + num) % 4] == connect[7]) return 6;
      }
    }

    break;

  case SHELL1:
  case SHELL2:

    /* 2D sides */
    if(nsnodes == 2 || nsnodes == 3) {
      /* SIDE 3 */
      if (side_nodes[0] == connect[0] &&
          side_nodes[1] == connect[1]) return 3;

      /* SIDE 4 */
      if (side_nodes[0] == connect[1] &&
          side_nodes[1] == connect[2]) return 4;

      /* SIDE 5 */
      if (side_nodes[0] == connect[2] &&
          side_nodes[1] == connect[3]) return 5;

      /* SIDE 6 */
      if (side_nodes[0] == connect[3] &&
          side_nodes[1] == connect[0]) return 6;
    }

    /* 3D faces */
    else if (nsnodes == 4 || nsnodes == 8) {

      /* SIDE 1 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 4] == connect[1] &&
            side_nodes[(2 + num) % 4] == connect[2] &&
            side_nodes[(3 + num) % 4] == connect[3]) return 1;
      }

      /* SIDE 2 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 4] == connect[3] &&
            side_nodes[(2 + num) % 4] == connect[2] &&
            side_nodes[(3 + num) % 4] == connect[1]) return 2;
      }
    }

    break;

  case WEDGE1:
  case WEDGE2:

    /* quad sides */
    if (nsnodes == 4 || nsnodes == 8) {
      /* SIDE 1 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 4] == connect[1] &&
            side_nodes[(2 + num) % 4] == connect[4] &&
            side_nodes[(3 + num) % 4] == connect[3]) return 1;
      }

      /* SIDE 2 */
      if((num = in_list(connect[1], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 4] == connect[2] &&
            side_nodes[(2 + num) % 4] == connect[5] &&
            side_nodes[(3 + num) % 4] == connect[4]) return 2;
      }

      /* SIDE 3 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 4] == connect[3] &&
            side_nodes[(2 + num) % 4] == connect[5] &&
            side_nodes[(3 + num) % 4] == connect[2]) return 3;
      }
    }

    /* triangle sides */
    else if (nsnodes == 3 || nsnodes == 6) {
      /* SIDE 4 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 3] == connect[2] &&
            side_nodes[(3 + num) % 3] == connect[1]) return 4;
      }

      /* SIDE 5 */
      if((num = in_list(connect[3], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 3] == connect[4] &&
            side_nodes[(3 + num) % 3] == connect[5]) return 5;
      }
    }

    break;

  case TSHELL1:
  case TSHELL2:

    /* 2D sides */
    if(nsnodes == 2 || ((etype == TSHELL2) && (nsnodes == 3))) {
      /* SIDE 3 */
      if (side_nodes[0] == connect[0] &&
          side_nodes[1] == connect[1]) return 3;

      /* SIDE 4 */
      if (side_nodes[0] == connect[1] &&
          side_nodes[1] == connect[2]) return 4;

      /* SIDE 5 */
      if (side_nodes[0] == connect[2] &&
          side_nodes[1] == connect[0]) return 5;

    }

    /* 3D faces */
    else if (nsnodes == 3 || nsnodes == 6) {

      /* SIDE 1 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 3] == connect[1] &&
            side_nodes[(2 + num) % 3] == connect[2]) return 1;
      }

      /* SIDE 2 */
      if((num = in_list(connect[0], nsnodes, side_nodes)) >= 0) {
        if (side_nodes[(1 + num) % 3] == connect[2] &&
            side_nodes[(2 + num) % 3] == connect[1]) return 2;
      }
    }

    break;


  default:
    sprintf(err_buff, "fatal: unknown element type %d in function %s",
            etype, func_name);
    Gen_Error(0, err_buff);
    return -1;

  } /* End "switch(etype)" */

  return 0;
} /*---------------------------End get_side_id()-----------------------------*/