Actual source code: vcreatea.c


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

  4: /* ---------------------------------------------------------------------*/

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

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

 16:    Collective

 18:    Input Parameter:
 19: .  comm - the MPI communicator to share the `PetscViewer`

 21:    Level: beginner

 23:    Note:
 24:      This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()`

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

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

 48: /*@C
 49:    PETSC_VIEWER_STDOUT_ - Creates a ASCII `PetscViewer` shared by all processors
 50:                     in a communicator.

 52:    Collective

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

 57:    Level: beginner

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

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

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

 80: /* ---------------------------------------------------------------------*/

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

 88: /*@
 89:    PetscViewerASCIIGetStderr - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processors
 90:                     in a communicator. Error returning version of `PETSC_VIEWER_STDERR_()`

 92:    Collective

 94:    Input Parameter:
 95: .  comm - the MPI communicator to share the `PetscViewer`

 97:    Level: beginner

 99:    Note:
100:      This should be used in all PETSc source code instead of `PETSC_VIEWER_STDERR_()`

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

110:   PetscSpinlockLock(&PetscViewerASCIISpinLockStderr);
111:   PetscCommDuplicate(comm, &ncomm, NULL);
112:   if (Petsc_Viewer_Stderr_keyval == MPI_KEYVAL_INVALID) MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stderr_keyval, NULL);
113:   MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg);
114:   if (!flg) { /* PetscViewer not yet created */
115:     PetscViewerASCIIOpen(ncomm, "stderr", viewer);
116:     PetscObjectRegisterDestroy((PetscObject)*viewer);
117:     MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer);
118:   }
119:   PetscCommDestroy(&ncomm);
120:   PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr);
121:   return 0;
122: }

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

128:    Collective

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

133:    Level: beginner

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

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

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

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

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

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

170: /*@C
171:    PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PetscViewer`.

173:    Collective

175:    Input Parameters:
176: +  comm - the communicator
177: -  name - the file name

179:    Output Parameter:
180: .  lab - the PetscViewer to use with the specified file

182:    Level: beginner

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

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

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

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

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

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

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

269: /*@C
270:    PetscViewerASCIIOpenWithFILE - Given an open file creates an ASCII viewer that prints to it.

272:    Collective

274:    Input Parameters:
275: +  comm - the communicator
276: -  fd - the FILE pointer

278:    Output Parameter:
279: .  lab - the `PetscViewer` to use with the specified file

281:    Level: beginner

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

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

290: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`,
291:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
292:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
293: @*/
294: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab)
295: {
296:   PetscViewerCreate(comm, lab);
297:   PetscViewerSetType(*lab, PETSCVIEWERASCII);
298:   PetscViewerASCIISetFILE(*lab, fd);
299:   return 0;
300: }

302: /*@C
303:    PetscViewerASCIISetFILE - Given an open file sets the ASCII viewer to use the file for output

305:    Not collective

307:    Input Parameters:
308: +  viewer - the `PetscViewer` to use with the specified file
309: -  fd - the FILE pointer

311:    Level: beginner

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

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

320: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`,
321:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
322:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
323: @*/
324: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
325: {
326:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

328:   vascii->fd        = fd;
329:   vascii->closefile = PETSC_FALSE;
330:   return 0;
331: }