logging_base.f90
Go to the documentation of this file.
1 !#############################################################################
2 !# #
3 !# fosite - 3D hydrodynamical simulation program #
4 !# module: common_types.f90 #
5 !# #
6 !# Copyright (C) 2006-2014 #
7 !# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
8 !# #
9 !# This program is free software; you can redistribute it and/or modify #
10 !# it under the terms of the GNU General Public License as published by #
11 !# the Free Software Foundation; either version 2 of the License, or (at #
12 !# your option) any later version. #
13 !# #
14 !# This program is distributed in the hope that it will be useful, but #
15 !# WITHOUT ANY WARRANTY; without even the implied warranty of #
16 !# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
17 !# NON INFRINGEMENT. See the GNU General Public License for more #
18 !# details. #
19 !# #
20 !# You should have received a copy of the GNU General Public License #
21 !# along with this program; if not, write to the Free Software #
22 !# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
23 !# #
24 !#############################################################################
25 
26 !----------------------------------------------------------------------------!
35 !----------------------------------------------------------------------------!
37 #ifdef PARALLEL
38 #ifdef HAVE_MPI_MOD
39  USE mpi
40 #endif
41 #endif
42  IMPLICIT NONE
43 #ifdef PARALLEL
44 #ifdef HAVE_MPIF_H
45  include 'mpif.h'
46 #endif
47 #endif
48  !--------------------------------------------------------------------------!
49  PRIVATE
57  PRIVATE
58  INTEGER :: mod_type
59  CHARACTER(LEN=32) :: mod_name
60  INTEGER, PUBLIC :: err
61  LOGICAL :: isinitialized = .false.
62  INTEGER, POINTER :: myrank => null()
63  INTEGER, POINTER :: ppnum => null()
64  LOGICAL, POINTER :: parinit => null()
65  CONTAINS
66  PROCEDURE :: initlogging
67  final :: finalize
68  PROCEDURE :: gettype
69  PROCEDURE :: getname
70  PROCEDURE :: getrank
71  PROCEDURE :: getnumprocs
72  PROCEDURE :: initialized
73  PROCEDURE :: info
74  PROCEDURE :: warning
75  PROCEDURE :: error
76  END TYPE logging_base
77  ! these variables should be the same for all objects
78  ! of the current process
79 #ifdef PARALLEL
80  INTEGER, SAVE :: default_mpi_real = mpi_real
81  INTEGER, SAVE :: default_mpi_2real = mpi_2real
82  INTEGER, SAVE :: default_mpi_complex = mpi_double_complex
83  REAL, PARAMETER :: dummy = 1.0
84 #endif
85  REAL, SAVE :: nan_default_real
86  INTEGER, PARAMETER :: stderr = 0
87  INTEGER, PARAMETER :: stdout = 6
88  INTEGER, SAVE, TARGET :: myrank = 0
89  INTEGER, SAVE, TARGET :: ppnum = 1
90  LOGICAL, SAVE, TARGET :: parinit = .false.
91  CHARACTER(LEN=1), SAVE :: prefix = ' '
92  !--------------------------------------------------------------------------!
93  PUBLIC :: &
94  ! types
95  logging_base, &
96 #ifdef PARALLEL
100 #endif
102  setprefix
103  !--------------------------------------------------------------------------!
104 
105 CONTAINS
106 
113  SUBROUTINE initlogging(this,t,n)
114  use, INTRINSIC :: ieee_arithmetic
115  IMPLICIT NONE
116  !------------------------------------------------------------------------!
117  CLASS(logging_base), INTENT(INOUT) :: this
118  INTEGER :: t
119  CHARACTER(LEN=*) :: n
120  !------------------------------------------------------------------------!
121  INTENT(IN) :: t,n
122  !------------------------------------------------------------------------!
123  this%mod_type = t
124  this%mod_name = n
125  this%myrank => myrank
126  this%ppnum => ppnum
127  this%parinit => parinit
128 #ifdef PARALLEL
129  IF (.NOT.parinit) THEN
130  CALL mpi_comm_rank(mpi_comm_world,this%myrank,this%err)
131  CALL mpi_comm_size(mpi_comm_world,this%ppnum,this%err)
132  this%parinit = .true.
133  ! determine the default MPI data type for real numbers
134  SELECT CASE (selected_real_kind(precision(dummy)))
135  CASE(4)
136  default_mpi_real = mpi_real4
137  default_mpi_2real = mpi_2real
138  CASE(8)
139  default_mpi_real = mpi_real8
140  default_mpi_2real = mpi_2double_precision
141  CASE DEFAULT
142  CALL warning(this,"InitCommon","Cannot determine default MPI real types.")
143  END SELECT
144  END IF
145 #endif
146  nan_default_real = ieee_value(nan_default_real,ieee_quiet_nan)
147  this%err = 0
148  this%isinitialized = .true.
149  END SUBROUTINE initlogging
150 
151 
154  SUBROUTINE finalize(this)
155  IMPLICIT NONE
156  !------------------------------------------------------------------------!
157  TYPE(logging_base), INTENT(INOUT) :: this
158  !------------------------------------------------------------------------!
159  this%isinitialized = .false.
160  END SUBROUTINE finalize
161 
162 
165  PURE FUNCTION gettype(this) RESULT(t)
166  IMPLICIT NONE
167  !------------------------------------------------------------------------!
168  CLASS(logging_base), INTENT(IN) :: this
169  INTEGER :: t
170  !------------------------------------------------------------------------!
171  t = this%mod_type
172  END FUNCTION gettype
173 
174 
177  SUBROUTINE setprefix(val)
178  IMPLICIT NONE
179  !------------------------------------------------------------------------!
180  CHARACTER(LEN=1), INTENT(IN) :: val
181  !------------------------------------------------------------------------!
182  prefix = val
183  END SUBROUTINE setprefix
184 
185 
188  PURE FUNCTION getname(this) RESULT(n)
189  IMPLICIT NONE
190  !------------------------------------------------------------------------!
191  CLASS(logging_base), INTENT(IN) :: this
192  CHARACTER(LEN=32) :: n
193  !------------------------------------------------------------------------!
194  n = this%mod_name
195  END FUNCTION getname
196 
197 
204  PURE FUNCTION getrank(this) RESULT(r)
205  IMPLICIT NONE
206  !------------------------------------------------------------------------!
207  CLASS(logging_base), INTENT(IN) :: this
208  INTEGER :: r
209  !------------------------------------------------------------------------!
210  r = this%myrank
211  END FUNCTION getrank
212 
213 
218  PURE FUNCTION getnumprocs(this) RESULT(p)
219  IMPLICIT NONE
220  !------------------------------------------------------------------------!
221  CLASS(logging_base), INTENT(IN) :: this
222  INTEGER :: p
223  !------------------------------------------------------------------------!
224  p = this%ppnum
225  END FUNCTION getnumprocs
226 
227 
232  PURE FUNCTION initialized(this) RESULT(i)
233  IMPLICIT NONE
234  !------------------------------------------------------------------------!
235  CLASS(logging_base), INTENT(IN) :: this
236  LOGICAL :: i
237  !------------------------------------------------------------------------!
238  i = this%isinitialized
239 #ifdef PARALLEL
240  IF (ASSOCIATED(this%parinit)) THEN
241  i = i.AND.this%parinit
242  ELSE
243  i = .false.
244  END IF
245 #endif
246  END FUNCTION initialized
247 
248 
259  SUBROUTINE info(this,msg,rank,node_info,tostderr)
260  IMPLICIT NONE
261  !------------------------------------------------------------------------!
262  CLASS(logging_base), INTENT(IN) :: this
263  CHARACTER(LEN=*), INTENT(IN) :: msg
264  INTEGER, OPTIONAL, INTENT(IN) :: rank
265  LOGICAL, OPTIONAL, INTENT(IN) :: node_info
266  LOGICAL, OPTIONAL, INTENT(IN) :: tostderr
267  !------------------------------------------------------------------------!
268 #ifdef PARALLEL
269  INTEGER :: ierr
270 #endif
271  INTEGER :: print_rank,output_unit
272  LOGICAL :: print_node_info
273  !------------------------------------------------------------------------!
274  IF (PRESENT(rank)) THEN
275  print_rank = rank
276  ELSE
277  print_rank = 0
278  END IF
279  IF (PRESENT(node_info)) THEN
280  print_node_info = node_info
281  ELSE
282  print_node_info = .false.
283  END IF
284  ! output unit for printing, defaults to STDOUT
285  output_unit = stdout
286  IF (PRESENT(tostderr)) THEN
287  IF (tostderr) output_unit = stderr ! print on STDERR if requested
288  ENDIF
289 #ifdef PARALLEL
290  IF (.NOT.parinit) CALL mpi_comm_rank(mpi_comm_world,myrank,ierr)
291 #endif
292  ! use "myrank" here instead of "this%myrank"
293  ! because "this" might be uninitialized
294  IF (myrank.EQ.print_rank) THEN
295  WRITE (output_unit,'(A)',advance='NO') prefix
296 #ifdef PARALLEL
297  IF (print_node_info) &
298  WRITE (output_unit,'(A,I4.4,A)',advance='NO') "NODE [", myrank, "] "
299 #endif
300  WRITE (output_unit,'(A)') trim(msg)
301  ! Flush the output buffer, to make sure it is written even if the
302  ! program is invoked from a batch system.
303  ! This is Fortran 2003 standard! In Fortran 90/95 flush is implemented
304  ! as a subroutine, hence one needs a CALL statement, i.e.,
305  ! CALL FLUSH(output_unit)
306  FLUSH(output_unit)
307  END IF
308  END SUBROUTINE info
309 
310 
315  SUBROUTINE warning(this,modproc,msg,rank)
316  IMPLICIT NONE
317  !------------------------------------------------------------------------!
318  CLASS(logging_base), INTENT(IN) :: this
319  CHARACTER(LEN=*), INTENT(IN) :: modproc
320  CHARACTER(LEN=*), INTENT(IN) :: msg
321  INTEGER, OPTIONAL, INTENT(IN) :: rank
322  !------------------------------------------------------------------------!
323  CALL info(this,"WARNING in " // trim(modproc) // ": " // trim(msg),&
324  rank,node_info=.true.,tostderr=.true.)
325  END SUBROUTINE warning
326 
327 
333  SUBROUTINE error(this,modproc,msg,rank,node_info)
334  IMPLICIT NONE
335  !------------------------------------------------------------------------!
336  CLASS(logging_base), INTENT(IN) :: this
337  CHARACTER(LEN=*), INTENT(IN) :: modproc
338  CHARACTER(LEN=*), INTENT(IN) :: msg
339  INTEGER, OPTIONAL, INTENT(IN) :: rank
340  LOGICAL, OPTIONAL, INTENT(IN) :: node_info
341  !------------------------------------------------------------------------!
342 #ifdef PARALLEL
343  INTEGER :: ierr
344 #endif
345  !------------------------------------------------------------------------!
346  CALL info(this,"ERROR in " // trim(modproc) // ": " // trim(msg),&
347  rank=rank,node_info=node_info,tostderr=.true.)
348  ! abort execution
349 #ifdef PARALLEL
350  CALL mpi_abort(mpi_comm_world,1,ierr)
351 #else
352  stop 99
353 #endif
354  END SUBROUTINE error
355 
356 END MODULE logging_base_mod
subroutine finalize(this)
Destructor of common class.
subroutine error(this, modproc, msg, rank, node_info)
Print error message on standard error and terminate the program.
integer, save default_mpi_complex
default real type for MPI
integer, save default_mpi_2real
default 2real type for MPI
integer, save default_mpi_real
default real type for MPI
subroutine setprefix(val)
Set character preceding the info output.
integer, target, save ppnum
MPI number of processes.
real, save nan_default_real
NaN real constant.
subroutine warning(this, modproc, msg, rank)
Print warning message on standard error.
pure character(len=32) function getname(this)
Get the module name.
Basic fosite module.
common data structure
integer, parameter stderr
fortran stderr unit
integer, target, save myrank
MPI rank.
pure integer function getnumprocs(this)
Get the total number of MPI processes.
pure integer function gettype(this)
Get the module type number.
integer, parameter stdout
fortran stdout unit
pure integer function getrank(this)
Get the MPI rank.
pure logical function initialized(this)
Query initialization status.
logical, target, save parinit
MPI initialization status.
subroutine initlogging(this, t, n)
Constructor of common class.
real, parameter dummy
check default real type
character(len=1), save prefix
preceds info output
subroutine info(this, msg, rank, node_info, tostderr)
Print information on standard output.