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