コード例 #1
0
/*
 * Zoltan_Oct_subtree_dref(oct)
 *
 * Coarsen octree so that leaf octants do not have less than MINOCTREGIONS 
 * regions. Refinement takes precedence, so coarsening will not take place 
 * unless all subtrees agree on it.
 */
static int Zoltan_Oct_subtree_dref(ZZ *zz, OCT_Global_Info *OCT_info,
				   pOctant oct) 
{
  pOctant child;                        /* child of an octant */
  int coarsen;                          /* flag to indicate need to coarsen */
  int i;                                /* index counter */
  int nregions;                         /* number of regions */
  int total;                            /* total number of regions */

  /* if terminal octant, cannot coarsen on own */
  if (Zoltan_Oct_isTerminal(oct)) {
    nregions=Zoltan_Oct_nRegions(oct);

    if (nregions > (MAXOCTREGIONS*2) ) {
      fprintf(stderr, 
	      "OCT Zoltan_Oct_subtree_dref: warning: too many (%d) regions "
	     "in oct (id=%d)\n",Zoltan_Oct_nRegions(oct),Zoltan_Oct_id(oct));
      return(-1);
    }
    else
      if (nregions < MINOCTREGIONS)
	return(nregions);
      else
	return(-1);
  }

  coarsen=1;                                        /* assume to be coarsen */
  total=0;

  /* look at each child, see if they need to be coarsened */
  for (i=0; coarsen && i<8; i++) {
    child = Zoltan_Oct_child(oct,i);
    /* if child is off processor cannot coarsen */
    /* if (!Zoltan_Oct_local(child) ) */
    if(!Zoltan_Oct_POct_local(OCT_info, oct, i))
      coarsen=0;
    else {
      /* get the number of region of the child */
      nregions=Zoltan_Oct_subtree_dref(zz, OCT_info,child);
      if (nregions<0)
	coarsen=0;
      else
	total+=nregions;                          /* total the region count */
    }
  }

  /* check if octant can be coarsened */
  if (coarsen && total<MAXOCTREGIONS) {
    Zoltan_Oct_terminal_coarsen(zz, OCT_info,oct);
    
    if (total < MINOCTREGIONS)
      return(total);
    else
      return(-1);
  }

  return(-1);
}
コード例 #2
0
/* KDDKDDFREE Changed root to *root to allow NULL from ZOLTAN_FREE to propagate 
 * KDDKDDFREE back to calling routine. */
int Zoltan_Oct_POct_delTree(OCT_Global_Info *OCT_info, pOctant *root) {
  int i;                                               /* index counter */
  pOctant child;                                       /* child of an octant */
  
  if(*root == NULL)
    return 1;

  if(Zoltan_Oct_isTerminal(*root)) {
    if(Zoltan_Oct_nRegions(*root))
      Zoltan_Oct_clearRegions(*root);
    Zoltan_Oct_POct_free(OCT_info, root);
  }
  else {
    for(i=0; i<8; i++) {
      child = Zoltan_Oct_child(*root, i);
      if(child != NULL && Zoltan_Oct_POct_local(OCT_info,*root, i)) {
	Zoltan_Oct_POct_delTree(OCT_info,&child);
        /* KDDKDDFREE propagate NULL from Zoltan_Oct_POct_delTree to root->child */
        (*root)->child[i] = NULL;  
        (*root)->cpid[i]  = -1;
      }
      /* KDDKDDFREE Added this condition so that tests (in other parts of the
       * KDDKDDFREE code) for NULL children work */
      else if (child != NULL) {
        (*root)->child[i] = NULL;
        (*root)->cpid[i]  = -1;
      }
      /* END KDDKDDFREE */
    }
    Zoltan_Oct_POct_free(OCT_info, root);
  }
  return 1;
}
コード例 #3
0
/*
 * void tag_regions()
 * Iterates through the list of octants on the processor and finds which
 * are to be migrated. It then looks at the region list for those octants 
 * and stores the migrating regions into the export_tags array.
 */
