int Zoltan_Inverse_Perm( ZZ *zz, /* Input: Zoltan struct */ int *perm, /* Input: Permutation to invert. */ int *inv_perm, /* Output: Inverse permutation of perm. */ int *vtxdist, /* Input: Distribution of the vectors. */ char *order_type, /* Input: Local or global ordering? */ int start_index /* Input: Do permutations start with 0 or 1? */ ) { int i, ierr, num_obj, nrecv, offset; int *proclist, *sendlist, *recvlist; ZOLTAN_COMM_OBJ *comm_plan; char msg[256]; char *yo = "Zoltan_Inverse_Perm"; ierr = ZOLTAN_OK; proclist = sendlist = recvlist = NULL; comm_plan = NULL; /* num_obj = local number of objects (elements in the perm vectors) */ num_obj = vtxdist[(zz->Proc)+1] - vtxdist[zz->Proc]; /* Verify that input permutation is really a permutation */ /* Also check that start_index is correct. */ /* Convert permutation vector to 0-base if necessary */ if (start_index>0){ for (i=0; i<num_obj; i++) perm[i] -= start_index; } if (strcmp(order_type, "LOCAL")==0){ /* Local inverse */ for (i=0; i<num_obj; i++) inv_perm[perm[i]] = i; } else if (strcmp(order_type, "GLOBAL")==0){ /* Global inverse; use Zoltan Comm package */ proclist = (int *) ZOLTAN_MALLOC (5*num_obj*sizeof(int)); sendlist = &proclist[num_obj]; recvlist = &proclist[3*num_obj]; /* Set up comm plan. We know where to send. */ /* Send pairs of (i, perm[i]) to other procs */ offset = vtxdist[zz->Proc]; for (i=0; i<num_obj; i++){ sendlist[2*i] = offset+i; sendlist[2*i+1] = perm[i]; proclist[i] = Zoltan_Get_Processor_Graph(vtxdist, zz->Num_Proc, perm[i]); } ierr = Zoltan_Comm_Create(&comm_plan, num_obj, proclist, zz->Communicator, TAG1, &nrecv); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error in Zoltan_Comm_Create"); goto error; } if (nrecv != num_obj){ /* This should never happen. */ sprintf(msg, "Internal error: nrecv (%3d) != num_obj (%3d). Invalid permutation.\n", nrecv, num_obj); ZOLTAN_PRINT_ERROR(zz->Proc, yo, msg); ierr = ZOLTAN_FATAL; goto error; } /* Do the communication. */ ierr = Zoltan_Comm_Do(comm_plan, TAG2, (char *)sendlist, 2*sizeof(int), (char *) recvlist); if (ierr != ZOLTAN_OK && ierr != ZOLTAN_WARN){ ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Error in Zoltan_Comm_Do"); goto error; } /* Permute data locally. */ for (i=0; i<num_obj; i++){ /* inv_perm[perm[i]] = i; */ inv_perm[recvlist[2*i+1]-offset] = recvlist[2*i]; } } else { ZOLTAN_PRINT_ERROR(zz->Proc, yo, "Unknown order_type."); ierr = ZOLTAN_FATAL; goto error; } /* Convert permutation vectors back to their right start_index */ if (start_index>0){ for (i=0; i<num_obj; i++){ perm[i] += start_index; inv_perm[i] += start_index; } } error: /* Free the comm_plan, proclist, sendlist, recvlist. */ if (comm_plan) Zoltan_Comm_Destroy( &comm_plan); if (proclist ) ZOLTAN_FREE(&proclist); return (ierr); }
int Zoltan_Order_Get_GID_Order( struct Zoltan_Struct *zz, ZOLTAN_ID_PTR global_ids, ZOLTAN_ID_PTR order_ids ) { int * proctab; ZOLTAN_ID_PTR sendgidtab; int * sendtab, *recvtab; int i; int nrecv; struct Zoltan_Comm_Obj *plan; int ierr = ZOLTAN_OK; int *vtxdist; int tag = 24061986; int offset; zz->Order.gidrank = order_ids; if (!strcmp(zz->Order.order_type, "LOCAL")) { for (i = 0 ; i < zz->Order.nbr_objects ; ++i) { order_ids[i] = global_ids[zz->Order.rank[i] - zz->Order.start_index]; } return (ZOLTAN_OK); } ierr = Zoltan_Get_Distribution(zz, &vtxdist); if (ierr != ZOLTAN_OK) return (ierr); proctab = (int*) ZOLTAN_MALLOC(3*zz->Order.nbr_objects*sizeof(int)); sendgidtab = ZOLTAN_MALLOC_GID_ARRAY(zz, 2*zz->Order.nbr_objects); if (proctab == NULL) { ZOLTAN_FREE(&vtxdist); return (ZOLTAN_MEMERR); } if (sendgidtab == NULL) { ZOLTAN_FREE(&proctab); ZOLTAN_FREE(&vtxdist); return (ZOLTAN_MEMERR); } sendtab = proctab + zz->Order.nbr_objects; recvtab = sendtab + zz->Order.nbr_objects; for (i = 0 ; i < zz->Order.nbr_objects ; ++i) { proctab[i] = Zoltan_Get_Processor_Graph(vtxdist, zz->Num_Proc, zz->Order.rank[i] - zz->Order.start_index); sendtab[i] = zz->Order.rank[i] - zz->Order.start_index; } ierr = Zoltan_Comm_Create(&plan, zz->Order.nbr_objects, proctab, zz->Communicator, tag++, &nrecv); if (ierr != ZOLTAN_OK) { ZOLTAN_FREE(&sendgidtab); ZOLTAN_FREE(&proctab); ZOLTAN_FREE(&vtxdist); return (ierr); } ierr = Zoltan_Comm_Do(plan, tag++, (char *) sendtab, sizeof(int), (char *) recvtab); if (ierr != ZOLTAN_OK) { ZOLTAN_FREE(&sendgidtab); ZOLTAN_FREE(&proctab); ZOLTAN_FREE(&vtxdist); return (ierr); } offset = vtxdist[zz->Proc]; for (i = 0 ; i < zz->Order.nbr_objects ; ++i) { int position; position = recvtab[i]-offset; ZOLTAN_SET_GID(zz, &sendgidtab[i], &global_ids[position]); } ierr = Zoltan_Comm_Do_Reverse(plan, tag++, (char *) sendgidtab, zz->Num_GID*sizeof(int), NULL, (char *) order_ids); Zoltan_Comm_Destroy(&plan); ZOLTAN_FREE(&sendgidtab); ZOLTAN_FREE(&proctab); ZOLTAN_FREE(&vtxdist); return (ierr); }