test_checkpoint_monitor_m.pf Source File


Contents


Source Code

module test_checkpoint_monitor_m
    !! Tests regarding the checkpoint monitor module
    !! Sets up several monitors and simulates a timestepping loop, checking
    !! their state and tallies at each timestep 
    use funit
    implicit none
contains

    @test
    subroutine test_checkpoint_monitor()
        !! Test of checkpoint monitor
        use precision_grillix_m, only : GP
        use helpers_m, only : almost_equal

        ! From module to test
        use checkpoint_monitor_m, only : checkpoint_monitor_t

        type(checkpoint_monitor_t) :: fast_monitor, slow_monitor, &
                                      unaligned_monitor
        integer :: it, major_tally_target, minor_tally_fwd_target, &
                   minor_tally_bwd_target
        real(GP) :: tau, dtau, tau_final, tau_offset
        integer :: tally_offset, rep, it_offset
        real(GP) :: fast_interval, slow_interval, unaligned_interval
       
        write(*,*)''
        write(*,*)''
        write(*,'(A80)')'test_checkpoint_monitor ---------------------------------------------------'
  
        ! Set up monitors
        fast_interval = 0.1_GP
        slow_interval = 1.0_GP
        unaligned_interval = 0.3455_GP

        ! Perform test routine twice, once with and once without offsets
        do rep = 1, 2
            if (rep == 1) then
                ! Next major checkpoint happens at start time, so zero offset
                tally_offset = 0
                tau_offset = 0.0_GP
                it_offset = 0
            elseif (rep == 2) then
                ! Next major checkpoint happens in 70 iterations (at 6.0) 
                tally_offset = 12
                tau_offset = 5.3_GP
                it_offset = 70
            endif
        
            ! Simple slow monitor defined by only major interval, its minor 
            ! interval will automatically match the major interval
            call slow_monitor%init(major_interval=slow_interval, &
                                   major_tally_offset=tally_offset)

            ! Monitor with major and minor intervals
            call fast_monitor%init(major_interval=slow_interval, &
                                   minor_interval=fast_interval, &
                                   major_tally_offset=tally_offset)

            ! Monitor with minor interval that doesnt align with major interval
            call unaligned_monitor%init(major_interval=slow_interval, &
                                        minor_interval=unaligned_interval, &
                                        major_tally_offset=tally_offset)

            ! Set up timestepping
            tau = tau_offset
            dtau = 0.01_GP
            tau_final = 3.0_GP + tau_offset

            ! Main timestepping loop
            do it = 1, 301
                ! Drive monitors
                call slow_monitor%drive(tau, dtau)
                call fast_monitor%drive(tau, dtau)
                call unaligned_monitor%drive(tau, dtau)
                
                ! Test major checkpoints for all monitors
                ! and minor checkpoints for slow monitors additionally

                if (rep == 1) then
                    select case(it)
                        ! Iterations that lie on a major checkpoint
                        case(1,101,201,301)
                            @assertTrue(slow_monitor%on_major_checkpoint())
                            @assertTrue(slow_monitor%on_minor_checkpoint())
                            @assertTrue(fast_monitor%on_major_checkpoint())
                            @assertTrue(unaligned_monitor%on_major_checkpoint())
                        case default
                            @assertFalse(slow_monitor%on_major_checkpoint())
                            @assertFalse(slow_monitor%on_minor_checkpoint())
                            @assertFalse(fast_monitor%on_major_checkpoint())
                            @assertFalse(unaligned_monitor%on_major_checkpoint())
                    end select
                elseif (rep == 2) then
                    select case(it)
                        ! Iterations with time offset that lie on a major checkpoint
                        case(71,171,271)
                            @assertTrue(slow_monitor%on_major_checkpoint())
                            @assertTrue(slow_monitor%on_minor_checkpoint())
                            @assertTrue(fast_monitor%on_major_checkpoint())
                            @assertTrue(unaligned_monitor%on_major_checkpoint())
                        case default
                            @assertFalse(slow_monitor%on_major_checkpoint())
                            @assertFalse(slow_monitor%on_minor_checkpoint())
                            @assertFalse(fast_monitor%on_major_checkpoint())
                            @assertFalse(unaligned_monitor%on_major_checkpoint())
                    end select
                else
                    @assertTrue(.false.)
                endif
                
                ! Test minor checkpoints of fast monitor

                select case(it)
                    ! Iterations that lie on a minor checkpoint, regardless of offset
                    case(1,11,21,31,41,51,61,71,81,91,101, &
                         111,121,131,141,151,161,171,181,191,201, &
                         211,221,231,241,251,261,271,281,291,301)
                        @assertTrue(fast_monitor%on_minor_checkpoint())
                    case default
                        @assertFalse(fast_monitor%on_minor_checkpoint())
                end select
                
                ! Test minor checkpoints of unaligned monitor

                if (rep == 1) then
                    select case(it)
                        ! Iterations that lie on a minor checkpoint without offset
                        case(1,36,70,105,139,174,208,243,277)
                            @assertTrue(unaligned_monitor%on_minor_checkpoint())
                        case default
                            @assertFalse(unaligned_monitor%on_minor_checkpoint())
                    end select
                elseif (rep == 2) then
                    select case(it)
                        ! Iterations that lie on a minor checkpoint with offset
                        case(24,58,93,127,162,197,231,266,300)
                            @assertTrue(unaligned_monitor%on_minor_checkpoint())
                        case default
                            @assertFalse(unaligned_monitor%on_minor_checkpoint())
                    end select
                else
                    @assertTrue(.false.)
                endif

                ! Test tally values

                ! For slow/fast monitor, we can precompute target values of 
                ! tallies at every iteration

                major_tally_target = floor((it-1 - it_offset) / 100.0_GP) + 1 &
                                     + tally_offset 

                if ( it <= it_offset ) then
                    ! With nonzero offset, the first minor cycle has a shorter 
                    ! length than the rest and must be computed differently
                    minor_tally_fwd_target = mod( &
                                                 floor((it-1)/10.0_GP), &
                                                 floor(it_offset/10.0_GP) &
                                                 ) + 1
                    minor_tally_bwd_target = mod( &
                                                 floor((it-1)/10.0_GP), &
                                                 floor(it_offset/10.0_GP) &
                                                 ) + 1
                else
                    minor_tally_fwd_target = mod( &
                                                 floor((it-1 - it_offset)/10.0_GP), &
                                                 10 &
                                                 ) + 1
                    ! Additional manual settings for bwd tally since they
                    ! cannot be computed in the modulo simply
                    if (it == 1) then
                        minor_tally_bwd_target = 1
                    else if (rep == 2 .and. it == 71) then
                        minor_tally_bwd_target = 8
                    else if (mod(it-1 - it_offset, 100) == 0) then
                        minor_tally_bwd_target = 10
                    else
                        minor_tally_bwd_target = mod( &
                                                     floor((it-1 - it_offset)/10.0_GP), &
                                                     10 &
                                                     ) 
                    endif
                endif 

                ! Test major tallies against target values
                @assertEqual(slow_monitor%get_major_tally(), major_tally_target )
                @assertEqual(fast_monitor%get_major_tally(), major_tally_target )
                @assertEqual(unaligned_monitor%get_major_tally(), major_tally_target)
                           
                ! Test minor tallies for slow monitor
                ! Forward tally is always 1, except for the first 70 iterations
                ! in the offset case where it is still 0.
                ! The backward tally is 1 only on a major checkpoint, otherwise 0
                if ( rep == 1 ) then
                    @assertEqual(slow_monitor%get_minor_tally_fwd(), 1)
                    select case(it)
                        case(1,101,201,301)
                            @assertEqual(slow_monitor%get_minor_tally_bwd(), 1)
                        case default
                            @assertEqual(slow_monitor%get_minor_tally_bwd(), 0)
                    end select
                else 
                    if ( it < 71 ) then
                        @assertEqual(slow_monitor%get_minor_tally_fwd(), 0)
                    endif
                    select case(it)
                        case(71,171,271)
                            @assertEqual(slow_monitor%get_minor_tally_bwd(), 1)
                        case default
                            @assertEqual(slow_monitor%get_minor_tally_bwd(), 0)
                    end select
                endif
    
                ! Test minor tallies for fast monitor
                @assertEqual(fast_monitor%get_minor_tally_fwd(), minor_tally_fwd_target)
                @assertEqual(fast_monitor%get_minor_tally_bwd(), minor_tally_bwd_target)
               
                ! Test minor tallies for unaligned monitor
                !   In the unaligned case, the target values follow a more
                !   complicated pattern, thus they are manually checked instead
                !   of using modulo functions to compute their target value.
                !   Each if-block below checks that the minor tally is equal to
                !   specific values in specific iteration ranges. The target 
                !   values change whenever the iteration reaches a 
                !   major checkpoint (which resets the tallies to 0), or a 
                !   minor checkpoint (which increments the tallies by 1).
                !   In total, the if-blocks together check all 300 iterations.

                if (rep == 1) then
                    ! 1. Non-offset case

                    ! Test values for minor_tally_fwd
                    if     (     ( (it >= 101) .and. (it < 105) ) &
                            .or. ( (it >= 201) .and. (it < 208) ) &
                            .or. ( (it == 301)                  ) ) then

                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 0)

                    elseif (     ( (it >= 1  ) .and. (it < 36 ) ) &
                            .or. ( (it >= 105) .and. (it < 139) ) &
                            .or. ( (it >= 208) .and. (it < 243) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 1)
                         
                    elseif (     ( (it >= 36 ) .and. (it < 70 ) ) &
                            .or. ( (it >= 139) .and. (it < 174) ) &
                            .or. ( (it >= 243) .and. (it < 277) ) ) then
                    
                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 2)
                                        
                    elseif (     ( (it >= 70 ) .and. (it < 101) ) &
                            .or. ( (it >= 174) .and. (it < 201) ) &
                            .or. ( (it >= 277) .and. (it < 301) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 3)
                        
                    else
                        @assertTrue(.false.)
                    endif

                    ! Test values for minor_tally_bwd
                    if     (     ( (it >= 2  ) .and. (it < 36 ) ) &
                            .or. ( (it >= 102) .and. (it < 105) ) &
                            .or. ( (it >= 202) .and. (it < 208) ) ) then

                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 0)

                    elseif (     ( (it == 1  )                  ) &
                            .or. ( (it >= 36 ) .and. (it < 70 ) ) &
                            .or. ( (it >= 105) .and. (it < 139) ) &
                            .or. ( (it >= 208) .and. (it < 243) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 1)
                         
                    elseif (     ( (it >= 70 ) .and. (it < 102) ) &
                            .or. ( (it >= 139) .and. (it < 174) ) &
                            .or. ( (it >= 139) .and. (it < 174) ) &
                            .or. ( (it >= 243) .and. (it < 277) ) ) then
                    
                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 2)
                                        
                    elseif (     ( (it >= 174) .and. (it < 202) ) &
                            .or. ( (it >= 277) .and. (it < 302) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 3)
                        
                    else
                        @assertTrue(.false.)
                    endif

                elseif (rep == 2) then
                    ! 2. Offset case

                    ! Test values for minor_tally_fwd
                    if     (     ( (it >=  1 ) .and. (it < 24 ) ) &
                            .or. ( (it >= 71 ) .and. (it < 93 ) ) &
                            .or. ( (it >= 171) .and. (it < 197) ) &
                            .or. ( (it >= 271) .and. (it < 300) ) ) then

                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 0)

                    elseif (     ( (it >= 24 ) .and. (it < 58 ) ) &
                            .or. ( (it >= 93 ) .and. (it < 127) ) &
                            .or. ( (it >= 197) .and. (it < 231) ) &
                            .or. ( (it >= 300) .and. (it < 302) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 1)
                         
                    elseif (     ( (it >= 58 ) .and. (it < 71 ) ) &
                            .or. ( (it >= 127) .and. (it < 162) ) &
                            .or. ( (it >= 231) .and. (it < 266) ) ) then
                    
                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 2)
                                        
                    elseif (     ( (it >= 162) .and. (it < 171) ) &
                            .or. ( (it >= 266) .and. (it < 271) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_fwd(), 3)
                        
                    else
                        @assertTrue(.false.)
                    endif

                    ! Test values for minor_tally_bwd
                    if     (     ( (it >=  1 ) .and. (it < 24 ) ) &
                            .or. ( (it >= 72 ) .and. (it < 93 ) ) &
                            .or. ( (it >= 172) .and. (it < 197) ) &
                            .or. ( (it >= 272) .and. (it < 300) ) ) then

                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 0)

                    elseif (     ( (it >= 24 ) .and. (it < 58 ) ) &
                            .or. ( (it >= 93 ) .and. (it < 127) ) &
                            .or. ( (it >= 197) .and. (it < 231) ) &
                            .or. ( (it >= 300) .and. (it < 302) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 1)
                         
                    elseif (     ( (it >= 58 ) .and. (it < 72 ) ) &
                            .or. ( (it >= 127) .and. (it < 162) ) &
                            .or. ( (it >= 231) .and. (it < 266) ) ) then
                    
                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 2)
                                        
                    elseif (     ( (it >= 162) .and. (it < 172) ) &
                            .or. ( (it >= 266) .and. (it < 272) ) ) then
                         
                        @assertEqual(unaligned_monitor%get_minor_tally_bwd(), 3)
                        
                    else
                        @assertTrue(.false.)
                    endif

                else
                    @assertTrue(.false.)
                endif
                
                ! Advance timestep
                tau = tau + dtau 
            enddo
            
        enddo

        write(*,'(A80)')'test_checkpoint_monitor complete ------------------------------------------'
        write(*,*)''
        write(*,*)''
  

    end subroutine
    
end module