static int Zoltan_Preprocess_Extract_Geom (ZZ *zz, ZOLTAN_ID_PTR *global_ids, ZOLTAN_ID_PTR *local_ids, ZOLTAN_Third_Graph *gr, ZOLTAN_Third_Geom *geo) { int ierr; double *geom_vec; int i; geom_vec = NULL; /* Get coordinate information */ ierr = Zoltan_Get_Coordinates(zz, gr->num_obj, *global_ids, *local_ids, &geo->ndims, &geom_vec); if (ierr) { ZOLTAN_THIRD_ERROR(ZOLTAN_FATAL, "Error returned from Zoltan_Get_Coordinates"); } /* Convert geometry info from double to float for ParMETIS */ if (gr->num_obj && geo->ndims) { geo->xyz = (float *) ZOLTAN_MALLOC(gr->num_obj * geo->ndims * sizeof(float)); if (geo->xyz == NULL) { ZOLTAN_THIRD_ERROR(ZOLTAN_MEMERR, "Memory error."); } for (i = 0; i < gr->num_obj * geo->ndims; i++) geo->xyz[i] = (float) geom_vec[i]; ZOLTAN_FREE(&geom_vec); } return ierr; }
static void Zoltan_Oct_get_bounds(ZZ *zz, pRegion *ptr1, int *num_objs, COORD min, COORD max, int wgtflag, float *c0) { char *yo = "Zoltan_Oct_get_bounds"; ZOLTAN_ID_PTR obj_global_ids = NULL; ZOLTAN_ID_PTR obj_local_ids = NULL; int *parts = NULL; /* Input partition assignments; currently unused. */ float *obj_wgts = NULL; double *geom_vec = NULL; float objwgt; /* Temporary value of an object weight; used to pass 0. to initialize_regions when wgtflag == 0. */ ZOLTAN_ID_PTR lid; /* Temporary pointer to a local ID; used to pass NULL to initialize_regions when NUM_LID_ENTRIES == 0. */ int num_dim; int i; pRegion tmp=NULL, ptr; COORD global_min, global_max; double PADDING = 0.0000001; int ierr = 0; int num_gid_entries = zz->Num_GID; int num_lid_entries = zz->Num_LID; /* Initialization */ max[0] = max[1] = max[2] = -DBL_MAX; min[0] = min[1] = min[2] = DBL_MAX; ierr = Zoltan_Get_Obj_List(zz, num_objs, &obj_global_ids, &obj_local_ids, wgtflag, &obj_wgts, &parts); if (ierr) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error returned from user function Zoltan_Get_Obj_List."); exit (-1); } ierr = Zoltan_Get_Coordinates(zz, *num_objs, obj_global_ids, obj_local_ids, &num_dim, &geom_vec); for (i = 0; i < (*num_objs); i++) { lid = (num_lid_entries ? obj_local_ids + i*num_lid_entries : NULL); objwgt = (wgtflag ? obj_wgts[i] : 0.); initialize_region(zz, &(ptr), obj_global_ids + i*num_gid_entries, lid, wgtflag, objwgt, num_dim, geom_vec + i*num_dim); if (i == 0) { tmp = ptr; *c0 = (float)tmp->Weight; vector_set(min, tmp->Coord); vector_set(max, tmp->Coord); *ptr1 = tmp; } else { *c0 += (float)ptr->Weight; /* the following is really a hack, since it has no real basis in vector mathematics.... */ if(ptr->Coord[0] < min[0]) min[0] = ptr->Coord[0]; if(ptr->Coord[1] < min[1]) min[1] = ptr->Coord[1]; if(ptr->Coord[2] < min[2]) min[2] = ptr->Coord[2]; if(ptr->Coord[0] > max[0]) max[0] = ptr->Coord[0]; if(ptr->Coord[1] > max[1]) max[1] = ptr->Coord[1]; if(ptr->Coord[2] > max[2]) max[2] = ptr->Coord[2]; tmp->next = ptr; tmp = tmp->next; } ptr = NULL; } ZOLTAN_FREE(&obj_global_ids); ZOLTAN_FREE(&obj_local_ids); ZOLTAN_FREE(&parts); ZOLTAN_FREE(&obj_wgts); ZOLTAN_FREE(&geom_vec); MPI_Allreduce(&(min[0]), &(global_min[0]), 3, MPI_DOUBLE, MPI_MIN, zz->Communicator); MPI_Allreduce(&(max[0]), &(global_max[0]), 3, MPI_DOUBLE, MPI_MAX, zz->Communicator); max[0] = global_max[0]; max[1] = global_max[1]; max[2] = global_max[2]; min[0] = global_min[0]; min[1] = global_min[1]; min[2] = global_min[2]; /* hack used for sample program since working in 2D -- */ /* causes problems for refining the octree */ if(max[2] == min[2]) max[2] = 1.0; for(i=0; i<3; i++) { /* min[i] -= PADDING; */ max[i] += PADDING; } return; }
int Zoltan_LocalHSFC_Order( ZZ *zz, /* Zoltan structure */ int num_obj, /* Number of (local) objects to order. */ ZOLTAN_ID_PTR gids, /* List of global ids (local to this proc) */ /* The application must allocate enough space */ ZOLTAN_ID_PTR lids, /* List of local ids (local to this proc) */ /* The application must allocate enough space */ int *rank, /* rank[i] is the rank of gids[i] */ int *iperm, ZOOS *order_opt /* Ordering options, parsed by Zoltan_Order */ ) { static char *yo = "Zoltan_LocalHSFC_Order"; int n, ierr=ZOLTAN_OK; double (*fhsfc)(ZZ*, double*); /* space filling curve function */ int wgt_dim=0; float *obj_wgts=0; int *parts=0; int numGeomDims=0; double *geomArray=0; /* Variables for bounding box */ double *minValInDim; double *maxValInDim; double *widthDim; double *hsfcKey=0; int *coordIndx=0; /* Counters */ int objNum; int dimNum; int offset=0; int myrank; MPI_Comm_rank(MPI_COMM_WORLD,&myrank); ZOLTAN_TRACE_ENTER(zz, yo); /******************************************************************/ /* If for some reason order_opt is NULL, allocate a new ZOOS here. */ /* This should really never happen. */ /******************************************************************/ if (!order_opt) { order_opt = (ZOOS *) ZOLTAN_MALLOC(sizeof(ZOOS)); strcpy(order_opt->method,"LOCAL_HSFC"); } /******************************************************************/ /* local HSFC only computes the rank vector */ order_opt->return_args = RETURN_RANK; /******************************************************************/ /* Check that num_obj equals the number of objects on this proc. */ /* This constraint may be removed in the future. */ /******************************************************************/ n = zz->Get_Num_Obj(zz->Get_Num_Obj_Data, &ierr); if ((ierr!= ZOLTAN_OK) && (ierr!= ZOLTAN_WARN)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Get_Num_Obj returned error."); return(ZOLTAN_FATAL); } if (n != num_obj) { /* Currently this is a fatal error. */ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Input num_obj does not equal the number of objects."); return(ZOLTAN_FATAL); } /******************************************************************/ /******************************************************************/ /* Get lists of objects */ /******************************************************************/ ierr = Zoltan_Get_Obj_List(zz, &n, &gids, &lids, wgt_dim, &obj_wgts, &parts); if ((ierr!= ZOLTAN_OK) && (ierr!= ZOLTAN_WARN)) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Get_Obj_List returned error."); return(ZOLTAN_FATAL); } /******************************************************************/ /******************************************************************/ /* Get geometry for objects*/ /******************************************************************/ ierr = Zoltan_Get_Coordinates(zz, n, gids, lids, &numGeomDims, &geomArray); if (ierr != 0) { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Zoltan_Get_Coordinates returned error."); return(ZOLTAN_FATAL); } /******************************************************************/ /******************************************************************/ /* Place coords in bounding box */ /******************************************************************/ minValInDim = (double *) malloc(numGeomDims * sizeof (double)); maxValInDim = (double *) malloc(numGeomDims * sizeof (double)); widthDim = (double *) malloc(numGeomDims * sizeof (double)); for(dimNum=0; dimNum<numGeomDims; dimNum++) { minValInDim[dimNum] = HUGE_VAL; maxValInDim[dimNum] = -HUGE_VAL; } /*************************************************************/ /* Determine min, max, and width for each dimension */ /*************************************************************/ for (objNum=0; objNum<n; objNum++) { for(dimNum=0; dimNum<numGeomDims; dimNum++) { if (geomArray[objNum * numGeomDims + dimNum] < minValInDim[dimNum]) { minValInDim[dimNum] = geomArray[objNum * numGeomDims + dimNum]; } if (geomArray[objNum * numGeomDims + dimNum] > maxValInDim[dimNum]) { maxValInDim[dimNum] = geomArray[objNum * numGeomDims + dimNum]; } } } for(dimNum=0; dimNum<numGeomDims; dimNum++) { widthDim[dimNum] = maxValInDim[dimNum] - minValInDim[dimNum]; } /*************************************************************/ /*************************************************************/ /* Rescale values to fit in bounding box */ /*************************************************************/ for (objNum=0; objNum<n; objNum++) { for(dimNum=0; dimNum<numGeomDims; dimNum++) { geomArray[objNum * numGeomDims + dimNum] -= minValInDim[dimNum]; geomArray[objNum * numGeomDims + dimNum] /= widthDim[dimNum]; } } /*************************************************************/ free(minValInDim); minValInDim=0; free(maxValInDim); maxValInDim=0; free(widthDim); widthDim=0; /******************************************************************/ /******************************************************************/ /* Specify which HSFC function to use (based on dim) */ /******************************************************************/ if (numGeomDims==1) { fhsfc = Zoltan_HSFC_InvHilbert1d; } else if (numGeomDims==2) { fhsfc = Zoltan_HSFC_InvHilbert2d; } else if (numGeomDims==3) { fhsfc = Zoltan_HSFC_InvHilbert3d; } else /* this error should have been previously caught */ { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Geometry should be of dimension 1, 2, or 3."); return(ZOLTAN_FATAL); } /******************************************************************/ /******************************************************************/ /* Generate hsfc keys and indices to be sorted */ /******************************************************************/ hsfcKey = (double *) malloc(n * sizeof (double)); coordIndx = (int *) malloc(n *sizeof(int)); for (objNum=0; objNum<n; objNum++) { hsfcKey[objNum] = fhsfc(zz, &(geomArray[objNum * numGeomDims]) ); coordIndx[objNum] = objNum; } /******************************************************************/ /******************************************************************/ /* Sort indices based on keys */ /******************************************************************/ Zoltan_quicksort_pointer_dec_double (coordIndx, hsfcKey, 0, n-1); /******************************************************************/ /******************************************************************/ /* get ranks */ /******************************************************************/ /******************************************************/ /* Determine offsets */ /******************************************************/ MPI_Scan(&n, &offset, 1, MPI_INT, MPI_SUM, zz->Communicator); offset -= n; /* MPI_Scan is inclusive, so subtract off local size */ /******************************************************/ for(objNum=0; objNum<n; objNum++) { /*MMW temporary hack to make Cedric's interface give me want I need */ /*rank[coordIndx[objNum]] = objNum + offset; */ rank[objNum] = coordIndx[objNum] + offset; } /******************************************************************/ /* iperm is to be deprecated so not calculated*/ free(hsfcKey); free(coordIndx); ZOLTAN_TRACE_EXIT(zz, yo); return (ZOLTAN_OK); }