Ejemplo n.º 1
0
int read_mesh(const std::string &exo_file,
              Problem_Description* problem,
              Mesh_Description<INT>* mesh,
              Weight_Description<INT>* weight
	      )
{
  float  version, *xptr, *yptr, *zptr;
  char   elem_type[MAX_STR_LENGTH+1];
  E_Type blk_elem_type;
  
  /*---------------------------Execution Begins--------------------------------*/

  /* Open the ExodusII file */
  int exoid, cpu_ws=0, io_ws=0;
  int mode = EX_READ | problem->int64api;
  if((exoid=ex_open(exo_file.c_str(), mode, &cpu_ws, &io_ws, &version)) < 0)
    {
      Gen_Error(0, "fatal: unable to open ExodusII mesh file");
      return 0;
    }

  /* Read the coordinates, if desired */
  xptr = yptr = zptr = NULL;
  if(problem->read_coords == ELB_TRUE)
    {
      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_get_coord(exoid, xptr, yptr, zptr) < 0)
	{
	  Gen_Error(0, "fatal: unable to read coordinate values for mesh");
	  return 0;
	}

    } /* End "if(problem->read_coords == ELB_TRUE)" */

  /* Read the element block IDs */
  std::vector<INT> el_blk_ids(mesh->num_el_blks);
  std::vector<INT> el_blk_cnts(mesh->num_el_blks);

  if(ex_get_elem_blk_ids(exoid, &el_blk_ids[0]) < 0)
    {
      Gen_Error(0, "fatal: unable to read element block IDs");
      return 0;
    }

  /* Read the element connectivity */
  size_t gelem_cnt=0;
  for(size_t cnt=0; cnt < mesh->num_el_blks; cnt++) {
    INT nodes_per_elem, num_attr;
    if(ex_get_elem_block(exoid, el_blk_ids[cnt], elem_type,
                         &(el_blk_cnts[cnt]), &nodes_per_elem,
                         &num_attr) < 0)
      {
	Gen_Error(0, "fatal: unable to read element block");
	return 0;
      }

    blk_elem_type = get_elem_type(elem_type, nodes_per_elem, mesh->num_dims);

    INT *blk_connect = (INT*)malloc(sizeof(INT)*el_blk_cnts[cnt]*nodes_per_elem);
    if(!blk_connect)
      {
	Gen_Error(0, "fatal: insufficient memory");
	return 0;
      }

    /* Get the connectivity for this element block */
    if(ex_get_elem_conn(exoid, el_blk_ids[cnt], blk_connect) < 0)
      {
	Gen_Error(0, "fatal: failed to get element connectivity");
	return 0;
      }

    /* find out if this element block is weighted */
    int wgt = -1;
    if (weight->type & EL_BLK)
      wgt = in_list(el_blk_ids[cnt], weight->elemblk);
    
    /* Fill the 2D global connectivity array */
    if (((problem->type == ELEMENTAL) && (weight->type & EL_BLK)) ||
        ((problem->type == NODAL) && (weight->type & EL_BLK))) {
      
      for(int64_t cnt2=0; cnt2 < el_blk_cnts[cnt]; cnt2++) {
	mesh->elem_type[gelem_cnt] = blk_elem_type;
      
	/* while going through the blocks, take care of the weighting */
	if ((problem->type == ELEMENTAL) && (weight->type & EL_BLK)) {
	  /* is this block weighted */
	  if (wgt >= 0) {
	    /* check if there is a read value */
	    if (weight->vertices[gelem_cnt] >= 1) {
	      /* and if it should be overwritten */
	      if (weight->ow_read)
		weight->vertices[gelem_cnt] = weight->elemblk_wgt[wgt];
	    }
	    else
	      weight->vertices[gelem_cnt] = weight->elemblk_wgt[wgt];
	  }
	  else {
	    /* now check if this weight has been initialized */
	    if (weight->vertices[gelem_cnt] < 1)
	      weight->vertices[gelem_cnt] = 1;
	  }
	}

	for(int64_t cnt3=0; cnt3 < nodes_per_elem; cnt3++) {
	  INT node = blk_connect[cnt3 + cnt2*nodes_per_elem] - 1;
	  assert(node >= 0);
	  mesh->connect[gelem_cnt][cnt3] = node;

	  /* deal with the weighting if necessary */
	  if ((problem->type == NODAL) && (weight->type & EL_BLK)) {
	    /* is this block weighted */
	    if (wgt >= 0) {
	      /* check if I read an exodus file */
	      if (weight->type & READ_EXO) {
		/* check if it can be overwritten */
		if (weight->ow_read) {
		  /* check if it has been overwritten already */
		  if (weight->ow[node]) {
		    weight->vertices[node] =
		      MAX(weight->vertices[node], weight->elemblk_wgt[wgt]);
		  }
		  else {
		    weight->vertices[node] = weight->elemblk_wgt[wgt];
		    weight->ow[node] = 1;   /* read value has been overwritten */
		  }
		}
	      }
	      else {
		weight->vertices[node] =
		  MAX(weight->vertices[node], weight->elemblk_wgt[wgt]);
	      }
	    }
	    else {
	      /* now check if this weight has been initialized */
	      if (weight->vertices[node] < 1)
		weight->vertices[node] = 1;
	    }
	  }
	}
	gelem_cnt++;
      }
    } else {
      // No weights...
      for (int64_t cnt2=0; cnt2 < el_blk_cnts[cnt]; cnt2++) {
	mesh->elem_type[gelem_cnt] = blk_elem_type;

	for (int64_t cnt3=0; cnt3 < nodes_per_elem; cnt3++) {
	  INT node = blk_connect[cnt2*nodes_per_elem + cnt3] - 1;
	  assert(node >= 0);
	  mesh->connect[gelem_cnt][cnt3] = node;
	}

	gelem_cnt++;
      }
    }
    /* Free up memory */
    free(blk_connect);

  } /* End "for(cnt=0; cnt < mesh->num_el_blks; cnt++)" */

  /* if there is a group designator, then parse it here */
  if (problem->groups != NULL) {
    if (!parse_groups(&el_blk_ids[0], &el_blk_cnts[0], mesh, problem)) {
      Gen_Error(0, "fatal: unable to parse group designator");
      ex_close(exoid);
      return 0;
    }
  }
  else problem->num_groups = 1; /* there is always one group */

  /* Close the ExodusII file */
  if(ex_close(exoid) < 0)
    Gen_Error(0, "warning: failed to close ExodusII mesh file");

  return 1;

} /*---------------------------End read_mesh()-------------------------------*/
Ejemplo n.º 2
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()-------------------------------*/
Ejemplo n.º 3
0
int read_mesh_params(const std::string &exo_file,
                     Problem_Description* problem,
                     Mesh_Description<INT>* mesh,
                     Sphere_Info* sphere
  )
{
  int    exoid, cpu_ws=0, io_ws=0;
  float  version;
  char   elem_type[MAX_STR_LENGTH+1];
/*---------------------------Execution Begins--------------------------------*/

  /* Open the ExodusII geometry file */
  int mode = EX_READ | problem->int64api;
  if((exoid=ex_open(exo_file.c_str(), mode, &cpu_ws, &io_ws, &version)) < 0)
  {
    Gen_Error(0, "fatal: unable to open ExodusII file for mesh params");
    return 0;
  }

  /* Get the init info */
  ex_init_params exo;
  if(ex_get_init_ext(exoid, &exo))
  {
    Gen_Error(0, "fatal: unable to get init info from ExodusII file");
    ex_close(exoid);
    return 0;
  }
  strcpy(mesh->title, exo.title);
  mesh->num_dims      = exo.num_dim;
  mesh->num_nodes     = exo.num_nodes;
  mesh->num_elems     = exo.num_elem;
  mesh->num_el_blks   = exo.num_elem_blk;
  mesh->num_node_sets = exo.num_node_sets;
  mesh->num_side_sets = exo.num_side_sets;

  /* Get the length of the concatenated node set node list */
  if(mesh->num_node_sets > 0)
  {
    mesh->ns_list_len = ex_inquire_int(exoid, EX_INQ_NS_NODE_LEN);
  }
  else
    mesh->ns_list_len = 0;

  /* Allocate and initialize memory for the sphere adjustment */
  sphere->adjust = (int*)malloc(sizeof(int)*3*(mesh->num_el_blks));
  if(!(sphere->adjust)) {
    Gen_Error(0, "fatal: insufficient memory");
    ex_close(exoid);
    return 0;
  }
  else {
    sphere->begin = sphere->adjust + mesh->num_el_blks;
    sphere->end   = sphere->begin  + mesh->num_el_blks;
    for(size_t cnt=0; cnt < mesh->num_el_blks; cnt++) {
      sphere->adjust[cnt] = 0;
      sphere->begin[cnt]  = 0;
      sphere->end[cnt]    = 0;
    }
  }

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

  /* Read the element block IDs */
  if(ex_get_elem_blk_ids(exoid, &el_blk_ids[0]) < 0) {
    Gen_Error(0, "fatal: unable to get element block IDs");
    ex_close(exoid);
    return 0;
  }

  /* Determine the maximum number of nodes per element */
  mesh->max_np_elem = 0;
  for(size_t cnt=0; cnt < mesh->num_el_blks; cnt++) {
    INT num_elems, idum;
    INT nodes_in_elem;
    
    if(ex_get_elem_block(exoid, el_blk_ids[cnt], elem_type,
                         &num_elems, &nodes_in_elem, &idum) < 0)
    {
      Gen_Error(0, "fatal: unable to get element block");
      ex_close(exoid);
      return 0;
    }

    if(cnt == 0)
      sphere->end[0] = num_elems;

    if(get_elem_type(elem_type, nodes_in_elem, mesh->num_dims) == SPHERE && problem->no_sph != 1) {
      sphere->num  += num_elems;
      sphere->adjust[cnt] = 0;
    }
    else
      sphere->adjust[cnt] = sphere->num;

    if(cnt != 0) {
      sphere->begin[cnt] = sphere->end[cnt-1];
      sphere->end[cnt]   = sphere->begin[cnt] + num_elems;
    }

    mesh->max_np_elem = MAX(mesh->max_np_elem, (size_t)nodes_in_elem);
  }

  /* Close the ExodusII file */
  if(ex_close(exoid) < 0)
    Gen_Error(1, "warning: unable to close ExodusII file");

  printf("ExodusII mesh information\n");
  if(strlen(mesh->title) > 0)
    printf("\ttitle: %s\n", mesh->title);
  printf("\tgeometry dimension: "ST_ZU"\n", mesh->num_dims);
  printf("\tnumber of nodes: "ST_ZU"\tnumber of elements: "ST_ZU"\n", mesh->num_nodes,
         mesh->num_elems);
  printf("\tnumber of element blocks: "ST_ZU"\n", mesh->num_el_blks);
  printf("\tnumber of node sets: "ST_ZU"\tnumber of side sets: "ST_ZU"\n",
         mesh->num_node_sets, mesh->num_side_sets);

  return 1;

} /*--------------------------End read_mesh_params()-------------------------*/