Actual source code: vcreatea.c


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

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

 10: /*@
 11:    PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processors
 12:                     in a communicator. Error returning version of `PETSC_VIEWER_STDOUT_()`

 14:    Collective

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

 19:    Level: beginner

 21:    Note:
 22:      This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking

 24: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
 25:           `PETSC_VIEWER_STDOUT_SELF`
 26: @*/
 27: PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
 28: {
 29:   PetscBool flg;
 30:   MPI_Comm  ncomm;

 32:   PetscFunctionBegin;
 33:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
 34:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
 35:   if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL));
 36:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg));
 37:   if (!flg) { /* PetscViewer not yet created */
 38:     PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer));
 39:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
 40:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
 41:   }
 42:   PetscCall(PetscCommDestroy(&ncomm));
 43:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
 44:   PetscFunctionReturn(PETSC_SUCCESS);
 45: }

 47: /*@C
 48:    PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 49:                     in a communicator.

 51:    Collective

 53:    Input Parameter:
 54: .  comm - the MPI communicator to share the `PetscViewer`

 56:    Level: beginner

 58:    Note:
 59:    Unlike almost all other PETSc routines, this does not return
 60:    an error code. Usually used in the form
 61: $      XXXView(XXX object, PETSC_VIEWER_STDOUT_(comm));

 63: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
 64:           `PETSC_VIEWER_STDOUT_SELF`
 65: @*/
 66: PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm)
 67: {
 68:   PetscErrorCode ierr;
 69:   PetscViewer    viewer;

 71:   PetscFunctionBegin;
 72:   ierr = PetscViewerASCIIGetStdout(comm, &viewer);
 73:   if (ierr) {
 74:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDOUT_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
 75:     PetscFunctionReturn(NULL);
 76:   }
 77:   PetscFunctionReturn(viewer);
 78: }

 80: /*
 81:     The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that
 82:   is attached to a communicator, in this case the attribute is a PetscViewer.
 83: */
 84: PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID;

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

 90:    Collective

 92:    Input Parameter:
 93: .  comm - the MPI communicator to share the `PetscViewer`

 95:    Level: beginner

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

100: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
101:           `PETSC_VIEWER_STDERR_SELF`
102: @*/
103: PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
104: {
105:   PetscBool flg;
106:   MPI_Comm  ncomm;

108:   PetscFunctionBegin;
109:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
110:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
111:   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));
112:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg));
113:   if (!flg) { /* PetscViewer not yet created */
114:     PetscCall(PetscViewerASCIIOpen(ncomm, "stderr", viewer));
115:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
116:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
117:   }
118:   PetscCall(PetscCommDestroy(&ncomm));
119:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
120:   PetscFunctionReturn(PETSC_SUCCESS);
121: }

123: /*@C
124:    PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
125:                     in a communicator.

127:    Collective

129:    Input Parameter:
130: .  comm - the MPI communicator to share the `PetscViewer`

132:    Level: beginner

134:    Notes:
135:    Unlike almost all other PETSc routines, this does not return
136:    an error code. Usually used in the form
137: $      XXXView(XXX object, PETSC_VIEWER_STDERR_(comm));

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

141: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`,
142:           `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF`
143: @*/
144: PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
145: {
146:   PetscErrorCode ierr;
147:   PetscViewer    viewer;

149:   PetscFunctionBegin;
150:   ierr = PetscViewerASCIIGetStderr(comm, &viewer);
151:   if (ierr) {
152:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDERR_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
153:     PetscFunctionReturn(NULL);
154:   }
155:   PetscFunctionReturn(viewer);
156: }

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

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

165: */
166: PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
167: {
168:   PetscFunctionBegin;
169:   PetscCallMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %ld\n", (long)comm));
170:   PetscFunctionReturn(MPI_SUCCESS);
171: }

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

176:    Collective

178:    Input Parameters:
179: +  comm - the communicator
180: -  name - the file name

