1af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
262e5d2d2SJDBetteridge #include <petsc/private/hashmapobj.h>
362e5d2d2SJDBetteridge #include <petsc/private/garbagecollector.h>
421532e8aSBarry Smith
5e5c89e4eSSatish Balay /*
6e5c89e4eSSatish Balay A simple way to manage tags inside a communicator.
7e5c89e4eSSatish Balay
8e5c89e4eSSatish Balay It uses the attributes to determine if a new communicator
9e5c89e4eSSatish Balay is needed and to store the available tags.
10e5c89e4eSSatish Balay
11e5c89e4eSSatish Balay */
12e5c89e4eSSatish Balay
13ffeef943SBarry Smith /*@
14e5c89e4eSSatish Balay PetscObjectGetNewTag - Gets a unique new tag from a PETSc object. All
15e5c89e4eSSatish Balay processors that share the object MUST call this routine EXACTLY the same
16e5c89e4eSSatish Balay number of times. This tag should only be used with the current objects
17e5c89e4eSSatish Balay communicator; do NOT use it with any other MPI communicator.
18e5c89e4eSSatish Balay
19c3339decSBarry Smith Collective
20e5c89e4eSSatish Balay
21e5c89e4eSSatish Balay Input Parameter:
22811af0c4SBarry Smith . obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
23811af0c4SBarry Smith `PetscObjectGetNewTag`((`PetscObject`)mat,&tag);
24e5c89e4eSSatish Balay
25e5c89e4eSSatish Balay Output Parameter:
26e5c89e4eSSatish Balay . tag - the new tag
27e5c89e4eSSatish Balay
28e5c89e4eSSatish Balay Level: developer
29e5c89e4eSSatish Balay
30811af0c4SBarry Smith Note:
31811af0c4SBarry Smith This tag is needed if one is writing MPI communication code involving message passing and needs unique MPI tags to ensure the messages are connected to this specific
32811af0c4SBarry Smith object.
33811af0c4SBarry Smith
34db781477SPatrick Sanan .seealso: `PetscCommGetNewTag()`
35e5c89e4eSSatish Balay @*/
PetscObjectGetNewTag(PetscObject obj,PetscMPIInt * tag)36d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectGetNewTag(PetscObject obj, PetscMPIInt *tag)
37d71ae5a4SJacob Faibussowitsch {
38e5c89e4eSSatish Balay PetscFunctionBegin;
399566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(obj->comm, tag));
403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
41e5c89e4eSSatish Balay }
42e5c89e4eSSatish Balay
43e30d2299SSatish Balay /*@
4410450e9eSJacob Faibussowitsch PetscCommGetNewTag - Gets a unique new tag from a PETSc communicator
45e5c89e4eSSatish Balay
46d083f849SBarry Smith Collective
47e5c89e4eSSatish Balay
48e5c89e4eSSatish Balay Input Parameter:
49655f41cfSBarry Smith . comm - the MPI communicator
50e5c89e4eSSatish Balay
51e5c89e4eSSatish Balay Output Parameter:
52e5c89e4eSSatish Balay . tag - the new tag
53e5c89e4eSSatish Balay
54e5c89e4eSSatish Balay Level: developer
55e5c89e4eSSatish Balay
5610450e9eSJacob Faibussowitsch Notes:
5710450e9eSJacob Faibussowitsch All processors that share the communicator MUST call this routine EXACTLY the same number of
5810450e9eSJacob Faibussowitsch times. This tag should only be used with the current objects communicator; do NOT use it
5910450e9eSJacob Faibussowitsch with any other MPI communicator.
6010450e9eSJacob Faibussowitsch
61db781477SPatrick Sanan .seealso: `PetscObjectGetNewTag()`, `PetscCommDuplicate()`
62e5c89e4eSSatish Balay @*/
PetscCommGetNewTag(MPI_Comm comm,PetscMPIInt * tag)63d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCommGetNewTag(MPI_Comm comm, PetscMPIInt *tag)
64d71ae5a4SJacob Faibussowitsch {
65480cf27aSJed Brown PetscCommCounter *counter;
66480cf27aSJed Brown PetscMPIInt *maxval, flg;
67e5c89e4eSSatish Balay
68e5c89e4eSSatish Balay PetscFunctionBegin;
694f572ea9SToby Isaac PetscAssertPointer(tag, 2);
70e5c89e4eSSatish Balay
719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Counter_keyval, &counter, &flg));
7228b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Bad MPI communicator supplied; must be a PETSc communicator");
73e5c89e4eSSatish Balay
74480cf27aSJed Brown if (counter->tag < 1) {
759566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Out of tags for object, starting to recycle. Comm reference count %" PetscInt_FMT "\n", counter->refcount));
769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxval, &flg));
7728b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_LIB, "MPI error: MPI_Comm_get_attr() is not returning a MPI_TAG_UB");
78480cf27aSJed Brown counter->tag = *maxval - 128; /* hope that any still active tags were issued right at the beginning of the run */
79e5c89e4eSSatish Balay }
80e5c89e4eSSatish Balay
81480cf27aSJed Brown *tag = counter->tag--;
8276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {
83655f41cfSBarry Smith /*
847b32b6dcSBarry Smith Hanging here means that some processes have called PetscCommGetNewTag() and others have not.
85655f41cfSBarry Smith */
869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm));
8776bd3646SJed Brown }
883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
8964260623SMatthew Knepley }
9064260623SMatthew Knepley
91e5c89e4eSSatish Balay /*@C
92811af0c4SBarry Smith PetscCommGetComm - get a new MPI communicator from a PETSc communicator that can be passed off to another package
9357f21012SBarry Smith
9457f21012SBarry Smith Collective
9557f21012SBarry Smith
9657f21012SBarry Smith Input Parameter:
9757f21012SBarry Smith . comm_in - Input communicator
9857f21012SBarry Smith
992fe279fdSBarry Smith Output Parameter:
10057f21012SBarry Smith . comm_out - Output communicator
10157f21012SBarry Smith
10221532e8aSBarry Smith Level: developer
10321532e8aSBarry Smith
10457f21012SBarry Smith Notes:
105811af0c4SBarry Smith Use `PetscCommRestoreComm()` to return the communicator when the external package no longer needs it
10657f21012SBarry Smith
107811af0c4SBarry Smith Certain MPI implementations have `MPI_Comm_free()` that do not work, thus one can run out of available MPI communicators causing
10857f21012SBarry Smith mysterious crashes in the code after running a long time. This routine allows reusing previously obtained MPI communicators that
10957f21012SBarry Smith are no longer needed.
11057f21012SBarry Smith
111db781477SPatrick Sanan .seealso: `PetscObjectGetNewTag()`, `PetscCommGetNewTag()`, `PetscCommDestroy()`, `PetscCommRestoreComm()`
11257f21012SBarry Smith @*/
PetscCommGetComm(MPI_Comm comm_in,MPI_Comm * comm_out)113d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCommGetComm(MPI_Comm comm_in, MPI_Comm *comm_out)
114d71ae5a4SJacob Faibussowitsch {
11557f21012SBarry Smith PetscCommCounter *counter;
11657f21012SBarry Smith PetscMPIInt flg;
11757f21012SBarry Smith
11857f21012SBarry Smith PetscFunctionBegin;
1199566063dSJacob Faibussowitsch PetscCall(PetscSpinlockLock(&PetscCommSpinLock));
1209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm_in, Petsc_Counter_keyval, &counter, &flg));
12128b400f6SJacob Faibussowitsch PetscCheck(flg, comm_in, PETSC_ERR_ARG_WRONGSTATE, "Requires a PETSc communicator as input, do not use something like MPI_COMM_WORLD");
12257f21012SBarry Smith
12357f21012SBarry Smith if (counter->comms) {
12457f21012SBarry Smith struct PetscCommStash *pcomms = counter->comms;
12557f21012SBarry Smith
12657f21012SBarry Smith *comm_out = pcomms->comm;
12757f21012SBarry Smith counter->comms = pcomms->next;
1289566063dSJacob Faibussowitsch PetscCall(PetscFree(pcomms));
1299566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Reusing a communicator %ld %ld\n", (long)comm_in, (long)*comm_out));
13057f21012SBarry Smith } else {
1319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_dup(comm_in, comm_out));
13257f21012SBarry Smith }
1339566063dSJacob Faibussowitsch PetscCall(PetscSpinlockUnlock(&PetscCommSpinLock));
1343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13557f21012SBarry Smith }
13657f21012SBarry Smith
13757f21012SBarry Smith /*@C
138811af0c4SBarry Smith PetscCommRestoreComm - restores an MPI communicator that was obtained with `PetscCommGetComm()`
13957f21012SBarry Smith
14057f21012SBarry Smith Collective
14157f21012SBarry Smith
14257f21012SBarry Smith Input Parameters:
14357f21012SBarry Smith + comm_in - Input communicator
14457f21012SBarry Smith - comm_out - returned communicator
14557f21012SBarry Smith
14657f21012SBarry Smith Level: developer
14757f21012SBarry Smith
14842747ad1SJacob Faibussowitsch .seealso: `PetscObjectGetNewTag()`, `PetscCommGetNewTag()`, `PetscCommDestroy()`
14957f21012SBarry Smith @*/
PetscCommRestoreComm(MPI_Comm comm_in,MPI_Comm * comm_out)150d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCommRestoreComm(MPI_Comm comm_in, MPI_Comm *comm_out)
151d71ae5a4SJacob Faibussowitsch {
15257f21012SBarry Smith PetscCommCounter *counter;
15357f21012SBarry Smith PetscMPIInt flg;
15457f21012SBarry Smith struct PetscCommStash *pcomms, *ncomm;
15557f21012SBarry Smith
15657f21012SBarry Smith PetscFunctionBegin;
1579566063dSJacob Faibussowitsch PetscCall(PetscSpinlockLock(&PetscCommSpinLock));
1589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm_in, Petsc_Counter_keyval, &counter, &flg));
15928b400f6SJacob Faibussowitsch PetscCheck(flg, comm_in, PETSC_ERR_ARG_WRONGSTATE, "Requires a PETSc communicator as input, do not use something like MPI_COMM_WORLD");
16057f21012SBarry Smith
1619566063dSJacob Faibussowitsch PetscCall(PetscMalloc(sizeof(struct PetscCommStash), &ncomm));
16257f21012SBarry Smith ncomm->comm = *comm_out;
16357f21012SBarry Smith ncomm->next = NULL;
16457f21012SBarry Smith pcomms = counter->comms;
16557f21012SBarry Smith while (pcomms && pcomms->next) pcomms = pcomms->next;
16657f21012SBarry Smith if (pcomms) {
16757f21012SBarry Smith pcomms->next = ncomm;
16857f21012SBarry Smith } else {
16957f21012SBarry Smith counter->comms = ncomm;
17057f21012SBarry Smith }
17157f21012SBarry Smith *comm_out = 0;
1729566063dSJacob Faibussowitsch PetscCall(PetscSpinlockUnlock(&PetscCommSpinLock));
1733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
17457f21012SBarry Smith }
17557f21012SBarry Smith
17657f21012SBarry Smith /*@C
1777b32b6dcSBarry Smith PetscCommDuplicate - Duplicates the communicator only if it is not already a PETSc communicator.
178e5c89e4eSSatish Balay
179d083f849SBarry Smith Collective
180e5c89e4eSSatish Balay
181f899ff85SJose E. Roman Input Parameter:
182e5c89e4eSSatish Balay . comm_in - Input communicator
183e5c89e4eSSatish Balay
184e5c89e4eSSatish Balay Output Parameters:
18521532e8aSBarry Smith + comm_out - Output communicator. May be `comm_in`.
18621532e8aSBarry Smith - first_tag - Tag available that has not already been used with this communicator (you may pass in `NULL` if you do not need a tag)
187e5c89e4eSSatish Balay
1882fe279fdSBarry Smith Level: developer
1892fe279fdSBarry Smith
190811af0c4SBarry Smith Note:
191e5c89e4eSSatish Balay PETSc communicators are just regular MPI communicators that keep track of which
192e5c89e4eSSatish Balay tags have been used to prevent tag conflict. If you pass a non-PETSc communicator into
193a98fc643SBarry Smith a PETSc creation routine it will attach a private communicator for use in the objects communications.
194811af0c4SBarry Smith The internal `MPI_Comm` is used to perform all the MPI calls for PETSc, the outer `MPI_Comm` is a user
195648c30bcSBarry Smith and is not used by PETSc.
196e5c89e4eSSatish Balay
197db781477SPatrick Sanan .seealso: `PetscObjectGetNewTag()`, `PetscCommGetNewTag()`, `PetscCommDestroy()`
198e5c89e4eSSatish Balay @*/
PetscCommDuplicate(MPI_Comm comm_in,MPI_Comm * comm_out,PetscMPIInt * first_tag)199d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCommDuplicate(MPI_Comm comm_in, MPI_Comm *comm_out, PetscMPIInt *first_tag)
200d71ae5a4SJacob Faibussowitsch {
20162e5d2d2SJDBetteridge PetscInt64 *cidx;
202480cf27aSJed Brown PetscCommCounter *counter;
203480cf27aSJed Brown PetscMPIInt *maxval, flg;
204e5c89e4eSSatish Balay
205e5c89e4eSSatish Balay PetscFunctionBegin;
2069566063dSJacob Faibussowitsch PetscCall(PetscSpinlockLock(&PetscCommSpinLock));
2079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm_in, Petsc_Counter_keyval, &counter, &flg));
208e5c89e4eSSatish Balay
2097b32b6dcSBarry Smith if (!flg) { /* this is NOT a PETSc comm */
2109371c9d4SSatish Balay union
2119371c9d4SSatish Balay {
2129371c9d4SSatish Balay MPI_Comm comm;
2139371c9d4SSatish Balay void *ptr;
2149371c9d4SSatish Balay } ucomm;
2156aad120cSJose E. Roman /* check if this communicator has a PETSc communicator embedded in it */
2169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm_in, Petsc_InnerComm_keyval, &ucomm, &flg));
217e5c89e4eSSatish Balay if (!flg) {
2187b32b6dcSBarry Smith /* This communicator is not yet known to this system, so we duplicate it and make an internal communicator */
2199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_dup(comm_in, comm_out));
2209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxval, &flg));
22128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_LIB, "MPI error: MPI_Comm_get_attr() is not returning a MPI_TAG_UB");
2229566063dSJacob Faibussowitsch PetscCall(PetscNew(&counter)); /* all fields of counter are zero'ed */
223480cf27aSJed Brown counter->tag = *maxval;
2249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(*comm_out, Petsc_Counter_keyval, counter));
22562e5d2d2SJDBetteridge /* Add an object creation index to the communicator */
22662e5d2d2SJDBetteridge PetscCall(PetscNew(&cidx));
22762e5d2d2SJDBetteridge PetscCallMPI(MPI_Comm_set_attr(*comm_out, Petsc_CreationIdx_keyval, cidx));
2289566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Duplicating a communicator %ld %ld max tags = %d\n", (long)comm_in, (long)*comm_out, *maxval));
229e5c89e4eSSatish Balay
230e5c89e4eSSatish Balay /* save PETSc communicator inside user communicator, so we can get it next time */
231265f3f35SJed Brown ucomm.comm = *comm_out; /* ONLY the comm part of the union is significant. */
2329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(comm_in, Petsc_InnerComm_keyval, ucomm.ptr));
233265f3f35SJed Brown ucomm.comm = comm_in;
2349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(*comm_out, Petsc_OuterComm_keyval, ucomm.ptr));
235e5c89e4eSSatish Balay } else {
236265f3f35SJed Brown *comm_out = ucomm.comm;
2377b32b6dcSBarry Smith /* pull out the inner MPI_Comm and hand it back to the caller */
2389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(*comm_out, Petsc_Counter_keyval, &counter, &flg));
23928b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inner PETSc communicator does not have its tag/name counter attribute set");
2409566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Using internal PETSc communicator %ld %ld\n", (long)comm_in, (long)*comm_out));
241e5c89e4eSSatish Balay }
242a297a907SKarl Rupp } else *comm_out = comm_in;
2433f34d28cSBarry Smith
24476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {
2453f34d28cSBarry Smith /*
2463f34d28cSBarry Smith Hanging here means that some processes have called PetscCommDuplicate() and others have not.
2476aad120cSJose E. Roman This likely means that a subset of processes in a MPI_Comm have attempted to create a PetscObject!
2483f34d28cSBarry Smith ALL processes that share a communicator MUST shared objects created from that communicator.
2493f34d28cSBarry Smith */
2509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm_in));
25176bd3646SJed Brown }
252e5c89e4eSSatish Balay
253480cf27aSJed Brown if (counter->tag < 1) {
2549566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Out of tags for object, starting to recycle. Comm reference count %" PetscInt_FMT "\n", counter->refcount));
2559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxval, &flg));
25628b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_LIB, "MPI error: MPI_Comm_get_attr() is not returning a MPI_TAG_UB");
257480cf27aSJed Brown counter->tag = *maxval - 128; /* hope that any still active tags were issued right at the beginning of the run */
258e5c89e4eSSatish Balay }
259e5c89e4eSSatish Balay
260a297a907SKarl Rupp if (first_tag) *first_tag = counter->tag--;
2615ef7c072SBarry Smith
2625c25fcd7SBarry Smith counter->refcount++; /* number of references to this comm */
2639566063dSJacob Faibussowitsch PetscCall(PetscSpinlockUnlock(&PetscCommSpinLock));
2643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
265e5c89e4eSSatish Balay }
266e5c89e4eSSatish Balay
267e5c89e4eSSatish Balay /*@C
268811af0c4SBarry Smith PetscCommDestroy - Frees communicator obtained with `PetscCommDuplicate()`.
269e5c89e4eSSatish Balay
270d083f849SBarry Smith Collective
271e5c89e4eSSatish Balay
272e5c89e4eSSatish Balay Input Parameter:
273e5c89e4eSSatish Balay . comm - the communicator to free
274e5c89e4eSSatish Balay
275e5c89e4eSSatish Balay Level: developer
276e5c89e4eSSatish Balay
277648c30bcSBarry Smith Notes:
278648c30bcSBarry Smith Sets `comm` to `NULL`
279648c30bcSBarry Smith
280648c30bcSBarry Smith The communicator is reference counted so it is only truly removed from the system when its reference count drops to zero
281648c30bcSBarry Smith
282db781477SPatrick Sanan .seealso: `PetscCommDuplicate()`
283e5c89e4eSSatish Balay @*/
PetscCommDestroy(MPI_Comm * comm)284d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCommDestroy(MPI_Comm *comm)
285d71ae5a4SJacob Faibussowitsch {
28662e5d2d2SJDBetteridge PetscInt64 *cidx;
287480cf27aSJed Brown PetscCommCounter *counter;
288480cf27aSJed Brown PetscMPIInt flg;
28962e5d2d2SJDBetteridge PetscGarbage garbage;
290e5c89e4eSSatish Balay MPI_Comm icomm = *comm, ocomm;
2919371c9d4SSatish Balay union
2929371c9d4SSatish Balay {
2939371c9d4SSatish Balay MPI_Comm comm;
2949371c9d4SSatish Balay void *ptr;
2959371c9d4SSatish Balay } ucomm;
296e5c89e4eSSatish Balay
297e5c89e4eSSatish Balay PetscFunctionBegin;
2983ba16761SJacob Faibussowitsch if (*comm == MPI_COMM_NULL) PetscFunctionReturn(PETSC_SUCCESS);
2999566063dSJacob Faibussowitsch PetscCall(PetscSpinlockLock(&PetscCommSpinLock));
3009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Counter_keyval, &counter, &flg));
3017b32b6dcSBarry Smith if (!flg) { /* not a PETSc comm, check if it has an inner comm */
3029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_InnerComm_keyval, &ucomm, &flg));
30328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have tag/name counter nor does it have inner MPI_Comm");
304265f3f35SJed Brown icomm = ucomm.comm;
3059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Counter_keyval, &counter, &flg));
30628b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory");
307e5c89e4eSSatish Balay }
3085c25fcd7SBarry Smith counter->refcount--;
309e93c322dSShri Abhyankar if (!counter->refcount) {
310b3ef52cdSBarry Smith /* if MPI_Comm has outer comm then remove reference to inner MPI_Comm from outer MPI_Comm */
3119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_OuterComm_keyval, &ucomm, &flg));
312dbc8283eSBarry Smith if (flg) {
313265f3f35SJed Brown ocomm = ucomm.comm;
3149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(ocomm, Petsc_InnerComm_keyval, &ucomm, &flg));
3150e6b6b59SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Outer MPI_Comm %ld does not have expected reference to inner comm %ld, problem with corrupted memory", (long int)ocomm, (long int)icomm);
3169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_delete_attr(ocomm, Petsc_InnerComm_keyval));
317e5c89e4eSSatish Balay }
318e5c89e4eSSatish Balay
31962e5d2d2SJDBetteridge /* Remove the object creation index on the communicator */
32062e5d2d2SJDBetteridge PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_CreationIdx_keyval, &cidx, &flg));
321*966bd95aSPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have object creation index");
32262e5d2d2SJDBetteridge PetscCall(PetscFree(cidx));
32362e5d2d2SJDBetteridge
32462e5d2d2SJDBetteridge /* Remove garbage hashmap set up by garbage collection */
32562e5d2d2SJDBetteridge PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Garbage_HMap_keyval, &garbage, &flg));
32662e5d2d2SJDBetteridge if (flg) {
32762e5d2d2SJDBetteridge PetscInt entries = 0;
32862e5d2d2SJDBetteridge PetscCall(PetscHMapObjGetSize(garbage.map, &entries));
32962e5d2d2SJDBetteridge if (entries > 0) PetscCall(PetscGarbageCleanup(icomm));
330f4f49eeaSPierre Jolivet PetscCall(PetscHMapObjDestroy(&garbage.map));
33162e5d2d2SJDBetteridge }
33262e5d2d2SJDBetteridge
3339566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Deleting PETSc MPI_Comm %ld\n", (long)icomm));
3349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&icomm));
335e5c89e4eSSatish Balay }
336542323b1SJed Brown *comm = MPI_COMM_NULL;
3379566063dSJacob Faibussowitsch PetscCall(PetscSpinlockUnlock(&PetscCommSpinLock));
3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
339e5c89e4eSSatish Balay }
340e5c89e4eSSatish Balay
34176270f95SDmitry Karpeev /*@C
3429abe469cSDmitry Karpeev PetscObjectsListGetGlobalNumbering - computes a global numbering
343811af0c4SBarry Smith of `PetscObject`s living on subcommunicators of a given communicator.
34476270f95SDmitry Karpeev
345d083f849SBarry Smith Collective.
34676270f95SDmitry Karpeev
34776270f95SDmitry Karpeev Input Parameters:
348811af0c4SBarry Smith + comm - the `MPI_Comm`
34921532e8aSBarry Smith . len - local length of `objlist`
3509abe469cSDmitry Karpeev - objlist - a list of PETSc objects living on subcomms of comm and containing this comm rank
3519abe469cSDmitry Karpeev (subcomm ordering is assumed to be deadlock-free)
35276270f95SDmitry Karpeev
35376270f95SDmitry Karpeev Output Parameters:
35426a11704SBarry Smith + count - global number of distinct subcommunicators on objlist (may be > `len`)
3559abe469cSDmitry Karpeev - numbering - global numbers of objlist entries (allocated by user)
35676270f95SDmitry Karpeev
35776270f95SDmitry Karpeev Level: developer
35876270f95SDmitry Karpeev
359811af0c4SBarry Smith Note:
360811af0c4SBarry Smith This is needed when PETSc is used with certain languages that do garbage collection to manage object life cycles.
361811af0c4SBarry Smith
36210450e9eSJacob Faibussowitsch .seealso: `PetscCommDuplicate()`, `PetscObjectDestroy()`
36376270f95SDmitry Karpeev @*/
PetscObjectsListGetGlobalNumbering(MPI_Comm comm,PetscInt len,PetscObject objlist[],PetscInt * count,PetscInt * numbering)3649c9354e5SBarry Smith PetscErrorCode PetscObjectsListGetGlobalNumbering(MPI_Comm comm, PetscInt len, PetscObject objlist[], PetscInt *count, PetscInt *numbering)
365d71ae5a4SJacob Faibussowitsch {
36676270f95SDmitry Karpeev PetscInt i, roots, offset;
3674924a606SDmitry Karpeev PetscMPIInt size, rank;
3685fd66863SKarl Rupp
36976270f95SDmitry Karpeev PetscFunctionBegin;
3704f572ea9SToby Isaac PetscAssertPointer(objlist, 3);
3713ba16761SJacob Faibussowitsch if (!count && !numbering) PetscFunctionReturn(PETSC_SUCCESS);
3729abe469cSDmitry Karpeev
3739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
3749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
37576270f95SDmitry Karpeev roots = 0;
37676270f95SDmitry Karpeev for (i = 0; i < len; ++i) {
3774924a606SDmitry Karpeev PetscMPIInt srank;
3789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(objlist[i]->comm, &srank));
37976270f95SDmitry Karpeev /* Am I the root of the i-th subcomm? */
3804924a606SDmitry Karpeev if (!srank) ++roots;
38176270f95SDmitry Karpeev }
3829abe469cSDmitry Karpeev if (count) {
38376270f95SDmitry Karpeev /* Obtain the sum of all roots -- the global number of distinct subcomms. */
384462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&roots, count, 1, MPIU_INT, MPI_SUM, comm));
3859abe469cSDmitry Karpeev }
3869abe469cSDmitry Karpeev if (numbering) {
3879abe469cSDmitry Karpeev /* Introduce a global numbering for subcomms, initially known only by subcomm roots. */
38876270f95SDmitry Karpeev /*
3896e4e7d8dSDmitry Karpeev At each subcomm root number all of the subcomms it owns locally
3906e4e7d8dSDmitry Karpeev and make it global by calculating the shift among all of the roots.
3916e4e7d8dSDmitry Karpeev The roots are ordered using the comm ordering.
39276270f95SDmitry Karpeev */
3939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&roots, &offset, 1, MPIU_INT, MPI_SUM, comm));
39476270f95SDmitry Karpeev offset -= roots;
3954924a606SDmitry Karpeev /* Now we are ready to broadcast global subcomm numbers within each subcomm.*/
3966a4f0f73SDmitry Karpeev /*
3974924a606SDmitry Karpeev This is where the assumption of a deadlock-free ordering of the subcomms is assumed:
3984924a606SDmitry Karpeev broadcast is collective on the subcomm.
3996a4f0f73SDmitry Karpeev */
4004bde246dSDmitry Karpeev roots = 0;
40176270f95SDmitry Karpeev for (i = 0; i < len; ++i) {
4024924a606SDmitry Karpeev PetscMPIInt srank;
4034924a606SDmitry Karpeev numbering[i] = offset + roots; /* only meaningful if !srank. */
404a297a907SKarl Rupp
4059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(objlist[i]->comm, &srank));
4069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(numbering + i, 1, MPIU_INT, 0, objlist[i]->comm));
4074924a606SDmitry Karpeev if (!srank) ++roots;
4086a4f0f73SDmitry Karpeev }
4099abe469cSDmitry Karpeev }
4103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
41176270f95SDmitry Karpeev }
412