xref: /petsc/src/sys/error/err.c (revision 0298fd7132830bec7daee99a80be0eddb2b310a5) !
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 (NULL if not desired)
279 -  specific - the specific error message that was set with SETERRxxx() or PetscError().  (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) *text = PetscErrorStrings[errnum-PETSC_ERR_MIN_VALUE-1];
292   else if (text) *text = 0;
293 
294   if (specific) *specific = PetscErrorBaseMessage;
295   PetscFunctionReturn(0);
296 }
297 
298 #undef __FUNCT__
299 #define __FUNCT__ "PetscError"
300 /*@C
301    PetscError - Routine that is called when an error has been detected,
302    usually called through the macro SETERRQ(PETSC_COMM_SELF,).
303 
304    Not Collective
305 
306    Input Parameters:
307 +  comm - communicator over which error occurred.  ALL ranks of this communicator MUST call this routine
308 .  line - the line number of the error (indicated by __LINE__)
309 .  func - the function where the error occured (indicated by __FUNCT__)
310 .  dir - the directory of file (indicated by __SDIR__)
311 .  file - the file in which the error was detected (indicated by __FILE__)
312 .  mess - an error text string, usually just printed to the screen
313 .  n - the generic error number
314 .  p - PETSC_ERROR_INITIAL indicates the error was initially detected, PETSC_ERROR_REPEAT indicates this is a traceback from a previously detected error
315 -  mess - formatted message string - aka printf
316 
317   Level: intermediate
318 
319    Notes:
320    Most users need not directly use this routine and the error handlers, but
321    can instead use the simplified interface SETERRQ, which has the calling
322    sequence
323 $     SETERRQ(comm,n,mess)
324 
325    Experienced users can set the error handler with PetscPushErrorHandler().
326 
327    Developer Note: Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
328    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
329    but this annoying.
330 
331    Concepts: error^setting condition
332 
333 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), SETERRQ(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2()
334 @*/
335 PetscErrorCode  PetscError(MPI_Comm comm,int line,const char *func,const char *file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,...)
336 {
337   va_list        Argp;
338   size_t         fullLength;
339   char           buf[2048],*lbuf = 0;
340   PetscBool      ismain,isunknown;
341   PetscErrorCode ierr;
342 
343   if (!func) func = "User provided function";
344   if (!file) file = "User file";
345   if (!dir)   dir = " ";
346 
347   PetscFunctionBegin;
348   /* Compose the message evaluating the print format */
349   if (mess) {
350     va_start(Argp,mess);
351     PetscVSNPrintf(buf,2048,mess,&fullLength,Argp);
352     va_end(Argp);
353     lbuf = buf;
354     if (p == 1) PetscStrncpy(PetscErrorBaseMessage,lbuf,1023);
355   }
356 
357   if (!eh) ierr = PetscTraceBackErrorHandler(comm,line,func,file,dir,n,p,lbuf,0);
358   else     ierr = (*eh->handler)(comm,line,func,file,dir,n,p,lbuf,eh->ctx);
359 
360   /*
361       If this is called from the main() routine we call MPI_Abort() instead of
362     return to allow the parallel program to be properly shutdown.
363 
364     Since this is in the error handler we don't check the errors below. Of course,
365     PetscStrncmp() does its own error checking which is problamatic
366   */
367   PetscStrncmp(func,"main",4,&ismain);
368   PetscStrncmp(func,"unknown",7,&isunknown);
369   if (ismain || isunknown) MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
370 
371 #if defined(PETSC_CLANGUAGE_CXX) && !defined(PETSC_USE_EXTERN_CXX)
372   if (p == PETSC_ERROR_IN_CXX) {
373     const char *str;
374     if (eh && eh->ctx) {
375       std::ostringstream *msg;
376       msg = (std::ostringstream*) eh->ctx;
377       str = msg->str().c_str();
378     } else str = "Error detected in C PETSc";
379 
380     throw PETSc::Exception(str);
381   }
382 #endif
383   PetscFunctionReturn(ierr);
384 }
385 
386 /* -------------------------------------------------------------------------*/
387 
388 #undef __FUNCT__
389 #define __FUNCT__ "PetscIntView"
390 /*@C
391     PetscIntView - Prints an array of integers; useful for debugging.
392 
393     Collective on PetscViewer
394 
395     Input Parameters:
396 +   N - number of integers in array
397 .   idx - array of integers
398 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
399 
400   Level: intermediate
401 
402     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
403 
404 .seealso: PetscRealView()
405 @*/
406 PetscErrorCode  PetscIntView(PetscInt N,const PetscInt idx[],PetscViewer viewer)
407 {
408   PetscErrorCode ierr;
409   PetscInt       j,i,n = N/20,p = N % 20;
410   PetscBool      iascii,isbinary;
411   MPI_Comm       comm;
412 
413   PetscFunctionBegin;
414   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
415   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,3);
416   if (N) PetscValidIntPointer(idx,2);
417   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
418 
419   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
420   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
421   if (iascii) {
422     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
423     for (i=0; i<n; i++) {
424       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D:",20*i);CHKERRQ(ierr);
425       for (j=0; j<20; j++) {
426         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %D",idx[i*20+j]);CHKERRQ(ierr);
427       }
428       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
429     }
430     if (p) {
431       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D:",20*n);CHKERRQ(ierr);
432       for (i=0; i<p; i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer," %D",idx[20*n+i]);CHKERRQ(ierr);}
433       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
434     }
435     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
436     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
437   } else if (isbinary) {
438     PetscMPIInt rank,size,*sizes,Ntotal,*displs,NN;
439     PetscInt    *array;
440 
441     ierr = PetscMPIIntCast(N,&NN);CHKERRQ(ierr);
442     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
443     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
444 
445     if (size > 1) {
446       if (rank) {
447         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
448         ierr = MPI_Gatherv((void*)idx,NN,MPIU_INT,0,0,0,MPIU_INT,0,comm);CHKERRQ(ierr);
449       } else {
450         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
451         ierr      = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
452         Ntotal    = sizes[0];
453         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
454         displs[0] = 0;
455         for (i=1; i<size; i++) {
456           Ntotal   += sizes[i];
457           displs[i] =  displs[i-1] + sizes[i-1];
458         }
459         ierr = PetscMalloc(Ntotal*sizeof(PetscInt),&array);CHKERRQ(ierr);
460         ierr = MPI_Gatherv((void*)idx,NN,MPIU_INT,array,sizes,displs,MPIU_INT,0,comm);CHKERRQ(ierr);
461         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
462         ierr = PetscFree(sizes);CHKERRQ(ierr);
463         ierr = PetscFree(displs);CHKERRQ(ierr);
464         ierr = PetscFree(array);CHKERRQ(ierr);
465       }
466     } else {
467       ierr = PetscViewerBinaryWrite(viewer,(void*) idx,N,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
468     }
469   } else {
470     const char *tname;
471     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
472     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
473   }
474   PetscFunctionReturn(0);
475 }
476 
477 #undef __FUNCT__
478 #define __FUNCT__ "PetscRealView"
479 /*@C
480     PetscRealView - Prints an array of doubles; useful for debugging.
481 
482     Collective on PetscViewer
483 
484     Input Parameters:
485 +   N - number of doubles in array
486 .   idx - array of doubles
487 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
488 
489   Level: intermediate
490 
491     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
492 
493 .seealso: PetscIntView()
494 @*/
495 PetscErrorCode  PetscRealView(PetscInt N,const PetscReal idx[],PetscViewer viewer)
496 {
497   PetscErrorCode ierr;
498   PetscInt       j,i,n = N/5,p = N % 5;
499   PetscBool      iascii,isbinary;
500   MPI_Comm       comm;
501 
502   PetscFunctionBegin;
503   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
504   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,3);
505   PetscValidScalarPointer(idx,2);
506   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
507 
508   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
509   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
510   if (iascii) {
511     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
512     for (i=0; i<n; i++) {
513       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*i);CHKERRQ(ierr);
514       for (j=0; j<5; j++) {
515         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[i*5+j]);CHKERRQ(ierr);
516       }
517       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
518     }
519     if (p) {
520       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*n);CHKERRQ(ierr);
521       for (i=0; i<p; i++) { PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[5*n+i]);CHKERRQ(ierr);}
522       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
523     }
524     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
525     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
526   } else if (isbinary) {
527     PetscMPIInt rank,size,*sizes,*displs, Ntotal,NN;
528     PetscReal   *array;
529 
530     ierr = PetscMPIIntCast(N,&NN);CHKERRQ(ierr);
531     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
532     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
533 
534     if (size > 1) {
535       if (rank) {
536         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
537         ierr = MPI_Gatherv((void*)idx,NN,MPI_DOUBLE,0,0,0,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
538       } else {
539         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
540         ierr      = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
541         Ntotal    = sizes[0];
542         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
543         displs[0] = 0;
544         for (i=1; i<size; i++) {
545           Ntotal   += sizes[i];
546           displs[i] =  displs[i-1] + sizes[i-1];
547         }
548         ierr = PetscMalloc(Ntotal*sizeof(PetscReal),&array);CHKERRQ(ierr);
549         ierr = MPI_Gatherv((void*)idx,NN,MPI_DOUBLE,array,sizes,displs,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
550         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_REAL,PETSC_TRUE);CHKERRQ(ierr);
551         ierr = PetscFree(sizes);CHKERRQ(ierr);
552         ierr = PetscFree(displs);CHKERRQ(ierr);
553         ierr = PetscFree(array);CHKERRQ(ierr);
554       }
555     } else {
556       ierr = PetscViewerBinaryWrite(viewer,(void*) idx,N,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr);
557     }
558   } else {
559     const char *tname;
560     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
561     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
562   }
563   PetscFunctionReturn(0);
564 }
565 
566 #undef __FUNCT__
567 #define __FUNCT__ "PetscScalarView"
568 /*@C
569     PetscScalarView - Prints an array of scalars; useful for debugging.
570 
571     Collective on PetscViewer
572 
573     Input Parameters:
574 +   N - number of scalars in array
575 .   idx - array of scalars
576 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
577 
578   Level: intermediate
579 
580     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
581 
582 .seealso: PetscIntView(), PetscRealView()
583 @*/
584 PetscErrorCode  PetscScalarView(PetscInt N,const PetscScalar idx[],PetscViewer viewer)
585 {
586   PetscErrorCode ierr;
587   PetscInt       j,i,n = N/3,p = N % 3;
588   PetscBool      iascii,isbinary;
589   MPI_Comm       comm;
590 
591   PetscFunctionBegin;
592   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
593   PetscValidHeader(viewer,3);
594   PetscValidScalarPointer(idx,2);
595   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
596 
597   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
598   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
599   if (iascii) {
600     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
601     for (i=0; i<n; i++) {
602       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",3*i);CHKERRQ(ierr);
603       for (j=0; j<3; j++) {
604 #if defined(PETSC_USE_COMPLEX)
605         ierr = PetscViewerASCIISynchronizedPrintf(viewer," (%12.4e,%12.4e)", PetscRealPart(idx[i*3+j]),PetscImaginaryPart(idx[i*3+j]));CHKERRQ(ierr);
606 #else
607         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[i*3+j]);CHKERRQ(ierr);
608 #endif
609       }
610       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
611     }
612     if (p) {
613       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",3*n);CHKERRQ(ierr);
614       for (i=0; i<p; i++) {
615 #if defined(PETSC_USE_COMPLEX)
616         ierr = PetscViewerASCIISynchronizedPrintf(viewer," (%12.4e,%12.4e)", PetscRealPart(idx[n*3+i]),PetscImaginaryPart(idx[n*3+i]));CHKERRQ(ierr);
617 #else
618         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[3*n+i]);CHKERRQ(ierr);
619 #endif
620       }
621       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
622     }
623     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
624     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
625   } else if (isbinary) {
626     PetscMPIInt size,rank,*sizes,Ntotal,*displs,NN;
627     PetscScalar *array;
628 
629     ierr = PetscMPIIntCast(N,&NN);CHKERRQ(ierr);
630     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
631     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
632 
633     if (size > 1) {
634       if (rank) {
635         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
636         ierr = MPI_Gatherv((void*)idx,NN,MPIU_SCALAR,0,0,0,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
637       } else {
638         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
639         ierr      = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
640         Ntotal    = sizes[0];
641         ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
642         displs[0] = 0;
643         for (i=1; i<size; i++) {
644           Ntotal   += sizes[i];
645           displs[i] =  displs[i-1] + sizes[i-1];
646         }
647         ierr = PetscMalloc(Ntotal*sizeof(PetscScalar),&array);CHKERRQ(ierr);
648         ierr = MPI_Gatherv((void*)idx,NN,MPIU_SCALAR,array,sizes,displs,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
649         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr);
650         ierr = PetscFree(sizes);CHKERRQ(ierr);
651         ierr = PetscFree(displs);CHKERRQ(ierr);
652         ierr = PetscFree(array);CHKERRQ(ierr);
653       }
654     } else {
655       ierr = PetscViewerBinaryWrite(viewer,(void*) idx,N,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
656     }
657   } else {
658     const char *tname;
659     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
660     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
661   }
662   PetscFunctionReturn(0);
663 }
664 
665 
666 
667 
668