182:    Output Parameter:
183: .  lab - the `PetscViewer` to use with the specified file

185:    Level: beginner

187:    Notes:
188:    To open a ASCII file as a viewer for reading one must use the sequence
189: .vb
190:    PetscViewerCreate(comm,&lab);
191:    PetscViewerSetType(lab,PETSCVIEWERASCII);
192:    PetscViewerFileSetMode(lab,FILE_MODE_READ);
193:    PetscViewerFileSetName(lab,name);
194: .ve

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

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

201:    As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with
202:    `MatView()` and `VecView()`
203: .vb
204:      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
205:      MatView(matrix,viewer);
206: .ve

208: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII`
209:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
210:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`,
211: @*/
212: PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *lab)
213: {
214:   PetscViewerLink *vlink, *nv;
215:   PetscBool        flg, eq;
216:   size_t           len;

218:   PetscFunctionBegin;
219:   PetscCall(PetscStrlen(name, &len));
220:   if (!len) {
221:     PetscCall(PetscViewerASCIIGetStdout(comm, lab));
222:     PetscCall(PetscObjectReference((PetscObject)*lab));
223:     PetscFunctionReturn(PETSC_SUCCESS);
224:   }
225:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen));
226:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
227:   /*
228:        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
229:      we cannot do that, since PetscFileSetName() takes a communicator that already exists.

231:       Plus if the original communicator that created the file has since been close this will not detect the old
232:       communictor and hence will overwrite the old data. It may be better to simply remove all this code
233:   */
234:   /* make sure communicator is a PETSc communicator */
235:   PetscCall(PetscCommDuplicate(comm, &comm, NULL));
236:   /* has file already been opened into a viewer */
237:   PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
238:   if (flg) {
239:     while (vlink) {
240:       PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)(vlink->viewer->data))->filename, &eq));
241:       if (eq) {
242:         PetscCall(PetscObjectReference((PetscObject)vlink->viewer));
243:         *lab = vlink->viewer;
244:         PetscCall(PetscCommDestroy(&comm));
245:         PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
246:         PetscFunctionReturn(PETSC_SUCCESS);
247:       }
248:       vlink = vlink->next;
249:     }
250:   }
251:   PetscCall(PetscViewerCreate(comm, lab));
252:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
253:   if (name) PetscCall(PetscViewerFileSetName(*lab, name));
254:   /* save viewer into communicator if needed later */
255:   PetscCall(PetscNew(&nv));
256:   nv->viewer = *lab;
257:   if (!flg) {
258:     PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
259:   } else {
260:     PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
261:     if (vlink) {
262:       while (vlink->next) vlink = vlink->next;
263:       vlink->next = nv;
264:     } else {
265:       PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
266:     }
267:   }
268:   PetscCall(PetscCommDestroy(&comm));
269:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
270:   PetscFunctionReturn(PETSC_SUCCESS);
271: }

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

276:    Collective

278:    Input Parameters:
279: +  comm - the communicator
280: -  fd - the `FILE` pointer

282:    Output Parameter:
283: .  lab - the `PetscViewer` to use with the specified file

285:    Level: beginner

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

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

294: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`,
295:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
296:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
297: @*/
298: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab)
299: {
300:   PetscFunctionBegin;
301:   PetscCall(PetscViewerCreate(comm, lab));
302:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
303:   PetscCall(PetscViewerASCIISetFILE(*lab, fd));
304:   PetscFunctionReturn(PETSC_SUCCESS);
305: }

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

310:    Not Collective

312:    Input Parameters:
313: +  viewer - the `PetscViewer` to use with the specified file
314: -  fd - the `FILE` pointer

316:    Level: beginner

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

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

325: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`,
326:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
327:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
328: @*/
329: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
330: {
331:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

333:   PetscFunctionBegin;
334:   vascii->fd        = fd;
335:   vascii->closefile = PETSC_FALSE;
336:   PetscFunctionReturn(PETSC_SUCCESS);
337: }