static int tag_regions(ZZ *zz,
		       pOctant *octs,
		       int *newpids,
		       int nocts, 
		       Region **exported_tags,
		       ZOLTAN_ID_PTR *exported_gids,
		       ZOLTAN_ID_PTR *exported_lids,
		       int *nsentags, 
		       int **tag_pids,
		       Region **p_tags, 
		       ZOLTAN_ID_PTR *p_gids,
		       ZOLTAN_ID_PTR *p_lids,
		       int *npimtags,
		       float *c2,
		       int *max_objs)
{
  char *yo = "tag_regions";
  int i;               /* index counter */
  pRegion regionlist;  /* list of region on this processor */
  int index;           /* index counter */
  int index2;          /* yet another index counter */
  int count;           /* count of objects exported form this processor */
  int count2;          /* count of objects that are kept on processor */
  int count3;
  int *exported_pids;  /* array of pids where regions are being exported to */
  pRegion mtags;       /* object tags of objects to be migrated */
  pRegion ptags;       /* tags of objects that were previously migrated */
  float ex_load;
  int ierr = ZOLTAN_OK;
  int num_gid_entries = zz->Num_GID;
  int num_lid_entries = zz->Num_LID;

  ex_load = 0;
  (*max_objs) = 0;

  if (!nsentags) 
    return ierr;

  /* find how many objects have been exported */
  count = 0;
  /* find number of local objs to export */
  count2 = 0;
  count3 = 0;

  for (i=0; i<nocts; i++) {
    if(Zoltan_Oct_isTerminal(octs[i])) {
      (*max_objs) += Zoltan_Oct_nRegions(octs[i]);

      regionlist = Zoltan_Oct_regionlist(octs[i]);
      while(regionlist != NULL) {
	count3++;
	if(regionlist->Proc != zz->Proc) {
	  count++;
	  if(newpids[i] != zz->Proc)
	    regionlist->newProc = newpids[i];
	  else
	    regionlist->newProc = zz->Proc;
	}
	else {
	  if(newpids[i] != zz->Proc) {
	    count2++;
	    regionlist->newProc = newpids[i];
	  }
	  else
	    regionlist->newProc = zz->Proc;
	}
	regionlist = regionlist->next;                 /* get next region */
      }
    }
  }

#if 0
  {
    {
      if (newpids[i]!=zz->Proc) {
	count+=Zoltan_Oct_nRegions(octs[i]);
      }
      else {
	pRegion regions;

	regions = Zoltan_Oct_regionlist(octs[i]);
	while(regions != NULL) {
	  if(regions->Proc != zz->Proc)
	    count2++;
	  regions = regions->next;
	}
      }
    }
  }
#endif

  /* set up the return pointers */
  *nsentags = count;
  *npimtags = count2;

  if (!exported_tags) {
    return ierr;
  }

  if (count > 0) {
    /* allocate some space */
    if((mtags=(pRegion)ZOLTAN_MALLOC((unsigned)count*sizeof(Region)))==NULL){
      ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory.");
      ZOLTAN_TRACE_EXIT(zz, yo);
      return ZOLTAN_MEMERR;
    }
    if((exported_pids = (int *)ZOLTAN_MALLOC((unsigned)count*sizeof(int))) ==
       NULL){
      ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory.");
      ZOLTAN_TRACE_EXIT(zz, yo);
      ZOLTAN_FREE(&mtags);
      return ZOLTAN_MEMERR;
    }
    *exported_gids = ZOLTAN_MALLOC_GID_ARRAY(zz, count);
    *exported_lids = ZOLTAN_MALLOC_LID_ARRAY(zz, count);
    if(!(*exported_gids) || (num_lid_entries && !(*exported_lids))) {
      ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory.");
      ZOLTAN_TRACE_EXIT(zz, yo);
      ZOLTAN_FREE(&mtags);
      ZOLTAN_FREE(&exported_pids);
      return ZOLTAN_MEMERR;
    }
  }
  else {
    mtags = NULL;
    exported_pids = NULL;
    *exported_gids = NULL;
    *exported_lids = NULL;
  }
  /* set up return pointers */
  *exported_tags=mtags;
  *tag_pids = exported_pids;
  
  if (count2 > 0) {
    /* allocate some space */
    if((ptags=(pRegion)ZOLTAN_MALLOC((unsigned)count2*sizeof(Region)))==NULL){
      ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient Memory.");
      ZOLTAN_TRACE_EXIT(zz, yo);
      ZOLTAN_FREE(&mtags);
      ZOLTAN_FREE(&exported_pids);
      ZOLTAN_FREE(exported_gids);
      ZOLTAN_FREE(exported_lids);
      return ZOLTAN_MEMERR;
    }
    *p_gids = ZOLTAN_MALLOC_GID_ARRAY(zz, count2);
    *p_lids = ZOLTAN_MALLOC_LID_ARRAY(zz, count2);
    if(!(*p_gids) || (num_lid_entries && !(*p_lids))) {
      ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient Memory.");
      ZOLTAN_TRACE_EXIT(zz, yo);
      ZOLTAN_FREE(&mtags);
      ZOLTAN_FREE(&exported_pids);
      ZOLTAN_FREE(exported_gids);
      ZOLTAN_FREE(exported_lids);
      ZOLTAN_FREE(&ptags);
      ZOLTAN_FREE(p_gids);
      ZOLTAN_FREE(p_lids);
      return ZOLTAN_MEMERR;
    }
  }
  else {
    ptags = NULL;
    *p_gids = NULL;
    *p_lids = NULL;
  }
  
  /* set up return pointers */
  *p_tags=ptags;
  
  index = index2 = 0;
  for (i=0; i<nocts; i++) {
    if(Zoltan_Oct_isTerminal(octs[i])) {
      regionlist = Zoltan_Oct_regionlist(octs[i]);
      while(regionlist != NULL) {
	if(regionlist->Proc != zz->Proc) {
	  /* place information in the appropritate array */
	  mtags[index] = *regionlist;
          ZOLTAN_SET_GID(zz, &((*exported_gids)[index*num_gid_entries]), 
			 regionlist->Global_ID);
          ZOLTAN_SET_LID(zz, &((*exported_lids)[index*num_lid_entries]),
			 regionlist->Local_ID);

	  /*ex_load += (float)(regionlist->Weight);*/
	  exported_pids[index] = regionlist->Proc;
	  index++;                                     /* increment counter */
	}
	else if(newpids[i] != zz->Proc) { 
	  ptags[index2] = *regionlist;	  /* get region information */
	  ZOLTAN_SET_GID(zz, &((*p_gids)[index2*num_gid_entries]),
			 regionlist->Global_ID);
	  ZOLTAN_SET_LID(zz, &((*p_lids)[index2*num_lid_entries]),
			 regionlist->Local_ID);
	  
	  index2++;                                  /* increment counter */
	}
	regionlist = regionlist->next;                 /* get next region */
      }
    }
  }
  
  if (index!=count) {                                        /* error check */
    ZOLTAN_TRACE_DETAIL(zz, yo, 
			"Fatal error, inconsistent number of regions.\n");
    return ZOLTAN_FATAL;
  }
  *c2 = ex_load;
  return ierr;
}
コード例 #4
0
/*
 * void lb_oct_init();
 *
 * initialize the calls needed to start the octree load balancing rounties
 */
