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

Last change on this file since 3000 was 1897, checked in by jvatant, 7 years ago

Making Titan's hazy again - part II
+ Major updates of J.Burgalat YAMMS library and optical coupling, including :
++ Added the routines for haze optics inside YAMMS
++ Calling rad. transf. with interactive haze is plugged
in but should stay unactive as long as the microphysics is
in test phase : cf "uncoupl_optic_haze" flag : true for now !
++ Also some sanity checks for negative tendencies and
some others upkeep of YAMMS model
+ Also added a temporary CPP key USE_QTEST in physiq_mod
that enables to have microphysical tendencies separated
from dynamics for debugging and test phases
-- JVO and JB

File size: 10.3 KB
Line 
1! Copyright Jérémie Burgalat (2010-2015,2017)
2!
3! jeremie.burgalat@univ-reims.fr
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: J. Burgalat
37!! date: 2013-2015,2017
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#endif
88  END TYPE error
89
90  INTERFACE
91    !! Clean subroutine interface
92    SUBROUTINE clean_callback(err)
93      !! A subroutine that may perform cleaning computation(s) before exit
94      IMPORT error
95      IMPLICIT NONE
96      TYPE(error), INTENT(in) :: err
97        !! An error object with the input error
98    END SUBROUTINE clean_callback
99  END INTERFACE
100
101  INTERFACE
102    subroutine abort_() bind(C, name="abort")
103    end subroutine
104  END INTERFACE
105
106  INTERFACE assert
107    !! _Raise_ an assertion.
108    !!
109    !! An assertion can be understood as a development error that should be raised in production mode.
110    MODULE PROCEDURE :: assert_r,assert_w
111  END INTERFACE assert
112
113  !> error equality operator
114  INTERFACE OPERATOR(==)
115    MODULE PROCEDURE error_equals, error_equals_int
116  END INTERFACE
117
118  !> error inequality operator
119  INTERFACE OPERATOR(/=)
120    MODULE PROCEDURE error_differs, error_differs_int
121  END INTERFACE
122
123  !> The no error error !
124  TYPE(error), PUBLIC, PARAMETER :: noerror = error("No error",0)
125
126  CONTAINS
127
128!===============================================================================
129! error TYPE RELATED METHODS
130!===============================================================================
131
132  FUNCTION error_equals(this, other) RESULT(res)
133    !! Check if two error objects are equivalent
134    TYPE(error), INTENT(in) :: this, & !! The first error object to compare
135                               other   !! The second error object to compare
136    LOGICAL :: res                     !! .true. if __this__ and __other__ identifiers are the same, .false. otherwise
137    res = (this%id == other%id)
138    RETURN
139  END FUNCTION error_equals
140
141  FUNCTION error_equals_int(this, id) RESULT(res)
142    !! Check if an error id is equal to a given integer
143    TYPE(error), INTENT(in) :: this !! An error object reference
144    INTEGER, INTENT(in)     :: id   !! An integer to compare to __this__ identifier
145    LOGICAL :: res                  !! .true. if __this__ identifier and __id__ have the same value, .false. otherwise
146    res = (this%id == id)
147    RETURN
148  END FUNCTION error_equals_int
149
150  FUNCTION error_differs(this, other) RESULT(res)
151    !! Check if two error objects are different
152    TYPE(error), INTENT(in) :: this, & !! The first error object to compare
153                               other   !! The second error object to compare
154    LOGICAL :: res                     !! .false. if __this__ and __other__ identifiers are the same, .true. otherwise
155    res = (this%id /= other%id)
156    RETURN
157  END FUNCTION error_differs
158
159  FUNCTION error_differs_int(this, id) RESULT(res)
160    !! Check if an error id is different from a given integer
161    TYPE(error), INTENT(in) :: this !! An error object reference
162    INTEGER, INTENT(in)     :: id   !! An integer to compare to __this__ identifier
163    LOGICAL :: res                  !! .false. if __this__ identifier and __id__ have the same value, .true. otherwise
164    res = (this%id /= id)
165    RETURN
166  END FUNCTION error_differs_int
167
168  FUNCTION error_to_string(this,progname,as_warning) RESULT(str)
169    !! (simple) String representation of the error
170    !!
171    !! The function returns a very simple formatted string with the error.
172    OBJECT(error), INTENT(in)              :: this
173      !! An error object reference
174    CHARACTER(len=*), INTENT(in), OPTIONAL :: progname
175      !! An optional string with the name of the program
176    LOGICAL, INTENT(in), OPTIONAL          :: as_warning
177      !! An optional boolean flag to print the message as warning rather than as error (default to .false.).
178    CHARACTER(len=:), ALLOCATABLE :: str
179      !! An allocatable string with the string representation of the error
180    CHARACTER(len=:), ALLOCATABLE :: pref
181    pref = "error: "
182    IF (PRESENT(as_warning)) THEN ; IF (as_warning) pref = "warning: " ; ENDIF
183    IF (PRESENT(progname)) THEN
184      IF (LEN_TRIM(progname) /=0) THEN
185        str = TRIM(progname)//': '//pref//TRIM(this%msg)
186      ELSE
187        str = pref//TRIM(this%msg)
188      ENDIF
189    ELSE
190      str = pref//TRIM(this%msg)
191    ENDIF
192    RETURN
193  END FUNCTION error_to_string
194
195  SUBROUTINE aborting(err)
196    !! Abort the program with specific exit code
197    !!
198    !! The method prints the message of the given error object and
199    !! stops the program using exit() subroutine.
200    TYPE(error), INTENT(in) :: err
201      !! An error object
202    IF (err /= 0) THEN
203      WRITE(*,'(a)') error_to_string(err)
204      CALL EXIT(err%id)
205    ENDIF
206  END SUBROUTINE aborting
207
208  SUBROUTINE assert_r(test,reason)
209    !! _Raise_ an assertion.
210    !!
211    !! The method raises an assertion and stops the execution if __test__ is .false.
212    !!
213    !! @note
214    !! If ISO_C_BINDING module is available, the method calls the method abort from the C standard library. Doing so,
215    !! developer is able to debug the source code by getting the backtrace of the execution.
216    !! In other situation, the method simply uses the Fortran STOP statement which makes its usage... useless.
217   LOGICAL, INTENT(in)          :: test
218     !! Expression to test.
219   CHARACTER(len=*), INTENT(in) :: reason
220     !! Optional assertion reason.
221   IF (.NOT.test) THEN
222     WRITE(stderr,'(a)') "assertion: "//reason
223     call abort_()
224   ENDIF
225  END SUBROUTINE assert_r
226
227  SUBROUTINE assert_w(test,where,reason)
228    !! _Raise_ an assertion.
229    !!
230    !! The method raises an assertion and stops the execution if __test__ is .false.
231    !!
232    !! See [[errors(module):assert_r(subroutine)]] remark.
233    LOGICAL, INTENT(in)         :: test
234     !! Expression to test.
235   CHARACTER(len=*), INTENT(in) :: where
236     !! Optional _location_ of the assertion.
237   CHARACTER(len=*), INTENT(in) :: reason
238     !! Optional assertion reason.
239   IF (.NOT.test) THEN
240     WRITE(stderr,'(a)') "assertion in "//where//": "//reason
241     call abort_()
242   ENDIF
243  END SUBROUTINE assert_w
244
245  FUNCTION free_lun() RESULT(lu)
246    !> Get the first free logical unit
247    !!
248    !! The function loops from 7 to 9999 and returns the first free logical unit.
249    !! @note
250    !! According to Fortran standard, the maximum value for a lun is processor
251    !! dependent. I just assume that [7,9999] is a valid range and I believe that
252    !! 9992 files to be opened is far enough for any program !
253    !! @note
254    !! If you intend to use loggers object from this library, you should keep in
255    !! mind that loggers open files with the first free logical unit. Consequently
256    !! if you need to perform I/O operations you should use this function to get a
257    !! free lun instead of just randomly set a lun !
258    INTEGER :: lu
259      !! First free logical unit in the range [7,9999]  or -1 if no lun is available
260    INTEGER, PARAMETER :: mxlu = 9999
261    LOGICAL :: notfree
262    lu = 6 ; notfree = .true.
263    DO WHILE(notfree.AND.lu<=mxlu)
264      lu=lu+1 ; INQUIRE(unit=lu,OPENED=notfree)
265    ENDDO
266    IF (lu >= mxlu) lu = -1
267  END FUNCTION free_lun
268
269
270
271END MODULE ERRORS
272
Note: See TracBrowser for help on using the repository browser.