Beispiel #1
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;
}
Beispiel #2
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);
}
Beispiel #3
0
/*
 * void Zoltan_Oct_costs_free(pOctant octant)
 *
 * deletes the cost associated with the octant
 */
void Zoltan_Oct_costs_free(OCT_Global_Info *OCT_info,pOctant octant) {
    pOctant children[8];                       /* children of the octant */
    int i;                                     /* index counter */

    Zoltan_Oct_modify_cost(octant, 0);

    if (!Zoltan_Oct_isTerminal(octant)) {
        Zoltan_Oct_children(octant,children);
        for (i=0; i<8; i++)
            if(Zoltan_Oct_POct_local(OCT_info, octant, i))
                Zoltan_Oct_costs_free(OCT_info,children[i]);
    }
}
Beispiel #4
0
/*
 * Zoltan_Oct_terminal_coarsen(oct)
 *
 * remove octant's children, accumulating regions
 * to octant
 *
 */
static void Zoltan_Oct_terminal_coarsen(ZZ *zz, OCT_Global_Info *OCT_info,
					pOctant oct) 
{
  pOctant child;                        /* child of an octant */
  pRegion region;                       /* region associated with an octant */
  int i;                                /* index counter */
  pRegion regionlist[8];                /* an array of region lists */

  oct_ncoarse++;                        /* increment coarsening counter */

  for(i=0; i<8; i++) {
    /* get the ith child of an octant */
    child = Zoltan_Oct_child(oct,i);
    
    /* cannot coarsen if child is off-processor */
    /* if(!Zoltan_Oct_POct_local(child)) X */
    /* cannot be off-processor */
    if(!Zoltan_Oct_POct_local(OCT_info, oct, i)) {
      fprintf(stderr,"OCT Zoltan_Oct_terminal_coarsen: child not local\n");
      abort();
    }
    
    if(!Zoltan_Oct_isTerminal(child)) {
      fprintf(stderr,"OCT Zoltan_Oct_terminal_coarsen: child not terminal\n");
      abort();
    }
    
    /* get each child's region list */
    regionlist[i] = Zoltan_Oct_regionlist(child);
    
    /* delete each child */
    /* KDDKDDFREE Change child to &child. */
    Zoltan_Oct_POct_free(OCT_info, &child);
    oct->child[i] = NULL;
  }
  oct->numChild = 0;
  /* 
   * copy contents of each region list into region list
   * of coarsened parent (which is now a terminal octant) 
   */
  for(i=0; i < 8; i++) {
    region = regionlist[i];
    /* go through the regionlist and add to octant */
    while(region != NULL) {
      Zoltan_Oct_addRegion(zz, oct,region);           
      region = region->next;
    }
  }
}
Beispiel #5
0
/*
 * void Zoltan_Oct_tag_subtree(pOctant octant, int partition_number)
 *
 * marks all the octants within the subtree to be in the current partition
 */
static void Zoltan_Oct_tag_subtree(OCT_Global_Info *OCT_info,pOctant octant, 
				   int part) {
  pOctant children[8];                                /* children of octant */
  int i;                                              /* index counter */

  /* modify NPID so octant know where to migrate to */
  Zoltan_Oct_modify_newpid(octant, part);

  if (Zoltan_Oct_isTerminal(octant))
    return;

  /* if octant has children, have to tag them too */
  Zoltan_Oct_children(octant,children);
  
  for (i=0; i<8; i++)                       /* Simple - just visit in order */
    /* if (children[i] && Zoltan_Oct_local(OCT_info, children[i])) */
    if(children[i] && Zoltan_Oct_POct_local(OCT_info, octant,i))
      Zoltan_Oct_tag_subtree(OCT_info,children[i],part);
}
Beispiel #6
0
/*
 * Zoltan_Oct_findOctant(oct, coord)
 *   (replaces : PO_findOctant(oct,coord))
 *  
 *
 * find the octant in a subtree containing coord (if coord
 * is not in the subtree, returns the closest octant in the subtree).
 * NOTE: return NULL if we hit an off-processor link
 *
 */
static pOctant Zoltan_Oct_findOctant(OCT_Global_Info *OCT_info,pOctant oct, 
				     COORD coord) 
{
  pOctant child;                                  /* child of an octant */
  int cnum;                                       /* child number */
  
  /* if octant is terminal, then this is the right octant */
  if (Zoltan_Oct_isTerminal(oct))
    return(oct);

  /* find closest child to coord */
  cnum = Zoltan_Oct_child_which_wrapper(OCT_info,oct,coord);
  child = Zoltan_Oct_child(oct, cnum);                    /* get that child */
  /* ATTN: are these local checks necessary? */
  /* if ( !Zoltan_Oct_POct_local(child) ) */
  if(!Zoltan_Oct_POct_local(OCT_info,oct, cnum))  /* make sure oct is local */
    return(NULL);

  /* recursivly search down the tree */
  return(Zoltan_Oct_findOctant(OCT_info,child,coord));
}
Beispiel #7
0
/*
 * float Zoltan_Oct_costs_subtree_compute(pOctant octant, int sequence_number)
 *
 * Do a DFS on the octree, calculating the costs for any given subtree.
 * (Subtree is defined as any octant and all its descendants.)
 *
 * Tag every octant visited with a sequence number, automatically
 * incrementing the sequence number.
 *
 * NOTE: must call Zoltan_Oct_costs_init() first
 */
