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