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