LCOV - code coverage report
Current view: top level - src/56_io_mpi - m_exit.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 56.3 % 71 40
Test Date: 2026-11-12 07:43:35 Functions: 100.0 % 8 8
Branches: 44.0 % 50 22

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_exit
       2                 :             : !! NAME
       3                 :             : !! m_exit
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !! COPYRIGHT
       8                 :             : !!  Copyright (C) 2008-2026 ABINIT group (MG, DCA, XG, GMR)
       9                 :             : !!  This file is distributed under the terms of the
      10                 :             : !!  GNU General Public License, see ~abinit/COPYING
      11                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      12                 :             : !!
      13                 :             : !! SOURCE
      14                 :             : 
      15                 :             : #if defined HAVE_CONFIG_H
      16                 :             : #include "config.h"
      17                 :             : #endif
      18                 :             : 
      19                 :             : #include "abi_common.h"
      20                 :             : 
      21                 :             : MODULE m_exit
      22                 :             : 
      23                 :             :  use defs_basis
      24                 :             :  use m_xmpi
      25                 :             :  use m_abicore
      26                 :             :  use m_errors
      27                 :             : 
      28                 :             :  use m_time,      only : abi_wtime, sec2str, timein
      29                 :             :  use m_fstrings,  only : inupper
      30                 :             :  use m_io_tools,  only : open_file
      31                 :             : 
      32                 :             :  implicit none
      33                 :             : 
      34                 :             :  private
      35                 :             : !!***
      36                 :             : 
      37                 :             :  public :: exit_init                  ! Initialize the global variables of the module
      38                 :             :  public :: get_start_time             ! Return the origin of time (begin of execution ) in seconds
      39                 :             :  public :: have_timelimit_in          ! True if the run must completed before timelimit.
      40                 :             :  public :: disable_timelimit          ! Disable time limit handlers.
      41                 :             :  public :: enable_timelimit_in        ! Eable time limit handler in the given function.
      42                 :             :  public :: get_timelimit              ! Return the time limit in seconds
      43                 :             :  public :: get_timelimit_string       ! Return the time limit in string form.
      44                 :             :  public :: exit_check                 ! Test if we should try to stop the code gracefully and to create a restart point.
      45                 :             : 
      46                 :             :  real(dp),private,save :: WALL0
      47                 :             : ! Origin of time in seconds.
      48                 :             : 
      49                 :             :  real(dp),private,save :: WTIME_LIMIT=-one
      50                 :             : ! Wall time limit in seconds. Negative value if not set.
      51                 :             : 
      52                 :             :  character(len=fnlen),private,save :: TIMELIMIT_INABIFUNC = "__None__"
      53                 :             : ! Name of the abinit function in which the time limit is handled.
      54                 :             : ! Note that there's **only one caller** in charge of the check.
      55                 :             : ! In structure relaxations, for example, only mover decides whether the itime loop must be exited
      56                 :             : ! and similar time limit handlers located in the children (e.g. scfcv) are automatically deactivated.
      57                 :             : ! This approach facilitates the treatment of nested parallelism e.g. image parallelism and reduce the number of MPI synchronizations.
      58                 :             : ! The drawback is that we loose the possibility of controlling the exit at a fine-grained level.
      59                 :             : ! If, for example, mover underestimates the time needed to complete the itime step, scfcv wont' be
      60                 :             : ! able to return if the time limit is approaching.
      61                 :             : 
      62                 :             : !----------------------------------------------------------------------
      63                 :             : 
      64                 :             : CONTAINS
      65                 :             : !!***
      66                 :             : 
      67                 :             : !!****f* m_exit/exit_init
      68                 :             : !! NAME
      69                 :             : !! exit_init
      70                 :             : !!
      71                 :             : !! FUNCTION
      72                 :             : !!  Initialize the global variables of the modules.
      73                 :             : !!  This is a collective function that should be called by all the nodes in COMM_WORLD
      74                 :             : !!
      75                 :             : !! INPUTS
      76                 :             : !!
      77                 :             : !! SOURCE
      78                 :             : 
      79                 :           4 : subroutine exit_init(time_limit)
      80                 :             : 
      81                 :             : !Arguments ------------------------------------
      82                 :             :  real(dp),intent(in) :: time_limit
      83                 :             : 
      84                 :             : ! *************************************************************************
      85                 :             : 
      86                 :           4 :  WTIME_LIMIT = time_limit
      87                 :           4 :  WALL0 = abi_wtime()
      88                 :             : 
      89                 :           4 : end subroutine exit_init
      90                 :             : !!***
      91                 :             : 
      92                 :             : !----------------------------------------------------------------------
      93                 :             : 
      94                 :             : !!****f* m_exit/disable_timelimit
      95                 :             : !! NAME
      96                 :             : !! disable_timelimit
      97                 :             : !!
      98                 :             : !! FUNCTION
      99                 :             : !!  Disable the time limit handler. This function should be called by a driver
     100                 :             : !!  routine that is not able to handle time limit events and wants to prevent
     101                 :             : !!  its children from installing their handlers.
     102                 :             : !!
     103                 :             : !! SOURCE
     104                 :             : 
     105                 :         495 : subroutine disable_timelimit()
     106                 :             : 
     107                 :             : !Local variables-------------------------------
     108                 :             : !scalars
     109                 :             :  character(len=500) :: msg
     110                 :             : 
     111                 :             : ! *************************************************************************
     112                 :             : 
     113                 :         495 :  WTIME_LIMIT = -one
     114                 :             : 
     115         [ -  + ]:         495 :  if (TIMELIMIT_INABIFUNC /= "__None__") then
     116                 :           0 :    msg = "Timelimit is already activated in function: "//trim(TIMELIMIT_INABIFUNC)
     117                 :           0 :    ABI_WARNING(msg)
     118                 :             :    !ABI_ERROR(msg)
     119                 :             :  end if
     120                 :             : 
     121                 :         495 : end subroutine disable_timelimit
     122                 :             : !!***
     123                 :             : 
     124                 :             : !----------------------------------------------------------------------
     125                 :             : 
     126                 :             : !!****f* m_exit/have_timelimit_in
     127                 :             : !! NAME
     128                 :             : !! have_timelimit_in
     129                 :             : !!
     130                 :             : !! FUNCTION
     131                 :             : !!  Return .True. if timelimit is enabled in this caller
     132                 :             : !!
     133                 :             : !! SOURCE
     134                 :             : 
     135                 :       60616 : logical pure function have_timelimit_in(abifunc) result(ans)
     136                 :             : 
     137                 :             : !Arguments -----------------------------------
     138                 :             :  character(len=*),intent(in) :: abifunc
     139                 :             : 
     140                 :             : ! *************************************************************************
     141                 :             : 
     142   [ +  +  -  + ]:       60616 :  ans = WTIME_LIMIT > zero .and. abifunc == TIMELIMIT_INABIFUNC
     143                 :             : 
     144                 :       60616 : end function have_timelimit_in
     145                 :             : !!***
     146                 :             : 
     147                 :             : !----------------------------------------------------------------------
     148                 :             : 
     149                 :             : !!****f* m_exit/enable_timelimit_in
     150                 :             : !! NAME
     151                 :             : !! enable_timelimit_in
     152                 :             : !!
     153                 :             : !! FUNCTION
     154                 :             : !!  Eable time limit handler in the given function if not already done in one of the callers.
     155                 :             : !!  Return the name of procedure that is handling the time limit.
     156                 :             : !!  Example:
     157                 :             : !!
     158                 :             : !!    ! enable time limit handler if not done in callers.
     159                 :             : !!    if (enable_timelimit_in(FUNC_NAME) == FUNC_NAME) then
     160                 :             : !!      write(std_out,*)"Enabling timelimit check in function: ",trim(FUNC_NAME)," with timelimit: ",trim(sec2str(get_timelimit()))
     161                 :             : !!    end if
     162                 :             : !!
     163                 :             : !! SOURCE
     164                 :             : 
     165                 :        9706 : function enable_timelimit_in(abifunc) result(prev_func)
     166                 :             : 
     167                 :             : !Arguments -----------------------------------
     168                 :             :  character(len=*),intent(in) :: abifunc
     169                 :             :  character(len=fnlen) :: prev_func
     170                 :             : 
     171                 :             : ! *************************************************************************
     172                 :             : 
     173   [ +  -  -  + ]:           4 :  if (WTIME_LIMIT > zero .and. TIMELIMIT_INABIFUNC == "__None__") TIMELIMIT_INABIFUNC = abifunc
     174                 :        9706 :  prev_func = TIMELIMIT_INABIFUNC
     175                 :             : 
     176         [ +  + ]:        9706 : end function enable_timelimit_in
     177                 :             : !!***
     178                 :             : 
     179                 :             : !----------------------------------------------------------------------
     180                 :             : 
     181                 :             : !!****f* m_exit/get_timelimit
     182                 :             : !! NAME
     183                 :             : !! get_timelimit
     184                 :             : !!
     185                 :             : !! FUNCTION
     186                 :             : !!  Return the time limit in seconds
     187                 :             : !!
     188                 :             : !! SOURCE
     189                 :             : 
     190                 :        2190 : real(dp) pure function get_timelimit()
     191                 :             : 
     192                 :        2190 :  get_timelimit = WTIME_LIMIT
     193                 :             : 
     194                 :        1030 : end function get_timelimit
     195                 :             : !!***
     196                 :             : 
     197                 :             : !----------------------------------------------------------------------
     198                 :             : 
     199                 :             : !!****f* m_exit/get_timelimit_string
     200                 :             : !! NAME
     201                 :             : !! get_timelimit_string
     202                 :             : !!
     203                 :             : !! FUNCTION
     204                 :             : !!  Return the time limit in string form.
     205                 :             : !!
     206                 :             : !! SOURCE
     207                 :             : 
     208                 :        1160 : pure function get_timelimit_string() result(string)
     209                 :             : 
     210                 :             : !Local variables-------------------------------
     211                 :             : !scalars
     212                 :             :  real(dp) :: timelimit
     213                 :             :  character(len=500) :: string
     214                 :             : 
     215                 :             : ! *************************************************************************
     216                 :             : 
     217                 :             :  ! Handle negative values
     218                 :        1160 :  timelimit = get_timelimit()
     219         [ +  + ]:        1160 :  if (timelimit > zero) then
     220                 :           1 :    string = sec2str(timelimit)
     221                 :             :  else
     222                 :        1159 :    string = "0"
     223                 :             :  end if
     224                 :             : 
     225                 :        1160 : end function get_timelimit_string
     226                 :             : !!***
     227                 :             : 
     228                 :             : !!****f* m_exit/get_start_time
     229                 :             : !! NAME
     230                 :             : !! get_start_time
     231                 :             : !!
     232                 :             : !! FUNCTION
     233                 :             : !!  Return the origin of execution time in seconds
     234                 :             : !!
     235                 :             : !! SOURCE
     236                 :             : 
     237                 :          16 : real(dp) pure function get_start_time()
     238                 :             : 
     239                 :          16 :  get_start_time = WALL0
     240                 :             : 
     241                 :          16 : end function get_start_time
     242                 :             : !!***
     243                 :             : 
     244                 :             : !!****f* m_exit/exit_check
     245                 :             : !! NAME
     246                 :             : !! exit_check
     247                 :             : !!
     248                 :             : !! FUNCTION
     249                 :             : !! This routine checks whether the CPU time limit is exceeded or not.
     250                 :             : !! If openexit is non-zero, it also checks the "filename" file
     251                 :             : !! for the "exit" character string in its first line and returns the location
     252                 :             : !! of the string on the line (0 if not found).  Maps both strings to upper case
     253                 :             : !! before attempting to match them. Also checks for the existence
     254                 :             : !! of the "abinit.exit" file in the directory where the job was started.
     255                 :             : !! Finally, checks whether the CPU time limit was not exceeded.
     256                 :             : !! If one of these conditions occurs, will induce graceful exit of iterations.
     257                 :             : !!
     258                 :             : !! INPUTS
     259                 :             : !!  cpus = CPU time limit
     260                 :             : !!  filename = character string giving name of file to be opened
     261                 :             : !!  iout = unit number to print output to
     262                 :             : !!  openexit = if 1, open the "filename" and "abinit.exit" files
     263                 :             : !!  comm=MPI communicator.
     264                 :             : !!
     265                 :             : !! OUTPUT
     266                 :             : !!  iexit = index of "exit" on first line of file (0 if not found),
     267                 :             : !!      or -1 if the exit was ordered through the existence of the "exit" file
     268                 :             : !!      or -2 if the exit was ordered through the CPU time limit.
     269                 :             : !!
     270                 :             : !! SOURCE
     271                 :             : 
     272                 :       80092 : subroutine exit_check(cpus,filename,iexit,iout,comm,openexit)
     273                 :             : 
     274                 :             : !Arguments ------------------------------------
     275                 :             :  integer,intent(in) :: comm
     276                 :             :  real(dp),intent(in) :: cpus
     277                 :             :  character(len=*),intent(in) :: filename
     278                 :             :  integer,intent(in) :: openexit,iout
     279                 :             :  integer,intent(out) :: iexit
     280                 :             : 
     281                 :             : !Local variables-------------------------------
     282                 :             : !scalars
     283                 :             :  integer,parameter :: master=0
     284                 :             :  integer,save :: iexit_save=0
     285                 :             :  integer :: ierr,temp_unit,ierrmpi
     286                 :             :  logical :: ex
     287                 :             :  real(dp),save :: tcpu_last=zero
     288                 :             :  character(len=500) :: message
     289                 :             :  character(len=fnlen) :: line
     290                 :             :  character(len=4), parameter :: string='EXIT'
     291                 :             : !arrays
     292                 :             :  real(dp) :: tsec(2)
     293                 :             : 
     294                 :             : ! *************************************************************************
     295                 :             : 
     296         [ +  - ]:       80092 :  if (iexit_save==0) then
     297                 :             :    ! ABINIT will pass again in this routine even after exit call has been detected
     298                 :             : 
     299         [ +  + ]:       80092 :    if (xmpi_comm_rank(comm)==master) then
     300                 :             :      ! Master tests and broadcast the result to others
     301                 :       64681 :      iexit=0
     302                 :             : 
     303                 :             :      ! Is it worth to test the cpu time ?
     304                 :       64681 :      tsec = zero
     305   [ +  -  +  + ]:       64681 :      if (abs(cpus)>1.0d-5 .or. openexit==1) then
     306                 :          24 :        call timein(tsec(1),tsec(2))
     307                 :             :      end if
     308                 :             : 
     309                 :             :      ! A first way of exiting: the cpu time limit
     310         [ -  + ]:       64681 :      if (abs(cpus)>1.0d-5) then
     311         [ #  # ]:           0 :        if(cpus<tsec(1))iexit=-2
     312                 :             :      end if
     313                 :             : 
     314                 :             :      ! Test the content of files only when sufficient time (2 sec) has elapsed from last time it was tested.
     315   [ +  +  +  -  :       64681 :      if (openexit==1 .and. iexit==0 .and. tsec(1)-tcpu_last>two ) then
                   -  + ]
     316                 :             :        ! TODO Remove this approach. Use abinit.exit!
     317                 :           0 :        tcpu_last=tsec(1)
     318                 :             :        ! Open file and read first line as character string
     319         [ #  # ]:           0 :        if (open_file(filename,message,newunit=temp_unit,form='formatted',status='old') /= 0) then
     320                 :           0 :          ABI_ERROR(message)
     321                 :             :        end if
     322                 :           0 :        rewind (unit=temp_unit)
     323                 :           0 :        read (unit=temp_unit,fmt='(a)',iostat=ierr) line
     324         [ #  # ]:           0 :        if(ierr/=0)then
     325                 :             :          write(message, '(a,a,a,i5,a,a)' )&
     326                 :           0 : &         'Problem when reading file=',TRIM(filename),'iostat =',ierr,ch10,&
     327                 :           0 : &         'Action: check whether this file is OK.'
     328                 :           0 :          ABI_ERROR(message)
     329                 :             :        end if
     330                 :             :        ! Make a local copy of matching string of length equal to nonblank length of input string
     331                 :             :        ! Map to upper case
     332                 :           0 :        call inupper(line)
     333                 :           0 :        iexit=index(line,string)
     334                 :           0 :        close (unit=temp_unit)
     335                 :             : 
     336                 :             :        ! This is another way of exiting : the previous one does not work
     337                 :             :        ! on some machines, may be because they keep a copy of the initial input file.
     338         [ #  # ]:           0 :        if(iexit==0)then
     339                 :           0 :          inquire(file='abinit.exit',exist=ex)
     340         [ #  # ]:           0 :          if(ex)iexit=-1
     341                 :             :        end if
     342                 :             : 
     343                 :             :      end if
     344                 :             :    end if
     345                 :             : 
     346                 :       80092 :    call xmpi_bcast(iexit,master,comm,ierrmpi)
     347                 :             : 
     348                 :             :  else
     349                 :             :    ! In case the exit mechanism has already been activated
     350                 :           0 :    iexit=iexit_save
     351                 :             :  end if
     352                 :             : 
     353         [ -  + ]:       80092 :  if (iexit/=0) then
     354         [ #  # ]:           0 :    if (iexit>0) write(message, '(a,a,a,a,a,a,a)' ) ch10,&
     355                 :           0 : &   ' chkexi: WARNING -',ch10,&
     356                 :           0 : &   '  Exit has been requested from file ',trim(filename),'.',ch10
     357         [ #  # ]:           0 :    if (iexit==-1) write(message, '(a,a,a,a,a)' ) ch10,&
     358                 :           0 : &   ' chkexi: WARNING -',ch10,&
     359                 :           0 : &   '  Exit has been requested from file "abinit.exit".',ch10
     360         [ #  # ]:           0 :    if (iexit==-2) write(message, '(a,a,a,a,a)' ) ch10,&
     361                 :           0 : &   ' chkexi: WARNING -',ch10,&
     362                 :           0 : &   '  Exit due to cpu time limit exceeded.',ch10
     363         [ #  # ]:           0 :    if (iout/=std_out) then
     364                 :           0 :      call wrtout(iout,message,'COLL')
     365                 :             :    end if
     366                 :           0 :    call wrtout(std_out,  message,'COLL')
     367                 :             :  end if
     368                 :             : 
     369                 :       80092 :  iexit_save=iexit
     370                 :             : 
     371                 :       80092 : end subroutine exit_check
     372                 :             : !!***
     373                 :             : 
     374                 :             : END MODULE m_exit
     375                 :             : !!***
        

Generated by: LCOV version 2.3-1