forked from openmc-dev/openmc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherror.F90
277 lines (221 loc) · 8.74 KB
/
error.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
module error
use, intrinsic :: ISO_C_BINDING
use, intrinsic :: ISO_FORTRAN_ENV
use constants
use message_passing
use settings, only: verbosity
implicit none
private
public :: fatal_error
public :: warning
public :: write_message
! Error codes
integer(C_INT), public, bind(C, name='OPENMC_E_UNASSIGNED') :: E_UNASSIGNED = -1
integer(C_INT), public, bind(C, name='OPENMC_E_ALLOCATE') :: E_ALLOCATE = -2
integer(C_INT), public, bind(C, name='OPENMC_E_OUT_OF_BOUNDS') :: E_OUT_OF_BOUNDS = -3
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_SIZE') :: E_INVALID_SIZE = -4
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_ARGUMENT') :: E_INVALID_ARGUMENT = -5
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_TYPE') :: E_INVALID_TYPE = -6
integer(C_INT), public, bind(C, name='OPENMC_E_INVALID_ID') :: E_INVALID_ID = -7
integer(C_INT), public, bind(C, name='OPENMC_E_GEOMETRY') :: E_GEOMETRY = -8
integer(C_INT), public, bind(C, name='OPENMC_E_DATA') :: E_DATA = -9
integer(C_INT), public, bind(C, name='OPENMC_E_PHYSICS') :: E_PHYSICS = -10
! Warning codes
integer(C_INT), public, bind(C, name='OPENMC_E_WARNING') :: E_WARNING = 1
! Error message
character(kind=C_CHAR), public, bind(C) :: openmc_err_msg(256)
public :: set_errmsg
contains
!===============================================================================
! SET_ERRMSG sets the 'openmc_err_msg' module variable that is exposed via the C
! API
!===============================================================================
subroutine set_errmsg(f_string)
character(*), intent(in) :: f_string
integer :: i, n
! Copy Fortran string to null-terminated C char array
n = len_trim(f_string)
do i = 1, n
openmc_err_msg(i) = f_string(i:i)
end do
openmc_err_msg(n + 1) = C_NULL_CHAR
end subroutine set_errmsg
!===============================================================================
! WARNING issues a warning to the user in the log file and the standard output
! stream.
!===============================================================================
subroutine warning(message)
character(*) :: message
integer :: i_start ! starting position
integer :: i_end ! ending position
integer :: line_wrap ! length of line
integer :: length ! length of message
integer :: indent ! length of indentation
! Write warning at beginning
write(ERROR_UNIT, fmt='(1X,A)', advance='no') 'WARNING: '
! Set line wrapping and indentation
line_wrap = 80
indent = 10
! Determine length of message
length = len_trim(message)
i_start = 0
do
if (length - i_start < line_wrap - indent + 1) then
! Remainder of message will fit on line
write(ERROR_UNIT, fmt='(A)') message(i_start+1:length)
exit
else
! Determine last space in current line
i_end = i_start + index(message(i_start+1:i_start+line_wrap-indent+1), &
' ', BACK=.true.)
if (i_end == i_start) then
! This is a special case where there is no space
i_end = i_start + line_wrap - indent + 1
write(ERROR_UNIT, fmt='(A/A)', advance='no') &
message(i_start+1:i_end-1), repeat(' ', indent)
i_end = i_end - 1
else
! Write up to last space
write(ERROR_UNIT, fmt='(A/A)', advance='no') &
message(i_start+1:i_end-1), repeat(' ', indent)
end if
! Advance starting position
i_start = i_end
if (i_start > length) exit
end if
end do
end subroutine warning
subroutine warning_from_c(message, message_len) bind(C)
integer(C_INT), intent(in), value :: message_len
character(kind=C_CHAR), intent(in) :: message(message_len)
character(message_len+1) :: message_out
write(message_out, *) message
call warning(message_out)
end subroutine
!===============================================================================
! FATAL_ERROR alerts the user that an error has been encountered and displays a
! message about the particular problem. Errors are considered 'fatal' and hence
! the program is aborted.
!===============================================================================
subroutine fatal_error(message, error_code)
character(*) :: message
integer, optional :: error_code ! error code
integer :: code ! error code
integer :: i_start ! starting position
integer :: i_end ! ending position
integer :: line_wrap ! length of line
integer :: length ! length of message
integer :: indent ! length of indentation
#ifdef OPENMC_MPI
integer :: mpi_err
#endif
! set default error code
if (present(error_code)) then
code = error_code
else
code = -1
end if
! Write error at beginning
write(ERROR_UNIT, fmt='(1X,A)', advance='no') 'ERROR: '
! Set line wrapping and indentation
line_wrap = 80
indent = 8
! Determine length of message
length = len_trim(message)
i_start = 0
do
if (length - i_start < line_wrap - indent + 1) then
! Remainder of message will fit on line
write(ERROR_UNIT, fmt='(A)') message(i_start+1:length)
exit
else
! Determine last space in current line
i_end = i_start + index(message(i_start+1:i_start+line_wrap-indent+1), &
' ', BACK=.true.)
if (i_end == i_start) then
! This is a special case where there is no space
i_end = i_start + line_wrap - indent + 1
write(ERROR_UNIT, fmt='(A/A)', advance='no') &
message(i_start+1:i_end-1), repeat(' ', indent)
i_end = i_end - 1
else
! Write up to last space
write(ERROR_UNIT, fmt='(A/A)', advance='no') &
message(i_start+1:i_end-1), repeat(' ', indent)
end if
! Advance starting position
i_start = i_end
if (i_start > length) exit
end if
end do
#ifdef OPENMC_MPI
! Abort MPI
call MPI_ABORT(mpi_intracomm, code, mpi_err)
#endif
! Abort program
#ifdef NO_F2008
stop
#else
error stop
#endif
end subroutine fatal_error
subroutine fatal_error_from_c(message, message_len) bind(C)
integer(C_INT), intent(in), value :: message_len
character(kind=C_CHAR), intent(in) :: message(message_len)
character(message_len+1) :: message_out
write(message_out, *) message
call fatal_error(message_out)
end subroutine
!===============================================================================
! WRITE_MESSAGE displays an informational message to the log file and the
! standard output stream.
!===============================================================================
subroutine write_message(message, level)
character(*), intent(in) :: message ! message to write
integer, intent(in), optional :: level ! verbosity level
integer :: i_start ! starting position
integer :: i_end ! ending position
integer :: line_wrap ! length of line
integer :: length ! length of message
integer :: last_space ! index of last space (relative to start)
! Set length of line
line_wrap = 80
! Only allow master to print to screen
if (.not. master .and. present(level)) return
if (.not. present(level) .or. level <= verbosity) then
! Determine length of message
length = len_trim(message)
i_start = 0
do
if (length - i_start < line_wrap + 1) then
! Remainder of message will fit on line
write(OUTPUT_UNIT, fmt='(1X,A)') message(i_start+1:length)
exit
else
! Determine last space in current line
last_space = index(message(i_start+1:i_start+line_wrap), &
' ', BACK=.true.)
if (last_space == 0) then
i_end = min(length + 1, i_start+line_wrap) - 1
write(OUTPUT_UNIT, fmt='(1X,A)') message(i_start+1:i_end)
else
i_end = i_start + last_space
write(OUTPUT_UNIT, fmt='(1X,A)') message(i_start+1:i_end-1)
end if
! Write up to last space
! Advance starting position
i_start = i_end
if (i_start > length) exit
end if
end do
end if
end subroutine write_message
subroutine write_message_from_c(message, message_len, level) bind(C)
integer(C_INT), intent(in), value :: message_len
character(kind=C_CHAR), intent(in) :: message(message_len)
integer(C_INT), intent(in), value :: level
character(message_len+1) :: message_out
write(message_out, *) message
call write_message(message_out, level)
end subroutine write_message_from_c
end module error