Actual source code: plog.c

  1: #define PETSC_DLL
  2: /*
  3:       PETSc code to log object creation and destruction and PETSc events.
  4: */
 5:  #include petsc.h
 6:  #include petsctime.h
  7: #if defined(PETSC_HAVE_MPE)
  8: #include "mpe.h"
  9: #endif
 10: #include <stdarg.h>
 11: #include <sys/types.h>
 12:  #include petscsys.h
 13: #if defined(PETSC_HAVE_STDLIB_H)
 14: #include <stdlib.h>
 15: #endif
 16: #if defined(PETSC_HAVE_MALLOC_H)
 17: #include <malloc.h>
 18: #endif
 19: #include "petscfix.h"
 20:  #include plog.h

 22: PetscLogEvent  PETSC_LARGEST_EVENT  = PETSC_EVENT;

 24: #if defined(PETSC_USE_LOG)
 25: #include "petscmachineinfo.h"
 26: #include "petscconfiginfo.h"

 28: /* used in the MPI_XXX() count macros in petsclog.h */

 30: /* Action and object logging variables */
 31: Action    *actions    = PETSC_NULL;
 32: Object    *objects    = PETSC_NULL;
 33: PetscTruth logActions = PETSC_FALSE;
 34: PetscTruth logObjects = PETSC_FALSE;
 35: int        numActions = 0, maxActions = 100;
 36: int        numObjects = 0, maxObjects = 100;
 37: int        numObjectsDestroyed = 0;

 39: /* Global counters */
 40: PetscLogDouble  BaseTime        = 0.0;
 41: PetscLogDouble  _TotalFlops     = 0.0; /* The number of flops */
 42: PetscLogDouble  petsc_tmp_flops = 0.0; /* The incremental number of flops */
 43: PetscLogDouble  send_ct         = 0.0; /* The number of sends */
 44: PetscLogDouble  recv_ct         = 0.0; /* The number of receives */
 45: PetscLogDouble  send_len        = 0.0; /* The total length of all sent messages */
 46: PetscLogDouble  recv_len        = 0.0; /* The total length of all received messages */
 47: PetscLogDouble  isend_ct        = 0.0; /* The number of immediate sends */
 48: PetscLogDouble  irecv_ct        = 0.0; /* The number of immediate receives */
 49: PetscLogDouble  isend_len       = 0.0; /* The total length of all immediate send messages */
 50: PetscLogDouble  irecv_len       = 0.0; /* The total length of all immediate receive messages */
 51: PetscLogDouble  wait_ct         = 0.0; /* The number of waits */
 52: PetscLogDouble  wait_any_ct     = 0.0; /* The number of anywaits */
 53: PetscLogDouble  wait_all_ct     = 0.0; /* The number of waitalls */
 54: PetscLogDouble  sum_of_waits_ct = 0.0; /* The total number of waits */
 55: PetscLogDouble  allreduce_ct    = 0.0; /* The number of reductions */
 56: PetscLogDouble  gather_ct       = 0.0; /* The number of gathers and gathervs */
 57: PetscLogDouble  scatter_ct      = 0.0; /* The number of scatters and scattervs */

 59: /* Logging functions */
 60: PetscErrorCode  (*_PetscLogPHC)(PetscObject) = PETSC_NULL;
 61: PetscErrorCode  (*_PetscLogPHD)(PetscObject) = PETSC_NULL;
 62: PetscErrorCode  (*_PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = PETSC_NULL;
 63: PetscErrorCode  (*_PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = PETSC_NULL;

 65: /* Tracing event logging variables */
 66: FILE          *tracefile       = PETSC_NULL;
 67: int            tracelevel      = 0;
 68: const char    *traceblanks     = "                                                                                                    ";
 69: char           tracespace[128] = " ";
 70: PetscLogDouble tracetime       = 0.0;

 72: /*---------------------------------------------- General Functions --------------------------------------------------*/
 75: /*@C
 76:   PetscLogDestroy - Destroys the object and event logging data and resets the global counters. 

 78:   Not Collective

 80:   Notes:
 81:   This routine should not usually be used by programmers. Instead employ 
 82:   PetscLogStagePush() and PetscLogStagePop().

 84:   Level: developer

 86: .keywords: log, destroy
 87: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogPrintSummary(), PetscLogStagePush(), PlogStagePop()
 88: @*/
 89: PetscErrorCode  PetscLogDestroy(void)
 90: {
 91:   StageLog       stageLog;

 95:   PetscFree(actions);
 96:   actions = PETSC_NULL;
 97:   PetscFree(objects);
 98:   objects =  PETSC_NULL;
 99:   PetscLogSet(PETSC_NULL, PETSC_NULL);

101:   /* Resetting phase */
102:   PetscLogGetStageLog(&stageLog);
103:   StageLogDestroy(stageLog);
104:   _TotalFlops         = 0.0;
105:   numActions          = 0;
106:   numObjects          = 0;
107:   numObjectsDestroyed = 0;
108:   return(0);
109: }

113: /*@C
114:   PetscLogSet - Sets the logging functions called at the beginning and ending of every event.

116:   Not Collective

118:   Input Parameters:
119: + b - The function called at beginning of event
120: - e - The function called at end of event

122:   Level: developer

124: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogAllBegin(), PetscLogTraceBegin()
125: @*/
126: PetscErrorCode  PetscLogSet(PetscErrorCode (*b)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject),
127:             PetscErrorCode (*e)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject))
128: {
130:   _PetscLogPLB = b;
131:   _PetscLogPLE = e;
132:   return(0);
133: }

135: /*------------------------------------------- Initialization Functions ----------------------------------------------*/
138: PetscErrorCode  PetscLogBegin_Private(void)
139: {
140:   static PetscTruth initialized = PETSC_FALSE;
141:   int               stage;
142:   PetscTruth        opt;
143:   PetscErrorCode    ierr;

146:   if (initialized) return(0);
147:   initialized = PETSC_TRUE;
148:   PetscOptionsHasName(PETSC_NULL, "-log_exclude_actions", &opt);
149:   if (opt) {
150:     logActions = PETSC_FALSE;
151:   }
152:   PetscOptionsHasName(PETSC_NULL, "-log_exclude_objects", &opt);
153:   if (opt) {
154:     logObjects = PETSC_FALSE;
155:   }
156:   if (logActions) {
157:     PetscMalloc(maxActions * sizeof(Action), &actions);
158:   }
159:   if (logObjects) {
160:     PetscMalloc(maxObjects * sizeof(Object), &objects);
161:   }
162:   _PetscLogPHC = PetscLogObjCreateDefault;
163:   _PetscLogPHD = PetscLogObjDestroyDefault;
164:   /* Setup default logging structures */
165:   StageLogCreate(&_stageLog);
166:   StageLogRegister(_stageLog, "Main Stage", &stage);
167:   /* All processors sync here for more consistent logging */
168:   MPI_Barrier(PETSC_COMM_WORLD);
169:   PetscTime(BaseTime);
170:   PetscLogStagePush(stage);
171:   return(0);
172: }

176: /*@C
177:   PetscLogBegin - Turns on logging of objects and events. This logs flop
178:   rates and object creation and should not slow programs down too much.
179:   This routine may be called more than once.

181:   Collective over PETSC_COMM_WORLD

183:   Options Database Keys:
184: + -log_summary - Prints summary of flop and timing information to the 
185:                   screen (for code compiled with PETSC_USE_LOG)
186: - -log - Prints detailed log information (for code compiled with PETSC_USE_LOG)

188:   Usage:
189: .vb
190:       PetscInitialize(...);
191:       PetscLogBegin();
192:        ... code ...
193:       PetscLogPrintSummary(MPI_Comm,filename); or PetscLogDump(); 
194:       PetscFinalize();
195: .ve

197:   Notes:
198:   PetscLogPrintSummary(MPI_Comm,filename) or PetscLogDump() actually cause the printing of 
199:   the logging information.

201:   Level: advanced

203: .keywords: log, begin
204: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogPrintSummary(), PetscLogTraceBegin()
205: @*/
206: PetscErrorCode  PetscLogBegin(void)
207: {

211:   PetscLogSet(PetscLogEventBeginDefault, PetscLogEventEndDefault);
212:   PetscLogBegin_Private();
213:   return(0);
214: }

218: /*@C
219:   PetscLogAllBegin - Turns on extensive logging of objects and events. Logs 
220:   all events. This creates large log files and slows the program down.

222:   Collective on PETSC_COMM_WORLD

224:   Options Database Keys:
225: . -log_all - Prints extensive log information (for code compiled with PETSC_USE_LOG)

227:   Usage:
228: .vb
229:      PetscInitialize(...);
230:      PetscLogAllBegin();
231:      ... code ...
232:      PetscLogDump(filename);
233:      PetscFinalize();
234: .ve

236:   Notes:
237:   A related routine is PetscLogBegin (with the options key -log), which is 
238:   intended for production runs since it logs only flop rates and object
239:   creation (and shouldn't significantly slow the programs).

241:   Level: advanced

243: .keywords: log, all, begin
244: .seealso: PetscLogDump(), PetscLogBegin(), PetscLogTraceBegin()
245: @*/
246: PetscErrorCode  PetscLogAllBegin(void)
247: {

251:   PetscLogSet(PetscLogEventBeginComplete, PetscLogEventEndComplete);
252:   PetscLogBegin_Private();
253:   return(0);
254: }

258: /*@
259:   PetscLogTraceBegin - Activates trace logging.  Every time a PETSc event
260:   begins or ends, the event name is printed.

262:   Collective on PETSC_COMM_WORLD

264:   Input Parameter:
265: . file - The file to print trace in (e.g. stdout)

267:   Options Database Key:
268: . -log_trace [filename] - Activates PetscLogTraceBegin()

270:   Notes:
271:   PetscLogTraceBegin() prints the processor number, the execution time (sec),
272:   then "Event begin:" or "Event end:" followed by the event name.

274:   PetscLogTraceBegin() allows tracing of all PETSc calls, which is useful
275:   to determine where a program is hanging without running in the 
276:   debugger.  Can be used in conjunction with the -info option. 

278:   Level: intermediate

280: .seealso: PetscLogDump(), PetscLogAllBegin(), PetscLogPrintSummary(), PetscLogBegin()
281: @*/
282: PetscErrorCode  PetscLogTraceBegin(FILE *file)
283: {

287:   tracefile = file;
288:   PetscLogSet(PetscLogEventBeginTrace, PetscLogEventEndTrace);
289:   PetscLogBegin_Private();
290:   return(0);
291: }

