Actual source code: vcreatea.c

  1: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>

  3: /*
  4:     The variable Petsc_Viewer_Stdout_keyval is used to indicate an MPI attribute that
  5:   is attached to a communicator, in this case the attribute is a PetscViewer.
  6: */
  7: PetscMPIInt Petsc_Viewer_Stdout_keyval = MPI_KEYVAL_INVALID;

  9: /*@C
 10:    PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 11:                     in a communicator.

 13:    Collective

 15:    Input Parameter:
 16: .  comm - the MPI communicator to share the `PetscViewer`

 18:    Level: beginner

 20:    Notes:
 21:    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

 23:    Unlike almost all other PETSc routines, this does not return
 24:    an error code. Usually used in the form
 25: $      XXXView(XXX object, PETSC_VIEWER_STDOUT_(comm));

 27: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
 28:           `PETSC_VIEWER_STDOUT_SELF`
 29: @*/
 30: PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm)
 31: {
 32:   PetscErrorCode ierr;
 33:   PetscViewer    viewer;

 35:   PetscFunctionBegin;
 36:   ierr = PetscViewerASCIIGetStdout(comm, &viewer);
 37:   if (ierr) {
 38:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDOUT_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
 39:     PetscFunctionReturn(NULL);
 40:   }
 41:   PetscFunctionReturn(viewer);
 42: }

 44: /*
 45:     The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that
 46:   is attached to a communicator, in this case the attribute is a PetscViewer.
 47: */
 48: PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID;

 50: /*@
 51:   PetscViewerASCIIGetStderr - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 52:   in a communicator. Error returning version of `PETSC_VIEWER_STDERR_()`

 54:   Collective

 56:   Input Parameter:
 57: . comm - the MPI communicator to share the `PetscViewer`

 59:   Output Parameter:
 60: . viewer - the viewer

 62:   Level: beginner

 64:   Note:
 65:   This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

 67:   Developer Note:
 68:   This should be used in all PETSc source code instead of `PETSC_VIEWER_STDERR_()` since it allows error checking

 70: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
 71:           `PETSC_VIEWER_STDERR_SELF`
 72: @*/
 73: PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
 74: {
 75:   PetscBool flg;
 76:   MPI_Comm  ncomm;

 78:   PetscFunctionBegin;
 79:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
 80:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
 81:   if (Petsc_Viewer_Stderr_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stderr_keyval, NULL));
 82:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg));
 83:   if (!flg) { /* PetscViewer not yet created */
 84:     PetscCall(PetscViewerASCIIOpen(ncomm, "stderr", viewer));
 85:     ((PetscObject)*viewer)->persistent = PETSC_TRUE;
 86:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
 87:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
 88:   }
 89:   PetscCall(PetscCommDestroy(&ncomm));
 90:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
 91:   PetscFunctionReturn(PETSC_SUCCESS);
 92: }

 94: /*@C
 95:    PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 96:                     in a communicator.

 98:    Collective

100:    Input Parameter:
101: .  comm - the MPI communicator to share the `PetscViewer`

103:    Level: beginner

105:    Notes:
106:    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

108:    Unlike almost all other PETSc routines, this does not return
109:    an error code. Usually used in the form
110: $      XXXView(XXX object, PETSC_VIEWER_STDERR_(comm));

112:    `PetscViewerASCIIGetStderr()` is preferred  since it allows error checking

114: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`,
115:           `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF`
116: @*/
117: PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
118: {
119:   PetscErrorCode ierr;
120:   PetscViewer    viewer;

122:   PetscFunctionBegin;
123:   ierr = PetscViewerASCIIGetStderr(comm, &viewer);
124:   if (ierr) {
125:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDERR_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
126:     PetscFunctionReturn(NULL);
127:   }
128:   PetscFunctionReturn(viewer);
129: }

131: PetscMPIInt Petsc_Viewer_keyval = MPI_KEYVAL_INVALID;
132: /*
133:    Called with MPI_Comm_free() is called on a communicator that has a viewer as an attribute. The viewer is not actually destroyed
134:    because that is managed by PetscObjectDestroyRegisterAll(). PetscViewerASCIIGetStdout() registers the viewer with PetscObjectDestroyRegister() to be destroyed when PetscFinalize() is called.

136:   This is called by MPI, not by users.

138: */
139: PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
140: {
141:   PetscFunctionBegin;
142:   (void)keyval;
143:   (void)attr_val;
144:   (void)extra_state;
145:   PetscCallMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)comm));
146:   PetscFunctionReturn(MPI_SUCCESS);
147: }

