Ejemplo n.º 1
0
int generate_graph(Problem_Description* problem,
                   Mesh_Description<INT>* mesh,
                   Graph_Description<INT>* graph,
                   Weight_Description<INT>* weight,
                   Sphere_Info* sphere)
{
  double time1 = get_time();
  /* Find the elements surrounding a node */
  if(!find_surnd_elems(mesh, graph)) {
    Gen_Error(0, "fatal: could not find surrounding elements");
    return 0;
  }
  double time2 = get_time();
  printf("Time to find surrounding elements: %fs\n", time2-time1);

  /* Find the adjacency, if required */
  if(problem->alloc_graph == ELB_TRUE) {
    if(!find_adjacency(problem, mesh, graph, weight, sphere)) {
      Gen_Error(0, "fatal: could not find adjacency");
      return 0;
    }
    time1 = get_time();
    printf("Time to find the adjacency: %fs\n", time1-time2);
  }
  return 1;
}
Ejemplo n.º 2
0
static int read_elem_info(int pexoid, int Proc, PROB_INFO_PTR prob,
                          MESH_INFO_PTR mesh)
{
  /* Local declarations. */
  char  *yo = "read_elem_info";
  int    iblk, ielem, inode, lnode, cnode, iplace, len;
  int    max_nsur = 0;
  int    i;
  int   *nmap, *emap, *connect;
  int  **sur_elem, *nsurnd;
  ELEM_INFO_PTR elements = mesh->elements;

  double tmp0, tmp1, tmp2;
  float *xptr = NULL, *yptr = NULL, *zptr = NULL;
/***************************** BEGIN EXECUTION ******************************/

  DEBUG_TRACE_START(Proc, yo);

  /* allocate memory for the global number maps */
  nmap = (int *) malloc ((mesh->num_nodes + mesh->num_elems) * sizeof(int));
  if (!nmap) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  emap = nmap + mesh->num_nodes;


  /*
   * get the global maps
   */
  if (ex_get_elem_num_map(pexoid, emap) < 0) {
    Gen_Error(0, "fatal: Error returned from ex_get_elem_num_map");
    return 0;
  }

  if (ex_get_node_num_map(pexoid, nmap) < 0) {
    Gen_Error(0, "fatal: Error returned from ex_get_node_num_map");
    return 0;
  }

  /* allocate memory for the coordinates */
  xptr = (float *) malloc (mesh->num_dims * mesh->num_nodes * sizeof(float));
  if (!xptr) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  switch (mesh->num_dims) {
    case 3:
      zptr = xptr + 2 * mesh->num_nodes;
      /* FALLTHRU */
    case 2:
      yptr = xptr + mesh->num_nodes;
  }

  if (ex_get_coord(pexoid, xptr, yptr, zptr) < 0) {
    Gen_Error(0, "fatal: Error returned from ex_get_coord");
    return 0;
  }

  /*
   * figure out which element block needs
   * the most space for its connect table
   */
  len = 0;
  for (iblk = 0; iblk < mesh->num_el_blks; iblk++)
    if ((iplace = mesh->eb_cnts[iblk] * mesh->eb_nnodes[iblk]) > len)
      len = iplace;

  connect = (int *) malloc (len * sizeof(int));
  if (!connect) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }

  /***************************************************************************/
  /* Fill the Connect table, Coordinates, Global Ids for each element        */
  /***************************************************************************/
  iplace = 0;
  for (iblk = 0; iblk < mesh->num_el_blks; iblk++) {

    if (mesh->eb_cnts[iblk] > 0) {
      if (ex_get_elem_conn(pexoid, mesh->eb_ids[iblk], connect) < 0) {
        Gen_Error(0, "fatal: Error returned from ex_get_elem_conn");
        return 0;
      }

      cnode = 0;
      for (ielem = 0; ielem < mesh->eb_cnts[iblk]; ielem++) {
        /* set some fields in the element structure */
        elements[iplace].border = 0;
        elements[iplace].globalID = emap[iplace];
        elements[iplace].elem_blk = iblk;
        elements[iplace].my_part = Proc;
        elements[iplace].perm_value = -1;
        elements[iplace].invperm_value = -1;
        elements[iplace].nadj = 0;
        elements[iplace].adj_len = 0;
        /* first weights are all 1 for now */
        elements[iplace].cpu_wgt[0] = 1.0;
        if (MAX_CPU_WGTS>1){
          /* second weights will be set later */
          elements[iplace].cpu_wgt[1] = 0.0;
          /* make artificial data for more multi-weights */
          for (i = 2; i < MAX_CPU_WGTS; i++)
            elements[iplace].cpu_wgt[i] = elements[iplace].my_part +
              0.5*((elements[iplace].globalID)%i);
        }
        elements[iplace].mem_wgt = 1.0;

        /* allocate space for the connect list and the coordinates */
        elements[iplace].connect = (int *) malloc(mesh->eb_nnodes[iblk] *
                                                  sizeof(int));
        if (!(elements[iplace].connect)) {
          Gen_Error(0, "fatal: insufficient memory");
          return 0;
        }

        elements[iplace].coord = (float **) malloc(mesh->eb_nnodes[iblk] *
                                                   sizeof(float *));
        if (!(elements[iplace].coord)) {
          Gen_Error(0, "fatal: insufficient memory");
          return 0;
        }

        /* save the connect table as local numbers for the moment */
        tmp0 = tmp1 = tmp2 = 0.;
        for (inode = 0; inode < mesh->eb_nnodes[iblk]; inode++) {
          lnode = connect[cnode] - 1;
          elements[iplace].connect[inode] = lnode;
          cnode++;

          elements[iplace].coord[inode] = (float *) calloc(mesh->num_dims,
                                                           sizeof(float));
          if (!(elements[iplace].coord[inode])) {
            Gen_Error(0, "fatal: insufficient memory");
            return 0;
          }

          switch (mesh->num_dims) {
            case 3:
              elements[iplace].coord[inode][2] = zptr[lnode];
              tmp2 += zptr[lnode];
              /* FALLTHRU */
            case 2:
              elements[iplace].coord[inode][1] = yptr[lnode];
              tmp1 += yptr[lnode];
              /* FALLTHRU */
            case 1:
              elements[iplace].coord[inode][0] = xptr[lnode];
              tmp0 += xptr[lnode];
          }
        } /* End: "for (inode = 0; inode < mesh->eb_nnodes[iblk]; inode++)" */

        elements[iplace].avg_coord[0] = tmp0 / mesh->eb_nnodes[iblk];
        elements[iplace].avg_coord[1] = tmp1 / mesh->eb_nnodes[iblk];
        elements[iplace].avg_coord[2] = tmp2 / mesh->eb_nnodes[iblk];

        iplace++;

      } /* End: "for (ielem = 0; ielem < mesh->eb_cnts[iblk]; ielem++)" */
    } /* End: "if (mesh->eb_cnts[iblk] > 0)" */
  } /* End: "for (iblk = 0; iblk < mesh->num_el_blks; iblk++)" */

  /* free some memory */
  free(connect);
  free(xptr);

  /*************************************************************************/
  /* Find the adjacency list for each element                              */
  /*	Part one: find the surrounding elements for each node                */
  /*************************************************************************/
  sur_elem = (int **) malloc(mesh->num_nodes * sizeof(int *));
  if (!sur_elem) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }
  nsurnd = (int *) malloc(mesh->num_nodes * sizeof(int));
  if (!nsurnd) {
    Gen_Error(0, "fatal: insufficient memory");
    return 0;
  }

  if (!find_surnd_elem(mesh, sur_elem, nsurnd, &max_nsur)) {
    Gen_Error(0, "fatal: Error returned from find_surnd_elems");
    return 0;
  }

  /*************************************************************************/
  /*	Part two: Find the adjacencies on this processor                     */
  /*		and get the edge weights                                     */ 
  /*************************************************************************/
  if (!find_adjacency(Proc, mesh, sur_elem, nsurnd, max_nsur)) {
    Gen_Error(0, "fatal: Error returned from find_adjacency");
    return 0;
  }

  /*
   * convert the node numbers in the connect lists to Global IDs
   * since they will be much easier to work with
   */
  for (ielem = 0; ielem < mesh->num_elems; ielem++) {
    iblk = elements[ielem].elem_blk;
    for (inode = 0; inode < mesh->eb_nnodes[iblk]; inode++) {
      elements[ielem].connect[inode] = nmap[elements[ielem].connect[inode]];
    }
  }

  /*
   * let cpu_wgt[1] be the number of sides (surfaces) not
   * connected to other elements. (useful test case for multi-weight
   * load balancing).
   */
  if (MAX_CPU_WGTS>1){
    for (ielem = 0; ielem < mesh->num_elems; ielem++) {
      elements[ielem].cpu_wgt[1] = elements[ielem].adj_len - elements[ielem].nadj;
      /* EBEB Strangely, nadj is often one less than expected so subtract one from the wgt to compensate. */
      if (elements[ielem].cpu_wgt[1] >= 1.0)
        elements[ielem].cpu_wgt[1] -= 1.0;
    }
  }

  for (inode = 0; inode < mesh->num_nodes; inode++) free(sur_elem[inode]);
  free(sur_elem);
  free(nsurnd);

  free(nmap);

  DEBUG_TRACE_END(Proc, yo);
  return 1;
}