295: /*@
296:   PetscLogActions - Determines whether actions are logged for the graphical viewer.

298:   Not Collective

300:   Input Parameter:
301: . flag - PETSC_TRUE if actions are to be logged

303:   Level: intermediate

305:   Note: Logging of actions continues to consume more memory as the program
306:   runs. Long running programs should consider turning this feature off.

308:   Options Database Keys:
309: . -log_exclude_actions - Turns off actions logging

311: .keywords: log, stage, register
312: .seealso: PetscLogStagePush(), PetscLogStagePop()
313: @*/
314: PetscErrorCode  PetscLogActions(PetscTruth flag)
315: {
317:   logActions = flag;
318:   return(0);
319: }

323: /*@
324:   PetscLogObjects - Determines whether objects are logged for the graphical viewer.

326:   Not Collective

328:   Input Parameter:
329: . flag - PETSC_TRUE if objects are to be logged

331:   Level: intermediate

333:   Note: Logging of objects continues to consume more memory as the program
334:   runs. Long running programs should consider turning this feature off.

336:   Options Database Keys:
337: . -log_exclude_objects - Turns off objects logging

339: .keywords: log, stage, register
340: .seealso: PetscLogStagePush(), PetscLogStagePop()
341: @*/
342: PetscErrorCode  PetscLogObjects(PetscTruth flag)
343: {
345:   logObjects = flag;
346:   return(0);
347: }

349: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
352: /*@C
353:   PetscLogStageRegister - Attaches a charactor string name to a logging stage.

355:   Not Collective

357:   Input Parameter:
358: . sname - The name to associate with that stage

360:   Output Parameter:
361: . stage - The stage number

363:   Level: intermediate

365: .keywords: log, stage, register
366: .seealso: PetscLogStagePush(), PetscLogStagePop()
367: @*/
368: PetscErrorCode  PetscLogStageRegister(const char sname[],PetscLogStage *stage)
369: {
370:   StageLog       stageLog;
371:   PetscLogEvent  event;

375:   PetscLogGetStageLog(&stageLog);
376:   StageLogRegister(stageLog, sname, stage);
377:   /* Copy events already changed in the main stage, this sucks */
378:   EventPerfLogEnsureSize(stageLog->stageInfo[*stage].eventLog, stageLog->eventLog->numEvents);
379:   for(event = 0; event < stageLog->eventLog->numEvents; event++) {
380:     EventPerfInfoCopy(&stageLog->stageInfo[0].eventLog->eventInfo[event],
381:                              &stageLog->stageInfo[*stage].eventLog->eventInfo[event]);
382:   }
383:   ClassPerfLogEnsureSize(stageLog->stageInfo[*stage].classLog, stageLog->classLog->numClasses);
384:   return(0);
385: }

389: /*@C
390:   PetscLogStagePush - This function pushes a stage on the stack.

392:   Not Collective

394:   Input Parameter:
395: . stage - The stage on which to log

397:   Usage:
398:   If the option -log_sumary is used to run the program containing the 
399:   following code, then 2 sets of summary data will be printed during
400:   PetscFinalize().
401: .vb
402:       PetscInitialize(int *argc,char ***args,0,0);
403:       [stage 0 of code]   
404:       PetscLogStagePush(1);
405:       [stage 1 of code]
406:       PetscLogStagePop();
407:       PetscBarrier(...);
408:       [more stage 0 of code]   
409:       PetscFinalize();
410: .ve
411:  
412:   Notes:
413:   Use PetscLogStageRegister() to register a stage.

415:   Level: intermediate

417: .keywords: log, push, stage
418: .seealso: PetscLogStagePop(), PetscLogStageRegister(), PetscBarrier()
419: @*/
420: PetscErrorCode  PetscLogStagePush(PetscLogStage stage)
421: {
422:   StageLog       stageLog;

426:   PetscLogGetStageLog(&stageLog);
427:   StageLogPush(stageLog, stage);
428:   return(0);
429: }

433: /*@C
434:   PetscLogStagePop - This function pops a stage from the stack.

436:   Not Collective

438:   Usage:
439:   If the option -log_sumary is used to run the program containing the 
440:   following code, then 2 sets of summary data will be printed during
441:   PetscFinalize().
442: .vb
443:       PetscInitialize(int *argc,char ***args,0,0);
444:       [stage 0 of code]   
445:       PetscLogStagePush(1);
446:       [stage 1 of code]
447:       PetscLogStagePop();
448:       PetscBarrier(...);
449:       [more stage 0 of code]   
450:       PetscFinalize();
451: .ve

453:   Notes:  
454:   Use PetscLogStageRegister() to register a stage.

456:   Level: intermediate

458: .keywords: log, pop, stage
459: .seealso: PetscLogStagePush(), PetscLogStageRegister(), PetscBarrier()
460: @*/
461: PetscErrorCode  PetscLogStagePop(void)
462: {
463:   StageLog       stageLog;

467:   PetscLogGetStageLog(&stageLog);
468:   StageLogPop(stageLog);
469:   return(0);
470: }

474: /*@
475:   PetscLogStageSetActive - Determines stage activity for PetscLogEventBegin() and PetscLogEventEnd().

477:   Not Collective 

479:   Input Parameters:
480: + stage    - The stage
481: - isActive - The activity flag, PETSC_TRUE for logging, else PETSC_FALSE (defaults to PETSC_TRUE)

483:   Level: intermediate

485: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogEventBegin(), PetscLogEventEnd(), PreLoadBegin(), PreLoadEnd(), PreLoadStage()
486: @*/
487: PetscErrorCode  PetscLogStageSetActive(PetscLogStage stage, PetscTruth isActive)
488: {
489:   StageLog       stageLog;

493:   PetscLogGetStageLog(&stageLog);
494:   StageLogSetActive(stageLog, stage, isActive);
495:   return(0);
496: }

500: /*@
501:   PetscLogStageGetActive - Returns stage activity for PetscLogEventBegin() and PetscLogEventEnd().

503:   Not Collective 

505:   Input Parameter:
506: . stage    - The stage

508:   Output Parameter:
509: . isActive - The activity flag, PETSC_TRUE for logging, else PETSC_FALSE (defaults to PETSC_TRUE)

511:   Level: intermediate

513: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogEventBegin(), PetscLogEventEnd(), PreLoadBegin(), PreLoadEnd(), PreLoadStage()
514: @*/
515: PetscErrorCode  PetscLogStageGetActive(PetscLogStage stage, PetscTruth *isActive)
516: {
517:   StageLog       stageLog;

521:   PetscLogGetStageLog(&stageLog);
522:   StageLogGetActive(stageLog, stage, isActive);
523:   return(0);
524: }

528: /*@
529:   PetscLogStageSetVisible - Determines stage visibility in PetscLogPrintSummary()

531:   Not Collective 

533:   Input Parameters:
534: + stage     - The stage
535: - isVisible - The visibility flag, PETSC_TRUE to print, else PETSC_FALSE (defaults to PETSC_TRUE)

537:   Level: intermediate

539: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogPrintSummary()
540: @*/
541: PetscErrorCode  PetscLogStageSetVisible(PetscLogStage stage, PetscTruth isVisible)
542: {
543:   StageLog       stageLog;

547:   PetscLogGetStageLog(&stageLog);
548:   StageLogSetVisible(stageLog, stage, isVisible);
549:   return(0);
550: }

554: /*@
555:   PetscLogStageGetVisible - Returns stage visibility in PetscLogPrintSummary()

557:   Not Collective 

559:   Input Parameter:
560: . stage     - The stage

562:   Output Parameter:
563: . isVisible - The visibility flag, PETSC_TRUE to print, else PETSC_FALSE (defaults to PETSC_TRUE)

565:   Level: intermediate

567: .seealso: PetscLogStagePush(), PetscLogStagePop(), PetscLogPrintSummary()
568: @*/
569: PetscErrorCode  PetscLogStageGetVisible(PetscLogStage stage, PetscTruth *isVisible)
570: {
571:   StageLog       stageLog;

575:   PetscLogGetStageLog(&stageLog);
576:   StageLogGetVisible(stageLog, stage, isVisible);
577:   return(0);
578: }

582: /*@C
583:   PetscLogStageGetId - Returns the stage id when given the stage name.

585:   Not Collective 

587:   Input Parameter:
588: . name  - The stage name

590:   Output Parameter:
591: . stage - The stage

593:   Level: intermediate

595: .seealso: PetscLogStagePush(), PetscLogStagePop(), PreLoadBegin(), PreLoadEnd(), PreLoadStage()
596: @*/
597: PetscErrorCode  PetscLogStageGetId(const char name[], PetscLogStage *stage)
598: {
599:   StageLog       stageLog;

603:   PetscLogGetStageLog(&stageLog);
604:   StageLogGetStage(stageLog, name, stage);
605:   return(0);
606: }

608: /*------------------------------------------------ Event Functions --------------------------------------------------*/
611: /*@C
612:   PetscLogEventRegister - Registers an event name for logging operations in an application code. 

614:   Not Collective

616:   Input Parameter:
617: + name   - The name associated with the event
618: - cookie - The cookie associated to the class for this event, obtain either with
619:            PetscCookieRegister() or use a predefined one such as KSP_COOKIE, SNES_COOKIE
620:             
621:   Output Parameter:
622: . event - The event id for use with PetscLogEventBegin() and PetscLogEventEnd().

624:   Example of Usage:
625: .vb
626:       PetscLogEvent USER_EVENT;
627:       PetscCookie cookie;
628:       int user_event_flops;
629:       PetscCookieRegister("class name",&cookie);
630:       PetscLogEventRegister("User event name",cookie,&USER_EVENT);
631:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
632:          [code segment to monitor]
633:          PetscLogFlops(user_event_flops);
634:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
635: .ve

637:   Notes: 
638:   PETSc automatically logs library events if the code has been
639:   compiled with -DPETSC_USE_LOG (which is the default) and -log,
640:   -log_summary, or -log_all are specified.  PetscLogEventRegister() is
641:   intended for logging user events to supplement this PETSc
642:   information. 

644:   PETSc can gather data for use with the utilities Upshot/Nupshot
645:   (part of the MPICH distribution).  If PETSc has been compiled
646:   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
647:   MPICH), the user can employ another command line option, -log_mpe,
648:   to create a logfile, "mpe.log", which can be visualized
649:   Upshot/Nupshot. 

651:   The cookie is associated with each event so that classes of events
652:   can be disabled simultaneously, such as all matrix events. The user
653:   can either use an existing cookie, such as MAT_COOKIE, or create
654:   their own as shown in the example.

656:   Level: intermediate

658: .keywords: log, event, register
659: .seealso: PetscLogEventBegin(), PetscLogEventEnd(), PetscLogFlops(),
660:           PetscLogEventMPEActivate(), PetscLogEventMPEDeactivate(),
661:           PetscLogEventActivate(), PetscLogEventDeactivate(), PetscCookieRegister()
662: @*/
663: PetscErrorCode  PetscLogEventRegister(const char name[],PetscCookie cookie,PetscLogEvent *event)
664: {
665:   StageLog       stageLog;
666:   int            stage;

670:   *event = PETSC_DECIDE;
671:   PetscLogGetStageLog(&stageLog);
672:   EventRegLogRegister(stageLog->eventLog, name, cookie, event);
673:   for(stage = 0; stage < stageLog->numStages; stage++) {
674:     EventPerfLogEnsureSize(stageLog->stageInfo[stage].eventLog, stageLog->eventLog->numEvents);
675:     ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
676:   }
677:   return(0);
678: }