static int lb_oct_init(
  ZZ *zz,                       /* The Zoltan structure with info for
                                   the OCTPART balancer.                    */
  int *num_export,              /* Number of non-local objs assigned to this
                                   processor in the new decomposition.      */
  ZOLTAN_ID_PTR *export_global_ids, /* Returned value: array of global IDs for
                                   non-local objects in this processor's new
                                   decomposition.                           */
  ZOLTAN_ID_PTR *export_local_ids,  /* Returned value:  array of local IDs for
                                   non-local objects in this processor's new
                                   decomposition.                           */
  int **export_procs,           /* Returned value:  array of processor IDs for
                                   processors owning the non-local objects in
                                   this processor's new decomposition.      */
  int **export_to_part,         /* Returned value:  array of partitions to 
                                   which objects are imported.
                                   KDDKDD Assume #parts==#procs.            */
  int oct_dim,                  /* Dimension of method (2D or 3D)           */
  int oct_method,               /* Flag specifying curve to be used.        */
  int oct_maxoctregions,        /* max # of objects in leaves of octree.    */
  int oct_minoctregions,        /* min # of objects in leaves of octree.    */
  int oct_output_level,         /* Flag specifying amount of output.        */
  int oct_wgtflag,              /* Flag specifying use of object weights.   */
  float *part_sizes             /* Array of size zz->Num_Global_Parts
                                   containing the percentage of work to be
                                   assigned to each partition.              */
) 
{
  char *yo = "lb_oct_init";
  OCT_Global_Info *OCT_info;
  int nsentags;                    /* number of tags being sent */
  pRegion export_regs;             /* */
  int nrectags;                    /* number of tags received */
  int kk;
  double time1,time2;              /* timers */
  double timestart,timestop;       /* timers */
  double timers[4];                /* diagnostic timers 
			              0 = start-up time before recursion
				      1 = time before median iterations
				      2 = time in median iterations
				      3 = communication time */
  int    counters[6];              /* diagnostic counts
			              0 = # of median iterations
				      1 = # of objects sent
				      2 = # of objects received
				      3 = most objects this proc ever owns
				      */
  float  c[4];
  int createpartree = 0;
  /*int num_gid_entries = zz->Num_GID;*/
  /*int num_lid_entries = zz->Num_LID;*/
  
  ZOLTAN_TRACE_ENTER(zz, yo);

  MPI_Barrier(zz->Communicator);
  timestart = MPI_Wtime();

  /* initialize timers and counters */
  counters[0] = 0;
  counters[1] = 0;
  counters[2] = 0;
  counters[3] = 0;
  counters[4] = 0;
  counters[5] = 0;
  c[0] = 0;
  c[1] = 0;
  c[2] = 0;
  c[3] = 0;
  timers[1] = 0.0;
  timers[2] = 0.0;
  timers[3] = 0.0;

  nsentags = nrectags = 0;

  if(zz->LB.Data_Structure == NULL) {
    OCT_info = Zoltan_Oct_POct_init(zz, zz->Proc, oct_dim);
    Zoltan_Oct_set_method(OCT_info, oct_method);
    Zoltan_Oct_set_maxregions(oct_maxoctregions);
    Zoltan_Oct_set_minregions(oct_minoctregions);
    createpartree = 1;
  }
  else {
    OCT_info = (OCT_Global_Info *) (zz->LB.Data_Structure);
  }

  /* create the octree structure */
  time1 = MPI_Wtime();

  ZOLTAN_TRACE_DETAIL(zz, yo, "Calling Zoltan_Oct_gen_tree_from_input_data");
  Zoltan_Oct_gen_tree_from_input_data(zz, oct_wgtflag, &counters[1],
				      &counters[2], &counters[3], &c[0], 
				      createpartree);

  time2 = MPI_Wtime();
  timers[0] = time2 - time1;                 /* time took to create octree */
  /* Zoltan_Oct_POct_printResults(OCT_info); */
  /* partition the octree structure */
  time1 = MPI_Wtime();
  ZOLTAN_TRACE_DETAIL(zz, yo, "Calling Zoltan_Oct_dfs_partition");
  /* old call to dfs_paritition: */ 
#if 0
  Zoltan_Oct_dfs_partition(zz, &counters[0], &c[1]);
#else
  /***************************
  if(zz->Proc == 0) {
    int debug_i;
    for(debug_i=0; debug_i<zz->Num_Proc; debug_i++) {
      fprintf(stdout,"Part_size[%d] = %f\n", debug_i, part_sizes[debug_i]);
    }
  }
  ****************************/
  Zoltan_Oct_dfs_partition(zz, &counters[0], &c[1], part_sizes);
#endif
  time2 = MPI_Wtime();
  timers[1] = time2 - time1;              /* time took to partition octree */

  if (oct_output_level > 2) {
    Zoltan_Oct_Plots(zz);
  }

  /* set up tags for migrations */
  time1 = MPI_Wtime();

#if 0  /* KDDKDD -- Count is never used; why is it computed? */
  {
  pRList  RootList;               /* list of all local roots */
  pOctant RootOct;                /* root octree octant */
  int count = 0; 
  RootList = Zoltan_Oct_POct_localroots(OCT_info);
  while((RootOct = RL_nextRootOctant(&RootList))) {
    while(RootOct) {
      if(Zoltan_Oct_isTerminal(RootOct)) {	
	count += Zoltan_Oct_nRegions(RootOct);
      }
      RootOct = Zoltan_Oct_POct_nextDfs(OCT_info, RootOct);
    }
  }
  }
#endif

  ZOLTAN_TRACE_DETAIL(zz, yo, "Calling Zoltan_Oct_dfs_migrate");
  Zoltan_Oct_dfs_migrate(zz, &nsentags, &export_regs, &nrectags, 
	         &c[2], &c[3], &counters[3], &counters[5]);

  ZOLTAN_TRACE_DETAIL(zz, yo, "Calling Zoltan_Oct_fix_tags");
  if (zz->LB.Return_Lists) {
    *num_export = nrectags;
    if (nrectags > 0)
      Zoltan_Oct_fix_tags(zz, export_global_ids, export_local_ids, 
			  export_procs, export_to_part, nrectags,
			  export_regs);
  }

  time2 = MPI_Wtime();
  timers[2] = time2 - time1;               /* time took to setup migration */


#if 0  /* KDDKDD -- Count is never used; why is it computed? */
  {
  /* count the number of objects on this processor */
  pRList  RootList;               /* list of all local roots */
  pOctant RootOct;                /* root octree octant */
  int count = 0; 
  RootList = Zoltan_Oct_POct_localroots(OCT_info);
  while((RootOct = RL_nextRootOctant(&RootList))) {
    while(RootOct) {
      if(Zoltan_Oct_isTerminal(RootOct)) {	
	count += Zoltan_Oct_nRegions(RootOct);
      }
      RootOct = Zoltan_Oct_POct_nextDfs(OCT_info, RootOct);
    }
  }
  }
#endif

  counters[4] = nsentags;
  MPI_Barrier(zz->Communicator);
  timestop = MPI_Wtime();

  if (oct_output_level > 0) {
    ZOLTAN_TRACE_DETAIL(zz, yo, "Calling Zoltan_Oct_print_stats");
    Zoltan_Oct_print_stats(zz, timestop-timestart, timers, counters, c, 
                       oct_output_level);
  }

  for (kk = 0; kk < nrectags; kk++) {
    ZOLTAN_FREE(&(export_regs[kk].Global_ID));
    ZOLTAN_FREE(&(export_regs[kk].Local_ID));
  }
  ZOLTAN_FREE(&export_regs);
  ZOLTAN_TRACE_DETAIL(zz, yo, "Calling Zoltan_Oct_global_clear");
  Zoltan_Oct_global_clear(OCT_info);
  /* KDDKDD Don't understand how re-used octree will work, especially without
   * KDDKDD the Zoltan_Oct_Bounds_Geom function.  For now, we'll delete everything;
   * KDDKDD we can move back to saving some of the tree later.
   */
  Zoltan_Oct_Free_Structure(zz);
  /* KDDKDD END */

  /* Temporary return value until error codes are fully implemented. */
  ZOLTAN_TRACE_EXIT(zz, yo);
  return(ZOLTAN_OK);
}