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