static float Zoltan_Oct_costs_subtree_compute(OCT_Global_Info *OCT_info,pOctant octant, int *seq) {
    pOctant children[8];                       /* the children of the octant */
    float c = 0;                               /* cost of each subtree */
    int i = 0;                                 /* index counter */

    /* #ifdef LGG_MIGOCT */
    Zoltan_Oct_setID(octant,(*seq)++);               /* set new ID for local ordering */
    /* #endif  */ /* LGG_MIGOCT */

    if (!Zoltan_Oct_isTerminal(octant)) {
        /* get the children of each octant */
        Zoltan_Oct_children(octant,children);
        /* sum the cost for each child to get octant's cost */
        for (i=0; i<8; i++)
            if(children[i] && Zoltan_Oct_POct_local(OCT_info, octant, i))
                c += Zoltan_Oct_costs_subtree_compute(OCT_info,children[i], seq);
    }
    else                                                           /* terminal */
        c=Zoltan_Oct_costs_weight(octant);

    /* set the cost data to the octant */
    Zoltan_Oct_modify_cost(octant, c);
    return(c);
}
Beispiel #8
0
/*
 * void Zoltan_Oct_visit(pOctant octant)
 * 
 * This routine references the following (static) global variables:
 *
 *   partition - (RW) number of the partition we are currently working on
 *   total     - (RW) total cost of all *previous* partitions
 *   pcost     - (RW) partition cost for current partition
 *   optcost   - (RO) optimal partition cost
 */
static void Zoltan_Oct_visit(ZZ *zz, pOctant octant, float *part_sizes) {
  float cost;                /* Cost of this octant */
  float togo;                /* Remaining room in current partition */
  float behind;              /* How many to make up for from all prev parts */
  pOctant children[8];       /* children of the octant */
  int i;                     /* index counter */
  COORD origin;              /* center of the octant */
  double volume;             /* volume of the octant */
  double prod[3];            /* product of octant origin and its volume */
  OCT_Global_Info *OCT_info = (OCT_Global_Info *)(zz->LB.Data_Structure);

  DFS_Part_Count++;
  cost = Zoltan_Oct_costs_value(octant);      /* get the cost of the octant */
  /*behind = partition * optcost - total;*/     /* calcuate how much behind */
  behind = (tmpcost*globalcost) - total;        /* calcuate how much behind */
  
  if(0)
    fprintf(stderr,"LGG[%d] pc=%f, c=%f, ps=%f, b=%f\n", partition, pcost,
	    cost, optsize, behind);
  /* If octant does not overflow the current partition, then use it. */
  /*if( cost==0 || (pcost+cost) <= (optcost+behind)) {*/
  if(cost==0 || ((pcost+cost) <= (optsize+behind))) {
    Zoltan_Oct_tag_subtree(OCT_info,octant,partition);
    /*fprintf(stderr,"LGG[%d] pc=%f, c=%f, ps=%f, b=%f\n", partition, pcost,
	    cost, optsize, behind);*/
    pcost+=cost;
    
    Zoltan_Oct_origin_volume(octant, origin, &volume);
    
    vector_cmult(prod,volume,origin);
    pmass+=volume;
    vector_add(pcoord,pcoord,prod);
    
    return;
  }

  /* 
   * Can't use entire octant because it is too big. If it has suboctants, 
   * visit them.
   */
  
  if (!Zoltan_Oct_isTerminal(octant)) {
    Zoltan_Oct_modify_newpid(octant, partition);                 /* Nonterm */
    Zoltan_Oct_children(octant,children);

    for (i=0; i<8; i++)                    /* Simple - just visit in order */
      if(children[i] && Zoltan_Oct_POct_local(OCT_info, octant,i))
        Zoltan_Oct_visit(zz,children[i],part_sizes);
    return;
  }
  
  /* 
   * No suboctants!
   * We've hit bottom - have to decide whether to add to
   * the current partition or start a new one.
   */
  togo = behind + optsize - pcost;

  /*printf("proc=%d, part=%d, b=%f, pcost=%f, cost=%f, os=%f\n",
	 zz->Proc, partition, behind, pcost, cost, optsize);*/

  if ((cost-togo) >= togo) {
    /*printf("proc=%d, part=%d, togo=%f, pcost=%f, cost=%f, g=%f\n",
	   zz->Proc, partition, togo, pcost, cost, globalcost);*/
    /*
     * End current part and start new one. We are more "over" than "under"
     */
    tmpcost += part_sizes[partition];
    partition++;                               /* Move on to next partition */
    while((part_sizes[partition] == 0) && (partition < (zz->Num_Proc - 1)))
      partition++;
    optsize = part_sizes[partition]*globalcost;
    total += pcost;
    pcost = 0;
    pmass = 0;
    vector_set_comp(pcoord,0,0,0);
  }

  /*** Add terminal octant to current partition */
  Zoltan_Oct_modify_newpid(octant, partition);
  pcost += cost;

  Zoltan_Oct_origin_volume(octant, origin, &volume);

  vector_cmult(prod,volume,origin);
  pmass += volume;
  vector_add(pcoord,pcoord,prod);
}