!
!
!   Description: Demonstrates how users can augment the PETSc profiling by
!                inserting their own event logging.
!
!/*T
!   Concepts: PetscLog^user-defined event profiling (basic example);
!   Concepts: PetscLog^activating/deactivating events for profiling (basic example);
!   Processors: n
!T*/
! -----------------------------------------------------------------------

      program SchoolDay

      implicit none

! Petsc types are needed:
#include <petsc/finclude/petscsys.h> 

! Petsc Logging is needed:
#include <petsc/finclude/petsclog.h> 

!====================================================================
!     Local Variables

      ! Settings:
      integer, parameter        :: verbose=0               ! 0: silent, >=1 : increasing amount of debugging output
      integer, parameter        :: msgLen = 30             ! number of reals which is sent with MPI_iSend
      PetscReal, parameter      :: second=0.1;             ! time is sped up by a factor 10

      ! Codes
      integer, parameter        :: BOY=1, GIRL=2, TEACHER=0
      PetscMPIInt, parameter    :: tagMsg   = 1200;

      ! Timers
      PetscLogEvent :: Morning,  Afternoon
      PetscLogEvent :: PlayBall, SkipRope
      PetscLogEvent :: TidyClass
      PetscLogEvent :: Lessons,  CorrectHomework

      ! Petsc-stuff
      PetscErrorCode            :: ierr
      PetscViewer               :: viewer
      PetscReal                 :: threshTime

      ! MPI-stuff
      integer                   :: rank, size
      PetscReal, allocatable    :: message(:,:)
      integer                   :: item, maxItem
      integer                   :: status(MPI_STATUS_SIZE)
      integer                   :: req

      ! Own stuff
      integer                   :: role                 ! is this process a BOY, a GIRL or a TEACHER?
      integer                   :: i, j
      character(len=60)         :: filename
!====================================================================
!     Initializations
      call PetscInitialize(PETSC_NULL_CHARACTER,ierr)
      call MPI_Comm_size(PETSC_COMM_WORLD, size,ierr)
      call MPI_Comm_rank(PETSC_COMM_WORLD, rank,ierr)

      if (rank==0) then 
         role = TEACHER
      else if (rank<0.4*size) then
         role = GIRL
      else 
         role = BOY
      end if

      allocate(message(msgLen,msglen))
      do i = 1,msgLen
         do j  = 1,msgLen
            message(i,j) = 10.0*j + i*1.0/(rank+1)
         end do
      end do
!
!====================================================================
!     Create new user-defined events
      call PetscLogEventRegister('Morning',         0, Morning,   ierr)
      call PetscLogEventRegister('Afternoon',       0, Afternoon, ierr)
      call PetscLogEventRegister('Play Ball',       0, PlayBall,  ierr)
      call PetscLogEventRegister('Skip Rope',       0, SkipRope,  ierr)
      call PetscLogEventRegister('Tidy Classroom',  0, TidyClass, ierr)
      call PetscLogEventRegister('Lessons',         0, Lessons,   ierr)
      call PetscLogEventRegister('Correct Homework',0,CorrectHomework,          &
     &                                                            ierr)
      if (verbose>=1) then
      print '(a,i0,a)','[',rank,'] SchoolDay events have been defined'
      endif

