xref: /petsc/src/sys/error/err.c (revision b00a91154f763f12aa55f3d53a3f2776f15f49e3)
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 #undef __FUNCT__
18 #define __FUNCT__ "PetscEmacsClientErrorHandler"
19 /*@C
20    PetscEmacsClientErrorHandler - Error handler that uses the emacsclient program to
21     load the file where the error occured. Then calls the "previous" error handler.
22 
23    Not Collective
24 
25    Input Parameters:
26 +  comm - communicator over which error occured
27 .  line - the line number of the error (indicated by __LINE__)
28 .  func - the function where error is detected (indicated by __FUNCT__)
29 .  file - the file in which the error was detected (indicated by __FILE__)
30 .  mess - an error text string, usually just printed to the screen
31 .  n - the generic error number
32 .  p - specific error number
33 -  ctx - error handler context
34 
35    Options Database Key:
36 .   -on_error_emacs <machinename>
37 
38    Level: developer
39 
40    Notes:
41    You must put (server-start) in your .emacs file for the emacsclient software to work
42 
43    Most users need not directly employ this routine and the other error
44    handlers, but can instead use the simplified interface SETERRQ, which has
45    the calling sequence
46 $     SETERRQ(PETSC_COMM_SELF,number,p,mess)
47 
48    Notes for experienced users:
49    Use PetscPushErrorHandler() to set the desired error handler.
50 
51    Developer Note: Since this is an error handler it cannot call CHKERRQ(); thus we just return if an error is detected.
52 
53    Concepts: emacs^going to on error
54    Concepts: error handler^going to line in emacs
55 
56 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
57           PetscAbortErrorHandler()
58  @*/
59 PetscErrorCode  PetscEmacsClientErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx)
60 {
61   PetscErrorCode ierr;
62   char           command[PETSC_MAX_PATH_LEN];
63   const char     *pdir;
64   FILE           *fp;
65   int            rval;
66 
67   PetscFunctionBegin;
68   ierr = PetscGetPetscDir(&pdir);if (ierr) PetscFunctionReturn(ierr);
69   sprintf(command,"cd %s; emacsclient --no-wait +%d %s\n",pdir,line,file);
70 #if defined(PETSC_HAVE_POPEN)
71   ierr = PetscPOpen(MPI_COMM_WORLD,(char*)ctx,command,"r",&fp);if (ierr) PetscFunctionReturn(ierr);
72   ierr = PetscPClose(MPI_COMM_WORLD,fp,&rval);if (ierr) PetscFunctionReturn(ierr);
73 #else
74   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
75 #endif
76   ierr = PetscPopErrorHandler();if (ierr) PetscFunctionReturn(ierr); /* remove this handler from the stack of handlers */
77   if (!eh) {
78     ierr = PetscTraceBackErrorHandler(comm,line,fun,file,n,p,mess,0);if (ierr) PetscFunctionReturn(ierr);
79   } else {
80     ierr = (*eh->handler)(comm,line,fun,file,n,p,mess,eh->ctx);if (ierr) PetscFunctionReturn(ierr);
81   }
82   PetscFunctionReturn(ierr);
83 }
84 
85 #undef __FUNCT__
86 #define __FUNCT__ "PetscPushErrorHandler"
87 /*@C
88    PetscPushErrorHandler - Sets a routine to be called on detection of errors.
89 
90    Not Collective
91 
92    Input Parameters:
93 +  handler - error handler routine
94 -  ctx - optional handler context that contains information needed by the handler (for
95          example file pointers for error messages etc.)
96 
97    Calling sequence of handler:
98 $    int handler(MPI_Comm comm,int line,char *func,char *file,PetscErrorCode n,int p,char *mess,void *ctx);
99 
100 +  comm - communicator over which error occured
101 .  func - the function where the error occured (indicated by __FUNCT__)
102 .  line - the line number of the error (indicated by __LINE__)
103 .  file - the file in which the error was detected (indicated by __FILE__)
104 .  n - the generic error number (see list defined in include/petscerror.h)
105 .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
106 .  mess - an error text string, usually just printed to the screen
107 -  ctx - the error handler context
108 
109    Options Database Keys:
110 +   -on_error_attach_debugger <noxterm,gdb or dbx>
111 -   -on_error_abort
112 
113    Level: intermediate
114 
115    Notes:
116    The currently available PETSc error handlers include PetscTraceBackErrorHandler(),
117    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler(), PetscReturnErrorHandler().
118 
119    Fortran Notes: You can only push one error handler from Fortran before poping it.
120 
121 .seealso: PetscPopErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), PetscTraceBackErrorHandler(), PetscPushSignalHandler()
122 
123 @*/
124 PetscErrorCode  PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*),void *ctx)
125 {
126   EH             neweh;
127   PetscErrorCode ierr;
128 
129   PetscFunctionBegin;
130   ierr = PetscNew(&neweh);CHKERRQ(ierr);
131   if (eh) neweh->previous = eh;
132   else    neweh->previous = 0;
133   neweh->handler = handler;
134   neweh->ctx     = ctx;
135   eh             = neweh;
136   PetscFunctionReturn(0);
137 }
138 
139 #undef __FUNCT__
140 #define __FUNCT__ "PetscPopErrorHandler"
141 /*@
142    PetscPopErrorHandler - Removes the latest error handler that was
143    pushed with PetscPushErrorHandler().
144 
145    Not Collective
146 
147    Level: intermediate
148 
149    Concepts: error handler^setting
150 
151 .seealso: PetscPushErrorHandler()
152 @*/
153 PetscErrorCode  PetscPopErrorHandler(void)
154 {
155   EH             tmp;
156   PetscErrorCode ierr;
157 
158   PetscFunctionBegin;
159   if (!eh) PetscFunctionReturn(0);
160   tmp  = eh;
161   eh   = eh->previous;
162   ierr = PetscFree(tmp);CHKERRQ(ierr);
163   PetscFunctionReturn(0);
164 }
165 
166 #undef __FUNCT__
167 #define __FUNCT__ "PetscReturnErrorHandler"
168 /*@C
169   PetscReturnErrorHandler - Error handler that causes a return to the current
170   level.
171 
172    Not Collective
173 
174    Input Parameters:
175 +  comm - communicator over which error occurred
176 .  line - the line number of the error (indicated by __LINE__)
177 .  func - the function where error is detected (indicated by __FUNCT__)
178 .  file - the file in which the error was detected (indicated by __FILE__)
179 .  mess - an error text string, usually just printed to the screen
180 .  n - the generic error number
181 .  p - specific error number
182 -  ctx - error handler context
183 
184    Level: developer
185 
186    Notes:
187    Most users need not directly employ this routine and the other error
188    handlers, but can instead use the simplified interface SETERRQ, which has
189    the calling sequence
190 $     SETERRQ(comm,number,mess)
191 
192    Notes for experienced users:
193    This routine is good for catching errors such as zero pivots in preconditioners
194    or breakdown of iterative methods. It is not appropriate for memory violations
195    and similar errors.
196 
197    Use PetscPushErrorHandler() to set the desired error handler.  The
198    currently available PETSc error handlers include PetscTraceBackErrorHandler(),
199    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscAbortErrorHandler()
200 
201    Concepts: error handler
202 
203 .seealso:  PetscPushErrorHandler(), PetscPopErrorHandler().
204  @*/
205 
206 PetscErrorCode  PetscReturnErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx)
207 {
208   PetscFunctionBegin;
209   PetscFunctionReturn(n);
210 }
211 
212 static char PetscErrorBaseMessage[1024];
213 /*
214        The numerical values for these are defined in include/petscerror.h; any changes
215    there must also be made here
216 */
217 static const char *PetscErrorStrings[] = {
218   /*55 */ "Out of memory",
219           "No support for this operation for this object type",
220           "No support for this operation on this system",
221   /*58 */ "Operation done in wrong order",
222   /*59 */ "Signal received",
223   /*60 */ "Nonconforming object sizes",
224           "Argument aliasing not permitted",
225           "Invalid argument",
226   /*63 */ "Argument out of range",
227           "Corrupt argument:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind",
228           "Unable to open file",
229           "Read from file failed",
230           "Write to file failed",
231           "Invalid pointer",
232   /*69 */ "Arguments must have same type",
233   /*70 */ "Attempt to use a pointer that does not point to a valid accessible location",
234   /*71 */ "Detected zero pivot in LU factorization:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#ZeroPivot",
235   /*72 */ "Floating point exception",
236   /*73 */ "Object is in wrong state",
237           "Corrupted Petsc object",
238           "Arguments are incompatible",
239           "Error in external library",
240   /*77 */ "Petsc has generated inconsistent data",
241           "Memory corruption",
242           "Unexpected data in file",
243   /*80 */ "Arguments must have same communicators",
244   /*81 */ "Detected zero pivot in Cholesky factorization:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#ZeroPivot",
245           "  ",
246           "  ",
247           "Overflow in integer operation:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#64-bit-indices",
248   /*85 */ "Null argument, when expecting valid pointer",
249   /*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",
250   /*87 */ "Not used",
251   /*88 */ "Error in system call",
252   /*89 */ "Object Type not set:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#objecttypenotset"
253   /*90 */ "  ",
254   /*   */ "  ",
255   /*   */ "  ",
256   /*   */ "  ",
257   /*   */ "  ",
258   /*95 */ "  ",
259 };
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "PetscErrorMessage"
263 /*@C
264    PetscErrorMessage - returns the text string associated with a PETSc error code.
265 
266    Not Collective
267 
268    Input Parameter:
269 .   errnum - the error code
270 
271    Output Parameter:
272 +  text - the error message (NULL if not desired)
273 -  specific - the specific error message that was set with SETERRxxx() or PetscError().  (NULL if not desired)
274 
275    Level: developer
276 
277    Concepts: error handler^messages
278 
279 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
280           PetscAbortErrorHandler(), PetscTraceBackErrorHandler()
281  @*/
282 PetscErrorCode  PetscErrorMessage(int errnum,const char *text[],char **specific)
283 {
284   PetscFunctionBegin;
285   if (text && errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) *text = PetscErrorStrings[errnum-PETSC_ERR_MIN_VALUE-1];
286   else if (text) *text = 0;
287 
288   if (specific) *specific = PetscErrorBaseMessage;
289   PetscFunctionReturn(0);
290 }
291 
292 #if defined(PETSC_CLANGUAGE_CXX)
293 /* C++ exceptions are formally not allowed to propagate through extern "C" code. In practice, far too much software
294  * would be broken if implementations did not handle it it some common cases. However, keep in mind
295  *
296  *   Rule 62. Don't allow exceptions to propagate across module boundaries
297  *
298  * in "C++ Coding Standards" by Sutter and Alexandrescu. (This accounts for part of the ongoing C++ binary interface
299  * instability.) Having PETSc raise errors as C++ exceptions was probably misguided and should eventually be removed.
300  */
301 static void PetscCxxErrorThrow() {
302   const char *str;
303   if (eh && eh->ctx) {
304     std::ostringstream *msg;
305     msg = (std::ostringstream*) eh->ctx;
306     str = msg->str().c_str();
307   } else str = "Error detected in C PETSc";
308 
309   throw PETSc::Exception(str);
310 }
311 #endif
312 
313 #undef __FUNCT__
314 #define __FUNCT__ "PetscError"
315 /*@C
316    PetscError - Routine that is called when an error has been detected,
317    usually called through the macro SETERRQ(PETSC_COMM_SELF,).
318 
319    Not Collective
320 
321    Input Parameters:
322 +  comm - communicator over which error occurred.  ALL ranks of this communicator MUST call this routine
323 .  line - the line number of the error (indicated by __LINE__)
324 .  func - the function where the error occured (indicated by __FUNCT__)
325 .  file - the file in which the error was detected (indicated by __FILE__)
326 .  mess - an error text string, usually just printed to the screen
327 .  n - the generic error number
328 .  p - PETSC_ERROR_INITIAL indicates the error was initially detected, PETSC_ERROR_REPEAT indicates this is a traceback from a previously detected error
329 -  mess - formatted message string - aka printf
330 
331   Level: intermediate
332 
333    Notes:
334    Most users need not directly use this routine and the error handlers, but
335    can instead use the simplified interface SETERRQ, which has the calling
336    sequence
337 $     SETERRQ(comm,n,mess)
338 
339    Experienced users can set the error handler with PetscPushErrorHandler().
340 
341    Developer Note: Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
342    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
343    but this annoying.
344 
345    Concepts: error^setting condition
346 
347 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), SETERRQ(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2()
348 @*/
349 PetscErrorCode  PetscError(MPI_Comm comm,int line,const char *func,const char *file,PetscErrorCode n,PetscErrorType p,const char *mess,...)
350 {
351   va_list        Argp;
352   size_t         fullLength;
353   char           buf[2048],*lbuf = 0;
354   PetscBool      ismain,isunknown;
355   PetscErrorCode ierr;
356 
357   PetscFunctionBegin;
358   if (!func) func = "User provided function";
359   if (!file) file = "User file";
360   if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF;
361 
362   /* Compose the message evaluating the print format */
363   if (mess) {
364     va_start(Argp,mess);
365     PetscVSNPrintf(buf,2048,mess,&fullLength,Argp);
366     va_end(Argp);
367     lbuf = buf;
368     if (p == 1) PetscStrncpy(PetscErrorBaseMessage,lbuf,1023);
369   }
370 
371   if (!eh) ierr = PetscTraceBackErrorHandler(comm,line,func,file,n,p,lbuf,0);
372   else     ierr = (*eh->handler)(comm,line,func,file,n,p,lbuf,eh->ctx);
373 
374   /*
375       If this is called from the main() routine we call MPI_Abort() instead of
376     return to allow the parallel program to be properly shutdown.
377 
378     Since this is in the error handler we don't check the errors below. Of course,
379     PetscStrncmp() does its own error checking which is problamatic
380   */
381   PetscStrncmp(func,"main",4,&ismain);
382   PetscStrncmp(func,"unknown",7,&isunknown);
383   if (ismain || isunknown) MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
384 
385 #if defined(PETSC_CLANGUAGE_CXX)
386   if (p == PETSC_ERROR_IN_CXX) {
387     PetscCxxErrorThrow();
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      = PetscMalloc1(size,&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      = PetscMalloc1(size,&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 = PetscMalloc1(Ntotal,&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((PetscReal*)idx,NN,MPIU_REAL,0,0,0,MPIU_REAL,0,comm);CHKERRQ(ierr);
545       } else {
546         ierr      = PetscMalloc1(size,&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      = PetscMalloc1(size,&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 = PetscMalloc1(Ntotal,&array);CHKERRQ(ierr);
556         ierr = MPI_Gatherv((PetscReal*)idx,NN,MPIU_REAL,array,sizes,displs,MPIU_REAL,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      = PetscMalloc1(size,&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      = PetscMalloc1(size,&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 = PetscMalloc1(Ntotal,&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