xref: /petsc/src/sys/error/err.c (revision 2d50711886017447cb8c1ab06d8b61e8775efc0e)
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    Concepts: emacs^going to on error
57    Concepts: error handler^going to line in emacs
58 
59 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
60           PetscAbortErrorHandler()
61  @*/
62 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)
63 {
64   PetscErrorCode ierr;
65   char        command[PETSC_MAX_PATH_LEN];
66   const char  *pdir;
67   FILE        *fp;
68   PetscInt    rval;
69 
70   PetscFunctionBegin;
71   /* Note: don't check error codes since this an error handler :-) */
72   ierr = PetscGetPetscDir(&pdir);
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);
76   ierr = PetscPClose(MPI_COMM_WORLD,fp,&rval);
77 #else
78   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
79 #endif
80   ierr = PetscPopErrorHandler(); /* remove this handler from the stack of handlers */
81   if (!eh)     ierr = PetscTraceBackErrorHandler(comm,line,fun,file,dir,n,p,mess,0);
82   else         ierr = (*eh->handler)(comm,line,fun,file,dir,n,p,mess,eh->ctx);
83   PetscFunctionReturn(ierr);
84 }
85 
86 #undef __FUNCT__
87 #define __FUNCT__ "PetscPushErrorHandler"
88 /*@C
89    PetscPushErrorHandler - Sets a routine to be called on detection of errors.
90 
91    Not Collective
92 
93    Input Parameters:
94 +  handler - error handler routine
95 -  ctx - optional handler context that contains information needed by the handler (for
96          example file pointers for error messages etc.)
97 
98    Calling sequence of handler:
99 $    int handler(MPI_Comm comm,int line,char *func,char *file,char *dir,PetscErrorCode n,int p,char *mess,void *ctx);
100 
101 +  comm - communicator over which error occured
102 .  func - the function where the error occured (indicated by __FUNCT__)
103 .  line - the line number of the error (indicated by __LINE__)
104 .  file - the file in which the error was detected (indicated by __FILE__)
105 .  dir - the directory of the file (indicated by __SDIR__)
106 .  n - the generic error number (see list defined in include/petscerror.h)
107 .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
108 .  mess - an error text string, usually just printed to the screen
109 -  ctx - the error handler context
110 
111    Options Database Keys:
112 +   -on_error_attach_debugger <noxterm,gdb or dbx>
113 -   -on_error_abort
114 
115    Level: intermediate
116 
117    Notes:
118    The currently available PETSc error handlers include PetscTraceBackErrorHandler(),
119    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler(), PetscReturnErrorHandler().
120 
121    Fortran Notes: You can only push one error handler from Fortran before poping it.
122 
123 .seealso: PetscPopErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), PetscTraceBackErrorHandler(), PetscPushSignalHandler()
124 
125 @*/
126 PetscErrorCode  PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm,int,const char *,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*),void *ctx)
127 {
128   EH             neweh;
129   PetscErrorCode ierr;
130 
131   PetscFunctionBegin;
132   ierr = PetscNew(struct _EH,&neweh);CHKERRQ(ierr);
133   if (eh) {neweh->previous = eh;}
134   else    {neweh->previous = 0;}
135   neweh->handler = handler;
136   neweh->ctx     = ctx;
137   eh             = neweh;
138   PetscFunctionReturn(0);
139 }
140 
141 #undef __FUNCT__
142 #define __FUNCT__ "PetscPopErrorHandler"
143 /*@
144    PetscPopErrorHandler - Removes the latest error handler that was
145    pushed with PetscPushErrorHandler().
146 
147    Not Collective
148 
149    Level: intermediate
150 
151    Concepts: error handler^setting
152 
153 .seealso: PetscPushErrorHandler()
154 @*/
155 PetscErrorCode  PetscPopErrorHandler(void)
156 {
157   EH             tmp;
158   PetscErrorCode ierr;
159 
160   PetscFunctionBegin;
161   if (!eh) PetscFunctionReturn(0);
162   tmp  = eh;
163   eh   = eh->previous;
164   ierr = PetscFree(tmp);CHKERRQ(ierr);
165 
166   PetscFunctionReturn(0);
167 }
168 
169 #undef __FUNCT__
170 #define __FUNCT__ "PetscReturnErrorHandler"
171 /*@C
172   PetscReturnErrorHandler - Error handler that causes a return to the current
173   level.
174 
175    Not Collective
176 
177    Input Parameters:
178 +  comm - communicator over which error occurred
179 .  line - the line number of the error (indicated by __LINE__)
180 .  func - the function where error is detected (indicated by __FUNCT__)
181 .  file - the file in which the error was detected (indicated by __FILE__)
182 .  dir - the directory of the file (indicated by __SDIR__)
183 .  mess - an error text string, usually just printed to the screen
184 .  n - the generic error number
185 .  p - specific error number
186 -  ctx - error handler context
187 
188    Level: developer
189 
190    Notes:
191    Most users need not directly employ this routine and the other error
192    handlers, but can instead use the simplified interface SETERRQ, which has
193    the calling sequence
194 $     SETERRQ(comm,number,mess)
195 
196    Notes for experienced users:
197    This routine is good for catching errors such as zero pivots in preconditioners
198    or breakdown of iterative methods. It is not appropriate for memory violations
199    and similar errors.
200 
201    Use PetscPushErrorHandler() to set the desired error handler.  The
202    currently available PETSc error handlers include PetscTraceBackErrorHandler(),
203    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscAbortErrorHandler()
204 
205    Concepts: error handler
206 
207 .seealso:  PetscPushErrorHandler(), PetscPopErrorHandler().
208  @*/
209 
210 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)
211 {
212   PetscFunctionBegin;
213   PetscFunctionReturn(n);
214 }
215 
216 static char PetscErrorBaseMessage[1024];
217 /*
218        The numerical values for these are defined in include/petscerror.h; any changes
219    there must also be made here
220 */
221 static const char *PetscErrorStrings[] = {
222   /*55 */ "Out of memory",
223           "No support for this operation for this object type",
224           "No support for this operation on this system",
225   /*58 */ "Operation done in wrong order",
226   /*59 */ "Signal received",
227   /*60 */ "Nonconforming object sizes",
228           "Argument aliasing not permitted",
229           "Invalid argument",
230   /*63 */ "Argument out of range",
231           "Corrupt argument:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind",
232           "Unable to open file",
233           "Read from file failed",
234           "Write to file failed",
235           "Invalid pointer",
236   /*69 */ "Arguments must have same type",
237   /*70 */ "Attempt to use a pointer that does not point to a valid accessible location",
238   /*71 */ "Detected zero pivot in LU factorization:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#ZeroPivot",
239   /*72 */ "Floating point exception",
240   /*73 */ "Object is in wrong state",
241           "Corrupted Petsc object",
242           "Arguments are incompatible",
243           "Error in external library",
244   /*77 */ "Petsc has generated inconsistent data",
245           "Memory corruption",
246           "Unexpected data in file",
247   /*80 */ "Arguments must have same communicators",
248   /*81 */ "Detected zero pivot in Cholesky factorization:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#ZeroPivot",
249           "  ",
250           "  ",
251           "Overflow in integer operation:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#64-bit-indices",
252   /*85 */ "Null argument, when expecting valid pointer",
253   /*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",
254   /*87 */ "Not used",
255   /*88 */ "Error in system call",
256   /*89 */ "Object Type not set:\nsee http://www.mcs.anl.gov/petsc/documentation/faq.html#objecttypenotset"
257   /*90 */ "  ",
258   /*   */ "  ",
259   /*   */ "  ",
260   /*   */ "  ",
261   /*   */ "  ",
262   /*95 */ "  ",
263 };
264 
265 #undef __FUNCT__
266 #define __FUNCT__ "PetscErrorMessage"
267 /*@C
268    PetscErrorMessage - returns the text string associated with a PETSc error code.
269 
270    Not Collective
271 
272    Input Parameter:
273 .   errnum - the error code
274 
275    Output Parameter:
276 +  text - the error message (PETSC_NULL if not desired)
277 -  specific - the specific error message that was set with SETERRxxx() or PetscError().  (PETSC_NULL if not desired)
278 
279    Level: developer
280 
281    Concepts: error handler^messages
282 
283 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
284           PetscAbortErrorHandler(), PetscTraceBackErrorHandler()
285  @*/
286 PetscErrorCode  PetscErrorMessage(int errnum,const char *text[],char **specific)
287 {
288   PetscFunctionBegin;
289   if (text && errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) {
290     *text = PetscErrorStrings[errnum-PETSC_ERR_MIN_VALUE-1];
291   } else if (text) *text = 0;
292 
293   if (specific) {
294     *specific = PetscErrorBaseMessage;
295   }
296   PetscFunctionReturn(0);
297 }
298 
299 #undef __FUNCT__
300 #define __FUNCT__ "PetscError"
301 /*@C
302    PetscError - Routine that is called when an error has been detected,
303    usually called through the macro SETERRQ(PETSC_COMM_SELF,).
304 
305    Not Collective
306 
307    Input Parameters:
308 +  comm - communicator over which error occurred.  ALL ranks of this communicator MUST call this routine
309 .  line - the line number of the error (indicated by __LINE__)
310 .  func - the function where the error occured (indicated by __FUNCT__)
311 .  dir - the directory of file (indicated by __SDIR__)
312 .  file - the file in which the error was detected (indicated by __FILE__)
313 .  mess - an error text string, usually just printed to the screen
314 .  n - the generic error number
315 .  p - PETSC_ERROR_INITIAL indicates the error was initially detected, PETSC_ERROR_REPEAT indicates this is a traceback from a previously detected error
316 -  mess - formatted message string - aka printf
317 
318   Level: intermediate
319 
320    Notes:
321    Most users need not directly use this routine and the error handlers, but
322    can instead use the simplified interface SETERRQ, which has the calling
323    sequence
324 $     SETERRQ(comm,n,mess)
325 
326    Experienced users can set the error handler with PetscPushErrorHandler().
327 
328    Concepts: error^setting condition
329 
330 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), SETERRQ(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2()
331 @*/
332 PetscErrorCode  PetscError(MPI_Comm comm,int line,const char *func,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,...)
333 {
334   va_list        Argp;
335   size_t         fullLength;
336   PetscErrorCode ierr;
337   char           buf[2048],*lbuf = 0;
338   PetscBool      ismain,isunknown;
339 
340   if (!func)  func = "User provided function";
341   if (!file)  file = "User file";
342   if (!dir)   dir = " ";
343 
344   PetscFunctionBegin;
345   /* Compose the message evaluating the print format */
346   if (mess) {
347     va_start(Argp,mess);
348     PetscVSNPrintf(buf,2048,mess,&fullLength,Argp);
349     va_end(Argp);
350     lbuf = buf;
351     if (p == 1) {
352       PetscStrncpy(PetscErrorBaseMessage,lbuf,1023);
353     }
354   }
355 
356   if (!eh)     ierr = PetscTraceBackErrorHandler(comm,line,func,file,dir,n,p,lbuf,0);
357   else         ierr = (*eh->handler)(comm,line,func,file,dir,n,p,lbuf,eh->ctx);
358 
359   /*
360       If this is called from the main() routine we call MPI_Abort() instead of
361     return to allow the parallel program to be properly shutdown.
362 
363     Since this is in the error handler we don't check the errors below. Of course,
364     PetscStrncmp() does its own error checking which is problamatic
365   */
366   PetscStrncmp(func,"main",4,&ismain);
367   PetscStrncmp(func,"unknown",7,&isunknown);
368   if (ismain || isunknown) {
369     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 {
379       str = "Error detected in C PETSc";
380     }
381     throw PETSc::Exception(str);
382   }
383 #endif
384   PetscFunctionReturn(ierr);
385 }
386 
387 /* -------------------------------------------------------------------------*/
388 
389 #undef __FUNCT__
390 #define __FUNCT__ "PetscIntView"
391 /*@C
392     PetscIntView - Prints an array of integers; useful for debugging.
393 
394     Collective on PetscViewer
395 
396     Input Parameters:
397 +   N - number of integers in array
398 .   idx - array of integers
399 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
400 
401   Level: intermediate
402 
403     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping 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 = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);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 = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
438   } else if (isbinary) {
439     PetscMPIInt rank,size,*sizes,Ntotal,*displs, NN = PetscMPIIntCast(N);
440     PetscInt    *array;
441     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
442     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
443 
444     if (size > 1) {
445       if (rank) {
446         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
447         ierr = MPI_Gatherv((void*)idx,NN,MPIU_INT,0,0,0,MPIU_INT,0,comm);CHKERRQ(ierr);
448       } else {
449 	ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
450         ierr      = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
451         Ntotal    = sizes[0];
452 	ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
453         displs[0] = 0;
454         for (i=1; i<size; i++) {
455           Ntotal    += sizes[i];
456           displs[i] =  displs[i-1] + sizes[i-1];
457         }
458 	ierr = PetscMalloc(Ntotal*sizeof(PetscInt),&array);CHKERRQ(ierr);
459         ierr = MPI_Gatherv((void*)idx,NN,MPIU_INT,array,sizes,displs,MPIU_INT,0,comm);CHKERRQ(ierr);
460         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
461         ierr = PetscFree(sizes);CHKERRQ(ierr);
462         ierr = PetscFree(displs);CHKERRQ(ierr);
463         ierr = PetscFree(array);CHKERRQ(ierr);
464       }
465     } else {
466       ierr = PetscViewerBinaryWrite(viewer,(void *) idx,N,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
467     }
468   } else {
469     const char *tname;
470     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
471     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
472   }
473   PetscFunctionReturn(0);
474 }
475 
476 #undef __FUNCT__
477 #define __FUNCT__ "PetscRealView"
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 doubles in array
485 .   idx - array of doubles
486 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
487 
488   Level: intermediate
489 
490     Developer Notes: idx cannot be const because may be passed to binary viewer where byte swappping is done
491 
492 .seealso: PetscIntView()
493 @*/
494 PetscErrorCode  PetscRealView(PetscInt N,const PetscReal idx[],PetscViewer viewer)
495 {
496   PetscErrorCode ierr;
497   PetscInt       j,i,n = N/5,p = N % 5;
498   PetscBool      iascii,isbinary;
499   MPI_Comm       comm;
500 
501   PetscFunctionBegin;
502   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
503   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,3);
504   PetscValidScalarPointer(idx,2);
505   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
506 
507   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
508   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
509   if (iascii) {
510     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
511     for (i=0; i<n; i++) {
512       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*i);CHKERRQ(ierr);
513       for (j=0; j<5; j++) {
514          ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[i*5+j]);CHKERRQ(ierr);
515       }
516       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
517     }
518     if (p) {
519       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*n);CHKERRQ(ierr);
520       for (i=0; i<p; i++) { PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[5*n+i]);CHKERRQ(ierr);}
521       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
522     }
523     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
524     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
525   } else if (isbinary) {
526     PetscMPIInt rank,size,*sizes,*displs, Ntotal,NN = PetscMPIIntCast(N);
527     PetscReal   *array;
528 
529     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
530     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
531 
532     if (size > 1) {
533       if (rank) {
534         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
535         ierr = MPI_Gatherv((void*)idx,NN,MPI_DOUBLE,0,0,0,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
536       } else {
537 	ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
538         ierr   = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
539         Ntotal = sizes[0];
540 	ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
541         displs[0] = 0;
542         for (i=1; i<size; i++) {
543           Ntotal    += sizes[i];
544           displs[i] =  displs[i-1] + sizes[i-1];
545         }
546 	ierr = PetscMalloc(Ntotal*sizeof(PetscReal),&array);CHKERRQ(ierr);
547         ierr = MPI_Gatherv((void*)idx,NN,MPI_DOUBLE,array,sizes,displs,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
548         ierr = PetscViewerBinaryWrite(viewer,array,Ntotal,PETSC_REAL,PETSC_TRUE);CHKERRQ(ierr);
549         ierr = PetscFree(sizes);CHKERRQ(ierr);
550         ierr = PetscFree(displs);CHKERRQ(ierr);
551         ierr = PetscFree(array);CHKERRQ(ierr);
552       }
553     } else {
554       ierr = PetscViewerBinaryWrite(viewer,(void *) idx,N,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr);
555     }
556   } else {
557     const char *tname;
558     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
559     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
560   }
561   PetscFunctionReturn(0);
562 }
563 
564 #undef __FUNCT__
565 #define __FUNCT__ "PetscScalarView"
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: idx cannot be const because may be passed to binary viewer where byte swappping is done
579 
580 .seealso: PetscIntView(), PetscRealView()
581 @*/
582 PetscErrorCode  PetscScalarView(PetscInt N,const PetscScalar idx[],PetscViewer viewer)
583 {
584   PetscErrorCode ierr;
585   PetscInt       j,i,n = N/3,p = N % 3;
586   PetscBool      iascii,isbinary;
587   MPI_Comm       comm;
588 
589   PetscFunctionBegin;
590   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
591   PetscValidHeader(viewer,3);
592   PetscValidScalarPointer(idx,2);
593   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
594 
595   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
596   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
597   if (iascii) {
598     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
599     for (i=0; i<n; i++) {
600       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",3*i);CHKERRQ(ierr);
601       for (j=0; j<3; j++) {
602 #if defined (PETSC_USE_COMPLEX)
603         ierr = PetscViewerASCIISynchronizedPrintf(viewer," (%12.4e,%12.4e)",
604                                  PetscRealPart(idx[i*3+j]),PetscImaginaryPart(idx[i*3+j]));CHKERRQ(ierr);
605 #else
606         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",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)",
616                                  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 = PetscMPIIntCast(N);
627     PetscScalar *array;
628 
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   = PetscMalloc(size*sizeof(PetscMPIInt),&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   = PetscMalloc(size*sizeof(PetscMPIInt),&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 = PetscMalloc(Ntotal*sizeof(PetscScalar),&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