/*@C PetscCommDestroy - Frees communicator. Use in conjunction with PetscCommDuplicate(). Collective on MPI_Comm Input Parameter: . comm - the communicator to free Level: developer Concepts: communicator^destroy .seealso: PetscCommDuplicate() @*/ PetscErrorCode PetscCommDestroy(MPI_Comm *comm) { PetscErrorCode ierr; PetscCommCounter *counter; PetscMPIInt flg; MPI_Comm icomm = *comm,ocomm; union {MPI_Comm comm; void *ptr;} ucomm; PetscFunctionBegin; if (*comm == MPI_COMM_NULL) PetscFunctionReturn(0); ierr = PetscSpinlockLock(&PetscCommSpinLock);CHKERRQ(ierr); ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) { /* not a PETSc comm, check if it has an inner comm */ ierr = MPI_Attr_get(icomm,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"MPI_Comm does not have tag/name counter nor does it have inner MPI_Comm"); icomm = ucomm.comm; ierr = MPI_Attr_get(icomm,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Inner MPI_Comm does not have expected tag/name counter, problem with corrupted memory"); } counter->refcount--; if (!counter->refcount) { /* if MPI_Comm has outer comm then remove reference to inner MPI_Comm from outer MPI_Comm */ ierr = MPI_Attr_get(icomm,Petsc_OuterComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { ocomm = ucomm.comm; ierr = MPI_Attr_get(ocomm,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (flg) { ierr = MPI_Attr_delete(ocomm,Petsc_InnerComm_keyval);CHKERRQ(ierr); } else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Outer MPI_Comm %ld does not have expected reference to inner comm %d, problem with corrupted memory",(long int)ocomm,(long int)icomm); } ierr = PetscInfo1(0,"Deleting PETSc MPI_Comm %ld\n",(long)icomm);CHKERRQ(ierr); ierr = MPI_Comm_free(&icomm);CHKERRQ(ierr); } *comm = MPI_COMM_NULL; ierr = PetscSpinlockUnlock(&PetscCommSpinLock);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscViewerASCIIGetStdout - Creates a ASCII PetscViewer shared by all processors in a communicator. Error returning version of PETSC_VIEWER_STDOUT_() Collective on MPI_Comm Input Parameter: . comm - the MPI communicator to share the PetscViewer Level: beginner Notes: This should be used in all PETSc source code instead of PETSC_VIEWER_STDOUT_() .seealso: PETSC_VIEWER_DRAW_(), PetscViewerASCIIOpen(), PETSC_VIEWER_STDERR_, PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF @*/ PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm,PetscViewer *viewer) { PetscErrorCode ierr; PetscBool flg; MPI_Comm ncomm; PetscFunctionBegin; ierr = PetscSpinlockLock(&PetscViewerASCIISpinLockStdout);CHKERRQ(ierr); ierr = PetscCommDuplicate(comm,&ncomm,NULL);CHKERRQ(ierr); if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) { ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Stdout_keyval,0);CHKERRQ(ierr); } ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Stdout_keyval,(void**)viewer,(PetscMPIInt*)&flg);CHKERRQ(ierr); if (!flg) { /* PetscViewer not yet created */ ierr = PetscViewerASCIIOpen(ncomm,"stdout",viewer);CHKERRQ(ierr); ierr = PetscObjectRegisterDestroy((PetscObject)*viewer);CHKERRQ(ierr); ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Stdout_keyval,(void*)*viewer);CHKERRQ(ierr); } ierr = PetscCommDestroy(&ncomm);CHKERRQ(ierr); ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscCommDuplicate - Duplicates the communicator only if it is not already a PETSc communicator. Collective on MPI_Comm Input Parameters: . comm_in - Input communicator Output Parameters: + comm_out - Output communicator. May be comm_in. - 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) PETSc communicators are just regular MPI communicators that keep track of which tags have been used to prevent tag conflict. If you pass a non-PETSc communicator into a PETSc creation routine it will attach a private communicator for use in the objects communications. The internal MPI_Comm is used to perform all the MPI calls for PETSc, the outer MPI_Comm is a user level MPI_Comm that may be performing communication for the user or other library and so IS NOT used by PETSc. Level: developer Concepts: communicator^duplicate .seealso: PetscObjectGetNewTag(), PetscCommGetNewTag(), PetscCommDestroy() @*/ PetscErrorCode PetscCommDuplicate(MPI_Comm comm_in,MPI_Comm *comm_out,PetscMPIInt *first_tag) { PetscErrorCode ierr; PetscCommCounter *counter; PetscMPIInt *maxval,flg; PetscFunctionBegin; ierr = PetscSpinlockLock(&PetscCommSpinLock);CHKERRQ(ierr); ierr = MPI_Attr_get(comm_in,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) { /* this is NOT a PETSc comm */ union {MPI_Comm comm; void *ptr;} ucomm; /* check if this communicator has a PETSc communicator imbedded in it */ ierr = MPI_Attr_get(comm_in,Petsc_InnerComm_keyval,&ucomm,&flg);CHKERRQ(ierr); if (!flg) { /* This communicator is not yet known to this system, so we duplicate it and make an internal communicator */ ierr = MPI_Comm_dup(comm_in,comm_out);CHKERRQ(ierr); ierr = MPI_Attr_get(MPI_COMM_WORLD,MPI_TAG_UB,&maxval,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI error: MPI_Attr_get() is not returning a MPI_TAG_UB"); ierr = PetscNew(&counter);CHKERRQ(ierr); counter->tag = *maxval; counter->refcount = 0; counter->namecount = 0; ierr = MPI_Attr_put(*comm_out,Petsc_Counter_keyval,counter);CHKERRQ(ierr); ierr = PetscInfo3(0,"Duplicating a communicator %ld %ld max tags = %d\n",(long)comm_in,(long)*comm_out,*maxval);CHKERRQ(ierr); /* save PETSc communicator inside user communicator, so we can get it next time */ ucomm.comm = *comm_out; /* ONLY the comm part of the union is significant. */ ierr = MPI_Attr_put(comm_in,Petsc_InnerComm_keyval,ucomm.ptr);CHKERRQ(ierr); ucomm.comm = comm_in; ierr = MPI_Attr_put(*comm_out,Petsc_OuterComm_keyval,ucomm.ptr);CHKERRQ(ierr); } else { *comm_out = ucomm.comm; /* pull out the inner MPI_Comm and hand it back to the caller */ ierr = MPI_Attr_get(*comm_out,Petsc_Counter_keyval,&counter,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inner PETSc communicator does not have its tag/name counter attribute set"); ierr = PetscInfo2(0,"Using internal PETSc communicator %ld %ld\n",(long)comm_in,(long)*comm_out);CHKERRQ(ierr); } } else *comm_out = comm_in; #if defined(PETSC_USE_DEBUG) /* Hanging here means that some processes have called PetscCommDuplicate() and others have not. This likley means that a subset of processes in a MPI_Comm have attempted to create a PetscObject! ALL processes that share a communicator MUST shared objects created from that communicator. */ ierr = MPI_Barrier(comm_in);CHKERRQ(ierr); #endif if (counter->tag < 1) { ierr = PetscInfo1(0,"Out of tags for object, starting to recycle. Comm reference count %d\n",counter->refcount);CHKERRQ(ierr); ierr = MPI_Attr_get(MPI_COMM_WORLD,MPI_TAG_UB,&maxval,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"MPI error: MPI_Attr_get() is not returning a MPI_TAG_UB"); counter->tag = *maxval - 128; /* hope that any still active tags were issued right at the beginning of the run */ } if (first_tag) *first_tag = counter->tag--; counter->refcount++; /* number of references to this comm */ ierr = PetscSpinlockUnlock(&PetscCommSpinLock);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscViewerASCIIOpen - Opens an ASCII file as a PetscViewer. Collective on MPI_Comm Input Parameters: + comm - the communicator - name - the file name Output Parameter: . lab - the PetscViewer to use with the specified file Level: beginner Notes: This PetscViewer can be destroyed with PetscViewerDestroy(). The MPI communicator used here must match that used by the object one is viewing. For example if the Mat was created with a PETSC_COMM_WORLD, then the Viewer must be created with PETSC_COMM_WORLD As shown below, PetscViewerASCIIOpen() is useful in conjunction with MatView() and VecView() .vb PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer); MatView(matrix,viewer); .ve Concepts: PetscViewerASCII^creating Concepts: printf Concepts: printing Concepts: accessing remote file Concepts: remote file .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(), PetscViewerASCIIGetPointer(), PetscViewerPushFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_, PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF, @*/ PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm,const char name[],PetscViewer *lab) { PetscErrorCode ierr; PetscViewerLink *vlink,*nv; PetscBool flg,eq; size_t len; PetscFunctionBegin; ierr = PetscStrlen(name,&len);CHKERRQ(ierr); if (!len) { ierr = PetscViewerASCIIGetStdout(comm,lab);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject)*lab);CHKERRQ(ierr); PetscFunctionReturn(0); } ierr = PetscSpinlockLock(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr); if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) { ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);CHKERRQ(ierr); } /* It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator we cannot do that, since PetscFileSetName() takes a communicator that already exists. Plus if the original communicator that created the file has since been close this will not detect the old communictor and hence will overwrite the old data. It may be better to simply remove all this code */ /* make sure communicator is a PETSc communicator */ ierr = PetscCommDuplicate(comm,&comm,NULL);CHKERRQ(ierr); /* has file already been opened into a viewer */ ierr = MPI_Attr_get(comm,Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRQ(ierr); if (flg) { while (vlink) { ierr = PetscStrcmp(name,((PetscViewer_ASCII*)(vlink->viewer->data))->filename,&eq);CHKERRQ(ierr); if (eq) { ierr = PetscObjectReference((PetscObject)vlink->viewer);CHKERRQ(ierr); *lab = vlink->viewer; ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr); PetscFunctionReturn(0); } vlink = vlink->next; } } ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr); ierr = PetscViewerSetType(*lab,PETSCVIEWERASCII);CHKERRQ(ierr); if (name) { ierr = PetscViewerFileSetName(*lab,name);CHKERRQ(ierr); } /* save viewer into communicator if needed later */ ierr = PetscNew(&nv);CHKERRQ(ierr); nv->viewer = *lab; if (!flg) { ierr = MPI_Attr_put(comm,Petsc_Viewer_keyval,nv);CHKERRQ(ierr); } else { ierr = MPI_Attr_get(comm,Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRQ(ierr); if (vlink) { while (vlink->next) vlink = vlink->next; vlink->next = nv; } else { ierr = MPI_Attr_put(comm,Petsc_Viewer_keyval,nv);CHKERRQ(ierr); } } ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr); PetscFunctionReturn(0); }