(git:374b731)
Loading...
Searching...
No Matches
cp_error_handling.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Module that contains the routines for error handling
10!> \author Ole Schuett
11! **************************************************************************************************
13 USE base_hooks, ONLY: cp_abort_hook,&
17 USE kinds, ONLY: dp
18 USE machine, ONLY: default_output_unit,&
19 m_flush,&
21 USE message_passing, ONLY: mp_abort
23 USE timings, ONLY: print_stack
24
25!$ USE OMP_LIB, ONLY: omp_get_thread_num
26
27 IMPLICIT NONE
28 PRIVATE
29
30 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_error_handling'
31
32 !API public routines
34
35 !API (via pointer assignment to hook, PR67982, not meant to be called directly)
37
38 INTEGER, PUBLIC, SAVE :: warning_counter = 0
39
40CONTAINS
41
42! **************************************************************************************************
43!> \brief Registers handlers with base_hooks.F
44!> \author Ole Schuett
45! **************************************************************************************************
50 END SUBROUTINE cp_error_handling_setup
51
52! **************************************************************************************************
53!> \brief Abort program with error message
54!> \param location ...
55!> \param message ...
56!> \author Ole Schuett
57! **************************************************************************************************
58 SUBROUTINE cp_abort_handler(location, message)
59 CHARACTER(len=*), INTENT(in) :: location, message
60
61 INTEGER :: unit_nr
62
63 CALL delay_non_master() ! cleaner output if all ranks abort simultaneously
64
66 IF (unit_nr <= 0) &
67 unit_nr = default_output_unit ! fall back to stdout
68
69 CALL print_abort_message(message, location, unit_nr)
70 CALL print_stack(unit_nr)
71 FLUSH (unit_nr) ! ignore &GLOBAL / FLUSH_SHOULD_FLUSH
72
73 CALL mp_abort()
74 END SUBROUTINE cp_abort_handler
75
76! **************************************************************************************************
77!> \brief Signal a warning
78!> \param location ...
79!> \param message ...
80!> \author Ole Schuett
81! **************************************************************************************************
82 SUBROUTINE cp_warn_handler(location, message)
83 CHARACTER(len=*), INTENT(in) :: location, message
84
85 INTEGER :: unit_nr
86
87!$OMP MASTER
89!$OMP END MASTER
90
92 IF (unit_nr > 0) THEN
93 CALL print_message("WARNING in "//trim(location)//' :: '//trim(adjustl(message)), unit_nr, 1, 1, 1)
94 CALL m_flush(unit_nr)
95 END IF
96 END SUBROUTINE cp_warn_handler
97
98! **************************************************************************************************
99!> \brief Signal a hint
100!> \param location ...
101!> \param message ...
102!> \author Ole Schuett
103! **************************************************************************************************
104 SUBROUTINE cp_hint_handler(location, message)
105 CHARACTER(len=*), INTENT(in) :: location, message
106
107 INTEGER :: unit_nr
108
110 IF (unit_nr > 0) THEN
111 CALL print_message("HINT in "//trim(location)//' :: '//trim(adjustl(message)), unit_nr, 1, 1, 1)
112 CALL m_flush(unit_nr)
113 END IF
114 END SUBROUTINE cp_hint_handler
115
116! **************************************************************************************************
117!> \brief Delay non-master ranks/threads, used by cp_abort_handler()
118!> \author Ole Schuett
119! **************************************************************************************************
120 SUBROUTINE delay_non_master()
121 INTEGER :: unit_nr
122 REAL(kind=dp) :: t1, wait_time
123
124 wait_time = 0.0_dp
125
126 ! we (ab)use the logger to determine the first MPI rank
128 IF (unit_nr <= 0) &
129 wait_time = wait_time + 1.0_dp ! rank-0 gets a head start of one second.
130
131!$ IF (omp_get_thread_num() /= 0) &
132!$ wait_time = wait_time + 1.0_dp ! master threads gets another second
133
134 ! sleep
135 IF (wait_time > 0.0_dp) THEN
136 t1 = m_walltime()
137 DO
138 IF (m_walltime() - t1 > wait_time .OR. t1 < 0) EXIT
139 END DO
140 END IF
141
142 END SUBROUTINE delay_non_master
143
144! **************************************************************************************************
145!> \brief Prints a nicely formatted abort message box
146!> \param message ...
147!> \param location ...
148!> \param output_unit ...
149!> \author Ole Schuett
150! **************************************************************************************************
151 SUBROUTINE print_abort_message(message, location, output_unit)
152 CHARACTER(LEN=*), INTENT(IN) :: message, location
153 INTEGER, INTENT(IN) :: output_unit
154
155 INTEGER, PARAMETER :: img_height = 8, img_width = 9, screen_width = 80, &
156 txt_width = screen_width - img_width - 5
157 CHARACTER(LEN=img_width), DIMENSION(img_height), PARAMETER :: img = [" ___ ", " / \ "&
158 , " [ABORT] ", " \___/ ", " | ", " O/| ", " /| | ", " / \ "]
159
160 CHARACTER(LEN=screen_width) :: msg_line
161 INTEGER :: a, b, c, fill, i, img_start, indent, &
162 msg_height, msg_start
163
164! count message lines
165
166 a = 1; b = -1; msg_height = 0
167 DO WHILE (b < len_trim(message))
168 b = next_linebreak(message, a, txt_width)
169 a = b + 1
170 msg_height = msg_height + 1
171 END DO
172
173 ! calculate message and image starting lines
174 IF (img_height > msg_height) THEN
175 msg_start = (img_height - msg_height)/2 + 1
176 img_start = 1
177 ELSE
178 msg_start = 1
179 img_start = msg_height - img_height + 2
180 END IF
181
182 ! print empty line
183 WRITE (unit=output_unit, fmt="(A)") ""
184
185 ! print opening line
186 WRITE (unit=output_unit, fmt="(T2,A)") repeat("*", screen_width - 1)
187
188 ! print body
189 a = 1; b = -1; c = 1
190 DO i = 1, max(img_height - 1, msg_height)
191 WRITE (unit=output_unit, fmt="(A)", advance='no') " *"
192 IF (i < img_start) THEN
193 WRITE (unit=output_unit, fmt="(A)", advance='no') repeat(" ", img_width)
194 ELSE
195 WRITE (unit=output_unit, fmt="(A)", advance='no') img(c)
196 c = c + 1
197 END IF
198 IF (i < msg_start) THEN
199 WRITE (unit=output_unit, fmt="(A)", advance='no') repeat(" ", txt_width + 2)
200 ELSE
201 b = next_linebreak(message, a, txt_width)
202 msg_line = message(a:b)
203 a = b + 1
204 fill = (txt_width - len_trim(msg_line))/2 + 1
205 indent = txt_width - len_trim(msg_line) - fill + 2
206 WRITE (unit=output_unit, fmt="(A)", advance='no') repeat(" ", indent)
207 WRITE (unit=output_unit, fmt="(A)", advance='no') trim(msg_line)
208 WRITE (unit=output_unit, fmt="(A)", advance='no') repeat(" ", fill)
209 END IF
210 WRITE (unit=output_unit, fmt="(A)", advance='yes') "*"
211 END DO
212
213 ! print location line
214 WRITE (unit=output_unit, fmt="(A)", advance='no') " *"
215 WRITE (unit=output_unit, fmt="(A)", advance='no') img(c)
216 indent = txt_width - len_trim(location) + 1
217 WRITE (unit=output_unit, fmt="(A)", advance='no') repeat(" ", indent)
218 WRITE (unit=output_unit, fmt="(A)", advance='no') trim(location)
219 WRITE (unit=output_unit, fmt="(A)", advance='yes') " *"
220
221 ! print closing line
222 WRITE (unit=output_unit, fmt="(T2,A)") repeat("*", screen_width - 1)
223
224 ! print empty line
225 WRITE (unit=output_unit, fmt="(A)") ""
226
227 END SUBROUTINE print_abort_message
228
229! **************************************************************************************************
230!> \brief Helper routine for print_abort_message()
231!> \param message ...
232!> \param pos ...
233!> \param rowlen ...
234!> \return ...
235!> \author Ole Schuett
236! **************************************************************************************************
237 FUNCTION next_linebreak(message, pos, rowlen) RESULT(ibreak)
238 CHARACTER(LEN=*), INTENT(IN) :: message
239 INTEGER, INTENT(IN) :: pos, rowlen
240 INTEGER :: ibreak
241
242 INTEGER :: i, n
243
244 n = len_trim(message)
245 IF (n - pos <= rowlen) THEN
246 ibreak = n ! remaining message shorter than line
247 ELSE
248 i = index(message(pos + 1:pos + 1 + rowlen), " ", back=.true.)
249 IF (i == 0) THEN
250 ibreak = pos + rowlen - 1 ! no space found, break mid-word
251 ELSE
252 ibreak = pos + i ! break at space closest to rowlen
253 END IF
254 END IF
255 END FUNCTION next_linebreak
256
257END MODULE cp_error_handling
Central dispatch for basic hooks.
Definition base_hooks.F:12
procedure(cp_warn_interface), pointer, public cp_warn_hook
Definition base_hooks.F:59
procedure(cp_abort_interface), pointer, public cp_abort_hook
Definition base_hooks.F:58
procedure(cp_hint_interface), pointer, public cp_hint_hook
Definition base_hooks.F:60
Module that contains the routines for error handling.
integer, save, public warning_counter
subroutine, public cp_abort_handler(location, message)
Abort program with error message.
subroutine, public cp_warn_handler(location, message)
Signal a warning.
subroutine, public cp_error_handling_setup()
Registers handlers with base_hooks.F.
subroutine, public cp_hint_handler(location, message)
Signal a hint.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
integer, parameter, public default_output_unit
Definition machine.F:45
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:106
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:123
Interface to the message passing library MPI.
subroutine, public mp_abort()
globally stops all tasks this is intended to be low level, most of CP2K should call cp_abort()
Perform an abnormal program termination.
subroutine, public print_message(message, output_unit, declev, before, after)
Perform a basic blocking of the text in message and print it optionally decorated with a frame of sta...
Timing routines for accounting.
Definition timings.F:17
subroutine, public print_stack(unit_nr)
Print current routine stack.
Definition timings.F:432