xref: /petsc/src/sys/error/err.c (revision e30d229923a696673d75fd4bbec7dc9405e48f2f)
1 #define PETSC_DLL
2 /*
3       Code that allows one to set the error handlers
4 */
5 #include "petsc.h"           /*I "petsc.h" I*/
6 #include "petscsys.h"
7 #include <stdarg.h>
8 #if defined(PETSC_HAVE_STDLIB_H)
9 #include <stdlib.h>
10 #endif
11 
12 typedef struct _EH *EH;
13 struct _EH {
14   int            cookie;
15   PetscErrorCode (*handler)(int,const char*,const char*,const char *,PetscErrorCode,int,const char*,void *);
16   void           *ctx;
17   EH             previous;
18 };
19 
20 static EH eh = 0;
21 
22 #undef __FUNCT__
23 #define __FUNCT__ "PetscEmacsClientErrorHandler"
24 /*@C
25    PetscEmacsClientErrorHandler - Error handler that uses the emacsclient program to
26     load the file where the error occured. Then calls the "previous" error handler.
27 
28    Not Collective
29 
30    Input Parameters:
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(number,p,mess)
52 
53    Notes for experienced users:
54    Use PetscPushErrorHandler() to set the desired error handler.  The
55    currently available PETSc error handlers include PetscTraceBackErrorHandler(),
56    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscStopErrorHandler()
57 
58    Concepts: emacs^going to on error
59    Concepts: error handler^going to line in emacs
60 
61 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
62           PetscAbortErrorHandler()
63  @*/
64 PetscErrorCode PETSC_DLLEXPORT PetscEmacsClientErrorHandler(int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,int p,const char *mess,void *ctx)
65 {
66   PetscErrorCode ierr;
67   char        command[PETSC_MAX_PATH_LEN];
68   const char  *pdir;
69   FILE        *fp;
70 
71   PetscFunctionBegin;
72   /* Note: don't check error codes since this an error handler :-) */
73   ierr = PetscGetPetscDir(&pdir);CHKERRQ(ierr);
74   sprintf(command,"emacsclient +%d %s/%s%s\n",line,pdir,dir,file);
75 #if defined(PETSC_HAVE_POPEN)
76   ierr = PetscPOpen(MPI_COMM_WORLD,(char*)ctx,command,"r",&fp);
77   ierr = PetscPClose(MPI_COMM_WORLD,fp);
78 #else
79   SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
80 #endif
81   ierr = PetscPopErrorHandler(); /* remove this handler from the stack of handlers */
82   if (!eh)     ierr = PetscTraceBackErrorHandler(line,fun,file,dir,n,p,mess,0);
83   else         ierr = (*eh->handler)(line,fun,file,dir,n,p,mess,eh->ctx);
84   PetscFunctionReturn(ierr);
85 }
86 
87 #undef __FUNCT__
88 #define __FUNCT__ "PetscPushErrorHandler"
89 /*@C
90    PetscPushErrorHandler - Sets a routine to be called on detection of errors.
91 
92    Not Collective
93 
94    Input Parameters:
95 +  handler - error handler routine
96 -  ctx - optional handler context that contains information needed by the handler (for
97          example file pointers for error messages etc.)
98 
99    Calling sequence of handler:
100 $    int handler(int line,char *func,char *file,char *dir,PetscErrorCode n,int p,char *mess,void *ctx);
101 
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 - the specific error number
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 .seealso: PetscPopErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), PetscTraceBackErrorHandler()
118 
119 @*/
120 PetscErrorCode PETSC_DLLEXPORT PetscPushErrorHandler(PetscErrorCode (*handler)(int,const char *,const char*,const char*,PetscErrorCode,int,const char*,void*),void *ctx)
121 {
122   EH  neweh;
123   PetscErrorCode ierr;
124 
125   PetscFunctionBegin;
126   ierr = PetscNew(struct _EH,&neweh);CHKERRQ(ierr);
127   if (eh) {neweh->previous = eh;}
128   else    {neweh->previous = 0;}
129   neweh->handler = handler;
130   neweh->ctx     = ctx;
131   eh             = neweh;
132   PetscFunctionReturn(0);
133 }
134 
135 #undef __FUNCT__
136 #define __FUNCT__ "PetscPopErrorHandler"
137 /*@
138    PetscPopErrorHandler - Removes the latest error handler that was
139    pushed with PetscPushErrorHandler().
140 
141    Not Collective
142 
143    Level: intermediate
144 
145    Concepts: error handler^setting
146 
147 .seealso: PetscPushErrorHandler()
148 @*/
149 PetscErrorCode PETSC_DLLEXPORT PetscPopErrorHandler(void)
150 {
151   EH  tmp;
152   PetscErrorCode ierr;
153 
154   PetscFunctionBegin;
155   if (!eh) PetscFunctionReturn(0);
156   tmp  = eh;
157   eh   = eh->previous;
158   ierr = PetscFree(tmp);CHKERRQ(ierr);
159 
160   PetscFunctionReturn(0);
161 }
162 
163 static char PetscErrorBaseMessage[1024];
164 /*
165        The numerical values for these are defined in include/petscerror.h; any changes
166    there must also be made here
167 */
168 static const char *PetscErrorStrings[] = {
169   /*55 */ "Out of memory",
170           "No support for this operation for this object type",
171           "No support for this operation on this system",
172   /*58 */ "Operation done in wrong order",
173   /*59 */ "Signal received",
174   /*60 */ "Nonconforming object sizes",
175           "Argument aliasing not permitted",
176           "Invalid argument",
177   /*63 */ "Argument out of range",
178           "Corrupt argument: see http://www.mcs.anl.gov/petsc/petsc-as/documentation/troubleshooting.html#Corrupt",
179           "Unable to open file",
180           "Read from file failed",
181           "Write to file failed",
182           "Invalid pointer",
183   /*69 */ "Arguments must have same type",
184           "",
185   /*71 */ "Detected zero pivot in LU factorization\nsee http://www.mcs.anl.gov/petsc/petsc-as/documentation/troubleshooting.html#ZeroPivot",
186   /*72 */ "Floating point exception",
187   /*73 */ "Object is in wrong state",
188           "Corrupted Petsc object",
189           "Arguments are incompatible",
190           "Error in external library",
191   /*77 */ "Petsc has generated inconsistent data",
192           "Memory corruption",
193           "Unexpected data in file",
194   /*80 */ "Arguments must have same communicators",
195   /*81 */ "Detected zero pivot in Cholesky factorization\nsee http://www.mcs.anl.gov/petsc/petsc-as/documentation/troubleshooting.html#ZeroPivot",
196           "  ",
197           "  ",
198           "  ",
199   /*85 */ "Null argument, when expecting valid pointer",
200   /*86 */ "Unknown type. Check for miss-spelling or missing external package needed for type"};
201 
202 #undef __FUNCT__
203 #define __FUNCT__ "PetscErrorMessage"
204 /*@C
205    PetscErrorMessage - returns the text string associated with a PETSc error code.
206 
207    Not Collective
208 
209    Input Parameter:
210 .   errnum - the error code
211 
212    Output Parameter:
213 +  text - the error message (PETSC_NULL if not desired)
214 -  specific - the specific error message that was set with SETERRxxx() or PetscError().  (PETSC_NULL if not desired)
215 
216    Level: developer
217 
218    Concepts: error handler^messages
219 
220 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
221           PetscAbortErrorHandler(), PetscTraceBackErrorHandler()
222  @*/
223 PetscErrorCode PETSC_DLLEXPORT PetscErrorMessage(int errnum,const char *text[],char **specific)
224 {
225   PetscFunctionBegin;
226   if (text && errnum >= PETSC_ERR_MEM && errnum <= PETSC_ERR_MEM_MALLOC_0) {
227     *text = PetscErrorStrings[errnum-PETSC_ERR_MEM];
228   } else if (text) *text = 0;
229 
230   if (specific) {
231     *specific = PetscErrorBaseMessage;
232   }
233   PetscFunctionReturn(0);
234 }
235 
236 #if defined(PETSC_USE_ERRORCHECKING)
237 PetscErrorCode PETSC_DLLEXPORT PetscErrorUncatchable[PETSC_EXCEPTIONS_MAX] = {0};
238 PetscInt       PETSC_DLLEXPORT PetscErrorUncatchableCount                  = 0;
239 PetscErrorCode PETSC_DLLEXPORT PetscExceptions[PETSC_EXCEPTIONS_MAX]       = {0};
240 PetscInt       PETSC_DLLEXPORT PetscExceptionsCount                        = 0;
241 PetscErrorCode PETSC_DLLEXPORT PetscExceptionTmp                           = 0;
242 
243 #undef __FUNCT__
244 #define __FUNCT__ "PetscErrorIsCatchable"
245 static PetscTruth PetscErrorIsCatchable(PetscErrorCode err)
246 {
247   PetscInt i;
248   for (i=0; i<PetscErrorUncatchableCount; i++) {
249     if (err == PetscErrorUncatchable[i]) return PETSC_FALSE;
250   }
251   return PETSC_TRUE;
252 }
253 
254 #undef __FUNCT__
255 #define __FUNCT__ "PetscErrorSetCatchable"
256 /*@
257       PetscErrorSetCatchable - Sets if a PetscErrorCode can be caught with a PetscExceptionTry1()
258     PetscExceptionCaught() pair. By default all errors are catchable.
259 
260   Input Parameters:
261 +   err - error code
262 -   flg - PETSC_TRUE means allow to be caught, PETSC_FALSE means do not allow to be caught
263 
264   Level: advanced
265 
266    Notes:
267     PETSc must not be configured using the option --with-errorchecking=0 for this to work
268 
269 .seealso: PetscExceptionTry1(), PetscExceptionCaught()
270 @*/
271 PetscErrorCode PETSC_DLLEXPORT PetscErrorSetCatchable(PetscErrorCode err,PetscTruth flg)
272 {
273   PetscFunctionBegin;
274   if (!flg && PetscErrorIsCatchable(err)) {
275     /* add to list of uncatchable */
276     if (PetscErrorUncatchableCount >= PETSC_EXCEPTIONS_MAX) SETERRQ(PETSC_ERR_PLIB,"Stack for PetscErrorUncatchable is overflowed, recompile \nsrc/sysd/error/err.c with a larger value for PETSC_EXCEPTIONS_MAX");
277     PetscErrorUncatchable[PetscErrorUncatchableCount++] = err;
278   } else if (flg && !PetscErrorIsCatchable(err)) {
279     /* remove from list of uncatchable */
280     PetscInt i;
281     for (i=0; i<PetscErrorUncatchableCount; i++) {
282       if (PetscErrorUncatchable[i] == err) break;
283     }
284     for (;i<PetscErrorUncatchableCount; i++) {
285       PetscErrorUncatchable[i] = PetscErrorUncatchable[i+1];
286     }
287     PetscErrorUncatchableCount--;
288   }
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNCT__
293 #define __FUNCT__ "PetscExceptionPush"
294 PetscErrorCode PETSC_DLLEXPORT PetscExceptionPush(PetscErrorCode err)
295 {
296   PetscFunctionBegin;
297   if (PetscExceptionsCount >= PETSC_EXCEPTIONS_MAX) SETERRQ(PETSC_ERR_PLIB,"Stack for PetscExceptions is overflowed, recompile \nsrc/sysd/error/err.c with a larger value for PETSC_EXCEPTIONS_MAX");
298   if (PetscErrorIsCatchable(err)) PetscExceptions[PetscExceptionsCount++] = err;
299   PetscFunctionReturn(0);
300 }
301 
302 #undef __FUNCT__
303 #define __FUNCT__ "PetscExceptionPop"
304 void PETSC_DLLEXPORT PetscExceptionPop(PetscErrorCode err)
305 {
306   /* if (PetscExceptionsCount <= 0)SETERRQ(PETSC_ERR_PLIB,"Stack for PetscExceptions is empty"); */
307   if (PetscErrorIsCatchable(err)) PetscExceptionsCount--;
308 }
309 #endif
310 
311 #undef __FUNCT__
312 #define __FUNCT__ "PetscError"
313 /*@C
314    PetscError - Routine that is called when an error has been detected,
315    usually called through the macro SETERRQ().
316 
317    Not Collective
318 
319    Input Parameters:
320 +  line - the line number of the error (indicated by __LINE__)
321 .  func - the function where the error occured (indicated by __FUNCT__)
322 .  dir - the directory of file (indicated by __SDIR__)
323 .  file - the file in which the error was detected (indicated by __FILE__)
324 .  mess - an error text string, usually just printed to the screen
325 .  n - the generic error number
326 .  p - 1 indicates the error was initially detected, 0 indicates this is a traceback from a
327    previously detected error
328 -  mess - formatted message string - aka printf
329 
330   Level: intermediate
331 
332    Notes:
333    Most users need not directly use this routine and the error handlers, but
334    can instead use the simplified interface SETERRQ, which has the calling
335    sequence
336 $     SETERRQ(n,mess)
337 
338    Experienced users can set the error handler with PetscPushErrorHandler().
339 
340    Concepts: error^setting condition
341 
342 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), SETERRQ(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2()
343 @*/
344 PetscErrorCode PETSC_DLLEXPORT PetscError(int line,const char *func,const char* file,const char *dir,PetscErrorCode n,int p,const char *mess,...)
345 {
346   va_list        Argp;
347   PetscErrorCode ierr;
348   char           buf[2048],*lbuf = 0;
349   PetscTruth     ismain,isunknown;
350 #if defined(PETSC_USE_ERRORCHECKING)
351   PetscInt       i;
352 #endif
353 
354   if (!func)  func = "User provided function";
355   if (!file)  file = "User file";
356   if (!dir)   dir = " ";
357 
358   PetscFunctionBegin;
359   /* Compose the message evaluating the print format */
360   if (mess) {
361     va_start(Argp,mess);
362     PetscVSNPrintf(buf,2048,mess,Argp);
363     va_end(Argp);
364     lbuf = buf;
365     if (p == 1) {
366       PetscStrncpy(PetscErrorBaseMessage,lbuf,1023);
367     }
368   }
369 
370 #if defined(PETSC_USE_ERRORCHECKING)
371   /* check if user is catching this exception */
372   for (i=0; i<PetscExceptionsCount; i++) {
373     if (n == PetscExceptions[i])  PetscFunctionReturn(n);
374   }
375 #endif
376 
377   if (!eh)     ierr = PetscTraceBackErrorHandler(line,func,file,dir,n,p,lbuf,0);
378   else         ierr = (*eh->handler)(line,func,file,dir,n,p,lbuf,eh->ctx);
379 
380   /*
381       If this is called from the main() routine we call MPI_Abort() instead of
382     return to allow the parallel program to be properly shutdown.
383 
384     Since this is in the error handler we don't check the errors below. Of course,
385     PetscStrncmp() does its own error checking which is problamatic
386   */
387   PetscStrncmp(func,"main",4,&ismain);
388   PetscStrncmp(func,"unknown",7,&isunknown);
389   if (ismain || isunknown) {
390     MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
391   }
392   PetscFunctionReturn(ierr);
393 }
394 
395 /* -------------------------------------------------------------------------*/
396 
397 #undef __FUNCT__
398 #define __FUNCT__ "PetscIntView"
399 /*@C
400     PetscIntView - Prints an array of integers; useful for debugging.
401 
402     Collective on PetscViewer
403 
404     Input Parameters:
405 +   N - number of integers in array
406 .   idx - array of integers
407 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
408 
409   Level: intermediate
410 
411 .seealso: PetscRealView()
412 @*/
413 PetscErrorCode PETSC_DLLEXPORT PetscIntView(PetscInt N,PetscInt idx[],PetscViewer viewer)
414 {
415   PetscErrorCode ierr;
416   PetscInt       j,i,n = N/20,p = N % 20;
417   PetscTruth     iascii,issocket;
418   MPI_Comm       comm;
419 
420   PetscFunctionBegin;
421   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
422   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,3);
423   PetscValidIntPointer(idx,2);
424   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
425 
426   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
427   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
428   if (iascii) {
429     for (i=0; i<n; i++) {
430       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D:",20*i);CHKERRQ(ierr);
431       for (j=0; j<20; j++) {
432         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %D",idx[i*20+j]);CHKERRQ(ierr);
433       }
434       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
435     }
436     if (p) {
437       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%D:",20*n);CHKERRQ(ierr);
438       for (i=0; i<p; i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer," %D",idx[20*n+i]);CHKERRQ(ierr);}
439       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
440     }
441     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
442 #if defined(PETSC_USE_SOCKET_VIEWER)
443   } else if (issocket) {
444     PetscMPIInt rank,size,*sizes,Ntotal,*displs, NN = (PetscMPIInt)N;
445     PetscInt    *array;
446     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
447     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
448 
449     if (size > 1) {
450       if (rank) {
451         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
452         ierr = MPI_Gatherv(idx,NN,MPIU_INT,0,0,0,MPIU_INT,0,comm);CHKERRQ(ierr);
453       } else {
454 	ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
455         ierr      = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
456         Ntotal    = sizes[0];
457 	ierr      = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
458         displs[0] = 0;
459         for (i=1; i<size; i++) {
460           Ntotal    += sizes[i];
461           displs[i] =  displs[i-1] + sizes[i-1];
462         }
463 	ierr = PetscMalloc(Ntotal*sizeof(PetscInt),&array);CHKERRQ(ierr);
464         ierr = MPI_Gatherv(idx,NN,MPIU_INT,array,sizes,displs,MPIU_INT,0,comm);CHKERRQ(ierr);
465         ierr = PetscViewerSocketPutInt(viewer,Ntotal,array);CHKERRQ(ierr);
466         ierr = PetscFree(sizes);CHKERRQ(ierr);
467         ierr = PetscFree(displs);CHKERRQ(ierr);
468         ierr = PetscFree(array);CHKERRQ(ierr);
469       }
470     } else {
471       ierr = PetscViewerSocketPutInt(viewer,N,idx);CHKERRQ(ierr);
472     }
473 #endif
474   } else {
475     const char *tname;
476     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
477     SETERRQ1(PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
478   }
479   PetscFunctionReturn(0);
480 }
481 
482 #undef __FUNCT__
483 #define __FUNCT__ "PetscRealView"
484 /*@C
485     PetscRealView - Prints an array of doubles; useful for debugging.
486 
487     Collective on PetscViewer
488 
489     Input Parameters:
490 +   N - number of doubles in array
491 .   idx - array of doubles
492 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
493 
494   Level: intermediate
495 
496 .seealso: PetscIntView()
497 @*/
498 PetscErrorCode PETSC_DLLEXPORT PetscRealView(PetscInt N,PetscReal idx[],PetscViewer viewer)
499 {
500   PetscErrorCode ierr;
501   PetscInt       j,i,n = N/5,p = N % 5;
502   PetscTruth     iascii,issocket;
503   MPI_Comm       comm;
504 
505   PetscFunctionBegin;
506   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
507   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,3);
508   PetscValidScalarPointer(idx,2);
509   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
510 
511   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
512   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
513   if (iascii) {
514     for (i=0; i<n; i++) {
515       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*i);CHKERRQ(ierr);
516       for (j=0; j<5; j++) {
517          ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[i*5+j]);CHKERRQ(ierr);
518       }
519       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
520     }
521     if (p) {
522       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%2d:",5*n);CHKERRQ(ierr);
523       for (i=0; i<p; i++) { PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[5*n+i]);CHKERRQ(ierr);}
524       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
525     }
526     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
527 #if defined(PETSC_USE_SOCKET_VIEWER)
528   } else if (issocket) {
529     PetscMPIInt rank,size,*sizes,*displs, Ntotal,NN = (PetscMPIInt)N;
530     PetscReal   *array;
531 
532     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
533     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
534 
535     if (size > 1) {
536       if (rank) {
537         ierr = MPI_Gather(&NN,1,MPI_INT,0,0,MPI_INT,0,comm);CHKERRQ(ierr);
538         ierr = MPI_Gatherv(idx,NN,MPI_DOUBLE,0,0,0,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
539       } else {
540 	ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&sizes);CHKERRQ(ierr);
541         ierr   = MPI_Gather(&NN,1,MPI_INT,sizes,1,MPI_INT,0,comm);CHKERRQ(ierr);
542         Ntotal = sizes[0];
543 	ierr   = PetscMalloc(size*sizeof(PetscMPIInt),&displs);CHKERRQ(ierr);
544         displs[0] = 0;
545         for (i=1; i<size; i++) {
546           Ntotal    += sizes[i];
547           displs[i] =  displs[i-1] + sizes[i-1];
548         }
549 	ierr = PetscMalloc(Ntotal*sizeof(PetscReal),&array);CHKERRQ(ierr);
550         ierr = MPI_Gatherv(idx,NN,MPI_DOUBLE,array,sizes,displs,MPI_DOUBLE,0,comm);CHKERRQ(ierr);
551         ierr = PetscViewerSocketPutReal(viewer,Ntotal,1,array);CHKERRQ(ierr);
552         ierr = PetscFree(sizes);CHKERRQ(ierr);
553         ierr = PetscFree(displs);CHKERRQ(ierr);
554         ierr = PetscFree(array);CHKERRQ(ierr);
555       }
556     } else {
557       ierr = PetscViewerSocketPutReal(viewer,N,1,idx);CHKERRQ(ierr);
558     }
559 #endif
560   } else {
561     const char *tname;
562     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
563     SETERRQ1(PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
564   }
565   PetscFunctionReturn(0);
566 }
567 
568 #undef __FUNCT__
569 #define __FUNCT__ "PetscScalarView"
570 /*@C
571     PetscScalarView - Prints an array of scalars; useful for debugging.
572 
573     Collective on PetscViewer
574 
575     Input Parameters:
576 +   N - number of scalars in array
577 .   idx - array of scalars
578 -   viewer - location to print array,  PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF or 0
579 
580   Level: intermediate
581 
582 .seealso: PetscIntView(), PetscRealView()
583 @*/
584 PetscErrorCode PETSC_DLLEXPORT PetscScalarView(PetscInt N,PetscScalar idx[],PetscViewer viewer)
585 {
586   PetscErrorCode ierr;
587   PetscInt       j,i,n = N/3,p = N % 3;
588   PetscTruth     iascii,issocket;
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 = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
598   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
599   if (iascii) {
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)",
605                                  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)",
617                                  PetscRealPart(idx[n*3+i]),PetscImaginaryPart(idx[n*3+i]));CHKERRQ(ierr);
618 #else
619         ierr = PetscViewerASCIISynchronizedPrintf(viewer," %12.4e",idx[3*n+i]);CHKERRQ(ierr);
620 #endif
621       }
622       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr);
623     }
624     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
625 #if defined(PETSC_USE_SOCKET_VIEWER)
626   } else if (issocket) {
627     PetscMPIInt size,rank,*sizes,Ntotal,*displs,NN = (PetscMPIInt)N;
628     PetscScalar *array;
629 
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(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(idx,NN,MPIU_SCALAR,array,sizes,displs,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
649         ierr = PetscViewerSocketPutScalar(viewer,Ntotal,1,array);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 = PetscViewerSocketPutScalar(viewer,N,1,idx);CHKERRQ(ierr);
656     }
657 #endif
658   } else {
659     const char *tname;
660     ierr = PetscObjectGetName((PetscObject)viewer,&tname);CHKERRQ(ierr);
661     SETERRQ1(PETSC_ERR_SUP,"Cannot handle that PetscViewer of type %s",tname);
662   }
663   PetscFunctionReturn(0);
664 }
665 
666 
667 
668 
669