/* * 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]); } }
/* * 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); }
/* * 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); }
/* * Zoltan_Oct_terminal_refine(oct) * * subdivide a terminal octant and divvy up * its regions to the 8 children; recurse if * necessary to satisfy MAXOCTREGIONS * */ static void Zoltan_Oct_terminal_refine(ZZ *zz, pOctant oct,int count) { COORD min, /* coordinates of minimum bounds of region */ max, /* coordinates of maximum bounds of region */ origin; /* origin of region */ pOctant child[8]; /* array of child octants */ int cnum; /* child number */ int i; /* index counter */ pRegion region; /* a region to be associated to an octant */ pRegion entry; COORD cmin[8], cmax[8]; OCT_Global_Info *OCT_info = (OCT_Global_Info *) (zz->LB.Data_Structure); for(i=0;i<3;i++) min[i] = max[i] = 0; /* upper limit of refinement levels */ /* ATTN: may not be used anymore, but can be put back in if necessary */ if (count>=20) { fprintf(stderr, "OCT ERROR: Zoltan_Oct_terminal_refine: bailing out at " "10 levels\n"); abort(); } oct_nref++; /* increment refinement counter */ /* octant should be terminal in order to be refined (subdivided) */ if (!Zoltan_Oct_isTerminal(oct)) { fprintf(stderr,"OCT ref_octant: oct not terminal\n"); abort(); } /* get the bounds of an octant */ Zoltan_Oct_bounds(oct,min,max); /* calculate the origin from the bounds */ Zoltan_Oct_bounds_to_origin(min,max,origin); region = Zoltan_Oct_regionlist(oct); /* Get list while still terminal */ oct->list = NULL; /* remove regions from octant, it won't be terminal */ /* create the children and set their id's */ Zoltan_Oct_child_bounds_wrapper(OCT_info,oct, cmin, cmax); for (i=0; i<8; i++) { if(OCT_info->OCT_dimension == 2) { /* KDDKDD 3/01 see changes to Zoltan_Oct_child_bounds_wrapper that allow this * KDDKDD 3/01 test to work for GRAY and HILBERT mappings. */ if(cmin[i][2] > OCT_info->OCT_gmin[2]) { /* ignore the z+ octants */ child[i] = NULL; continue; } } child[i]=Zoltan_Oct_POct_new(OCT_info); /* create a new octant */ child[i]->dir = Zoltan_Oct_get_child_dir(OCT_info, oct->dir, i); /* create a new octant */ /* set the child->parent link */ Zoltan_Oct_POct_setparent(OCT_info, child[i], oct, zz->Proc); Zoltan_Oct_setchildnum(child[i], i); /* which child of the parent */ Zoltan_Oct_setchild(oct, i, child[i]); /* set the parent->child link */ #ifdef LGG_MIGOCT Zoltan_Oct_setID(child[i], Zoltan_Oct_nextId()); /* set child id num */ #endif /* LGG_MIGOCT */ Zoltan_Oct_setbounds(child[i], cmin[i], cmax[i]); /* set child bounds */ Zoltan_Oct_setCpid(oct, i, zz->Proc); /* set child to be a local oct */ /* Zoltan_Oct_setOrientation(child[i], Zoltan_Oct_child_orientation(oct->orientation, oct->which)); */ } /* assign newly created children to child array*/ if(OCT_info->OCT_dimension == 3) { if(Zoltan_Oct_children(oct, child) != 8) { /* * if subdivision of oct was successful, oct should have 8 children; * thus a return value of 0 here is a fatal error */ fprintf(stderr, "OCT ref_octant: subdivide failed, %d children.\n", Zoltan_Oct_children(oct, child)); abort(); } } else if(Zoltan_Oct_children(oct, child) != 4) { /* * if subdivision of oct was successful, oct should have 4 children; * thus a return value of 0 here is a fatal error */ fprintf(stderr, "OCT ref_octant:subdivide failed, %d children, expected 4\n", Zoltan_Oct_children(oct, child)); abort(); } /* iterate through and find which child each region should belong to */ while(region != NULL) { entry = region->next; cnum=Zoltan_Oct_child_which_wrapper(OCT_info,oct, region->Coord); /* add region to octant's regionlist */ Zoltan_Oct_addRegion(zz, child[cnum], region); ZOLTAN_FREE(&(region->Global_ID)); ZOLTAN_FREE(&(region->Local_ID)); ZOLTAN_FREE(®ion); region = entry; } for (i=0; i<8; i++) /* Recursion */ if(child[i] != NULL) /* KDDKDD Replaced the following to allow multiple regions with the * KDDKDD same coordinates to be placed in the same octant. if (Zoltan_Oct_nRegions(child[i]) > MAXOCTREGIONS) { */ if (Zoltan_Oct_nUniqueRegions(OCT_info,child[i]) > MAXOCTREGIONS) { Zoltan_Oct_terminal_refine(zz, child[i],count+1); } }
/* * 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); }