source: trunk/LMDZ.TITAN/libf/muphytitan/errors.F90 @ 1794

Last change on this file since 1794 was 1793, checked in by jvatant, 7 years ago

Making Titan's hazy again, part I
+ Added the source folder libf/muphytitan which contains

YAMMS ( Titan's microphysical model ) from J. Burgalat

+ Modif. compilation files linked to this change
JVO

File size: 11.4 KB
Line 
1! Copyright Jérémie Burgalat (2010-2015)
2!
3! burgalat.jeremie@gmail.com
4!
5! This software is a computer program whose purpose is to provide configuration
6! file and command line arguments parsing features to Fortran programs.
7!
8! This software is governed by the CeCILL-B license under French law and
9! abiding by the rules of distribution of free software.  You can  use,
10! modify and/ or redistribute the software under the terms of the CeCILL-B
11! license as circulated by CEA, CNRS and INRIA at the following URL
12! "http://www.cecill.info".
13!
14! As a counterpart to the access to the source code and  rights to copy,
15! modify and redistribute granted by the license, users are provided only
16! with a limited warranty  and the software's author,  the holder of the
17! economic rights,  and the successive licensors  have only  limited
18! liability.
19!
20! In this respect, the user's attention is drawn to the risks associated
21! with loading,  using,  modifying and/or developing or reproducing the
22! software by the user in light of its specific status of free software,
23! that may mean  that it is complicated to manipulate,  and  that  also
24! therefore means  that it is reserved for developers  and  experienced
25! professionals having in-depth computer knowledge. Users are therefore
26! encouraged to load and test the software's suitability as regards their
27! requirements in conditions enabling the security of their systems and/or
28! data to be ensured and,  more generally, to use and operate it in the
29! same conditions as regards security.
30!
31! The fact that you are presently reading this means that you have had
32! knowledge of the CeCILL-B license and that you accept its terms.
33
34!! file: errors.F90
35!! summary: Errors handling source file
36!! author: Burgalat
37!! date: 2013-2015
38
39#include "defined.h"
40
41MODULE ERRORS
42  !! Error handler module
43  !!
44  !! This module provides a single derived type, [[error(type)]] which is used in all
45  !! other parts of the library in order to handle errors.
46  USE, INTRINSIC :: ISO_C_BINDING
47  USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : stdout=>OUTPUT_UNIT, stderr=>ERROR_UNIT
48
49  IMPLICIT NONE
50
51  PUBLIC
52
53  PRIVATE :: error_equals,error_equals_int,error_differs,error_differs_int, &
54             msg_length
55
56
57  INTEGER, PARAMETER :: msg_length = 250 !! Length of error message.
58
59  TYPE, PUBLIC :: error
60    !! Define an error
61    !!
62    !! The following derived type represents in the simplest way (I believe) an error which
63    !! stores:
64    !!
65    !! - An integer to numerically identify the error
66    !! - A string (250 chars max) with an appropriate error message
67    !! - A bounded procedure to get a string representation of the error (if bounded
68    !!   procedures are supported by the library).
69    !! - internal subroutines for derived type IO WRITE statement (if Derived IO
70    !!   subroutines are supported by the library).
71    !!
72    !! error type comes also with two operators ("==", "/=") to compare error type with
73    !! another one or an integer.
74    !! If an error is not initialized explicitly, then it is set to [[errors(module):noerror(variable)]].
75    CHARACTER(len=msg_length) :: msg = "No error"
76      !! Message associated to the error
77      !! @note
78      !! The message should be short (250 characters maximum) and explicit.
79    INTEGER :: id = 0
80      !! Numerical identifier of the error
81      !! @note
82      !! The error identifier is used to test the equality/inequality of two error objects.
83#if HAVE_FTNPROC
84    CONTAINS
85      PROCEDURE, PUBLIC :: to_string => error_to_string
86        !! Get a string representation of the error
87!#if HAVE_FTNDTIO
88!      PROCEDURE, PRIVATE :: e_write_wfm
89!      PROCEDURE, PRIVATE :: e_write_wofm
90!      GENERIC, PUBLIC :: write(formatted) => e_write_wfm
91!        !! Generic formatted write statement subroutine interface
92!      GENERIC, PUBLIC :: write(unformatted) => e_write_wofm
93!        !! Generic unformatted write statement subroutine interface
94!#endif
95#endif
96  END TYPE error
97
98  INTERFACE
99    !! Clean subroutine interface
100    SUBROUTINE clean_callback(err)
101      !! A subroutine that may perform cleaning computation(s) before exit
102      IMPORT error
103      IMPLICIT NONE
104      TYPE(error), INTENT(in) :: err
105        !! An error object with the input error
106    END SUBROUTINE clean_callback
107  END INTERFACE
108
109  INTERFACE
110    subroutine abort_() bind(C, name="abort")
111    end subroutine
112  END INTERFACE
113
114  INTERFACE assert
115    !! _Raise_ an assertion.
116    !!
117    !! An assertion can be understood as a development error that should be raised in production mode.
118    MODULE PROCEDURE :: assert_r,assert_w
119  END INTERFACE assert
120
121  !> error equality operator
122  INTERFACE OPERATOR(==)
123    MODULE PROCEDURE error_equals, error_equals_int
124  END INTERFACE
125
126  !> error inequality operator
127  INTERFACE OPERATOR(/=)
128    MODULE PROCEDURE error_differs, error_differs_int
129  END INTERFACE
130
131  !> The no error error !
132  TYPE(error), PUBLIC, PARAMETER :: noerror = error("No error",0)
133
134  CONTAINS
135
136!===============================================================================
137! error TYPE RELATED METHODS
138!===============================================================================
139
140  FUNCTION error_equals(this, other) RESULT(res)
141    !! Check if two error objects are equivalent
142    TYPE(error), INTENT(in) :: this, & !! The first error object to compare
143                               other   !! The second error object to compare
144    LOGICAL :: res                     !! .true. if __this__ and __other__ identifiers are the same, .false. otherwise
145    res = (this%id == other%id)
146    RETURN
147  END FUNCTION error_equals
148
149  FUNCTION error_equals_int(this, id) RESULT(res)
150    !! Check if an error id is equal to a given integer
151    TYPE(error), INTENT(in) :: this !! An error object reference
152    INTEGER, INTENT(in)     :: id   !! An integer to compare to __this__ identifier
153    LOGICAL :: res                  !! .true. if __this__ identifier and __id__ have the same value, .false. otherwise
154    res = (this%id == id)
155    RETURN
156  END FUNCTION error_equals_int
157
158  FUNCTION error_differs(this, other) RESULT(res)
159    !! Check if two error objects are different
160    TYPE(error), INTENT(in) :: this, & !! The first error object to compare
161                               other   !! The second error object to compare
162    LOGICAL :: res                     !! .false. if __this__ and __other__ identifiers are the same, .true. otherwise
163    res = (this%id /= other%id)
164    RETURN
165  END FUNCTION error_differs
166
167  FUNCTION error_differs_int(this, id) RESULT(res)
168    !! Check if an error id is different from a given integer
169    TYPE(error), INTENT(in) :: this !! An error object reference
170    INTEGER, INTENT(in)     :: id   !! An integer to compare to __this__ identifier
171    LOGICAL :: res                  !! .false. if __this__ identifier and __id__ have the same value, .true. otherwise
172    res = (this%id /= id)
173    RETURN
174  END FUNCTION error_differs_int
175
176  FUNCTION error_to_string(this,progname,as_warning) RESULT(str)
177    !! (simple) String representation of the error
178    !!
179    !! The function returns a very simple formatted string with the error.
180    OBJECT(error), INTENT(in)              :: this
181      !! An error object reference
182    CHARACTER(len=*), INTENT(in), OPTIONAL :: progname
183      !! An optional string with the name of the program
184    LOGICAL, INTENT(in), OPTIONAL          :: as_warning
185      !! An optional boolean flag to print the message as warning rather than as error (default to .false.).
186    CHARACTER(len=:), ALLOCATABLE :: str
187      !! An allocatable string with the string representation of the error
188    CHARACTER(len=:), ALLOCATABLE :: pref
189    pref = "error: "
190    IF (PRESENT(as_warning)) THEN ; IF (as_warning) pref = "warning: " ; ENDIF
191    IF (PRESENT(progname)) THEN
192      IF (LEN_TRIM(progname) /=0) THEN
193        str = TRIM(progname)//': '//pref//TRIM(this%msg)
194      ELSE
195        str = pref//TRIM(this%msg)
196      ENDIF
197    ELSE
198      str = pref//TRIM(this%msg)
199    ENDIF
200    RETURN
201  END FUNCTION error_to_string
202
203!#if HAVE_FTNDTIO
204!  SUBROUTINE e_write_wfm(dtv,unit,iotype,v_list,iostat,iomsg)
205!    !> Error derived type formatted IO write statement subroutine
206!    !!
207!    !! The method quietly ignores the derived type edit descriptor as the
208!    !! purpose of the subroutine is only to print a string. The edit descriptor
209!    !! used here is simply '(a)'.
210!    CLASS(error), INTENT(in)         :: dtv
211!      !! A reference to the string object
212!    INTEGER, INTENT(in)              :: unit
213!      !! Logical unit where to print the object
214!    CHARACTER (len=*), INTENT(in)    :: iotype
215!      !! Type of IO
216!    INTEGER, INTENT(in)              :: v_list(:)
217!      !! List of value from edit descriptor
218!    INTEGER, INTENT(out)             :: iostat
219!      !! Error status code (set to 2 if dtv's value if not allocated)
220!    CHARACTER (len=*), INTENT(inout) :: iomsg
221!      !! Error message
222!    CHARACTER(len=15) :: i2s
223!    iostat = 0 ; iomsg = ""
224!    WRITE(i2s,'(I15)') dtv%id ; i2s=ADJUSTL(i2s)
225!    WRITE(unit, '(a)') 'error('//TRIM(i2s)//'): '//TRIM(dtv%msg)
226!  END SUBROUTINE e_write_wfm
227!
228!  SUBROUTINE e_write_wofm(dtv, unit, iostat, iomsg)
229!    !! Error type IO unformatted write statement subroutine
230!    CLASS(error), INTENT(in)         :: dtv
231!      !! A reference to the string object
232!    INTEGER, INTENT(in)              :: unit
233!      !! Logical unit where to print the object
234!    INTEGER, INTENT(out)             :: iostat
235!      !! Error status code (set to 2 if dtv's value if not allocated)
236!    CHARACTER (len=*), INTENT(inout) :: iomsg
237!      !! Error message
238!    CHARACTER(len=15) :: i2s
239!    iostat = 0 ; iomsg = ""
240!    WRITE(i2s,'(I15)') dtv%id ; i2s=ADJUSTL(i2s)
241!    WRITE(unit, '(a)') 'error('//TRIM(i2s)//'): '//TRIM(dtv%msg)
242!  END SUBROUTINE e_write_wofm
243!#endif
244
245  SUBROUTINE aborting(err)
246    !! Abort the program with specific exit code
247    !!
248    !! The method prints the message of the given error object and
249    !! stops the program using exit() subroutine.
250    TYPE(error), INTENT(in) :: err
251      !! An error object
252    IF (err /= 0) THEN
253      WRITE(*,'(a)') error_to_string(err)
254      CALL EXIT(err%id)
255    ENDIF
256  END SUBROUTINE aborting
257
258  SUBROUTINE assert_r(test,reason)
259    !! _Raise_ an assertion.
260    !!
261    !! The method raises an assertion and stops the execution if __test__ is .false.
262    !!
263    !! @note
264    !! If ISO_C_BINDING module is available, the method calls the method abort from the C standard library. Doing so,
265    !! developer is able to debug the source code by getting the backtrace of the execution.
266    !! In other situation, the method simply uses the Fortran STOP statement which makes its usage... useless.
267   LOGICAL, INTENT(in)          :: test
268     !! Expression to test.
269   CHARACTER(len=*), INTENT(in) :: reason
270     !! Optional assertion reason.
271   IF (.NOT.test) THEN
272     WRITE(stderr,'(a)') "assertion: "//reason
273     call abort_()
274   ENDIF
275  END SUBROUTINE assert_r
276
277  SUBROUTINE assert_w(test,where,reason)
278    !! _Raise_ an assertion.
279    !!
280    !! The method raises an assertion and stops the execution if __test__ is .false.
281    !!
282    !! See [[errors(module):assert_r(subroutine)] remark.
283    LOGICAL, INTENT(in)         :: test
284     !! Expression to test.
285   CHARACTER(len=*), INTENT(in) :: where
286     !! Optional _location_ of the assertion.
287   CHARACTER(len=*), INTENT(in) :: reason
288     !! Optional assertion reason.
289   IF (.NOT.test) THEN
290     WRITE(stderr,'(a)') "assertion in "//where//": "//reason
291     call abort_()
292   ENDIF
293  END SUBROUTINE assert_w
294
295
296END MODULE ERRORS
297
Note: See TracBrowser for help on using the repository browser.