149: /*@C
150:   PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`.

152:   Collective

154:   Input Parameters:
155: + comm - the communicator
156: - name - the file name

158:   Output Parameter:
159: . lab - the `PetscViewer` to use with the specified file

161:   Level: beginner

163:   Notes:
164:   To open a ASCII file as a viewer for reading one must use the sequence
165: .vb
166:    PetscViewerCreate(comm,&lab);
167:    PetscViewerSetType(lab,PETSCVIEWERASCII);
168:    PetscViewerFileSetMode(lab,FILE_MODE_READ);
169:    PetscViewerFileSetName(lab,name);
170: .ve

172:   This `PetscViewer` can be destroyed with `PetscViewerDestroy()`.

174:   The MPI communicator used here must match that used by the object one is viewing. For example if the
175:   Mat was created with a `PETSC_COMM_WORLD`, then the Viewer must be created with `PETSC_COMM_WORLD`

177:   As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with
178:   `MatView()` and `VecView()`
179: .vb
180:      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
181:      MatView(matrix,viewer);
182: .ve

184: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII`
185:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
186:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`,
187: @*/
188: PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *lab)
189: {
190:   PetscViewerLink *vlink, *nv;
191:   PetscBool        flg, eq;
192:   size_t           len;

194:   PetscFunctionBegin;
195:   PetscCall(PetscStrlen(name, &len));
196:   if (!len) {
197:     PetscCall(PetscViewerASCIIGetStdout(comm, lab));
198:     PetscCall(PetscObjectReference((PetscObject)*lab));
199:     PetscFunctionReturn(PETSC_SUCCESS);
200:   }
201:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen));
202:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
203:   /*
204:        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
205:      we cannot do that, since PetscFileSetName() takes a communicator that already exists.

207:       Plus if the original communicator that created the file has since been close this will not detect the old
208:       communictor and hence will overwrite the old data. It may be better to simply remove all this code
209:   */
210:   /* make sure communicator is a PETSc communicator */
211:   PetscCall(PetscCommDuplicate(comm, &comm, NULL));
212:   /* has file already been opened into a viewer */
213:   PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
214:   if (flg) {
215:     while (vlink) {
216:       PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)vlink->viewer->data)->filename, &eq));
217:       if (eq) {
218:         PetscCall(PetscObjectReference((PetscObject)vlink->viewer));
219:         *lab = vlink->viewer;
220:         PetscCall(PetscCommDestroy(&comm));
221:         PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
222:         PetscFunctionReturn(PETSC_SUCCESS);
223:       }
224:       vlink = vlink->next;
225:     }
226:   }
227:   PetscCall(PetscViewerCreate(comm, lab));
228:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
229:   if (name) PetscCall(PetscViewerFileSetName(*lab, name));
230:   /* save viewer into communicator if needed later */
231:   PetscCall(PetscNew(&nv));
232:   nv->viewer = *lab;
233:   if (!flg) {
234:     PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
235:   } else {
236:     PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
237:     if (vlink) {
238:       while (vlink->next) vlink = vlink->next;
239:       vlink->next = nv;
240:     } else {
241:       PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
242:     }
243:   }
244:   PetscCall(PetscCommDestroy(&comm));
245:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
246:   PetscFunctionReturn(PETSC_SUCCESS);
247: }

249: /*@C
250:   PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it.

252:   Collective

254:   Input Parameters:
255: + comm - the communicator
256: - fd   - the `FILE` pointer

258:   Output Parameter:
259: . lab - the `PetscViewer` to use with the specified file

261:   Level: beginner

263:   Notes:
264:   This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the fd will NOT be closed.

266:   If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`),
267:   then only the first processor in the group uses the file.  All other
268:   processors send their data to the first processor to print.

270:   Fortran Notes:
271:   Use `PetscViewerASCIIOpenWithFileUnit()`

273: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIOpenWithFileUnit()`,
274:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
275:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
276: @*/
277: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab)
278: {
279:   PetscFunctionBegin;
280:   PetscCall(PetscViewerCreate(comm, lab));
281:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
282:   PetscCall(PetscViewerASCIISetFILE(*lab, fd));
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: /*@C
287:   PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output

289:   Not Collective

291:   Input Parameters:
292: + viewer - the `PetscViewer` to use with the specified file
293: - fd     - the `FILE` pointer

295:   Level: beginner

297:   Notes:
298:   This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the `fd` will NOT be closed.

300:   If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`),
301:   then only the first processor in the group uses the file.  All other
302:   processors send their data to the first processor to print.

304:   Fortran Notes:
305:   Use `PetscViewerASCIISetFileUnit()`

307: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIISetFileUnit()`,
308:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
309:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
310: @*/
311: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
312: {
313:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

315:   PetscFunctionBegin;
316:   vascii->fd        = fd;
317:   vascii->closefile = PETSC_FALSE;
318:   PetscFunctionReturn(PETSC_SUCCESS);
319: }