682: /*@
683:   PetscLogEventActivate - Indicates that a particular event should be logged.

685:   Not Collective

687:   Input Parameter:
688: . event - The event id

690:   Usage:
691: .vb
692:       PetscLogEventDeactivate(VEC_SetValues);
693:         [code where you do not want to log VecSetValues()]
694:       PetscLogEventActivate(VEC_SetValues);
695:         [code where you do want to log VecSetValues()]
696: .ve 

698:   Note:
699:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
700:   or an event number obtained with PetscLogEventRegister().

702:   Level: advanced

704: .keywords: log, event, activate
705: .seealso: PetscLogEventMPEDeactivate(),PetscLogEventMPEActivate(),PlogEventDeactivate()
706: @*/
707: PetscErrorCode  PetscLogEventActivate(PetscLogEvent event)
708: {
709:   StageLog       stageLog;
710:   int            stage;

714:   PetscLogGetStageLog(&stageLog);
715:   StageLogGetCurrent(stageLog, &stage);
716:   EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
717:   return(0);
718: }

722: /*@
723:   PetscLogEventDeactivate - Indicates that a particular event should not be logged. 

725:   Not Collective

727:   Input Parameter:
728: . event - The event id

730:   Usage:
731: .vb
732:       PetscLogEventDeactivate(VEC_SetValues);
733:         [code where you do not want to log VecSetValues()]
734:       PetscLogEventActivate(VEC_SetValues);
735:         [code where you do want to log VecSetValues()]
736: .ve 

738:   Note: 
739:   The event may be either a pre-defined PETSc event (found in
740:   include/petsclog.h) or an event number obtained with PetscLogEventRegister()).

742:   Level: advanced

744: .keywords: log, event, deactivate
745: .seealso: PetscLogEventMPEDeactivate(),PetscLogEventMPEActivate(),PlogEventActivate()
746: @*/
747: PetscErrorCode  PetscLogEventDeactivate(PetscLogEvent event)
748: {
749:   StageLog       stageLog;
750:   int            stage;

754:   PetscLogGetStageLog(&stageLog);
755:   StageLogGetCurrent(stageLog, &stage);
756:   EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
757:   return(0);
758: }

762: /*@
763:   PetscLogEventSetActiveAll - Sets the event activity in every stage.

765:   Not Collective

767:   Input Parameters:
768: + event    - The event id
769: - isActive - The activity flag determining whether the event is logged

771:   Level: advanced

773: .keywords: log, event, activate
774: .seealso: PetscLogEventMPEDeactivate(),PetscLogEventMPEActivate(),PlogEventActivate(),PlogEventDeactivate()
775: @*/
776: PetscErrorCode  PetscLogEventSetActiveAll(PetscLogEvent event, PetscTruth isActive)
777: {
778:   StageLog       stageLog;
779:   int            stage;

783:   PetscLogGetStageLog(&stageLog);
784:   for(stage = 0; stage < stageLog->numStages; stage++) {
785:     if (isActive) {
786:       EventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event);
787:     } else {
788:       EventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event);
789:     }
790:   }
791:   return(0);
792: }

796: /*@
797:   PetscLogEventActivateClass - Activates event logging for a PETSc object class.

799:   Not Collective

801:   Input Parameter:
802: . cookie - The event class, for example MAT_COOKIE, SNES_COOKIE, etc.

804:   Level: developer

806: .keywords: log, event, activate, class
807: .seealso: PetscInfoActivate(),PetscInfo(),PetscInfoAllow(),PetscLogEventDeactivateClass(), PetscLogEventActivate(),PetscLogEventDeactivate()
808: @*/
809: PetscErrorCode  PetscLogEventActivateClass(PetscCookie cookie)
810: {
811:   StageLog       stageLog;
812:   int            stage;

816:   PetscLogGetStageLog(&stageLog);
817:   StageLogGetCurrent(stageLog, &stage);
818:   EventPerfLogActivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, cookie);
819:   return(0);
820: }

824: /*@
825:   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class.

827:   Not Collective

829:   Input Parameter:
830: . cookie - The event class, for example MAT_COOKIE, SNES_COOKIE, etc.

832:   Level: developer

834: .keywords: log, event, deactivate, class
835: .seealso: PetscInfoActivate(),PetscInfo(),PetscInfoAllow(),PetscLogEventActivateClass(), PetscLogEventActivate(),PetscLogEventDeactivate()
836: @*/
837: PetscErrorCode  PetscLogEventDeactivateClass(PetscCookie cookie)
838: {
839:   StageLog       stageLog;
840:   int            stage;

844:   PetscLogGetStageLog(&stageLog);
845:   StageLogGetCurrent(stageLog, &stage);
846:   EventPerfLogDeactivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, cookie);
847:   return(0);
848: }

850: /*MC
851:    PetscLogEventBegin - Logs the beginning of a user event. 

853:    Input Parameters:
854: +  e - integer associated with the event obtained from PetscLogEventRegister()
855: -  o1,o2,o3,o4 - objects associated with the event, or 0

857:    Synopsis:
858:    void PetscLogEventBegin(int e,PetscObject o1,PetscObject o2,PetscObject o3,
859:                        PetscObject o4)

861:    Fortran Synopsis:
862:    void PetscLogEventEnd(int e,PetscErrorCode ierr)

864:    Usage:
865: .vb
866:      int USER_EVENT;
867:      int user_event_flops;
868:      PetscLogEventRegister("User event",0,&USER_EVENT);
869:      PetscLogEventBegin(USER_EVENT,0,0,0,0);
870:         [code segment to monitor]
871:         PetscLogFlops(user_event_flops);
872:      PetscLogEventEnd(USER_EVENT,0,0,0,0);
873: .ve

875:    Notes:
876:    You need to register each integer event with the command 
877:    PetscLogEventRegister().  The source code must be compiled with 
878:    -DPETSC_USE_LOG, which is the default.

880:    PETSc automatically logs library events if the code has been
881:    compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
882:    specified.  PetscLogEventBegin() is intended for logging user events
883:    to supplement this PETSc information.

885:    Level: intermediate

887: .seealso: PetscLogEventRegister(), PetscLogEventEnd(), PetscLogFlops()

889: .keywords: log, event, begin
890: M*/

892: /*MC
893:    PetscLogEventEnd - Log the end of a user event.

895:    Input Parameters:
896: +  e - integer associated with the event obtained with PetscLogEventRegister()
897: -  o1,o2,o3,o4 - objects associated with the event, or 0

899:    Synopsis:
900:    void PetscLogEventEnd(int e,PetscObject o1,PetscObject o2,PetscObject o3,
901:                      PetscObject o4)

903:    Fortran Synopsis:
904:    void PetscLogEventEnd(int e,PetscErrorCode ierr)

906:    Usage:
907: .vb
908:      int USER_EVENT;
909:      int user_event_flops;
910:      PetscLogEventRegister("User event",0,&USER_EVENT,);
911:      PetscLogEventBegin(USER_EVENT,0,0,0,0);
912:         [code segment to monitor]
913:         PetscLogFlops(user_event_flops);
914:      PetscLogEventEnd(USER_EVENT,0,0,0,0);
915: .ve

917:    Notes:
918:    You should also register each additional integer event with the command 
919:    PetscLogEventRegister(). Source code must be compiled with 
920:    -DPETSC_USE_LOG, which is the default.

922:    PETSc automatically logs library events if the code has been
923:    compiled with -DPETSC_USE_LOG, and -log, -log_summary, or -log_all are
924:    specified.  PetscLogEventEnd() is intended for logging user events
925:    to supplement this PETSc information.

927:    Level: intermediate

929: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogFlops()

931: .keywords: log, event, end
932: M*/

934: /*MC
935:    PetscLogEventBarrierBegin - Logs the time in a barrier before an event.

937:    Input Parameters:
938: .  e - integer associated with the event obtained from PetscLogEventRegister()
939: .  o1,o2,o3,o4 - objects associated with the event, or 0
940: .  comm - communicator the barrier takes place over

942:    Synopsis:
943:    void PetscLogEventBarrierBegin(int e,PetscObject o1,PetscObject o2,PetscObject o3,
944:                   PetscObject o4,MPI_Comm comm)

946:    Usage:
947: .vb
948:      PetscLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
949:        MPI_Allreduce()
950:      PetscLogEventBarrierEnd(VEC_NormBarrier,0,0,0,0,comm);
951: .ve

953:    Notes:
954:    This is for logging the amount of time spent in a barrier for an event
955:    that requires synchronization. 

957:    Additional Notes:
958:    Synchronization events always come in pairs; for example, VEC_NormBarrier and 
959:    VEC_NormComm = VEC_NormBarrier + 1

961:    Level: advanced

963: .seealso: PetscLogEventRegister(), PetscLogEventEnd(), PetscLogFlops(), PetscLogEventBegin(),
964:           PetscLogEventBarrierEnd()

966: .keywords: log, event, begin, barrier
967: M*/

969: /*MC
970:    PetscLogEventBarrierEnd - Logs the time in a barrier before an event.

972:    Input Parameters:
973: .  e - integer associated with the event obtained from PetscLogEventRegister()
974: .  o1,o2,o3,o4 - objects associated with the event, or 0
975: .  comm - communicator the barrier takes place over

977:    Synopsis:
978:    void PetscLogEventBarrierEnd(int e,PetscObject o1,PetscObject o2,PetscObject o3,
979:                   PetscObject o4,MPI_Comm comm)

981:     Usage:
982: .vb
983:      PetscLogEventBarrierBegin(VEC_NormBarrier,0,0,0,0,comm);
984:        MPI_Allreduce()
985:      PetscLogEventBarrierEnd(VEC_NormBarrier,0,0,0,0,comm);
986: .ve

988:    Notes:
989:    This is for logging the amount of time spent in a barrier for an event
990:    that requires synchronization. 

992:    Additional Notes:
993:    Synchronization events always come in pairs; for example, VEC_NormBarrier and 
994:    VEC_NormComm = VEC_NormBarrier + 1

996:    Level: advanced

998: .seealso: PetscLogEventRegister(), PetscLogEventEnd(), PetscLogFlops(), PetscLogEventBegin(),
999:           PetscLogEventBarrierBegin()

1001: .keywords: log, event, begin, barrier
1002: M*/

