I've updated these to return request handles, as per Tim's stuff with tag copying. A. Request in-migration of an entity (this is a pull migration). This entity must be on the part bdry and is identified by local handle, and the implementation handles the rest. This operation will require multiple rounds of communication, and at some times certain entities may be locked (unavailable for local modification) while info about their remote copies is still in question. It's worth mentioning that implementations will have to take care to migrate tags and parallel set membership as well as adjacency info. CHANGES: Returns a request handle. Assumes you wouldn't be asking if you didn't need the upward adjacencies as well. void iMeshP_migrateEntity(iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, const iBase_EntityHandle local_entity_handle, iMeshP_RequestHandle *request, int *err); B. Update vertex coordinates. One could argue that we could overload the setVtxCoords function to do this, and maybe we should. But that obfuscates when communication could occur. The communication here is push-and-forget. CHANGES: None. Because this is push-and-forget, no request handle -should- be generated. void iMeshP_updateVtxCoords(iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, const iBase_EntityHandle local_vertex_handle, int *err); C. Poll for messages. The internals of this function are going to have to cover a lot of ground. The array in the return is there as a placeholder to tell the application that something interesting / useful has been done to a handle. This might indicate successful in-migration, a recent change in vertex location, or successful completion of handle matching. CHANGES: Returns an array of requests that have been handled. IMO, if the array has a size allocated already, then the impl should stop working when it's generated that many completed requests, even if there are more messages waiting. The syntax on this call should perhaps be modified somewhat to make it more compatible with an analogous MPI call. Should also perhaps have its name changed to handleMessages or some such thing, since the function should, IMO, not only poll for unexpected messages, but also handle expected ones --- I see no reason to separately call two different functions to handle non-blocking receives for different types of messages. void iMeshP_pollForRequests(iMeshP_RequestHandle **requests_completed, int *requests_allocated, int *requests_size, int *err); D. Done with micro-migration. This is a blocking call, to get everything up-to-date and back in synch. Essentially, waits for all message traffic to clear, as well as (possibly) rebuilding a bunch of ghost info that was allowed to go obsolete. void iMeshP_finishMigration(iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, int *err); E. Replace entities. This refers to changes on the part bdry where the application/service is responsible for ensuring that things are done identically on both sides and that the args are passed in an order that can be matched. (Specifically, matching new entities should appear in the same order in the call array.) Communication here could be a two-way push-and-forget, or some variant on push-and-confirm. CHANGES: At Onkar's suggestion, added an offset array (similar to array adjacency requests) so that a single call can easily handle coordination with multiple parts. void iMeshP_replaceOnPartBdry(iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, const iBase_EntityHandle *old_entities, const int old_entities_size, const iBase_EntityHandle *new_entities, const int new_entities_size, const int *offset, const int offset_size, int *err); F. As Tim suggests, the ability to create and delete ghosts is likely to be useful, even though for common topologically-based cases, ghost maintainence can (and IMO should) be handled automagically, either at migration time or during iMeshP_synchParts. Communication here is push-and-confirm for creation (so that the original knows ID's of the ghosts), push-and-forget for deletion (in the latter case, no request handle is needed). I'm assuming here that the closure of a new ghost will be pushed automatically as part of the underlying communication, and that the remote part will clean up the closure as appropriate during deletion. void iMeshP_createGhostOf(iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, const iMeshP_PartHandle target_part, const iBase_EntityHandle ghost_to_push, iMeshP_RequestHandle *request, int *err); void iMeshP_deleteGhostOf(iMesh_Instance instance, const iMeshP_PartitionHandle partition_handle, const iMeshP_PartHandle target_part, const iBase_EntityHandle ghost_to_purge, int *err); Finally, I see no intrinsic reason why the wait calls Tim proposed for handling tag updates can't be used here.