/* * Function that initializes the region data structure. It uses the * global ID, coordinates and weight provided by the application. */ static void initialize_region(ZZ *zz, pRegion *ret, ZOLTAN_ID_PTR global_id, ZOLTAN_ID_PTR local_id, int wgtflag, float wgt, int num_dim, double *geom_vec) { pRegion reg; int i; reg = (pRegion) ZOLTAN_MALLOC(sizeof(Region)); *ret = reg; reg->Global_ID = ZOLTAN_MALLOC_GID(zz); reg->Local_ID = ZOLTAN_MALLOC_LID(zz); ZOLTAN_SET_GID(zz, reg->Global_ID, global_id); ZOLTAN_SET_LID(zz, reg->Local_ID, local_id); reg->Proc = zz->Proc; /* reg->Proc = 0; */ reg->Coord[0] = reg->Coord[1] = reg->Coord[2] = 0.0; for (i = 0; i < num_dim; i++) reg->Coord[i] = geom_vec[i]; #if 0 Zoltan_Print_Sync_Start(zz->Communicator, TRUE); fprintf(stderr, "Result info on %d: %d %d %d %lf %lf %lf\n", zz->Proc, reg->Local_ID, reg->Global_ID, reg->Proc, reg->Coord[0], reg->Coord[1], reg->Coord[2]); Zoltan_Print_Sync_End(zz->Communicator, TRUE); #endif if (wgtflag) reg->Weight = wgt; else reg->Weight = 1; reg->next = NULL; }
/* * void Zoltan_Oct_addRegion(pOctant octant, pRegion region) * add a region to oct's list */ int Zoltan_Oct_addRegion(ZZ *zz, pOctant oct, pRegion region) { char *yo = "Zoltan_Oct_addRegion"; pRegion entry; /* pointer to new entry in region list */ if(oct == NULL) return ZOLTAN_WARN; entry = (pRegion) ZOLTAN_MALLOC(sizeof(Region)); /* malloc space for region */ if(entry == NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Cannot allocated memory for region."); return ZOLTAN_MEMERR; } entry->Global_ID = ZOLTAN_MALLOC_GID(zz); entry->Local_ID = ZOLTAN_MALLOC_LID(zz); /* copy region information into the entry */ vector_set(entry->Coord, region->Coord); entry->Weight = region->Weight; ZOLTAN_SET_GID(zz, entry->Global_ID, region->Global_ID); ZOLTAN_SET_LID(zz, entry->Local_ID, region->Local_ID); entry->Proc = region->Proc; /* attach region to region list */ entry->next = oct->list; oct->list = entry; return ZOLTAN_OK; }
/* * int Zoltan_Oct_copy_info(pRegion *destination, pRegion source) * * Copies region information from the source to the destination */ static int Zoltan_Oct_copy_info(ZZ *zz, pRegion src, pRegion *dest) { pRegion copy; char *yo = "Zoltan_Oct_copy_info"; int ierr = ZOLTAN_OK; /* mallloc space for destination */ copy = (pRegion) ZOLTAN_MALLOC(sizeof(Region)); if(copy == NULL) { ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } copy->Global_ID = ZOLTAN_MALLOC_GID(zz); copy->Local_ID = ZOLTAN_MALLOC_LID(zz); if (copy->Global_ID == NULL || (zz->Num_LID && copy->Local_ID == NULL)) { ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } /* set up return pointer */ *dest = copy; /* copy all important information */ vector_set(copy->Coord, src->Coord); copy->Weight = src->Weight; ZOLTAN_SET_GID(zz, copy->Global_ID, src->Global_ID); ZOLTAN_SET_LID(zz, copy->Local_ID, src->Local_ID); copy->Proc = src->Proc; copy->attached = 0; return ierr; }
static int Zoltan_Reftree_Export_Lists(ZZ *zz, ZOLTAN_REFTREE *subroot, int *num_export, ZOLTAN_ID_PTR *export_global_ids, ZOLTAN_ID_PTR *export_local_ids, int **export_to_partition, int **export_procs) { /* * Function to build the export lists */ int i, ierr; /* * if this subtree has no leaves assigned to this processor then there can be * no exports below it */ if (!subroot->assigned_to_me) return(ZOLTAN_OK); if (subroot->num_child == 0) { /* * if this is a leaf, put it on the export lists if it is to be exported */ if (export_it(subroot,zz,&ierr)) { ZOLTAN_SET_GID(zz, &((*export_global_ids)[(*num_export)*zz->Num_GID]), subroot->global_id); ZOLTAN_SET_LID(zz, &((*export_local_ids)[(*num_export)*zz->Num_LID]), subroot->local_id); (*export_to_partition)[*num_export] = subroot->partition; (*export_procs)[*num_export] = Zoltan_LB_Part_To_Proc(zz,subroot->partition,subroot->global_id); *num_export += 1; } if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) return(ierr); } else { /* * if it is not a leaf, traverse the subtree */ for (i=0; i<subroot->num_child; i++) { ierr = Zoltan_Reftree_Export_Lists(zz, &(subroot->children[i]),num_export, export_global_ids,export_local_ids, export_to_partition,export_procs); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) return(ierr); } } return(ZOLTAN_OK); }
static int actual_arrays( ZZ *zz, int num_gid_entries, int num_lid_entries, int num, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int *procs, int *to_part, int *actual_num, ZOLTAN_ID_PTR *actual_gids, ZOLTAN_ID_PTR *actual_lids, int **actual_procs, int **actual_to_part, int *actual_allocated ) { char *yo = "actual_arrays"; int i, j; /* * Test whether to pack objects that have changed partition * but not changed processor. * If packing them, the actual objects == objects passed to this function. * If not packing them, build arrays with them stripped out. */ *actual_allocated = 0; if (!(zz->Migrate.Only_Proc_Changes)) { /* Pack all objects, even if they are not changing processor. */ *actual_num = num; *actual_gids = gids; *actual_lids = lids; *actual_procs = procs; *actual_to_part = to_part; } else { /* zz->Migrate.Only_Proc_Changes */ /* Pack only objects that are actually changing processor. */ *actual_num = 0; for (i = 0; i < num; i++) if (procs[i] != zz->Proc) (*actual_num)++; if (*actual_num == num) { /* Number of actual objects == number of objects in input arrays. */ /* No stripping needed. */ *actual_gids = gids; *actual_lids = lids; *actual_procs = procs; *actual_to_part = to_part; } else if (*actual_num != num && *actual_num > 0) { /* Number of actual_num < num. Build arrays */ /* containing only actual objects. */ *actual_allocated = 1; *actual_gids = ZOLTAN_MALLOC_GID_ARRAY(zz, *actual_num); *actual_lids = ZOLTAN_MALLOC_LID_ARRAY(zz, *actual_num); *actual_procs = (int *) ZOLTAN_MALLOC(sizeof(int) * (*actual_num)); if (to_part != NULL) *actual_to_part = (int *) ZOLTAN_MALLOC(sizeof(int)*(*actual_num)); if (*actual_gids == NULL || (num_lid_entries && *actual_lids == NULL) || *actual_procs == NULL || (to_part != NULL && *actual_to_part == NULL)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory Error."); Zoltan_Multifree(__FILE__, __LINE__, 4, actual_gids, actual_lids, actual_procs, actual_to_part); return (ZOLTAN_MEMERR); } for (j = 0, i = 0; i < num; i++) { if (procs[i] != zz->Proc) { ZOLTAN_SET_GID(zz, *actual_gids + j*num_gid_entries, gids + i*num_gid_entries); if (num_lid_entries) ZOLTAN_SET_LID(zz, *actual_lids + j*num_lid_entries, lids + i*num_lid_entries); (*actual_procs)[j] = procs[i]; if (to_part) (*actual_to_part)[j] = to_part[i]; j++; } } } } return ZOLTAN_OK; }
int Zoltan_Random( ZZ *zz, /* The Zoltan structure. */ float *part_sizes, /* Input: Array of size zz->LB.Num_Global_Parts * zz->Obj_Weight_Dim containing the percentage of work to be assigned to each partition. */ int *num_import, /* Return -1. Random uses only export lists. */ ZOLTAN_ID_PTR *import_global_ids, /* Not used. */ ZOLTAN_ID_PTR *import_local_ids, /* Not used. */ int **import_procs, /* Not used. */ int **import_to_part, /* Not used. */ int *num_export, /* Output: Number of objects to export. */ ZOLTAN_ID_PTR *export_global_ids, /* Output: GIDs to export. */ ZOLTAN_ID_PTR *export_local_ids, /* Output: LIDs to export. */ int **export_procs, /* Output: Processsors to export to. */ int **export_to_part /* Output: Partitions to export to. */ ) { int ierr = ZOLTAN_OK; int i, count, num_obj; int max_export; double rand_frac = 1.0; /* Default is to move all objects. */ ZOLTAN_ID_PTR global_ids = NULL; ZOLTAN_ID_PTR local_ids = NULL; int *parts = NULL; float *dummy = NULL; static char *yo = "Zoltan_Random"; static int first_time = 1; ZOLTAN_TRACE_ENTER(zz, yo); /* Synchronize the random number generator. * This synchronization is needed only for sanity in our nightly testing. * If some other operation (eg., Zoltan_LB_Eval) changes the status of * the random number generator, the answers here will change. They won't * be wrong, but they will be different from our accepted answers. */ if (first_time) { Zoltan_Srand(zz->Seed, NULL); Zoltan_Rand(NULL); first_time=0; } /* No import lists computed. */ *num_import = -1; /* Get parameter values. */ Zoltan_Bind_Param(Random_params, "RANDOM_MOVE_FRACTION", (void *) &rand_frac); Zoltan_Assign_Param_Vals(zz->Params, Random_params, zz->Debug_Level, zz->Proc, zz->Debug_Proc); /* Get list of local objects. */ ierr = Zoltan_Get_Obj_List(zz, &num_obj, &global_ids, &local_ids, 0, &dummy, &parts); /* Bound number of objects to export. */ max_export = 1.5*rand_frac*num_obj; /* Allocate export lists. */ *export_global_ids = *export_local_ids = NULL; *export_procs = *export_to_part = NULL; if (max_export > 0) { if (!Zoltan_Special_Malloc(zz, (void **)export_global_ids, max_export, ZOLTAN_SPECIAL_MALLOC_GID) || !Zoltan_Special_Malloc(zz, (void **)export_local_ids, max_export, ZOLTAN_SPECIAL_MALLOC_LID) || !Zoltan_Special_Malloc(zz, (void **)export_procs, max_export, ZOLTAN_SPECIAL_MALLOC_INT) || !Zoltan_Special_Malloc(zz, (void **)export_to_part, max_export, ZOLTAN_SPECIAL_MALLOC_INT)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory error."); ierr = ZOLTAN_MEMERR; goto End; } } /* Randomly assign ids to procs. */ count=0; for (i=0; i<num_obj; i++){ /* Randomly select some objects to move (export) */ if ((count<max_export) && (Zoltan_Rand(NULL)<rand_frac*ZOLTAN_RAND_MAX)){ /* export_global_ids[count] = global_ids[i]; */ ZOLTAN_SET_GID(zz, &((*export_global_ids)[count*zz->Num_GID]), &global_ids[i*zz->Num_GID]); if (local_ids) /* export_local_ids[count] = local_ids[i]; */ ZOLTAN_SET_LID(zz, &((*export_local_ids)[count*zz->Num_LID]), &local_ids[i*zz->Num_LID]); /* Randomly pick new partition number. */ (*export_to_part)[count] = Zoltan_Rand_InRange(NULL, zz->LB.Num_Global_Parts); /* Processor number is derived from partition number. */ (*export_procs)[count] = Zoltan_LB_Part_To_Proc(zz, (*export_to_part)[count], &global_ids[i*zz->Num_GID]); /* printf("Debug: Export gid %u to part %d and proc %d.\n", (*export_global_ids)[count], (*export_to_part)[count], (*export_procs)[count]); */ ++count; } } (*num_export) = count; End: /* Free local memory, but not export lists. */ ZOLTAN_FREE(&global_ids); ZOLTAN_FREE(&local_ids); ZOLTAN_FREE(&parts); ZOLTAN_TRACE_EXIT(zz, yo); return ierr; }
/* * void Zoltan_Oct_fix_tags() * * fixes the import tags so that region tags that were previously * exported aren't counted when imported back. */ int Zoltan_Oct_fix_tags(ZZ *zz, ZOLTAN_ID_PTR *import_global_ids, ZOLTAN_ID_PTR *import_local_ids, int **import_procs, int **import_to_part, int nrectags, pRegion import_regs) { char *yo = "Zoltan_Oct_fix_tags"; int i; /* index counter */ int ierr = ZOLTAN_OK; int num_gid_entries = zz->Num_GID; int num_lid_entries = zz->Num_LID; /* allocate memory */ if (!Zoltan_Special_Malloc(zz,(void **)import_global_ids,nrectags, ZOLTAN_SPECIAL_MALLOC_GID)) { ZOLTAN_PRINT_ERROR(zz->Proc,yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } if (!Zoltan_Special_Malloc(zz,(void **)import_local_ids,nrectags, ZOLTAN_SPECIAL_MALLOC_LID)) { Zoltan_Special_Free(zz,(void **)import_global_ids, ZOLTAN_SPECIAL_MALLOC_GID); ZOLTAN_PRINT_ERROR(zz->Proc,yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } if (!Zoltan_Special_Malloc(zz,(void **)import_procs,nrectags, ZOLTAN_SPECIAL_MALLOC_INT)) { Zoltan_Special_Free(zz,(void **)import_global_ids, ZOLTAN_SPECIAL_MALLOC_GID); Zoltan_Special_Free(zz,(void **)import_local_ids, ZOLTAN_SPECIAL_MALLOC_LID); ZOLTAN_PRINT_ERROR(zz->Proc,yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } if (!Zoltan_Special_Malloc(zz,(void **)import_to_part,nrectags, ZOLTAN_SPECIAL_MALLOC_INT)) { Zoltan_Special_Free(zz,(void **)import_global_ids, ZOLTAN_SPECIAL_MALLOC_GID); Zoltan_Special_Free(zz,(void **)import_local_ids, ZOLTAN_SPECIAL_MALLOC_LID); Zoltan_Special_Free(zz,(void **)import_procs,ZOLTAN_SPECIAL_MALLOC_INT); ZOLTAN_PRINT_ERROR(zz->Proc,yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } /* for each region imported, look at its originating processor */ for(i=0; i<nrectags; i++) { ZOLTAN_SET_GID(zz, &((*import_global_ids)[i*num_gid_entries]), import_regs[i].Global_ID); ZOLTAN_SET_LID(zz, &((*import_local_ids)[i*num_lid_entries]), import_regs[i].Local_ID); (*import_procs)[i] = import_regs[i].newProc; /*(*import_to_part)[i] = zz->Proc;*/ (*import_to_part)[i] = import_regs[i].newProc; } return ierr; }
/* * void malloc_new_objects(); * * gets the tags being imported into this processor, and sets up the * import_tags array, and the nrectags array. */ static int malloc_new_objects(ZZ *zz, int nsentags, pRegion exported_tags, ZOLTAN_ID_PTR exported_gids, ZOLTAN_ID_PTR exported_lids, int *tag_pids, int *nstags, pRegion *ex_tags, pRegion prev_tags, ZOLTAN_ID_PTR prev_gids, ZOLTAN_ID_PTR prev_lids, int npimtags, float *c3) { char *yo = "malloc_new_objects"; int i; /* index counter */ int nreceives; /* number of messages received */ pRegion t_b_exp; /* array of tags to be exported */ pRegion tmp = NULL; ZOLTAN_ID_PTR tmp_gids = NULL; ZOLTAN_ID_PTR tmp_lids = NULL; int msgtag, msgtag2; int j; int ierr = ZOLTAN_OK; int num_gid_entries = zz->Num_GID; int num_lid_entries = zz->Num_LID; float im_load; ZOLTAN_COMM_OBJ *comm_plan; /* Object returned by communication routines */ im_load = 0; msgtag = 32767; ierr = Zoltan_Comm_Create(&comm_plan, nsentags, tag_pids, zz->Communicator, msgtag, &nreceives); if(ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from Zoltan_Comm_Create."); ZOLTAN_TRACE_EXIT(zz, yo); return(ierr); } if (nreceives > 0) { tmp = (pRegion) ZOLTAN_MALLOC(nreceives * sizeof(Region)); tmp_gids = ZOLTAN_MALLOC_GID_ARRAY(zz, nreceives); tmp_lids = ZOLTAN_MALLOC_LID_ARRAY(zz, nreceives); if(tmp == NULL || !tmp_gids || (num_lid_entries && !tmp_lids)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } } msgtag2 = 32766; ierr = Zoltan_Comm_Do(comm_plan, msgtag2, (char *) exported_tags, sizeof(Region), (char *) tmp); if(ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from Zoltan_Comm_Do."); ZOLTAN_TRACE_EXIT(zz, yo); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); return(ierr); } msgtag2--; ierr = Zoltan_Comm_Do(comm_plan, msgtag2, (char *) exported_gids, sizeof(ZOLTAN_ID_TYPE)*num_gid_entries, (char *) tmp_gids); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from Zoltan_Comm_Do."); fprintf(stderr, "OCT %s Error %s returned from Zoltan_Comm_Do\n", yo, (ierr == ZOLTAN_MEMERR ? "ZOLTAN_MEMERR" : "ZOLTAN_FATAL")); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); return(ierr); } if (num_lid_entries > 0) { msgtag2--; ierr = Zoltan_Comm_Do(comm_plan, msgtag2, (char *) exported_lids, sizeof(ZOLTAN_ID_TYPE)*num_lid_entries, (char *) tmp_lids); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from Zoltan_Comm_Do."); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); return(ierr); } } ierr = Zoltan_Comm_Destroy(&comm_plan); if(ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from Zoltan_Comm_Destroy."); ZOLTAN_TRACE_EXIT(zz, yo); ZOLTAN_FREE(&tmp); return(ierr); } /* get each message sent, and store region in import array */ j=0; for (i=0; i<nreceives; i++) { im_load += tmp[i].Weight; if(tmp[i].newProc != zz->Proc) { j++; } } if((j + npimtags) != 0) { /* malloc import array */ if((t_b_exp = (pRegion)ZOLTAN_MALLOC((j+npimtags)*sizeof(Region)))==NULL){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); return ZOLTAN_MEMERR; } } else t_b_exp = NULL; /* setup return pointer */ (*ex_tags) = t_b_exp; j=0; for (i=0; i<nreceives; i++) { if(tmp[i].newProc != zz->Proc) { t_b_exp[j] = tmp[i]; t_b_exp[j].Global_ID = ZOLTAN_MALLOC_GID(zz); t_b_exp[j].Local_ID = ZOLTAN_MALLOC_LID(zz); if (!(t_b_exp[j].Global_ID) || (num_lid_entries && !(t_b_exp[j].Local_ID))) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); return ZOLTAN_MEMERR; } ZOLTAN_SET_GID(zz, t_b_exp[j].Global_ID, &(tmp_gids[i*num_gid_entries])); ZOLTAN_SET_LID(zz, t_b_exp[j].Local_ID, &(tmp_lids[i*num_lid_entries])); j++; } } if(npimtags > 0) { for(i=0; i<npimtags; i++) { t_b_exp[j] = prev_tags[i]; t_b_exp[j].Global_ID = ZOLTAN_MALLOC_GID(zz); t_b_exp[j].Local_ID = ZOLTAN_MALLOC_LID(zz); if (!(t_b_exp[j].Global_ID) || (num_lid_entries && !(t_b_exp[j].Local_ID))) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); return ZOLTAN_MEMERR; } ZOLTAN_SET_GID(zz, t_b_exp[j].Global_ID, &(prev_gids[i*num_gid_entries])); ZOLTAN_SET_LID(zz, t_b_exp[j].Local_ID, &(prev_lids[i*num_lid_entries])); j++; } } *nstags = j; ZOLTAN_FREE(&tmp); ZOLTAN_FREE(&tmp_gids); ZOLTAN_FREE(&tmp_lids); if((*nstags == 0) && (*ex_tags != NULL)) { ZOLTAN_TRACE_DETAIL(zz, yo, "Fatal error, import tags not empty but no tags received\n"); return ZOLTAN_FATAL; } *c3 = im_load; return ierr; }
/* * 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; }
int Zoltan_Block( ZZ *zz, /* The Zoltan structure. */ float *part_sizes, /* Input: Array of size zz->LB.Num_Global_Parts containing the percentage of work to be assigned to each partition. */ int *num_import, /* Return -1. We use only export lists. */ ZOLTAN_ID_PTR *import_global_ids, /* Not used. */ ZOLTAN_ID_PTR *import_local_ids, /* Not used. */ int **import_procs, /* Not used. */ int **import_to_part, /* Not used. */ int *num_export, /* Output: Number of objects to export. */ ZOLTAN_ID_PTR *export_global_ids, /* Output: GIDs to export. */ ZOLTAN_ID_PTR *export_local_ids, /* Output: LIDs to export. */ int **export_procs, /* Output: Processsors to export to. */ int **export_to_part /* Output: Partitions to export to. */ ) { int ierr = ZOLTAN_OK; int i, count, num_obj; int wtflag = 0; ZOLTAN_ID_PTR global_ids = NULL; ZOLTAN_ID_PTR local_ids = NULL; int *parts = NULL; int *newparts = NULL; float *wgts = NULL; static char *yo = "Zoltan_Block"; ZOLTAN_TRACE_ENTER(zz, yo); /* No import lists computed. */ *num_import = -1; *export_global_ids = *export_local_ids = NULL; *export_procs = *export_to_part = NULL; /* Get list of local objects. */ if (zz->Obj_Weight_Dim > 1) { ierr = ZOLTAN_FATAL; ZOLTAN_PRINT_ERROR(zz->Proc, yo, "OBJ_WEIGHT_DIM > 1 not supported by LB_METHOD BLOCK."); goto End; } wtflag = (zz->Obj_Weight_Dim>0 ? 1 : 0); ierr = Zoltan_Get_Obj_List(zz, &num_obj, &global_ids, &local_ids, wtflag, &wgts, &parts); /* Compute the new partition numbers. */ newparts = (int *) ZOLTAN_MALLOC(num_obj * sizeof(int)); if (num_obj && (!newparts)){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory error."); ierr = ZOLTAN_MEMERR; goto End; } block_part(zz, num_obj, wtflag, wgts, part_sizes, newparts); /* Check how many partition numbers changed. */ count=0; for (i=0; i<num_obj; i++){ if (newparts[i] != parts[i]) ++count; } (*num_export) = count; /* Allocate export lists. */ if ((*num_export) > 0) { if (!Zoltan_Special_Malloc(zz, (void **)export_global_ids, (*num_export), ZOLTAN_SPECIAL_MALLOC_GID) || !Zoltan_Special_Malloc(zz, (void **)export_local_ids, (*num_export), ZOLTAN_SPECIAL_MALLOC_LID) || !Zoltan_Special_Malloc(zz, (void **)export_procs, (*num_export), ZOLTAN_SPECIAL_MALLOC_INT) || !Zoltan_Special_Malloc(zz, (void **)export_to_part, (*num_export), ZOLTAN_SPECIAL_MALLOC_INT)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory error."); ierr = ZOLTAN_MEMERR; goto End; } } /* Loop over objects and fill export lists. */ count=0; for (i=0; i<num_obj; i++){ if (newparts[i] != parts[i]){ /* export_global_ids[count] = global_ids[i]; */ ZOLTAN_SET_GID(zz, &((*export_global_ids)[count*zz->Num_GID]), &global_ids[i*zz->Num_GID]); if (local_ids) /* export_local_ids[count] = local_ids[i]; */ ZOLTAN_SET_LID(zz, &((*export_local_ids)[count*zz->Num_LID]), &local_ids[i*zz->Num_LID]); /* Set new partition number. */ (*export_to_part)[count] = newparts[i]; /* Processor is derived from partition number. */ (*export_procs)[count] = Zoltan_LB_Part_To_Proc(zz, (*export_to_part)[count], &global_ids[i*zz->Num_GID]); ++count; } } End: /* Free local memory, but not export lists. */ ZOLTAN_FREE(&global_ids); ZOLTAN_FREE(&local_ids); ZOLTAN_FREE(&parts); ZOLTAN_FREE(&newparts); if (wtflag) ZOLTAN_FREE(&wgts); ZOLTAN_TRACE_EXIT(zz, yo); return ierr; }
static int Zoltan_PHG_Return_Lists ( ZZ *zz, ZHG *zhg, int *num_exp, ZOLTAN_ID_PTR *exp_gids, ZOLTAN_ID_PTR *exp_lids, int **exp_procs, int **exp_to_part) { /* Routine to build export lists of ZOLTAN_LB_FN. */ char *yo = "Zoltan_PHG_Return_Lists"; int i, j; int ierr = ZOLTAN_OK; int eproc; int num_gid_entries = zz->Num_GID; int num_lid_entries = zz->Num_LID; int nObj = zhg->nObj; Partition input_parts = zhg->Input_Parts; ZOLTAN_ID_PTR gids = zhg->GIDs; ZOLTAN_ID_PTR lids = zhg->LIDs; int *outparts = zhg->Output_Parts; if (zz->LB.Return_Lists == ZOLTAN_LB_NO_LISTS) goto End; /* Count number of objects with new partitions or new processors. */ *num_exp = 0; for (i = 0; i < nObj; i++) { eproc = Zoltan_LB_Part_To_Proc(zz, outparts[i], &gids[i*num_gid_entries]); if (outparts[i] != input_parts[i] || zz->Proc != eproc) (*num_exp)++; } /* Allocate memory for return lists. */ if (*num_exp > 0) { if (!Zoltan_Special_Malloc(zz, (void**)exp_gids, *num_exp, ZOLTAN_SPECIAL_MALLOC_GID) || !Zoltan_Special_Malloc(zz, (void**)exp_lids, *num_exp, ZOLTAN_SPECIAL_MALLOC_LID) || !Zoltan_Special_Malloc(zz, (void**)exp_procs, *num_exp, ZOLTAN_SPECIAL_MALLOC_INT) || !Zoltan_Special_Malloc(zz, (void**)exp_to_part, *num_exp, ZOLTAN_SPECIAL_MALLOC_INT)) { Zoltan_Special_Free(zz,(void**)exp_gids, ZOLTAN_SPECIAL_MALLOC_GID); Zoltan_Special_Free(zz,(void**)exp_lids, ZOLTAN_SPECIAL_MALLOC_LID); Zoltan_Special_Free(zz,(void**)exp_procs, ZOLTAN_SPECIAL_MALLOC_INT); Zoltan_Special_Free(zz,(void**)exp_to_part,ZOLTAN_SPECIAL_MALLOC_INT); ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Memory error."); ierr = ZOLTAN_MEMERR; goto End; } for (j = 0, i = 0; i < nObj; i++) { eproc = Zoltan_LB_Part_To_Proc(zz, outparts[i], &gids[i*num_gid_entries]); if (outparts[i] != input_parts[i] || eproc != zz->Proc) { ZOLTAN_SET_GID(zz, &((*exp_gids)[j*num_gid_entries]), &(gids[i*num_gid_entries])); if (num_lid_entries > 0) ZOLTAN_SET_LID(zz, &((*exp_lids)[j*num_lid_entries]), &(lids[i*num_lid_entries])); (*exp_procs) [j] = eproc; (*exp_to_part)[j] = outparts[i]; j++; } } } End: return ierr; }
static int Zoltan_Postprocess_Partition (ZZ *zz, ZOLTAN_Third_Graph *gr, ZOLTAN_Third_Part *prt, ZOLTAN_Output_Part *part, ZOLTAN_ID_PTR global_ids, ZOLTAN_ID_PTR local_ids) { static char * yo = "Zoltan_Postprocess_Partition"; int ierr = ZOLTAN_OK; int i, j, nsend; int *newproc, *tmp_part, *tmp_input_part; int num_gid_entries = zz->Num_GID; int num_lid_entries = zz->Num_LID; /* Partitioning */ /* Determine new processor and number of objects to export */ newproc = (int *) ZOLTAN_MALLOC(gr->num_obj * sizeof(int)); if (gr->num_obj && !newproc){ /* Not enough memory */ ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Out of memory. "); } for (i=0; i<gr->num_obj; i++){ newproc[i] = Zoltan_LB_Part_To_Proc(zz, (int)prt->part[i], &(global_ids[i*num_gid_entries])); if (newproc[i]<0){ ZOLTAN_FREE(&newproc); ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, "Zoltan_LB_Part_To_Proc returned invalid processor number."); } } if (zz->LB.Remap_Flag) { int new_map; if (sizeof(indextype) == sizeof(int)){ ierr = Zoltan_LB_Remap(zz, &new_map, gr->num_obj, newproc, (int *)prt->input_part, (int *)prt->part, 1); } else{ tmp_part = (int *)ZOLTAN_MALLOC(sizeof(int) * gr->num_obj); tmp_input_part = (int *)ZOLTAN_MALLOC(sizeof(int) * gr->num_obj); if (gr->num_obj && (!tmp_part || !tmp_input_part)){ ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory."); } for (i=0; i < gr->num_obj; i++){ tmp_part[i] = (int)prt->part[i]; tmp_input_part[i] = (int)prt->input_part[i]; } ierr = Zoltan_LB_Remap(zz, &new_map, gr->num_obj, newproc, tmp_input_part, tmp_part, 1); for (i=0; i < gr->num_obj; i++){ prt->part[i] = (indextype)tmp_part[i]; prt->input_part[i] = (indextype)tmp_input_part[i]; } ZOLTAN_FREE(&tmp_part); ZOLTAN_FREE(&tmp_input_part); } if (ierr < 0) { ZOLTAN_FREE(&newproc); ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, "Error returned from Zoltan_LB_Remap"); } } nsend = 0; for (i=0; i<gr->num_obj; i++){ if ((prt->part[i] != prt->input_part[i]) || ((!part->compute_only_part_changes) && (newproc[i] != zz->Proc))) nsend++; if (zz->Debug_Level >= ZOLTAN_DEBUG_ALL) printf("[%1d] DEBUG: local object %1d: old part = " TPL_IDX_SPEC ", new part = " TPL_IDX_SPEC "\n", zz->Proc, i, prt->input_part[i], prt->part[i]); } /* Create export lists */ if (zz->LB.Return_Lists){ if (zz->LB.Return_Lists == ZOLTAN_LB_CANDIDATE_LISTS) { ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, "Candidate Lists not supported in GRAPH;" "change RETURN_LISTS parameter."); } part->num_exp = nsend; if (nsend > 0) { if (!Zoltan_Special_Malloc(zz,(void **)part->exp_gids,nsend,ZOLTAN_SPECIAL_MALLOC_GID)) { ZOLTAN_FREE(&newproc); ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory."); } if (!Zoltan_Special_Malloc(zz,(void **)part->exp_lids,nsend,ZOLTAN_SPECIAL_MALLOC_LID)) { Zoltan_Special_Free(zz,(void **)part->exp_gids,ZOLTAN_SPECIAL_MALLOC_GID); ZOLTAN_FREE(&newproc); ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory."); } if (!Zoltan_Special_Malloc(zz,(void **)part->exp_procs,nsend,ZOLTAN_SPECIAL_MALLOC_INT)) { Zoltan_Special_Free(zz,(void **)part->exp_lids,ZOLTAN_SPECIAL_MALLOC_LID); Zoltan_Special_Free(zz,(void **)part->exp_gids,ZOLTAN_SPECIAL_MALLOC_GID); ZOLTAN_FREE(&newproc); ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory."); } if (!Zoltan_Special_Malloc(zz,(void **)part->exp_part,nsend,ZOLTAN_SPECIAL_MALLOC_INT)) { Zoltan_Special_Free(zz,(void **)part->exp_lids,ZOLTAN_SPECIAL_MALLOC_LID); Zoltan_Special_Free(zz,(void **)part->exp_gids,ZOLTAN_SPECIAL_MALLOC_GID); Zoltan_Special_Free(zz,(void **)part->exp_procs,ZOLTAN_SPECIAL_MALLOC_INT); ZOLTAN_FREE(&newproc); ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Not enough memory."); } j = 0; for (i=0; i<gr->num_obj; i++){ if ((prt->part[i] != prt->input_part[i]) || ((!part->compute_only_part_changes) && (newproc[i] != zz->Proc))){ /* Object should move to new partition or processor */ ZOLTAN_SET_GID(zz, &((*(part->exp_gids))[j*num_gid_entries]), &(global_ids[i*num_gid_entries])); if (num_lid_entries) ZOLTAN_SET_LID(zz, &((*(part->exp_lids))[j*num_lid_entries]), &(local_ids[i*num_lid_entries])); (*(part->exp_part))[j] = (int)prt->part[i]; (*(part->exp_procs))[j] = newproc[i]; /* printf("[%1d] Debug: Move object %1d to part %1d, proc %1d\n", */ /* zz->Proc, i, prt->part[i], newproc[i]); */ j++; } } } } ZOLTAN_FREE(&newproc); return (ZOLTAN_OK); }
int Zoltan_Oct_migreg_migrate_orphans(ZZ *zz, pRegion RegionList, int nregions, int level, Map *array, int *c1, int *c2) { int i, j, k; /* index counters */ pRegion ptr; /* region in the mesh */ COORD origin; /* centroid coordinate information */ pRegion *regions = NULL; /* an array of regions */ int *npids = NULL; Region *regions2 = NULL; /* an array of regions */ int *npids2 = NULL; int nreg; /* number of regions */ COORD min, /* minimum bounds of an octant */ max; /* maximum bounds of an octant */ COORD cmin, /* minimum bounds of a child octant */ cmax; /* maximum bounds of a child octant */ COORD rmin, /* minimum bounds of a remote octant */ rmax; /* maximum bounds of a remote octant */ int new_num; int n; int dir = 0; pRList RootList; pOctant RootOct; OCT_Global_Info *OCT_info = (OCT_Global_Info *)(zz->LB.Data_Structure); char *yo = "Zoltan_Oct_migreg_migrate_orphans_static"; int ierr = ZOLTAN_OK; ZOLTAN_ID_PTR gids2, lids2; int num_gid_entries = zz->Num_GID; int num_lid_entries = zz->Num_LID; if(nregions > 0) { /* create the array of messages to be sent to other processors */ /* Array = (Message *) ZOLTAN_MALLOC(nregions * sizeof(Message)); */ if((regions = (pRegion *) ZOLTAN_MALLOC(nregions * sizeof(pRegion))) == NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); return ZOLTAN_MEMERR; } if((npids = (int *) ZOLTAN_MALLOC(nregions * sizeof(int))) == NULL) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Insufficient memory."); ZOLTAN_TRACE_EXIT(zz, yo); ZOLTAN_FREE(®ions); return ZOLTAN_MEMERR; } } ptr = RegionList; n = nreg = 0; while((ptr != NULL) && (nregions > 0)) { if(ptr->attached == 1) { /* if region already attached to an octant, then skip to next region */ ptr = ptr->next; continue; } /* region not attached, have to find which processor to send to */ j=0; dir = 0; vector_set(min, OCT_info->OCT_gmin); vector_set(max, OCT_info->OCT_gmax); /* * for each level of refinement, find which child region belongs to. * translate which child to which entry in map array. */ for(i=0; i<level; i++) { Zoltan_Oct_bounds_to_origin(min, max, origin); if(OCT_info->OCT_dimension == 2) j = j * 4; else j = j * 8; k = Zoltan_Oct_child_which(OCT_info,origin, ptr->Coord); new_num = Zoltan_Oct_convert_idx_from_map(OCT_info, dir, k); dir = Zoltan_Oct_get_child_dir(OCT_info, dir, new_num); j += new_num; Zoltan_Oct_child_bounds(min, max, origin, k, cmin, cmax); vector_set(min, cmin); vector_set(max, cmax); } /* inform message which processor to send to */ npids[n] = array[j].npid; RootList = array[j].list; while((RootOct = RL_nextRootOctant(&RootList))) { Zoltan_Oct_bounds(RootOct,rmin,rmax); if (Zoltan_Oct_in_box_closure(OCT_info, ptr->Coord ,rmin, rmax)) { npids[n] = RootOct->npid; break; } } if((npids[n] != -1) && (npids[n] != zz->Proc)) { Zoltan_Oct_copy_info(zz, ptr, &(regions[n++])); } else { Zoltan_Oct_insert_orphan(zz, *ptr); } nreg++; /* increment region counter */ ptr = ptr->next; /* look at next region */ } /* * if regions looked at != number of regions in region list, * then there is an error */ if (nreg!=nregions) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "regions found != to expected number of regions"); return ZOLTAN_FATAL; } regions2 = (Region *) ZOLTAN_MALLOC(n * sizeof(Region)); gids2 = ZOLTAN_MALLOC_GID_ARRAY(zz, n); lids2 = ZOLTAN_MALLOC_LID_ARRAY(zz, n); npids2 = (int *) ZOLTAN_MALLOC(n * sizeof(int)); for(i=0; i<n; i++) { npids2[i] = npids[i]; vector_set(regions2[i].Coord, regions[i]->Coord); regions2[i].Weight = regions[i]->Weight; regions2[i].Global_ID = &(gids2[i*num_gid_entries]); regions2[i].Local_ID = (num_lid_entries ? &(lids2[i*num_lid_entries]) : NULL); ZOLTAN_SET_GID(zz, &(gids2[i*num_gid_entries]), regions[i]->Global_ID); ZOLTAN_SET_LID(zz, &(lids2[i*num_lid_entries]), regions[i]->Local_ID); regions2[i].Proc = regions[i]->Proc; regions2[i].attached = 0; } *c1 = n; /* migrate the orphan regions according to the message array */ Zoltan_Oct_migreg_migrate_regions(zz, regions2, gids2, lids2, npids2, n, c2); for (i=0; i < n; i++) { ZOLTAN_FREE(&(regions[i]->Global_ID)); ZOLTAN_FREE(&(regions[i]->Local_ID)); ZOLTAN_FREE(&(regions[i])); } ZOLTAN_FREE(®ions); ZOLTAN_FREE(&npids); ZOLTAN_FREE(®ions2); ZOLTAN_FREE(&gids2); ZOLTAN_FREE(&lids2); ZOLTAN_FREE(&npids2); return ierr; }