1006: /*@C
1007:   PetscLogEventGetId - Returns the event id when given the event name.

1009:   Not Collective 

1011:   Input Parameter:
1012: . name  - The event name

1014:   Output Parameter:
1015: . event - The event

1017:   Level: intermediate

1019: .seealso: PetscLogEventBegin(), PetscLogEventEnd(), PetscLogStageGetId()
1020: @*/
1021: PetscErrorCode  PetscLogEventGetId(const char name[], PetscLogEvent *event)
1022: {
1023:   StageLog       stageLog;

1027:   PetscLogGetStageLog(&stageLog);
1028:   EventRegLogGetEvent(stageLog->eventLog, name, event);
1029:   return(0);
1030: }


1033: /*------------------------------------------------ Output Functions -------------------------------------------------*/
1036: /*@C
1037:   PetscLogDump - Dumps logs of objects to a file. This file is intended to 
1038:   be read by petsc/bin/petscview.

1040:   Collective on PETSC_COMM_WORLD

1042:   Input Parameter:
1043: . name - an optional file name

1045:   Options Database Keys:
1046: + -log     - Prints basic log information (for code compiled with PETSC_USE_LOG)
1047: - -log_all - Prints extensive log information (for code compiled with PETSC_USE_LOG)
1048:    
1049:   Usage:
1050: .vb
1051:      PetscInitialize(...);
1052:      PetscLogBegin(); or PetscLogAllBegin(); 
1053:      ... code ...
1054:      PetscLogDump(filename);
1055:      PetscFinalize();
1056: .ve

1058:   Notes:
1059:   The default file name is 
1060: $    Log.<rank>
1061:   where <rank> is the processor number. If no name is specified, 
1062:   this file will be used.

1064:   Level: advanced

1066: .keywords: log, dump
1067: .seealso: PetscLogBegin(), PetscLogAllBegin(), PetscLogPrintSummary()
1068: @*/
1069: PetscErrorCode  PetscLogDump(const char sname[])
1070: {
1071:   StageLog       stageLog;
1072:   EventPerfInfo *eventInfo;
1073:   FILE          *fd;
1074:   char           file[PETSC_MAX_PATH_LEN], fname[PETSC_MAX_PATH_LEN];
1075:   PetscLogDouble flops, _TotalTime;
1076:   PetscMPIInt    rank;
1077:   int            action, object, curStage;
1078:   PetscLogEvent  event;
1080: 
1082:   /* Calculate the total elapsed time */
1083:   PetscTime(_TotalTime);
1084:   _TotalTime -= BaseTime;
1085:   /* Open log file */
1086:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1087:   if (sname) {
1088:     sprintf(file, "%s.%d", sname, rank);
1089:   } else {
1090:     sprintf(file, "Log.%d", rank);
1091:   }
1092:   PetscFixFilename(file, fname);
1093:   PetscFOpen(PETSC_COMM_WORLD, fname, "w", &fd);
1094:   if ((!rank) && (!fd)) SETERRQ1(PETSC_ERR_FILE_OPEN, "Cannot open file: %s", fname);
1095:   /* Output totals */
1096:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Total Flops %14e %16.8e\n", _TotalFlops, _TotalTime);
1097:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Clock Resolution %g\n", 0.0);
1098:   /* Output actions */
1099:   if (logActions) {
1100:     PetscFPrintf(PETSC_COMM_WORLD, fd, "Actions accomplished %d\n", numActions);
1101:     for(action = 0; action < numActions; action++) {
1102:       PetscFPrintf(PETSC_COMM_WORLD, fd, "%g %d %d %d %d %d %d %g %g %g\n",
1103:                           actions[action].time, actions[action].action, (int)actions[action].event, (int)actions[action].cookie, actions[action].id1,
1104:                           actions[action].id2, actions[action].id3, actions[action].flops, actions[action].mem, actions[action].maxmem);
1105:     }
1106:   }
1107:   /* Output objects */
1108:   if (logObjects) {
1109:     PetscFPrintf(PETSC_COMM_WORLD, fd, "Objects created %d destroyed %d\n", numObjects, numObjectsDestroyed);
1110:     for(object = 0; object < numObjects; object++) {
1111:       PetscFPrintf(PETSC_COMM_WORLD, fd, "Parent ID: %d Memory: %d\n", objects[object].parent, (int) objects[object].mem);
1112:       if (!objects[object].name[0]) {
1113:         PetscFPrintf(PETSC_COMM_WORLD, fd,"No Name\n");
1114:       } else {
1115:         PetscFPrintf(PETSC_COMM_WORLD, fd, "Name: %s\n", objects[object].name);
1116:       }
1117:       if (objects[object].info[0] != 0) {
1118:         PetscFPrintf(PETSC_COMM_WORLD, fd, "No Info\n");
1119:       } else {
1120:         PetscFPrintf(PETSC_COMM_WORLD, fd, "Info: %s\n", objects[object].info);
1121:       }
1122:     }
1123:   }
1124:   /* Output events */
1125:   PetscFPrintf(PETSC_COMM_WORLD, fd, "Event log:\n");
1126:   PetscLogGetStageLog(&stageLog);
1127:   StackTop(stageLog->stack, &curStage);
1128:   eventInfo = stageLog->stageInfo[curStage].eventLog->eventInfo;
1129:   for(event = 0; event < stageLog->stageInfo[curStage].eventLog->numEvents; event++) {
1130:     if (eventInfo[event].time != 0.0) {
1131:       flops = eventInfo[event].flops/eventInfo[event].time;
1132:     } else {
1133:       flops = 0.0;
1134:     }
1135:     PetscFPrintf(PETSC_COMM_WORLD, fd, "%d %16d %16g %16g %16g\n", event, eventInfo[event].count,
1136:                         eventInfo[event].flops, eventInfo[event].time, flops);
1137:   }
1138:   PetscFClose(PETSC_COMM_WORLD, fd);
1139:   return(0);
1140: }

