xref: /petsc/src/sys/error/err.c (revision bbd56ea5790821d2a217d362e8e9710702952333)
1 
2 /*
3       Code that allows one to set the error handlers
4 */
5 #include <petscsys.h>           /*I "petscsys.h" I*/
6 #include <stdarg.h>
7 #if defined(PETSC_HAVE_STDLIB_H)
8 #include <stdlib.h>
9 #endif
10 
11 typedef struct _EH *EH;
12 struct _EH {
13   PetscErrorCode (*handler)(MPI_Comm,int,const char*,const char*,const char *,PetscErrorCode,PetscErrorType,const char*,void *);
14   void           *ctx;
15   EH             previous;
16 };
17 
18 static EH eh = 0;
19 
20 #undef __FUNCT__
21 #define __FUNCT__ "PetscEmacsClientErrorHandler"
22 /*@C
23    PetscEmacsClientErrorHandler - Error handler that uses the emacsclient program to
24     load the file where the error occured. Then calls the "previous" error handler.
25 
26    Not Collective
27 
28    Input Parameters:
29 +  comm - communicator over which error occured
30 .  line - the line number of the error (indicated by __LINE__)
31 .  func - the function where error is detected (indicated by __FUNCT__)
32 .  file - the file in which the error was detected (indicated by __FILE__)
33 .  dir - the directory of the file (indicated by __SDIR__)
34 .  mess - an error text string, usually just printed to the screen
35 .  n - the generic error number
36 .  p - specific error number
37 -  ctx - error handler context
38 
39    Options Database Key:
40 .   -on_error_emacs <machinename>
41 
42    Level: developer
43 
44    Notes:
45    You must put (server-start) in your .emacs file for the emacsclient software to work
46 
47    Most users need not directly employ this routine and the other error
48    handlers, but can instead use the simplified interface SETERRQ, which has
49    the calling sequence
50 $     SETERRQ(PETSC_COMM_SELF,number,p,mess)
51 
52    Notes for experienced users:
53    Use PetscPushErrorHandler() to set the desired error handler.
54 
55    Developer Note: Since this is an error handler it cannot call CHKERRQ(); thus we just return if an error is detected.
56 
57    Concepts: emacs^going to on error
58    Concepts: error handler^going to line in emacs
59 
60 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
61           PetscAbortErrorHandler()
62  @*/
63 PetscErrorCode  PetscEmacsClientErrorHandler(MPI_Comm comm,int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx)
64 {
65   PetscErrorCode ierr;
66   char           command[PETSC_MAX_PATH_LEN];
67   const char     *pdir;
68   FILE           *fp;
69   PetscInt       rval;
70 
71   PetscFunctionBegin;
72   ierr = PetscGetPetscDir(&pdir);if (ierr) PetscFunctionReturn(ierr);
73   sprintf(command,"cd %s; emacsclient --no-wait +%d %s%s\n",pdir,line,dir,file);
74 #if defined(PETSC_HAVE_POPEN)
75   ierr = PetscPOpen(MPI_COMM_WORLD,(char*)ctx,command,"r",&fp);if (ierr) PetscFunctionReturn(ierr);
76   ierr = PetscPClose(MPI_COMM_WORLD,fp,&rval);if (ierr) PetscFunctionReturn(ierr);
77 #else
78   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
79 #endif
80   ierr = PetscPopErrorHandler();if (ierr) PetscFunctionReturn(ierr); /* remove this handler from the stack of handlers */
81   if (!eh) {
82     ierr = PetscTraceBackErrorHandler(comm,line,fun,file,dir,n,p,mess,0);if (ierr) PetscFunctionReturn(ierr);
83   } else {
84     ierr = (*eh->handler)(comm,line,fun,file,dir,n,p,mess,eh->ctx);if (ierr) PetscFunctionReturn(ierr);
85   }
86   PetscFunctionReturn(ierr);
87 }
88 
89 #undef __FUNCT__
90 #define __FUNCT__ "PetscPushErrorHandler"
91 /*@C
92    PetscPushErrorHandler - Sets a routine to be called on detection of errors.
93 
94    Not Collective
95 
96    Input Parameters:
97 +  handler - error handler routine
98 -  ctx - optional handler context that contains information needed by the handler (for
99          example file pointers for error messages etc.)
100 
101    Calling sequence of handler:
102 $    int handler(MPI_Comm comm,int line,char *func,char *file,char *dir,PetscErrorCode n,int p,char *mess,void *ctx);
103 
104 +  comm - communicator over which error occured
105 .  func - the function where the error occured (indicated by __FUNCT__)
106 .  line - the line number of the error (indicated by __LINE__)
107 .  file - the file in which the error was detected (indicated by __FILE__)
108 .  dir - the directory of the file (indicated by __SDIR__)
109 .  n - the generic error number (see list defined in include/petscerror.h)
110 .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
111 .  mess - an error text string, usually just printed to the screen
112 -  ctx - the error handler context
113 
114    Options Database Keys:
115 +   -on_error_attach_debugger <noxterm,gdb or dbx>
116 -   -on_error_abort
117 
118    Level: intermediate
119 
120    Notes:
121    The currently available PETSc error handlers include PetscTraceBackErrorHandler(),
122    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler(), PetscReturnErrorHandler().
123 
124    Fortran Notes: You can only push one error handler from Fortran before poping it.
125 
126 .seealso: PetscPopErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), PetscTraceBackErrorHandler(), PetscPushSignalHandler()
127 
128 @*/
129 PetscErrorCode  PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm,int,const char *,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*),void *ctx)
130 {
131   EH             neweh;
132   PetscErrorCode ierr;
133 
134   PetscFunctionBegin;
135   ierr = PetscNew(struct _EH,&neweh);CHKERRQ(ierr);
136   if (eh) {neweh->previous = eh;}
137   else    {neweh->previous = 0;}
138   neweh->handler = handler;
139   neweh->ctx     = ctx;
140   eh             = neweh;
141   PetscFunctionReturn(0);
142 }
143 
144 #undef __FUNCT__
145 #define __FUNCT__ "PetscPopErrorHandler"
146 /*@
147    PetscPopErrorHandler - Removes the latest error handler that was
148    pushed with PetscPushErrorHandler().
149 
150    Not Collective
151 
152    Level: intermediate
153 
154    Concepts: error handler^setting
155 
156 .seealso: PetscPushErrorHandler()
157 @*/
158 PetscErrorCode  PetscPopErrorHandler(void)
159 {
160   EH             tmp;
161   PetscErrorCode ierr;
162 
163   PetscFunctionBegin;
164   if (!eh) PetscFunctionReturn(0);
165   tmp  = eh;
166   eh   = eh->previous;
167   ierr = PetscFree(tmp);CHKERRQ(ierr);
168   PetscFunctionReturn(0);
169 }
170 
171 #undef __FUNCT__
172 #define __FUNCT__ "PetscReturnErrorHandler"
173 /*@C
174   PetscReturnErrorHandler - Error handler that causes a return to the current
175   level.
176 
177    Not Collective
178 
179    Input Parameters:
180 +  comm - communicator over which error occurred
181 .  line - the line number of the error (indicated by __LINE__)
182 .  func - the function where error is detected (indicated by __FUNCT__)
183 .  file - the file in which the error was detected (indicated by __FILE__)
184 .  dir - the directory of the file (indicated by __SDIR__)
185 .  mess - an error text string, usually just printed to the screen
186 .  n - the generic error number
187 .  p - specific error number
188 -  ctx - error handler context
189 
190    Level: developer
191 
192    Notes:
193    Most users need not directly employ this routine and the other error
194    handlers, but can instead use the simplified interface SETERRQ, which has
195    the calling sequence
196 $     SETERRQ(comm,number,mess)
197 
198    Notes for experienced users:
199    This routine is good for catching errors such as zero pivots in preconditioners
200    or breakdown of iterative methods. It is not appropriate for memory violations
201    and similar errors.
202 
203    Use PetscPushErrorHandler() to set the desired error handler.  The
204    currently available PETSc error handlers include PetscTraceBackErrorHandler(),
205    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscAbortErrorHandler()
206 
207    Concepts: error handler
208 
209 .seealso:  PetscPushErrorHandler(), PetscPopErrorHandler().
210  @*/
211 
212 PetscErrorCode  PetscReturnErrorHandler(MPI_Comm comm,int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx)
213 {
214   PetscFunctionBegin;
215   PetscFunctionReturn(n);
216 }
217 
218 static char PetscErrorBaseMessage[1024];
219 /*
220        The numerical values for these are defined in include/petscerror.h; any changes
221    there must also be made here
222 */
223 static const char *PetscErrorStrings[] = {
224   /*55 */ "Out of memory",
225           "No support for this operation for this object type",
226           "No support for this operation on this system",
227   /*58 */ "Operation done in wrong order",
228   /*59 */ "Signal received",
229   /*60 */ "Nonconforming object sizes",
230           "Argument aliasing not permitted",
231           "Invalid argument",
232   /*63 */ "Argument out of range",
233           "Corrupt argument:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind",
234           "Unable to open file",
235           "Read from file failed",
236           "Write to file failed",
237           "Invalid pointer",
238   /*69 */ "Arguments must have same type",
239   /*70 */ "Attempt to use a pointer that does not point to a valid accessible location",
240   /*71 */ "Detected zero pivot in LU factorization:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#ZeroPivot",
241   /*72 */ "Floating point exception",
242   /*73 */ "Object is in wrong state",
243           "Corrupted Petsc object",
244           "Arguments are incompatible",
245           "Error in external library",
246   /*77 */ "Petsc has generated inconsistent data",
247           "Memory corruption",
248           "Unexpected data in file",
249   /*80 */ "Arguments must have same communicators",
250   /*81 */ "Detected zero pivot in Cholesky factorization:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#ZeroPivot",
251           "  ",
252           "  ",
253           "Overflow in integer operation:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#64-bit-indices",
254   /*85 */ "Null argument, when expecting valid pointer",
255   /*86 */ "Unknown type. Check for miss-spelling or missing external package needed for type:\nsee http://www.mcs.anl.gov/petsc/documentation/installation.html#external",
256   /*87 */ "Not used",
257   /*88 */ "Error in system call",
258   /*89 */ "Object Type not set:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#objecttypenotset"
259   /*90 */ "  ",
260   /*   */ "  ",
261   /*   */ "  ",
262   /*   */ "  ",
263   /*   */ "  ",
264   /*95 */ "  ",
265 };
266 
267 #undef __FUNCT__
268 #define __FUNCT__ "PetscErrorMessage"
269 /*@C
270    PetscErrorMessage - returns the text string associated with a PETSc error code.
271 
272    Not Collective
273 
274    Input Parameter:
275 .   errnum - the error code
276 
277    Output Parameter:
278 +  text - the error message (PETSC_NULL if not desired)
279 -  specific - the specific error message that was set with SETERRxxx() or PetscError().  (PETSC_NULL if not desired)
280 
281    Level: developer
282 
283    Concepts: error handler^messages
284 
285 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
286           PetscAbortErrorHandler(), PetscTraceBackErrorHandler()
287  @*/
288 PetscErrorCode  PetscErrorMessage(int errnum,const char *text[],char **specific)
289 {
290   PetscFunctionBegin;
291   if (text && errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) {
292     *text = PetscErrorStrings[errnum-PETSC_ERR_MIN_VALUE-1];
293   } else if (text) *text = 0;
294 
295   if (specific) {
296     *specific = PetscErrorBaseMessage;
297   }
298   PetscFunctionReturn(0);
299 }
300 
301 #undef __FUNCT__
302 #define __FUNCT__ "PetscError"
303 /*@C
304    PetscError - Routine that is called when an error has been detected,
305    usually called through the macro SETERRQ(PETSC_COMM_SELF,).
306 
307    Not Collective
308 
309    Input Parameters:
310 +  comm - communicator over which error occurred.  ALL ranks of this communicator MUST call this routine
311 .  line - the line number of the error (indicated by __LINE__)
312 .  func - the function where the error occured (indicated by __FUNCT__)
313 .  dir - the directory of file (indicated by __SDIR__)
314 .  file - the file in which the error was detected (indicated by __FILE__)
315 .  mess - an error text string, usually just printed to the screen
316 .  n - the generic error number
317 .  p - PETSC_ERROR_INITIAL indicates the error was initially detected, PETSC_ERROR_REPEAT indicates this is a traceback from a previously detected error
318 -  mess - formatted message string - aka printf
319 
320   Level: intermediate
321 
322    Notes:
323    Most users need not directly use this routine and the error handlers, but
324    can instead use the simplified interface SETERRQ, which has the calling
325    sequence
326 $     SETERRQ(comm,n,mess)
327 
328    Experienced users can set the error handler with PetscPushErrorHandler().
329 
330    Developer Note: Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
331    BUT this routine does call regular PETSc functions that may call error handlers, this is problematic and could be fixed by never calling other PETSc routines
332    but this annoying.
333 
334    Concepts: error^setting condition
335 
336 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), SETERRQ(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2()
337 @*/
338 PetscErrorCode  PetscError(MPI_Comm comm,int line,const char *func,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,...)
339 {
340   va_list        Argp;
341   size_t         fullLength;
342   char           buf[2048],*lbuf = 0;
343   PetscBool      ismain,isunknown;
344   PetscErrorCode ierr;
345 
346   if (!func)  func = "User provided function";
347   if (!file)  file = "User file";
348   if (!dir)   dir = " ";
349 
350   PetscFunctionBegin;
351   /* Compose the message evaluating the print format */
352   if (mess) {
353     va_start(Argp,mess);
354     PetscVSNPrintf(buf,2048,mess,&fullLength,Argp);
355     va_end(Argp);
356     lbuf = buf;
357     if (p == 1) {
358       PetscStrncpy(PetscErrorBaseMessage,lbuf,1023);
359     }
360   }
361 
362   if (!eh) ierr = PetscTraceBackErrorHandler(comm,line,func,file,dir,n,p,lbuf,0);
363   else     ierr = (*eh->handler)(comm,line,func,file,dir,n,p,lbuf,eh->ctx);
364 
365   /*
366       If this is called from the main() routine we call MPI_Abort() instead of
367     return to allow the parallel program to be properly shutdown.
368 
369     Since this is in the error handler we don't check the errors below. Of course,
370     PetscStrncmp() does its own error checking which is problamatic
371   */
372   PetscStrncmp(func,"main",4,&ismain);
373   PetscStrncmp(func,"unknown",7,&isunknown);
374   if (ismain || isunknown) {
375     MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
376   }
377 #if defined(PETSC_CLANGUAGE_CXX) && !defined(PETSC_USE_EXTERN_CXX)
378   if (p == PETSC_ERROR_IN_CXX) {
379     const char *str;
380     if (eh && eh->ctx) {
381       std::ostringstream *msg;
382       msg = (std::ostringstream*) eh->ctx;
383       str = msg->str().c_str();
384     } else {
385       str = "Error detected in C PETSc";
386     }
387     throw PETSc::Exception(str);
388   }
389 #endif
390   PetscFunctionReturn(ierr);
391 }
392 
393 /* -------------------------------------------------------------------------*/
394 
395 #undef __FUNCT__
396 #define __FUNCT__ "PetscIntView"
397 /*@C
398     PetscIntView - Prints an array of integers; useful for debugging.
399 
400     Collective on PetscViewer
401 
402     Input Parameters:
403 +   N - number of integers in array
404 .   idx - array of integers
405 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
406 
407   Level: intermediate
408 
409     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
410 
411 .seealso: PetscRealView()
412 @*/
413 PetscErrorCode  PetscIntView(PetscInt N,const PetscInt idx[],PetscViewer viewer)
414 {
415   PetscErrorCode ierr;
416   PetscInt       j,i,n = N/20,p = N % 20;
417   PetscBool      iascii,isbinary;
418   MPI_Comm       comm;
419 
420   PetscFunctionBegin;
421   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
422   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,3);
423   if (N) PetscValidIntPointer(idx,2);
424   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
425 
426   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
427   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
428   if (iascii) {
429     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
430     for (i=0; i<n; i++) {
431       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D:",20*i);CHKERRQ(ierr);
432       for (j=0; j<20; j++) {
433         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %D",idx[i*20+j]);CHKERRQ(ierr);
434       }
435       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
436     }
437     if (p) {
438       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D:",20*n);CHKERRQ(ierr);
439       for (i=0; i<p; i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer," %D",idx[20*n+i]);CHKERRQ(ierr);}
440       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
441     }
442     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
443     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
444   } else if (isbinary) {
445     PetscMPIInt rank,size,*sizes,Ntotal,*displs,NN;
446     PetscInt    *array;
447 
448     ierr = PetscMPIIntCast(N,&NN);CHKERRQ(ierr);
449     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
450     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
451 
452     if (size > 1) {
453       if (rank) {
454         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
455         ierr = MPI_Gatherv((void*)idx,NN,MPIU_INT,0,0,0,MPIU_INT,0,comm);CHKERRQ(ierr);
456       } else {
457         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
458         ierr      = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
459         Ntotal    = sizes[0];
460         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
461         displs[0] = 0;
462         for (i=1; i<size; i++) {
463           Ntotal    += sizes[i];
464           displs[i] =  displs[i-1] + sizes[i-1];
465         }
466         ierr = PetscMalloc(Ntotal*sizeof(PetscInt),&array);CHKERRQ(ierr);
467         ierr = MPI_Gatherv((void*)idx,NN,MPIU_INT,array,sizes,displs,MPIU_INT,0,comm);CHKERRQ(ierr);
468         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
469         ierr = PetscFree(sizes);CHKERRQ(ierr);
470         ierr = PetscFree(displs);CHKERRQ(ierr);
471         ierr = PetscFree(array);CHKERRQ(ierr);
472       }
473     } else {
474       ierr = PetscViewerBinaryWrite(viewer,(void *) idx,N,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
475     }
476   } else {
477     const char *tname;
478     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
479     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
480   }
481   PetscFunctionReturn(0);
482 }
483 
484 #undef __FUNCT__
485 #define __FUNCT__ "PetscRealView"
486 /*@C
487     PetscRealView - Prints an array of doubles; useful for debugging.
488 
489     Collective on PetscViewer
490 
491     Input Parameters:
492 +   N - number of doubles in array
493 .   idx - array of doubles
494 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
495 
496   Level: intermediate
497 
498     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
499 
500 .seealso: PetscIntView()
501 @*/
502 PetscErrorCode  PetscRealView(PetscInt N,const PetscReal idx[],PetscViewer viewer)
503 {
504   PetscErrorCode ierr;
505   PetscInt       j,i,n = N/5,p = N % 5;
506   PetscBool      iascii,isbinary;
507   MPI_Comm       comm;
508 
509   PetscFunctionBegin;
510   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
511   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,3);
512   PetscValidScalarPointer(idx,2);
513   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
514 
515   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
516   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
517   if (iascii) {
518     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
519     for (i=0; i<n; i++) {
520       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*i);CHKERRQ(ierr);
521       for (j=0; j<5; j++) {
522          ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[i*5+j]);CHKERRQ(ierr);
523       }
524       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
525     }
526     if (p) {
527       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*n);CHKERRQ(ierr);
528       for (i=0; i<p; i++) { PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[5*n+i]);CHKERRQ(ierr);}
529       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
530     }
531     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
532     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
533   } else if (isbinary) {
534     PetscMPIInt rank,size,*sizes,*displs, Ntotal,NN;
535     PetscReal   *array;
536 
537     ierr = PetscMPIIntCast(N,&NN);CHKERRQ(ierr);
538     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
539     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
540 
541     if (size > 1) {
542       if (rank) {
543         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
544         ierr = MPI_Gatherv((void*)idx,NN,MPI_DOUBLE,0,0,0,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
545       } else {
546         ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
547         ierr   = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
548         Ntotal = sizes[0];
549         ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
550         displs[0] = 0;
551         for (i=1; i<size; i++) {
552           Ntotal    += sizes[i];
553           displs[i] =  displs[i-1] + sizes[i-1];
554         }
555         ierr = PetscMalloc(Ntotal*sizeof(PetscReal),&array);CHKERRQ(ierr);
556         ierr = MPI_Gatherv((void*)idx,NN,MPI_DOUBLE,array,sizes,displs,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
557         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_REAL,PETSC_TRUE);CHKERRQ(ierr);
558         ierr = PetscFree(sizes);CHKERRQ(ierr);
559         ierr = PetscFree(displs);CHKERRQ(ierr);
560         ierr = PetscFree(array);CHKERRQ(ierr);
561       }
562     } else {
563       ierr = PetscViewerBinaryWrite(viewer,(void *) idx,N,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr);
564     }
565   } else {
566     const char *tname;
567     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
568     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
569   }
570   PetscFunctionReturn(0);
571 }
572 
573 #undef __FUNCT__
574 #define __FUNCT__ "PetscScalarView"
575 /*@C
576     PetscScalarView - Prints an array of scalars; useful for debugging.
577 
578     Collective on PetscViewer
579 
580     Input Parameters:
581 +   N - number of scalars in array
582 .   idx - array of scalars
583 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
584 
585   Level: intermediate
586 
587     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
588 
589 .seealso: PetscIntView(), PetscRealView()
590 @*/
591 PetscErrorCode  PetscScalarView(PetscInt N,const PetscScalar idx[],PetscViewer viewer)
592 {
593   PetscErrorCode ierr;
594   PetscInt       j,i,n = N/3,p = N % 3;
595   PetscBool      iascii,isbinary;
596   MPI_Comm       comm;
597 
598   PetscFunctionBegin;
599   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
600   PetscValidHeader(viewer,3);
601   PetscValidScalarPointer(idx,2);
602   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
603 
604   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
605   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
606   if (iascii) {
607     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
608     for (i=0; i<n; i++) {
609       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",3*i);CHKERRQ(ierr);
610       for (j=0; j<3; j++) {
611 #if defined (PETSC_USE_COMPLEX)
612         ierr = PetscViewerASCIISynchronizedPrintf(viewer," (%12.4e,%12.4e)", PetscRealPart(idx[i*3+j]),PetscImaginaryPart(idx[i*3+j]));CHKERRQ(ierr);
613 #else
614         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[i*3+j]);CHKERRQ(ierr);
615 #endif
616       }
617       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
618     }
619     if (p) {
620       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",3*n);CHKERRQ(ierr);
621       for (i=0; i<p; i++) {
622 #if defined (PETSC_USE_COMPLEX)
623         ierr = PetscViewerASCIISynchronizedPrintf(viewer," (%12.4e,%12.4e)", PetscRealPart(idx[n*3+i]),PetscImaginaryPart(idx[n*3+i]));CHKERRQ(ierr);
624 #else
625         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[3*n+i]);CHKERRQ(ierr);
626 #endif
627       }
628       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
629     }
630     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
631     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
632   } else if (isbinary) {
633     PetscMPIInt size,rank,*sizes,Ntotal,*displs,NN;
634     PetscScalar *array;
635 
636     ierr = PetscMPIIntCast(N,&NN);CHKERRQ(ierr);
637     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
638     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
639 
640     if (size > 1) {
641       if (rank) {
642         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
643         ierr = MPI_Gatherv((void*)idx,NN,MPIU_SCALAR,0,0,0,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
644       } else {
645         ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
646         ierr   = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
647         Ntotal = sizes[0];
648         ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
649         displs[0] = 0;
650         for (i=1; i<size; i++) {
651           Ntotal    += sizes[i];
652           displs[i] =  displs[i-1] + sizes[i-1];
653         }
654         ierr = PetscMalloc(Ntotal*sizeof(PetscScalar),&array);CHKERRQ(ierr);
655         ierr = MPI_Gatherv((void*)idx,NN,MPIU_SCALAR,array,sizes,displs,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
656         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr);
657         ierr = PetscFree(sizes);CHKERRQ(ierr);
658         ierr = PetscFree(displs);CHKERRQ(ierr);
659         ierr = PetscFree(array);CHKERRQ(ierr);
660       }
661     } else {
662       ierr = PetscViewerBinaryWrite(viewer,(void *) idx,N,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
663     }
664   } else {
665     const char *tname;
666     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
667     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
668   }
669   PetscFunctionReturn(0);
670 }
671 
672 
673 
674 
675