!====================================================================
!     Go through the school day
      call PetscLogEventBegin(Morning,ierr)

         call PetscLogFlops(190000d0,ierr)
         call PetscSleep(0.5*second,ierr)

         call PetscLogEventBegin(Lessons,ierr)
         call PetscLogFlops(23000d0,ierr)
         call PetscSleep(1*second, ierr)
         call MPI_iSend( message, msgLen, MPI_DOUBLE_PRECISION,                             &
     &                        mod(rank+1,size),                                             &
     &                        tagMsg+rank, PETSC_COMM_WORLD, req, ierr)
         call  MPI_Recv( message, msgLen, MPI_DOUBLE_PRECISION,                             &
     &                       mod(rank-1+size,size),                                         &
     &                  tagMsg+mod(rank-1+size,size), PETSC_COMM_WORLD,                     &
     &        status, ierr)
         call MPI_Wait(req,MPI_STATUS_IGNORE,ierr)
         call PetscLogEventEnd(Lessons,ierr)

         if (role==TEACHER) then
            call PetscLogEventBegin(TidyClass,ierr)
            call PetscLogFlops(600000d0,ierr)
            call PetscSleep(0.6*second, ierr)
               call PetscLogEventBegin(CorrectHomework,ierr)
               call PetscLogFlops(234700d0,ierr)
               call PetscSleep(0.4*second, ierr)
               call PetscLogEventEnd(CorrectHomework,ierr)
            call PetscLogEventEnd(TidyClass,ierr)
         else if (role==BOY) then
            call PetscLogEventBegin(SkipRope,ierr)
            call PetscSleep(0.8*second, ierr)
            call PetscLogEventEnd(SkipRope,ierr)
         else 
            call PetscLogEventBegin(PlayBall,ierr)
            call PetscSleep(0.9*second, ierr)
            call PetscLogEventEnd(PlayBall,ierr)
         end if

         call PetscLogEventBegin(Lessons,ierr)
         call PetscLogFlops(120000d0,ierr)
         call PetscSleep(0.7*second, ierr)
         call PetscLogEventEnd(Lessons,ierr)

      call PetscLogEventEnd(Morning,ierr)

      call PetscLogEventBegin(Afternoon,ierr)

         item = rank*(3-rank)
         call MPI_Allreduce(item, maxItem, 1, MPI_INTEGER, MPI_MAX,                    &
     &                           PETSC_COMM_WORLD, ierr)

         item = rank*(10-rank)
         call MPI_Allreduce(item, maxItem, 1, MPI_INTEGER, MPI_MAX,                    &
     &                           PETSC_COMM_WORLD, ierr)

         call PetscLogFlops(58988d0,ierr)
         call PetscSleep(0.6*second,ierr)

         call PetscLogEventBegin(Lessons,ierr)
         call PetscLogFlops(123456d0,ierr)
         call PetscSleep(1*second, ierr)
         call PetscLogEventEnd(Lessons,ierr)

         if (role==TEACHER) then
            call PetscLogEventBegin(TidyClass,ierr)
            call PetscLogFlops(17800d0,ierr)
            call PetscSleep(1.1*second, ierr)
            call PetscLogEventBegin(Lessons,ierr)
            call PetscLogFlops(72344d0,ierr)
            call PetscSleep(0.5*second, ierr)
            call PetscLogEventEnd(Lessons,ierr)
            call PetscLogEventEnd(TidyClass,ierr)
         else if (role==GIRL) then
            call PetscLogEventBegin(SkipRope,ierr)
            call PetscSleep(0.7*second, ierr)
            call PetscLogEventEnd(SkipRope,ierr)
         else 
            call PetscLogEventBegin(PlayBall,ierr)
            call PetscSleep(0.8*second, ierr)
            call PetscLogEventEnd(PlayBall,ierr)
         end if

         call PetscLogEventBegin(Lessons,ierr)
         call PetscLogFlops(72344d0,ierr)
         call PetscSleep(0.5*second, ierr)
         call PetscLogEventEnd(Lessons,ierr)

      call PetscLogEventEnd(Afternoon,ierr)

      if (.false.) then
         continue
      else if (role==TEACHER) then
         call PetscLogEventBegin(TidyClass,ierr)
         call PetscLogFlops(612300d0,ierr)
         call PetscSleep(1.1*second, ierr)
         call PetscLogEventEnd(TidyClass,ierr)
         call PetscLogEventBegin(CorrectHomework,ierr)
         call PetscLogFlops(234700d0,ierr)
         call PetscSleep(1.1*second, ierr)
         call PetscLogEventEnd(CorrectHomework,ierr)
      else 
         call PetscLogEventBegin(SkipRope,ierr)
         call PetscSleep(0.7*second, ierr)
         call PetscLogEventEnd(SkipRope,ierr)
         call PetscLogEventBegin(PlayBall,ierr)
         call PetscSleep(0.8*second, ierr)
         call PetscLogEventEnd(PlayBall,ierr)
      end if

      call PetscLogEventBegin(Lessons,ierr)
      call PetscLogFlops(120000d0,ierr)
      call PetscSleep(0.7*second, ierr)
      call PetscLogEventEnd(Lessons,ierr)

      call PetscSleep(0.25*second,ierr)

      call PetscLogEventBegin(Morning,ierr)

         call PetscLogFlops(190000d0,ierr)
         call PetscSleep(0.5*second,ierr)

         call PetscLogEventBegin(Lessons,ierr)
         call PetscLogFlops(23000d0,ierr)
         call PetscSleep(1*second, ierr)
         call MPI_ISend( message, msgLen, MPI_DOUBLE_PRECISION,                             &
     &                        mod(rank+1,size),                                             &
     &                   tagMsg+rank, PETSC_COMM_WORLD, req, ierr)
         call MPI_Recv( message, msgLen, MPI_DOUBLE_PRECISION,                              &
     &                  mod(rank-1+size,size),                                              &
     &                  tagMsg+mod(rank-1+size,size), PETSC_COMM_WORLD,                     &
     &                   status, ierr)
         call MPI_Wait(req,MPI_STATUS_IGNORE,ierr)
         call PetscLogEventEnd(Lessons,ierr)

         if (role==TEACHER) then
            call PetscLogEventBegin(TidyClass,ierr)
            call PetscLogFlops(600000d0,ierr)
            call PetscSleep(1.2*second, ierr)
            call PetscLogEventEnd(TidyClass,ierr)
         else if (role==BOY) then
            call PetscLogEventBegin(SkipRope,ierr)
            call PetscSleep(0.8*second, ierr)
            call PetscLogEventEnd(SkipRope,ierr)
         else 
            call PetscLogEventBegin(PlayBall,ierr)
            call PetscSleep(0.9*second, ierr)
            call PetscLogEventEnd(PlayBall,ierr)
         end if

         call PetscLogEventBegin(Lessons,ierr)
         call PetscLogFlops(120000d0,ierr)
         call PetscSleep(0.7*second, ierr)
         call PetscLogEventEnd(Lessons,ierr)

      call PetscLogEventEnd(Morning,ierr)

      deallocate(message)

      call PetscFinalize(ierr)

      end program SchoolDay