1144: /*@C
1145:   PetscLogPrintSummary - Prints a summary of the logging.

1147:   Collective over MPI_Comm

1149:   Input Parameter:
1150: + comm - The MPI communicator (only one processor prints output)
1151: - file - [Optional] The output file name

1153:   Options Database Keys:
1154: . -log_summary - Prints summary of log information (for code compiled with PETSC_USE_LOG)

1156:   Usage:
1157: .vb
1158:      PetscInitialize(...);
1159:      PetscLogBegin();
1160:      ... code ...
1161:      PetscLogPrintSummary(MPI_Comm,filename);
1162:      PetscFinalize(...);
1163: .ve

1165:   Notes:
1166:   By default the summary is printed to stdout.

1168:   Level: beginner
1169:    
1170: .keywords: log, dump, print
1171: .seealso: PetscLogBegin(), PetscLogDump()
1172: @*/
1173: PetscErrorCode  PetscLogPrintSummary(MPI_Comm comm, const char filename[])
1174: {
1175:   FILE           *fd = PETSC_STDOUT;
1176:   PetscLogDouble zero = 0.0;
1177:   StageLog       stageLog;
1178:   StageInfo     *stageInfo = PETSC_NULL;
1179:   EventPerfInfo *eventInfo = PETSC_NULL;
1180:   ClassPerfInfo *classInfo;
1181:   char           arch[10], hostname[64], username[16], pname[PETSC_MAX_PATH_LEN], date[64];
1182:   const char    *name;
1183:   PetscLogDouble locTotalTime, TotalTime, TotalFlops;
1184:   PetscLogDouble numMessages, messageLength, avgMessLen, numReductions;
1185:   PetscLogDouble stageTime, flops, flopr, mem, mess, messLen, red;
1186:   PetscLogDouble fracTime, fracFlops, fracMessages, fracLength, fracReductions, fracMess, fracMessLen, fracRed;
1187:   PetscLogDouble fracStageTime, fracStageFlops, fracStageMess, fracStageMessLen, fracStageRed;
1188:   PetscLogDouble min, max, tot, ratio, avg, x, y;
1189:   PetscLogDouble minf, maxf, totf, ratf, mint, maxt, tott, ratt, ratCt, totm, totml, totr;
1190:   PetscMPIInt    minCt, maxCt;
1191:   PetscMPIInt    size, rank;
1192:   PetscTruth    *localStageUsed,    *stageUsed;
1193:   PetscTruth    *localStageVisible, *stageVisible;
1194:   int            numStages, localNumEvents, numEvents;
1195:   int            stage, lastStage, oclass;
1196:   PetscLogEvent  event;
1198:   char           version[256];

1201:   MPI_Comm_size(comm, &size);
1202:   MPI_Comm_rank(comm, &rank);
1203:   /* Pop off any stages the user forgot to remove */
1204:   lastStage = 0;
1205:   PetscLogGetStageLog(&stageLog);
1206:   StageLogGetCurrent(stageLog, &stage);
1207:   while (stage >= 0) {
1208:     lastStage = stage;
1209:     StageLogPop(stageLog);
1210:     StageLogGetCurrent(stageLog, &stage);
1211:   }
1212:   /* Get the total elapsed time */
1213:   PetscTime(locTotalTime);  locTotalTime -= BaseTime;
1214:   /* Open the summary file */
1215:   if (filename) {
1216:     PetscFOpen(comm, filename, "w", &fd);
1217:   }

1219:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1220:   PetscFPrintf(comm, fd, "***             WIDEN YOUR WINDOW TO 120 CHARACTERS.  Use 'enscript -r -fCourier9' to print this document            ***\n");
1221:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1222:   PetscFPrintf(comm, fd, "\n---------------------------------------------- PETSc Performance Summary: ----------------------------------------------\n\n");
1223:   PetscGetArchType(arch, 10);
1224:   PetscGetHostName(hostname, 64);
1225:   PetscGetUserName(username, 16);
1226:   PetscGetProgramName(pname, PETSC_MAX_PATH_LEN);
1227:   PetscGetDate(date, 64);
1228:   PetscGetVersion(version,256);
1229:   if (size == 1) {
1230:     PetscFPrintf(comm,fd,"%s on a %s named %s with %d processor, by %s %s\n", pname, arch, hostname, size, username, date);
1231:   } else {
1232:     PetscFPrintf(comm,fd,"%s on a %s named %s with %d processors, by %s %s\n", pname, arch, hostname, size, username, date);
1233:   }
1234:   PetscFPrintf(comm, fd, "Using %s\n", version);

1236:   /* Must preserve reduction count before we go on */
1237:   red  = allreduce_ct + gather_ct + scatter_ct;

1239:   /* Calculate summary information */
1240:   PetscFPrintf(comm, fd, "\n                         Max       Max/Min        Avg      Total \n");
1241:   /*   Time */
1242:   MPI_Allreduce(&locTotalTime, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1243:   MPI_Allreduce(&locTotalTime, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1244:   MPI_Allreduce(&locTotalTime, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1245:   avg  = (tot)/((PetscLogDouble) size);
1246:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1247:   PetscFPrintf(comm, fd, "Time (sec):           %5.3e   %10.5f   %5.3e\n", max, ratio, avg);
1248:   TotalTime = tot;
1249:   /*   Objects */
1250:   avg  = (PetscLogDouble) numObjects;
1251:   MPI_Allreduce(&avg,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1252:   MPI_Allreduce(&avg,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1253:   MPI_Allreduce(&avg,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1254:   avg  = (tot)/((PetscLogDouble) size);
1255:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1256:   PetscFPrintf(comm, fd, "Objects:              %5.3e   %10.5f   %5.3e\n", max, ratio, avg);
1257:   /*   Flops */
1258:   MPI_Allreduce(&_TotalFlops,  &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1259:   MPI_Allreduce(&_TotalFlops,  &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1260:   MPI_Allreduce(&_TotalFlops,  &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1261:   avg  = (tot)/((PetscLogDouble) size);
1262:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1263:   PetscFPrintf(comm, fd, "Flops:                %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1264:   TotalFlops = tot;
1265:   /*   Flops/sec -- Must talk to Barry here */
1266:   if (locTotalTime != 0.0) flops = _TotalFlops/locTotalTime; else flops = 0.0;
1267:   MPI_Allreduce(&flops,        &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1268:   MPI_Allreduce(&flops,        &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1269:   MPI_Allreduce(&flops,        &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1270:   avg  = (tot)/((PetscLogDouble) size);
1271:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1272:   PetscFPrintf(comm, fd, "Flops/sec:            %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1273:   /*   Memory */
1274:   PetscMallocGetMaximumUsage(&mem);
1275:   if (mem > 0.0) {
1276:     MPI_Allreduce(&mem,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1277:     MPI_Allreduce(&mem,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1278:     MPI_Allreduce(&mem,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1279:     avg  = (tot)/((PetscLogDouble) size);
1280:     if (min != 0.0) ratio = max/min; else ratio = 0.0;
1281:     PetscFPrintf(comm, fd, "Memory:               %5.3e   %10.5f              %5.3e\n", max, ratio, tot);
1282:   }
1283:   /*   Messages */
1284:   mess = 0.5*(irecv_ct + isend_ct + recv_ct + send_ct);
1285:   MPI_Allreduce(&mess,         &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1286:   MPI_Allreduce(&mess,         &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1287:   MPI_Allreduce(&mess,         &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1288:   avg  = (tot)/((PetscLogDouble) size);
1289:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1290:   PetscFPrintf(comm, fd, "MPI Messages:         %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1291:   numMessages = tot;
1292:   /*   Message Lengths */
1293:   mess = 0.5*(irecv_len + isend_len + recv_len + send_len);
1294:   MPI_Allreduce(&mess,         &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1295:   MPI_Allreduce(&mess,         &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1296:   MPI_Allreduce(&mess,         &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1297:   if (numMessages != 0) avg = (tot)/(numMessages); else avg = 0.0;
1298:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1299:   PetscFPrintf(comm, fd, "MPI Message Lengths:  %5.3e   %10.5f   %5.3e  %5.3e\n", max, ratio, avg, tot);
1300:   messageLength = tot;
1301:   /*   Reductions */
1302:   MPI_Allreduce(&red,          &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1303:   MPI_Allreduce(&red,          &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1304:   MPI_Allreduce(&red,          &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1305:   if (min != 0.0) ratio = max/min; else ratio = 0.0;
1306:   PetscFPrintf(comm, fd, "MPI Reductions:       %5.3e   %10.5f\n", max, ratio);
1307:   numReductions = red; /* wrong because uses count from process zero */
1308:   PetscFPrintf(comm, fd, "\nFlop counting convention: 1 flop = 1 real number operation of type (multiply/divide/add/subtract)\n");
1309:   PetscFPrintf(comm, fd, "                            e.g., VecAXPY() for real vectors of length N --> 2N flops\n");
1310:   PetscFPrintf(comm, fd, "                            and VecAXPY() for complex vectors of length N --> 8N flops\n");

1312:   /* Get total number of stages --
1313:        Currently, a single processor can register more stages than another, but stages must all be registered in order.
1314:        We can removed this requirement if necessary by having a global stage numbering and indirection on the stage ID.
1315:        This seems best accomplished by assoicating a communicator with each stage.
1316:   */
1317:   MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm);
1318:   PetscMalloc(numStages * sizeof(PetscTruth), &localStageUsed);
1319:   PetscMalloc(numStages * sizeof(PetscTruth), &stageUsed);
1320:   PetscMalloc(numStages * sizeof(PetscTruth), &localStageVisible);
1321:   PetscMalloc(numStages * sizeof(PetscTruth), &stageVisible);
1322:   if (numStages > 0) {
1323:     stageInfo = stageLog->stageInfo;
1324:     for(stage = 0; stage < numStages; stage++) {
1325:       if (stage < stageLog->numStages) {
1326:         localStageUsed[stage]    = stageInfo[stage].used;
1327:         localStageVisible[stage] = stageInfo[stage].perfInfo.visible;
1328:       } else {
1329:         localStageUsed[stage]    = PETSC_FALSE;
1330:         localStageVisible[stage] = PETSC_TRUE;
1331:       }
1332:     }
1333:     MPI_Allreduce(localStageUsed,    stageUsed,    numStages, MPI_INT, MPI_LOR,  comm);
1334:     MPI_Allreduce(localStageVisible, stageVisible, numStages, MPI_INT, MPI_LAND, comm);
1335:     for(stage = 0; stage < numStages; stage++) {
1336:       if (stageUsed[stage]) {
1337:         PetscFPrintf(comm, fd, "\nSummary of Stages:   ----- Time ------  ----- Flops -----  --- Messages ---  -- Message Lengths --  -- Reductions --\n");
1338:         PetscFPrintf(comm, fd, "                        Avg     %%Total     Avg     %%Total   counts   %%Total     Avg         %%Total   counts   %%Total \n");
1339:         break;
1340:       }
1341:     }
1342:     for(stage = 0; stage < numStages; stage++) {
1343:       if (!stageUsed[stage]) continue;
1344:       if (localStageUsed[stage]) {
1345:         MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1346:         MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1347:         MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1348:         MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1349:         MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1350:         name = stageInfo[stage].name;
1351:       } else {
1352:         MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1353:         MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1354:         MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1355:         MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1356:         MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1357:         name = "";
1358:       }
1359:       mess *= 0.5; messLen *= 0.5; red /= size;
1360:       if (TotalTime     != 0.0) fracTime       = stageTime/TotalTime;    else fracTime       = 0.0;
1361:       if (TotalFlops    != 0.0) fracFlops      = flops/TotalFlops;       else fracFlops      = 0.0;
1362:       /* Talk to Barry if (stageTime     != 0.0) flops          = (size*flops)/stageTime; else flops          = 0.0; */
1363:       if (numMessages   != 0.0) fracMessages   = mess/numMessages;       else fracMessages   = 0.0;
1364:       if (numMessages   != 0.0) avgMessLen     = messLen/numMessages;    else avgMessLen     = 0.0;
1365:       if (messageLength != 0.0) fracLength     = messLen/messageLength;  else fracLength     = 0.0;
1366:       if (numReductions != 0.0) fracReductions = red/numReductions;      else fracReductions = 0.0;
1367:       PetscFPrintf(comm, fd, "%2d: %15s: %6.4e %5.1f%%  %6.4e %5.1f%%  %5.3e %5.1f%%  %5.3e      %5.1f%%  %5.3e %5.1f%% \n",
1368:                           stage, name, stageTime/size, 100.0*fracTime, flops, 100.0*fracFlops,
1369:                           mess, 100.0*fracMessages, avgMessLen, 100.0*fracLength, red, 100.0*fracReductions);
1370:     }
1371:   }

1373:   PetscFPrintf(comm, fd,
1374:     "\n------------------------------------------------------------------------------------------------------------------------\n");
1375: 
1376:   PetscFPrintf(comm, fd, "See the 'Profiling' chapter of the users' manual for details on interpreting output.\n");
1377:   PetscFPrintf(comm, fd, "Phase summary info:\n");
1378:   PetscFPrintf(comm, fd, "   Count: number of times phase was executed\n");
1379:   PetscFPrintf(comm, fd, "   Time and Flops: Max - maximum over all processors\n");
1380:   PetscFPrintf(comm, fd, "                   Ratio - ratio of maximum to minimum over all processors\n");
1381:   PetscFPrintf(comm, fd, "   Mess: number of messages sent\n");
1382:   PetscFPrintf(comm, fd, "   Avg. len: average message length\n");
1383:   PetscFPrintf(comm, fd, "   Reduct: number of global reductions\n");
1384:   PetscFPrintf(comm, fd, "   Global: entire computation\n");
1385:   PetscFPrintf(comm, fd, "   Stage: stages of a computation. Set stages with PetscLogStagePush() and PetscLogStagePop().\n");
1386:   PetscFPrintf(comm, fd, "      %%T - percent time in this phase         %%F - percent flops in this phase\n");
1387:   PetscFPrintf(comm, fd, "      %%M - percent messages in this phase     %%L - percent message lengths in this phase\n");
1388:   PetscFPrintf(comm, fd, "      %%R - percent reductions in this phase\n");
1389:   PetscFPrintf(comm, fd, "   Total Mflop/s: 10e-6 * (sum of flops over all processors)/(max time over all processors)\n");
1390:   PetscFPrintf(comm, fd,
1391:     "------------------------------------------------------------------------------------------------------------------------\n");
1392: 

1394: #if defined(PETSC_USE_DEBUG)
1395:   PetscFPrintf(comm, fd, "\n\n");
1396:   PetscFPrintf(comm, fd, "      ##########################################################\n");
1397:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1398:   PetscFPrintf(comm, fd, "      #                          WARNING!!!                    #\n");
1399:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1400:   PetscFPrintf(comm, fd, "      #   This code was compiled with a debugging option,      #\n");
1401:   PetscFPrintf(comm, fd, "      #   To get timing results run config/configure.py        #\n");
1402:   PetscFPrintf(comm, fd, "      #   using --with-debugging=no, the performance will      #\n");
1403:   PetscFPrintf(comm, fd, "      #   be generally two or three times faster.              #\n");
1404:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1405:   PetscFPrintf(comm, fd, "      ##########################################################\n\n\n");
1406: #endif
1407: #if defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_FORTRAN_KERNELS)
1408:   PetscFPrintf(comm, fd, "\n\n");
1409:   PetscFPrintf(comm, fd, "      ##########################################################\n");
1410:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1411:   PetscFPrintf(comm, fd, "      #                          WARNING!!!                    #\n");
1412:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1413:   PetscFPrintf(comm, fd, "      #   The code for various complex numbers numerical       #\n");
1414:   PetscFPrintf(comm, fd, "      #   kernels uses C++, which generally is not well        #\n");
1415:   PetscFPrintf(comm, fd, "      #   optimized.  For performance that is about 4-5 times  #\n");
1416:   PetscFPrintf(comm, fd, "      #   faster, specify --with-fortran-kernels=generic       #\n");
1417:   PetscFPrintf(comm, fd, "      #   when running config/configure.py.                    #\n");
1418:   PetscFPrintf(comm, fd, "      #                                                        #\n");
1419:   PetscFPrintf(comm, fd, "      ##########################################################\n\n\n");
1420: #endif

1422:   /* Report events */
1423:   PetscFPrintf(comm, fd,
1424:     "Event                Count      Time (sec)     Flops                             --- Global ---  --- Stage ---   Total\n");
1425: 
1426:   PetscFPrintf(comm, fd,
1427:     "                   Max Ratio  Max     Ratio   Max  Ratio  Mess   Avg len Reduct  %%T %%F %%M %%L %%R  %%T %%F %%M %%L %%R Mflop/s\n");
1428: 
1429:   PetscFPrintf(comm,fd,
1430:     "------------------------------------------------------------------------------------------------------------------------\n");

1432: 
1433:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
1434:   for(stage = 0; stage < numStages; stage++) {
1435:     if (!stageVisible[stage]) continue;
1436:     if (localStageUsed[stage]) {
1437:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1438:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1439:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1440:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1441:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1442:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1443:     } else {
1444:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
1445:       MPI_Allreduce(&zero,                           &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1446:       MPI_Allreduce(&zero,                           &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1447:       MPI_Allreduce(&zero,                           &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1448:       MPI_Allreduce(&zero,                           &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1449:       MPI_Allreduce(&zero,                           &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1450:     }
1451:     mess *= 0.5; messLen *= 0.5; red /= size;

1453:     /* Get total number of events in this stage --
1454:        Currently, a single processor can register more events than another, but events must all be registered in order,
1455:        just like stages. We can removed this requirement if necessary by having a global event numbering and indirection
1456:        on the event ID. This seems best accomplished by assoicating a communicator with each stage.

1458:        Problem: If the event did not happen on proc 1, its name will not be available.
1459:        Problem: Event visibility is not implemented
1460:     */
1461:     if (localStageUsed[stage]) {
1462:       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
1463:       localNumEvents = stageLog->stageInfo[stage].eventLog->numEvents;
1464:     } else {
1465:       localNumEvents = 0;
1466:     }
1467:     MPI_Allreduce(&localNumEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm);
1468:     for(event = 0; event < numEvents; event++) {
1469:       if (localStageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents) && (eventInfo[event].depth == 0)) {
1470:         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) {
1471:           flopr = eventInfo[event].flops;
1472:         } else {
1473:           flopr = 0.0;
1474:         }
1475:         MPI_Allreduce(&flopr,                          &minf,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1476:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1477:         MPI_Allreduce(&eventInfo[event].flops,         &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1478:         MPI_Allreduce(&eventInfo[event].time,          &mint,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1479:         MPI_Allreduce(&eventInfo[event].time,          &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1480:         MPI_Allreduce(&eventInfo[event].time,          &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1481:         MPI_Allreduce(&eventInfo[event].numMessages,   &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1482:         MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1483:         MPI_Allreduce(&eventInfo[event].numReductions, &totr,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1484:         MPI_Allreduce(&eventInfo[event].count,         &minCt, 1, MPI_INT,             MPI_MIN, comm);
1485:         MPI_Allreduce(&eventInfo[event].count,         &maxCt, 1, MPI_INT,             MPI_MAX, comm);
1486:         name = stageLog->eventLog->eventInfo[event].name;
1487:       } else {
1488:         flopr = 0.0;
1489:         MPI_Allreduce(&flopr,                          &minf,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1490:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1491:         MPI_Allreduce(&zero,                           &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1492:         MPI_Allreduce(&zero,                           &mint,  1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm);
1493:         MPI_Allreduce(&zero,                           &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm);
1494:         MPI_Allreduce(&zero,                           &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1495:         MPI_Allreduce(&zero,                           &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1496:         MPI_Allreduce(&zero,                           &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1497:         MPI_Allreduce(&zero,                           &totr,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm);
1498:         MPI_Allreduce(&ierr,                           &minCt, 1, MPI_INT,             MPI_MIN, comm);
1499:         MPI_Allreduce(&ierr,                           &maxCt, 1, MPI_INT,             MPI_MAX, comm);
1500:         name = "";
1501:       }
1502:       if (mint < 0.0) {
1503:         PetscFPrintf(comm, fd, "WARNING!!! Minimum time %g over all processors for %s is negative! This happens\n on some machines whose times cannot handle too rapid calls.!\n artificially changing minimum to zero.\n",mint,name);
1504:         mint = 0;
1505:       }
1506:       if (minf < 0.0) SETERRQ2(PETSC_ERR_PLIB,"Minimum flops %g over all processors for %s is negative! Not possible!",minf,name);
1507:       totm *= 0.5; totml *= 0.5; totr /= size;
1508: 
1509:       if (maxCt != 0) {
1510:         if (minCt         != 0)   ratCt            = ((PetscLogDouble) maxCt)/minCt; else ratCt            = 0.0;
1511:         if (mint          != 0.0) ratt             = maxt/mint;                  else ratt             = 0.0;
1512:         if (minf          != 0.0) ratf             = maxf/minf;                  else ratf             = 0.0;
1513:         if (TotalTime     != 0.0) fracTime         = tott/TotalTime;             else fracTime         = 0.0;
1514:         if (TotalFlops    != 0.0) fracFlops        = totf/TotalFlops;            else fracFlops        = 0.0;
1515:         if (stageTime     != 0.0) fracStageTime    = tott/stageTime;             else fracStageTime    = 0.0;
1516:         if (flops         != 0.0) fracStageFlops   = totf/flops;                 else fracStageFlops   = 0.0;
1517:         if (numMessages   != 0.0) fracMess         = totm/numMessages;           else fracMess         = 0.0;
1518:         if (messageLength != 0.0) fracMessLen      = totml/messageLength;        else fracMessLen      = 0.0;
1519:         if (numReductions != 0.0) fracRed          = totr/numReductions;         else fracRed          = 0.0;
1520:         if (mess          != 0.0) fracStageMess    = totm/mess;                  else fracStageMess    = 0.0;
1521:         if (messLen       != 0.0) fracStageMessLen = totml/messLen;              else fracStageMessLen = 0.0;
1522:         if (red           != 0.0) fracStageRed     = totr/red;                   else fracStageRed     = 0.0;
1523:         if (totm          != 0.0) totml           /= totm;                       else totml            = 0.0;
1524:         if (maxt          != 0.0) flopr            = totf/maxt;                  else flopr            = 0.0;
1525:         PetscFPrintf(comm, fd,
1526:           "%-16s %7d%4.1f %5.4e%4.1f %3.2e%4.1f %2.1e %2.1e %2.1e%3.0f%3.0f%3.0f%3.0f%3.0f %3.0f%3.0f%3.0f%3.0f%3.0f %5.0f\n",
1527:                             name, maxCt, ratCt, maxt, ratt, maxf, ratf, totm, totml, totr,
1528:                             100.0*fracTime, 100.0*fracFlops, 100.0*fracMess, 100.0*fracMessLen, 100.0*fracRed,
1529:                             100.0*fracStageTime, 100.0*fracStageFlops, 100.0*fracStageMess, 100.0*fracStageMessLen, 100.0*fracStageRed,
1530:                             flopr/1.0e6);
1531:       }
1532:     }
1533:   }

1535:   /* Memory usage and object creation */
1536:   PetscFPrintf(comm, fd,
1537:     "------------------------------------------------------------------------------------------------------------------------\n");
1538:   PetscFPrintf(comm, fd, "\n");
1539:   PetscFPrintf(comm, fd, "Memory usage is given in bytes:\n\n");

1541:   /* Right now, only stages on the first processor are reported here, meaning only objects associated with
1542:      the global communicator, or MPI_COMM_SELF for proc 1. We really should report global stats and then
1543:      stats for stages local to processor sets.
1544:   */
1545:   /* We should figure out the longest object name here (now 20 characters) */
1546:   PetscFPrintf(comm, fd, "Object Type          Creations   Destructions   Memory  Descendants' Mem.\n");
1547:   for(stage = 0; stage < numStages; stage++) {
1548:     if (localStageUsed[stage]) {
1549:       classInfo = stageLog->stageInfo[stage].classLog->classInfo;
1550:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1551:       for(oclass = 0; oclass < stageLog->stageInfo[stage].classLog->numClasses; oclass++) {
1552:         if ((classInfo[oclass].creations > 0) || (classInfo[oclass].destructions > 0)) {
1553:           PetscFPrintf(comm, fd, "%20s %5d          %5d  %9d     %g\n", stageLog->classLog->classInfo[oclass].name,
1554:                               classInfo[oclass].creations, classInfo[oclass].destructions, (int) classInfo[oclass].mem,
1555:                               classInfo[oclass].descMem);
1556:         }
1557:       }
1558:     } else {
1559:       PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage);
1560:     }
1561:   }

1563:   PetscFree(localStageUsed);
1564:   PetscFree(stageUsed);
1565:   PetscFree(localStageVisible);
1566:   PetscFree(stageVisible);

1568:   /* Information unrelated to this particular run */
1569:   PetscFPrintf(comm, fd,
1570:     "========================================================================================================================\n");
1571:   PetscTime(y);
1572:   PetscTime(x);
1573:   PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y);
1574:   PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y); PetscTime(y);
1575:   PetscFPrintf(comm,fd,"Average time to get PetscTime(): %g\n", (y-x)/10.0);
1576:   /* MPI information */
1577:   if (size > 1) {
1578:     MPI_Status  status;
1579:     PetscMPIInt tag;
1580:     MPI_Comm    newcomm;

1582:     MPI_Barrier(comm);
1583:     PetscTime(x);
1584:     MPI_Barrier(comm);
1585:     MPI_Barrier(comm);
1586:     MPI_Barrier(comm);
1587:     MPI_Barrier(comm);
1588:     MPI_Barrier(comm);
1589:     PetscTime(y);
1590:     PetscFPrintf(comm, fd, "Average time for MPI_Barrier(): %g\n", (y-x)/5.0);
1591:     PetscCommDuplicate(comm,&newcomm, &tag);
1592:     MPI_Barrier(comm);
1593:     if (rank) {
1594:       MPI_Recv(0, 0, MPI_INT, rank-1,            tag, newcomm, &status);
1595:       MPI_Send(0, 0, MPI_INT, (rank+1)%size, tag, newcomm);
1596:     } else {
1597:       PetscTime(x);
1598:       MPI_Send(0, 0, MPI_INT, 1,          tag, newcomm);
1599:       MPI_Recv(0, 0, MPI_INT, size-1, tag, newcomm, &status);
1600:       PetscTime(y);
1601:       PetscFPrintf(comm,fd,"Average time for zero size MPI_Send(): %g\n", (y-x)/size);
1602:     }
1603:     PetscCommDestroy(&newcomm);
1604:   }
1605:   if (!rank) {
1606:     PetscOptionsPrint(fd);
1607:   }
1608:   /* Machine and compile information */
1609: #if defined(PETSC_USE_FORTRAN_KERNELS)
1610:   PetscFPrintf(comm, fd, "Compiled with FORTRAN kernels\n");
1611: #else
1612:   PetscFPrintf(comm, fd, "Compiled without FORTRAN kernels\n");
1613: #endif
1614: #if defined(PETSC_USE_SINGLE)
1615:   PetscFPrintf(comm, fd, "Compiled with single precision PetscScalar and PetscReal\n");
1616: #elif defined(PETSC_USE_LONGDOUBLE)
1617:   PetscFPrintf(comm, fd, "Compiled with long double precision PetscScalar and PetscReal\n");
1618: #elif defined(PETSC_USE_INT)
1619:   PetscFPrintf(comm, fd, "Compiled with int PetscScalar and PetscReal\n");
1620: #endif

1622: #if defined(PETSC_USE_MAT_SINGLE)
1623:   PetscFPrintf(comm, fd, "Compiled with single precision matrices\n");
1624: #else
1625:   PetscFPrintf(comm, fd, "Compiled with full precision matrices (default)\n");
1626: #endif
1627:   PetscFPrintf(comm, fd, "sizeof(short) %d sizeof(int) %d sizeof(long) %d sizeof(void*) %d sizeof(PetscScalar) %d\n",
1628:                       (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(void*),(int) sizeof(PetscScalar));

1630:   PetscFPrintf(comm, fd, "Configure run at: %s\n",petscconfigureruntime);
1631:   PetscFPrintf(comm, fd, "Configure options: %s",petscconfigureoptions);
1632:   PetscFPrintf(comm, fd, "%s", petscmachineinfo);
1633:   PetscFPrintf(comm, fd, "%s", petsccompilerinfo);
1634:   PetscFPrintf(comm, fd, "%s", petsccompilerflagsinfo);
1635:   PetscFPrintf(comm, fd, "%s", petsclinkerinfo);

1637:   /* Cleanup */
1638:   PetscFPrintf(comm, fd, "\n");
1639:   PetscFClose(comm, fd);
1640:   StageLogPush(stageLog, lastStage);
1641:   return(0);
1642: }

1646: /*@C
1647:   PetscLogPrintDetailed - Each process prints the times for its own events

1649:   Collective over MPI_Comm

1651:   Input Parameter:
1652: + comm - The MPI communicator (only one processor prints output)
1653: - file - [Optional] The output file name

1655:   Options Database Keys:
1656: . -log_summary_detailed - Prints summary of log information (for code compiled with PETSC_USE_LOG)

1658:   Usage:
1659: .vb
1660:      PetscInitialize(...);
1661:      PetscLogBegin();
1662:      ... code ...
1663:      PetscLogPrintDetailed(MPI_Comm,filename);
1664:      PetscFinalize(...);
1665: .ve

1667:   Notes:
1668:   By default the summary is printed to stdout.

1670:   Level: beginner
1671:    
1672: .keywords: log, dump, print
1673: .seealso: PetscLogBegin(), PetscLogDump(), PetscLogPrintSummary()
1674: @*/
1675: PetscErrorCode  PetscLogPrintDetailed(MPI_Comm comm, const char filename[])
1676: {
1677:   FILE          *fd = PETSC_STDOUT;
1678:   StageLog       stageLog;
1679:   StageInfo     *stageInfo = PETSC_NULL;
1680:   EventPerfInfo *eventInfo = PETSC_NULL;
1681:   const char    *name = PETSC_NULL;
1682:   PetscLogDouble TotalTime;
1683:   PetscLogDouble stageTime, flops, flopr, mess, messLen, red;
1684:   PetscLogDouble maxf, totf, maxt, tott, totm, totml, totr = 0.0;
1685:   PetscMPIInt    maxCt;
1686:   PetscMPIInt    size, rank;
1687:   PetscTruth     *stageUsed;
1688:   PetscTruth     *stageVisible;
1689:   int            numStages, numEvents;
1690:   int            stage;
1691:   PetscLogEvent  event;

1695:   MPI_Comm_size(comm, &size);
1696:   MPI_Comm_rank(comm, &rank);
1697:   /* Pop off any stages the user forgot to remove */
1698:   PetscLogGetStageLog(&stageLog);
1699:   StageLogGetCurrent(stageLog, &stage);
1700:   while (stage >= 0) {
1701:     StageLogPop(stageLog);
1702:     StageLogGetCurrent(stageLog, &stage);
1703:   }
1704:   /* Get the total elapsed time */
1705:   PetscTime(TotalTime);  TotalTime -= BaseTime;
1706:   /* Open the summary file */
1707:   if (filename) {
1708:     PetscFOpen(comm, filename, "w", &fd);
1709:   }

1711:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");
1712:   PetscFPrintf(comm, fd, "***             WIDEN YOUR WINDOW TO 120 CHARACTERS.  Use 'enscript -r -fCourier9' to print this document            ***\n");
1713:   PetscFPrintf(comm, fd, "************************************************************************************************************************\n");


1716:   numStages = stageLog->numStages;
1717:   PetscMalloc(numStages * sizeof(PetscTruth), &stageUsed);
1718:   PetscMalloc(numStages * sizeof(PetscTruth), &stageVisible);
1719:   if (numStages > 0) {
1720:     stageInfo = stageLog->stageInfo;
1721:     for(stage = 0; stage < numStages; stage++) {
1722:       if (stage < stageLog->numStages) {
1723:         stageUsed[stage]    = stageInfo[stage].used;
1724:         stageVisible[stage] = stageInfo[stage].perfInfo.visible;
1725:       } else {
1726:         stageUsed[stage]    = PETSC_FALSE;
1727:         stageVisible[stage] = PETSC_TRUE;
1728:       }
1729:     }
1730:   }

1732:   /* Report events */
1733:   PetscFPrintf(comm, fd,"Event                Count      Time (sec)     Flops/sec                          \n");
1734:   PetscFPrintf(comm, fd,"                                                            Mess   Avg len Reduct \n");
1735:   PetscFPrintf(comm,fd,"-----------------------------------------------------------------------------------\n");
1736:   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
1737:   for(stage = 0; stage < numStages; stage++) {
1738:     if (!stageVisible[stage]) continue;
1739:     if (stageUsed[stage]) {
1740:       PetscSynchronizedFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name);
1741:       MPI_Allreduce(&stageInfo[stage].perfInfo.time,          &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1742:       MPI_Allreduce(&stageInfo[stage].perfInfo.flops,         &flops,     1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1743:       MPI_Allreduce(&stageInfo[stage].perfInfo.numMessages,   &mess,      1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1744:       MPI_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen,   1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1745:       MPI_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red,       1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1746:     }
1747:     mess *= 0.5; messLen *= 0.5;

1749:     /* Get total number of events in this stage --
1750:     */
1751:     if (stageUsed[stage]) {
1752:       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
1753:       numEvents = stageLog->stageInfo[stage].eventLog->numEvents;
1754:     } else {
1755:       numEvents = 0;
1756:     }
1757:     for(event = 0; event < numEvents; event++) {
1758:       if (stageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents)) {
1759:         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) {
1760:           flopr = eventInfo[event].flops/eventInfo[event].time;
1761:         } else {
1762:           flopr = 0.0;
1763:         }
1764:         MPI_Allreduce(&flopr,                          &maxf,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, PETSC_COMM_SELF);
1765:         MPI_Allreduce(&eventInfo[event].flops,         &totf,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1766:         MPI_Allreduce(&eventInfo[event].time,          &maxt,  1, MPIU_PETSCLOGDOUBLE, MPI_MAX, PETSC_COMM_SELF);
1767:         MPI_Allreduce(&eventInfo[event].time,          &tott,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1768:         MPI_Allreduce(&eventInfo[event].numMessages,   &totm,  1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1769:         MPI_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, PETSC_COMM_SELF);
1770:         totr = eventInfo[event].numReductions;
1771:         MPI_Allreduce(&eventInfo[event].count,         &maxCt, 1, MPI_INT,             MPI_MAX, PETSC_COMM_SELF);
1772:         name = stageLog->eventLog->eventInfo[event].name;
1773:         totm *= 0.5; totml *= 0.5;
1774:       }
1775: 
1776:       if (maxCt != 0) {
1777:         if (totm          != 0.0) totml           /= totm;                       else totml            = 0.0;
1778:         PetscSynchronizedFPrintf(comm, fd,"%-16s %7d      %5.4e      %3.2e      %2.1e %2.1e %2.1e\n",name, maxCt,  maxt,  maxf, totm, totml, totr);
1779:       }
1780:     }
1781:   }
1782:   PetscSynchronizedFlush(comm);

1784:   PetscFree(stageUsed);
1785:   PetscFree(stageVisible);

1787:   PetscFClose(comm, fd);
1788:   return(0);
1789: }

1791: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
1794: /*@C
1795:    PetscGetFlops - Returns the number of flops used on this processor 
1796:    since the program began. 

1798:    Not Collective

1800:    Output Parameter:
1801:    flops - number of floating point operations 

1803:    Notes:
1804:    A global counter logs all PETSc flop counts.  The user can use
1805:    PetscLogFlops() to increment this counter to include flops for the 
1806:    application code.  

1808:    PETSc automatically logs library events if the code has been
1809:    compiled with -DPETSC_USE_LOG (which is the default), and -log,
1810:    -log_summary, or -log_all are specified.  PetscLogFlops() is
1811:    intended for logging user flops to supplement this PETSc
1812:    information.

1814:    Level: intermediate

1816: .keywords: log, flops, floating point operations

1818: .seealso: PetscGetTime(), PetscLogFlops()
1819: @*/
1820: PetscErrorCode  PetscGetFlops(PetscLogDouble *flops)
1821: {
1823:   *flops = _TotalFlops;
1824:   return(0);
1825: }

1829: PetscErrorCode  PetscLogObjectState(PetscObject obj, const char format[], ...)
1830: {
1832:   int            fullLength;
1833:   va_list        Argp;

1836:   if (!logObjects) return(0);
1837:   va_start(Argp, format);
1838:   PetscVSNPrintf(objects[obj->id].info, 64,format,&fullLength, Argp);
1839:   va_end(Argp);
1840:   return(0);
1841: }

1845: /*@
1846:   PetscLogGetStageLog - This function returns the default stage logging object.

1848:   Not collective

1850:   Output Parameter:
1851: . stageLog - The default StageLog

1853:   Level: beginner

1855: .keywords: log, stage
1856: .seealso: StageLogCreate()
1857: @*/
1858: PetscErrorCode  PetscLogGetStageLog(StageLog *stageLog)
1859: {
1862:   *stageLog = _stageLog;
1863:   return(0);
1864: }

1866: /*MC
1867:    PetscLogFlops - Adds floating point operations to the global counter.

1869:    Input Parameter:
1870: .  f - flop counter

1872:    Synopsis:
1873:    void PetscLogFlops(int f)

1875:    Usage:
1876: .vb
1877:      int USER_EVENT;
1878:      PetscLogEventRegister("User event",0,&USER_EVENT);
1879:      PetscLogEventBegin(USER_EVENT,0,0,0,0);
1880:         [code segment to monitor]
1881:         PetscLogFlops(user_flops)
1882:      PetscLogEventEnd(USER_EVENT,0,0,0,0);
1883: .ve

1885:    Notes:
1886:    A global counter logs all PETSc flop counts.  The user can use
1887:    PetscLogFlops() to increment this counter to include flops for the 
1888:    application code.  

1890:    PETSc automatically logs library events if the code has been
1891:    compiled with -DPETSC_USE_LOG (which is the default), and -log,
1892:    -log_summary, or -log_all are specified.  PetscLogFlops() is
1893:    intended for logging user flops to supplement this PETSc
1894:    information.

1896:    Level: intermediate

1898: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PetscGetFlops()

1900: .keywords: log, flops, floating point operations
1901: M*/

1903: /*MC
1904:    PreLoadBegin - Begin a segment of code that may be preloaded (run twice)
1905:     to get accurate timings

1907:    Input Parameter:
1908: +   flag - PETSC_TRUE to run twice, PETSC_FALSE to run once, may be overridden
1909:            with command line option -preload true or -preload false
1910: -   name - name of first stage (lines of code timed separately with -log_summary) to
1911:            be preloaded

1913:    Synopsis:
1914:    void PreLoadBegin(PetscTruth flag,char *name);

1916:    Usage:
1917: .vb
1918:      PreLoadBegin(PETSC_TRUE,"first stage);
1919:        lines of code
1920:        PreLoadStage("second stage");
1921:        lines of code
1922:      PreLoadEnd();
1923: .ve

1925:    Notes: Only works in C/C++, not Fortran

1927:      Flags available within the macro. 
1928: +    PetscPreLoadingUsed - true if we are or have done preloading 
1929: .    PetscPreLoadingOn - true if it is CURRENTLY doing preload
1930: .    PreLoadIt - 0 for the first computation (with preloading turned off it is only 0) 1 for the second
1931: -    PreLoadMax - number of times it will do the computation, only one when preloading is turned on
1932:      The first two variables are available throughout the program, the second two only between the PreLoadBegin()
1933:      and PreLoadEnd()

1935:    Level: intermediate

1937: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PreLoadEnd(), PreLoadStage()

1939:    Concepts: preloading
1940:    Concepts: timing^accurate
1941:    Concepts: paging^eliminating effects of


1944: M*/

1946: /*MC
1947:    PreLoadEnd - End a segment of code that may be preloaded (run twice)
1948:     to get accurate timings

1950:    Synopsis:
1951:    void PreLoadEnd(void);

1953:    Usage:
1954: .vb
1955:      PreLoadBegin(PETSC_TRUE,"first stage);
1956:        lines of code
1957:        PreLoadStage("second stage");
1958:        lines of code
1959:      PreLoadEnd();
1960: .ve

1962:    Notes: only works in C/C++ not fortran

1964:    Level: intermediate

1966: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PreLoadBegin(), PreLoadStage()

1968: M*/

1970: /*MC
1971:    PreLoadStage - Start a new segment of code to be timed separately.
1972:     to get accurate timings

1974:    Synopsis:
1975:    void PreLoadStage(char *name);

1977:    Usage:
1978: .vb
1979:      PreLoadBegin(PETSC_TRUE,"first stage);
1980:        lines of code
1981:        PreLoadStage("second stage");
1982:        lines of code
1983:      PreLoadEnd();
1984: .ve

1986:    Notes: only works in C/C++ not fortran

1988:    Level: intermediate

1990: .seealso: PetscLogEventRegister(), PetscLogEventBegin(), PetscLogEventEnd(), PreLoadBegin(), PreLoadEnd()

1992: M*/

1994: /*----------------------------------------------- Stack Functions ---------------------------------------------------*/
1997: /*@C
1998:   StackDestroy - This function destroys a stack.

2000:   Not Collective

2002:   Input Parameter:
2003: . stack - The stack

2005:   Level: beginner

2007: .keywords: log, stack, destroy
2008: .seealso: StackCreate(), StackEmpty(), StackPush(), StackPop(), StackTop()
2009: @*/
2010: PetscErrorCode StackDestroy(IntStack stack)
2011: {

2015:   PetscFree(stack->stack);
2016:   PetscFree(stack);
2017:   return(0);
2018: }

2022: /*@C
2023:   StackEmpty - This function determines whether any items have been pushed.

2025:   Not Collective

2027:   Input Parameter:
2028: . stack - The stack

2030:   Output Parameter:
2031: . empty - PETSC_TRUE if the stack is empty

2033:   Level: intermediate

2035: .keywords: log, stack, empty
2036: .seealso: StackCreate(), StackDestroy(), StackPush(), StackPop(), StackTop()
2037: @*/
2038: PetscErrorCode StackEmpty(IntStack stack, PetscTruth *empty)
2039: {
2042:   if (stack->top == -1) {
2043:     *empty = PETSC_TRUE;
2044:   } else {
2045:     *empty = PETSC_FALSE;
2046:   }
2047:   return(0);
2048: }

2052: /*@C
2053:   StackTop - This function returns the top of the stack.

2055:   Not Collective

2057:   Input Parameter:
2058: . stack - The stack

2060:   Output Parameter:
2061: . top - The integer on top of the stack

2063:   Level: intermediate

2065: .keywords: log, stack, top
2066: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPush(), StackPop()
2067: @*/
2068: PetscErrorCode StackTop(IntStack stack, int *top)
2069: {
2072:   *top = stack->stack[stack->top];
2073:   return(0);
2074: }

2078: /*@C
2079:   StackPush - This function pushes an integer on the stack.

2081:   Not Collective

2083:   Input Parameters:
2084: + stack - The stack
2085: - item  - The integer to push

2087:   Level: intermediate

2089: .keywords: log, stack, push
2090: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPop(), StackTop()
2091: @*/
2092: PetscErrorCode StackPush(IntStack stack, int item)
2093: {
2094:   int            *array;

2098:   stack->top++;
2099:   if (stack->top >= stack->max) {
2100:     PetscMalloc(stack->max*2 * sizeof(int), &array);
2101:     PetscMemcpy(array, stack->stack, stack->max * sizeof(int));
2102:     PetscFree(stack->stack);
2103:     stack->stack = array;
2104:     stack->max  *= 2;
2105:   }
2106:   stack->stack[stack->top] = item;
2107:   return(0);
2108: }

2112: /*@C
2113:   StackPop - This function pops an integer from the stack.

2115:   Not Collective

2117:   Input Parameter:
2118: . stack - The stack

2120:   Output Parameter:
2121: . item  - The integer popped

2123:   Level: intermediate

2125: .keywords: log, stack, pop
2126: .seealso: StackCreate(), StackDestroy(), StackEmpty(), StackPush(), StackTop()
2127: @*/
2128: PetscErrorCode StackPop(IntStack stack, int *item)
2129: {
2132:   if (stack->top == -1) SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Stack is empty");
2133:   *item = stack->stack[stack->top--];
2134:   return(0);
2135: }

2139: /*@C
2140:   StackCreate - This function creates a stack.

2142:   Not Collective

2144:   Output Parameter:
2145: . stack - The stack

2147:   Level: beginner

2149: .keywords: log, stack, pop
2150: .seealso: StackDestroy(), StackEmpty(), StackPush(), StackPop(), StackTop()
2151: @*/
2152: PetscErrorCode StackCreate(IntStack *stack)
2153: {
2154:   IntStack       s;

2159:   PetscNew(struct _n_IntStack, &s);
2160:   s->top = -1;
2161:   s->max = 128;
2162:   PetscMalloc(s->max * sizeof(int), &s->stack);
2163:   PetscMemzero(s->stack, s->max * sizeof(int));
2164:   *stack = s;
2165:   return(0);
2166: }

2168: #else /* end of -DPETSC_USE_LOG section */

2172: PetscErrorCode  PetscLogObjectState(PetscObject obj, const char format[], ...)
2173: {
2175:   return(0);
2176: }

2178: #endif /* PETSC_USE_LOG*/


2181: PetscCookie PETSC_LARGEST_COOKIE = PETSC_SMALLEST_COOKIE;
2182: PetscCookie PETSC_OBJECT_COOKIE  = 0;

2186: /*@C
2187:   PetscCookieRegister - Registers a new class name for objects and logging operations in an application code. 

2189:   Not Collective

2191:   Input Parameter:
2192: . name   - The class name
2193:             
2194:   Output Parameter:
2195: . oclass - The class id or cookie

2197:   Level: developer

2199: .keywords: log, class, register

2201: @*/
2202: PetscErrorCode  PetscCookieRegister(const char name[],PetscCookie *oclass )
2203: {
2204: #if defined(PETSC_USE_LOG)
2205:   StageLog       stageLog;
2206:   PetscInt       stage;
2208: #endif

2211:   *oclass = ++PETSC_LARGEST_COOKIE;
2212: #if defined(PETSC_USE_LOG)
2213:   PetscLogGetStageLog(&stageLog);
2214:   ClassRegLogRegister(stageLog->classLog, name, *oclass);
2215:   for(stage = 0; stage < stageLog->numStages; stage++) {
2216:     ClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses);
2217:   }
2218: #endif
2219:   return(0);
2220: }