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: /*@
 10:    PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes in a communicator.

 12:    Collective

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

 17:    Level: beginner

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

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

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

 35:   PetscFunctionBegin;
 36:   PetscCallNull(PetscViewerASCIIGetStdout(comm, &viewer));
 37:   PetscFunctionReturn(viewer);
 38: }

 40: /*
 41:     The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that
 42:   is attached to a communicator, in this case the attribute is a PetscViewer.
 43: */
 44: PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID;

 46: /*@
 47:   PetscViewerASCIIGetStderr - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 48:   in a communicator that prints to `stderr`. Error returning version of `PETSC_VIEWER_STDERR_()`

 50:   Collective

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

 55:   Output Parameter:
 56: . viewer - the viewer

 58:   Level: beginner

 60:   Note:
 61:   Use `PetscViewerDestroy()` to destroy it

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

 66: .seealso: [](sec_viewers), `PetscViewerASCIIGetStdout()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
 67:           `PETSC_VIEWER_STDERR_SELF`
 68: @*/
 69: PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
 70: {
 71:   PetscMPIInt iflg;
 72:   MPI_Comm    ncomm;

 74:   PetscFunctionBegin;
 75:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
 76:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
 77:   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));
 78:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, &iflg));
 79:   if (!iflg) { /* PetscViewer not yet created */
 80:     PetscCall(PetscViewerCreate(ncomm, viewer));
 81:     PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
 82:     PetscCall(PetscViewerFileSetName(*viewer, "stderr"));
 83:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
 84:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
 85:   }
 86:   PetscCall(PetscCommDestroy(&ncomm));
 87:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
 88:   PetscFunctionReturn(PETSC_SUCCESS);
 89: }

 91: /*@
 92:    PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 93:                     in a communicator.

 95:    Collective

 97:    Input Parameter:
 98: .  comm - the MPI communicator to share the `PetscViewer`

100:    Level: beginner

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

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

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

111: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`,
112:           `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF`
113: @*/
114: PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
115: {
116:   PetscViewer viewer;

118:   PetscFunctionBegin;
119:   PetscCallNull(PetscViewerASCIIGetStderr(comm, &viewer));
120:   PetscFunctionReturn(viewer);
121: }

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

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

130: */
131: PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
132: {
133:   PetscFunctionBegin;
134:   (void)keyval;
135:   (void)attr_val;
136:   (void)extra_state;
137:   PetscCallReturnMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)comm));
138:   PetscFunctionReturn(MPI_SUCCESS);
139: }

141: /*@
142:   PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`.

144:   Collective

146:   Input Parameters:
147: + comm - the communicator
148: - name - the file name

150:   Output Parameter:
151: . viewer - the `PetscViewer` to use with the specified file

153:   Level: beginner

155:   Notes:
156:   This routine only opens files for writing. To open a ASCII file as a `PetscViewer` for reading use the sequence
157: .vb
158:    PetscViewerCreate(comm,&viewer);
159:    PetscViewerSetType(viewer,PETSCVIEWERASCII);
160:    PetscViewerFileSetMode(viewer,FILE_MODE_READ);
161:    PetscViewerFileSetName(viewer,name);
162: .ve

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

166:   The MPI communicator used here must match that used by the object viewed. For example if the
167:   Mat was created with a `PETSC_COMM_WORLD`, then `viewer` must be created with `PETSC_COMM_WORLD`

169:   As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with
170:   `MatView()` and `VecView()`
171: .vb
172:      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
173:      MatView(matrix,viewer);
174: .ve

176:   Developer Note:
177:   When called with `NULL`, `stdout`, or `stderr` this does not return the same communicator as `PetscViewerASCIIGetStdout()` or `PetscViewerASCIIGetStderr()`
178:   but that is ok.

180: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII`,
181:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
182:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIGetStdout()`, `PetscViewerASCIIGetStderr()`
183: @*/
184: PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *viewer)
185: {
186:   PetscViewerLink *vlink, *nv;
187:   PetscMPIInt      iflg;
188:   PetscBool        eq;
189:   size_t           len;

191:   PetscFunctionBegin;
192:   PetscAssertPointer(viewer, 3);
193:   PetscCall(PetscStrlen(name, &len));
194:   if (!len) name = "stdout";
195:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen));
196:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, NULL));
197:   /*
198:        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
199:      we cannot do that, since PetscFileSetName() takes a communicator that already exists.

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

243: /*@
244:   PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it.

246:   Collective

248:   Input Parameters:
249: + comm - the communicator
250: - fd   - the `FILE` pointer

252:   Output Parameter:
253: . viewer - the `PetscViewer` to use with the specified file

255:   Level: beginner

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

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

264:   Fortran Notes:
265:   Use `PetscViewerASCIIOpenWithFileUnit()`

267: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIOpenWithFileUnit()`,
268:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
269:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
270: @*/
271: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *viewer)
272: {
273:   PetscFunctionBegin;
274:   PetscCall(PetscViewerCreate(comm, viewer));
275:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
276:   PetscCall(PetscViewerASCIISetFILE(*viewer, fd));
277:   PetscFunctionReturn(PETSC_SUCCESS);
278: }

280: /*@
281:   PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output

283:   Not Collective

285:   Input Parameters:
286: + viewer - the `PetscViewer` to use with the specified file
287: - fd     - the `FILE` pointer

289:   Level: beginner

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

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

298:   Fortran Note:
299:   Use `PetscViewerASCIISetFileUnit()`

301: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIISetFileUnit()`,
302:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
303:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
304: @*/
305: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
306: {
307:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

309:   PetscFunctionBegin;
310:   vascii->fd        = fd;
311:   vascii->closefile = PETSC_FALSE;
312:   PetscFunctionReturn(PETSC_SUCCESS);
313: }