SCALE-RM
scale_monitor.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
10 !-------------------------------------------------------------------------------
11 #include "scalelib.h"
13  !-----------------------------------------------------------------------------
14  !
15  !++ Used modules
16  !
17  use scale_precision
18  use scale_io
19  use scale_prof
20  !-----------------------------------------------------------------------------
21  implicit none
22  private
23  !-----------------------------------------------------------------------------
24  !
25  !++ Public procedures
26  !
27  public :: monitor_setup
28  public :: monitor_set_dim
29  public :: monitor_reg
30  public :: monitor_put
31  public :: monitor_in
32  public :: monitor_write
33  public :: monitor_finalize
34 
35  interface monitor_in
36  module procedure monitor_in_2d
37  module procedure monitor_in_3d
38  end interface monitor_in
39 
40  interface monitor_put
41  module procedure monitor_put_2d
42  module procedure monitor_put_3d
43  end interface monitor_put
44 
45  !-----------------------------------------------------------------------------
46  !
47  !++ Public parameters & variables
48  !
49  !-----------------------------------------------------------------------------
50  !
51  !++ Private procedures
52  !
53  private :: monitor_writeheader
54 
55  !-----------------------------------------------------------------------------
56  !
57  !++ Private parameters & variables
58  !
59  integer :: monitor_fid = -1
60 
61  character(len=H_LONG) :: monitor_out_basename = 'monitor'
62  logical :: monitor_usedevation = .true.
63  integer :: monitor_step_interval = 1
64 
65  real(DP) :: monitor_dt
66 
67  integer, parameter :: monitor_req_max = 1000
68  integer :: monitor_nreqs = 0
69  character(len=H_SHORT) :: monitor_reqs(monitor_req_max)
70 
71  type item
72  character(len=H_SHORT) :: name
73  character(len=H_MID) :: desc
74  character(len=H_SHORT) :: unit
75  real(DP) :: var
76  real(DP) :: var0
77  logical :: first
78  logical :: flux
79  integer :: dimid
80  end type item
81  integer :: monitor_nitems = 0
82  type(item), allocatable :: monitor_items(:)
83 
84  type dim_type
85  character(len=H_SHORT) :: name
86  integer :: ka, ks, ke
87  integer :: ia, is, ie
88  integer :: ja, js, je
89  integer :: dim_size
90  real(RP), allocatable :: area(:,:)
91  real(RP) :: total_area
92  real(RP), allocatable :: volume(:,:,:)
93  real(RP) :: total_volume
94  end type dim_type
95  integer, parameter :: monitor_dim_max = 30
96  integer :: monitor_ndims = 0
97  type(dim_type) :: monitor_dims(monitor_dim_max)
98 
99  !-----------------------------------------------------------------------------
100 contains
101  !-----------------------------------------------------------------------------
103  subroutine monitor_setup( dt )
104  use scale_prc, only: &
105  prc_abort
106  implicit none
107 
108  real(DP), intent(in) :: dt
109 
110  namelist / param_monitor / &
111  monitor_out_basename, &
112  monitor_usedevation, &
113  monitor_step_interval
114 
115  character(len=H_SHORT) :: NAME
116 
117  namelist / monitor_item / &
118  name
119 
120  integer :: ierr
121  integer :: n
122  !---------------------------------------------------------------------------
123 
124  log_newline
125  log_info("MONITOR_setup",*) 'Setup'
126 
127  !--- read namelist
128  rewind(io_fid_conf)
129  read(io_fid_conf,nml=param_monitor,iostat=ierr)
130  if( ierr < 0 ) then !--- missing
131  log_info('MONITOR_setup',*) 'Not found namelist. Default used.'
132  elseif( ierr > 0 ) then !--- fatal error
133  log_error('MONITOR_setup',*) 'Not appropriate names in namelist PARAM_MONITOR. Check!'
134  call prc_abort
135  endif
136  log_nml(param_monitor)
137 
138  ! listup monitor request
139  rewind(io_fid_conf)
140  do n = 1, monitor_req_max
141  read(io_fid_conf,nml=monitor_item,iostat=ierr)
142  if( ierr /= 0 ) exit
143  enddo
144  monitor_nreqs = n - 1
145 
146  if ( monitor_nreqs > monitor_req_max ) then
147  log_error('MONITOR_setup',*) 'request of monitor file is exceed! n >', monitor_req_max
148  call prc_abort
149  elseif( monitor_nreqs == 0 ) then
150  log_info('MONITOR_setup',*) 'No monitor file specified.'
151  return
152  else
153  log_info('MONITOR_setup',*) 'Number of requested monitor item : ', monitor_nreqs
154  log_info('MONITOR_setup',*) 'Monitor output interval [step] : ', monitor_step_interval
155  log_info('MONITOR_setup',*) 'Use deviation from first step? : ', monitor_usedevation
156  endif
157 
158  allocate( monitor_items(monitor_nreqs) )
159 
160  rewind(io_fid_conf)
161  do n = 1, monitor_nreqs
162  ! set default
163  name = 'unknown'
164 
165  read(io_fid_conf,nml=monitor_item,iostat=ierr)
166  if( ierr /= 0 ) exit
167 
168  if ( io_fid_nml /= io_fid_log ) then
169  log_nml(monitor_item)
170  end if
171 
172  monitor_reqs(n) = name
173  enddo
174 
175 
176  monitor_dt = dt
177 
178  return
179  end subroutine monitor_setup
180 
181  !-----------------------------------------------------------------------------
183  subroutine monitor_set_dim( &
184  KA, KS, KE, IA, IS, IE, JA, JS, JE, &
185  dim_type, dim_size, &
186  area, total_area, &
187  volume, total_volume )
188  integer, intent(in) :: KA, KS, KE
189  integer, intent(in) :: IA, IS, IE
190  integer, intent(in) :: JA, JS, JE
191 
192  character(len=*), intent(in) :: dim_type
193  integer, intent(in) :: dim_size
194  real(RP), intent(in), optional :: area(ia,ja)
195  real(RP), intent(in), optional :: total_area
196  real(RP), intent(in), optional :: volume(ka,ia,ja)
197  real(RP), intent(in), optional :: total_volume
198 
199  integer :: n
200 
201  monitor_ndims = monitor_ndims + 1
202  n = monitor_ndims
203 
204  monitor_dims(n)%name = dim_type
205  monitor_dims(n)%dim_size = dim_size
206 
207  monitor_dims(n)%KA = ka
208  monitor_dims(n)%KS = ks
209  monitor_dims(n)%KE = ke
210  monitor_dims(n)%IA = ia
211  monitor_dims(n)%IS = is
212  monitor_dims(n)%IE = ie
213  monitor_dims(n)%JA = ja
214  monitor_dims(n)%JS = js
215  monitor_dims(n)%JE = je
216 
217  if ( dim_size >= 2 ) then
218  allocate( monitor_dims(n)%area(ia,ja) )
219  monitor_dims(n)%area(:,:) = area(:,:)
220  monitor_dims(n)%total_area = total_area
221  end if
222 
223  if ( dim_size >= 3 ) then
224  allocate( monitor_dims(n)%volume(ka,ia,ja) )
225  monitor_dims(n)%volume(:,:,:) = volume(:,:,:)
226  monitor_dims(n)%total_volume = total_volume
227  end if
228 
229  return
230  end subroutine monitor_set_dim
231 
232  !-----------------------------------------------------------------------------
234  subroutine monitor_reg( &
235  name, desc, unit, &
236  itemid, &
237  ndims, dim_type, &
238  isflux )
239  use scale_prc, only: &
240  prc_abort
241  implicit none
242 
243  character(len=*), intent(in) :: name
244  character(len=*), intent(in) :: desc
245  character(len=*), intent(in) :: unit
246 
247  integer, intent(out) :: itemid
248 
249  integer, intent(in), optional :: ndims
250  character(len=*), intent(in), optional :: dim_type
251  logical, intent(in), optional :: isflux
252 
253  integer :: n, reqid, dimid
254  !---------------------------------------------------------------------------
255 
256  !--- search existing item
257  do itemid = 1, monitor_nitems
258  if ( name == monitor_items(itemid)%name ) return ! match existing item
259  enddo
260 
261  do reqid = 1, monitor_nreqs
262  if ( name == monitor_reqs(reqid) ) then
263  monitor_nitems = monitor_nitems + 1
264  itemid = monitor_nitems
265 
266  ! new file registration
267  monitor_items(itemid)%name = name
268  monitor_items(itemid)%desc = desc
269  monitor_items(itemid)%unit = unit
270 
271  dimid = -1
272  if ( present(dim_type) ) then
273  do n = 1, monitor_ndims
274  if ( monitor_dims(n)%name == dim_type ) then
275  dimid = n
276  exit
277  end if
278  end do
279  if ( dimid < 0 ) then
280  log_error('MONITOR_reg',*) 'dim_type (', trim(dim_type), ') must be registerd by MONITOR_set_dim'
281  call prc_abort
282  end if
283  else if ( present(ndims) ) then
284  do n = 1, monitor_ndims
285  if ( monitor_dims(n)%dim_size == ndims ) then
286  dimid = n
287  exit
288  end if
289  end do
290  if ( dimid == -1 ) then
291  log_error('MONITOR_reg','(a,i1,a)') 'dim_type of ', ndims, 'D must be registerd with MONITOR_set_dim'
292  call prc_abort
293  end if
294  else
295  ! ndims = 3 is assumed as default
296  do n = 1, monitor_ndims
297  if ( monitor_dims(n)%dim_size == 3 ) then
298  dimid = n
299  exit
300  end if
301  end do
302  if ( dimid == -1 ) then
303  log_error('MONITOR_reg',*) 'dim_type or ndims must be specified'
304  call prc_abort
305  end if
306  end if
307 
308  monitor_items(itemid)%dimid = dimid
309 
310  monitor_items(itemid)%var = 0.0_dp
311  monitor_items(itemid)%var0 = 0.0_dp
312  monitor_items(itemid)%first = .true.
313  if ( present(isflux) ) then
314  monitor_items(itemid)%flux = isflux
315  else
316  monitor_items(itemid)%flux = .false.
317  end if
318 
319  log_newline
320  log_info('MONOTOR_reg','(A,I3)') ' Item registration No.= ', itemid
321  log_info_cont(*) 'Name : ', trim(monitor_items(itemid)%name)
322  log_info_cont(*) 'Description : ', trim(monitor_items(itemid)%desc)
323  log_info_cont(*) 'Unit : ', trim(monitor_items(itemid)%unit)
324  log_info_cont(*) 'Dimension type : ', trim(monitor_dims(monitor_items(itemid)%dimid)%name)
325  log_info_cont(*) 'Integ. with dt? : ', monitor_items(itemid)%flux
326 
327  return
328  end if
329  end do
330 
331  itemid = -1 ! not found
332 
333  return
334  end subroutine monitor_reg
335 
336  !-----------------------------------------------------------------------------
338  subroutine monitor_put_2d( &
339  itemid, var )
340  use scale_statistics, only: &
341  statistics_total
342  implicit none
343  integer, intent(in) :: itemid
344  real(RP), intent(in) :: var(:,:)
345 
346  integer :: dimid
347  real(DP) :: total
348  !---------------------------------------------------------------------------
349 
350  if( itemid <= 0 ) return
351 
352  dimid = monitor_items(itemid)%dimid
353 
354  call statistics_total( monitor_dims(dimid)%IA, monitor_dims(dimid)%IS, monitor_dims(dimid)%IE, &
355  monitor_dims(dimid)%JA, monitor_dims(dimid)%JS, monitor_dims(dimid)%JE, &
356  var(:,:), monitor_items(itemid)%name, & ! (in)
357  monitor_dims(dimid)%area(:,:), monitor_dims(dimid)%total_area, & ! (in)
358  log_suppress = .true., & ! (in)
359  sum = total ) ! (out)
360 
361  if ( monitor_items(itemid)%flux ) then
362  if ( monitor_items(itemid)%first ) then
363  monitor_items(itemid)%var = total * monitor_dt ! first put
364  monitor_items(itemid)%first = .false.
365  else
366  monitor_items(itemid)%var = monitor_items(itemid)%var + total * monitor_dt ! integrate by last put
367  endif
368  else
369  if ( monitor_usedevation ) then
370  if ( monitor_items(itemid)%first ) then
371  monitor_items(itemid)%var = 0.0_rp
372  monitor_items(itemid)%var0 = total
373  monitor_items(itemid)%first = .false.
374  else
375  monitor_items(itemid)%var = total - monitor_items(itemid)%var0 ! overwrite by last put
376  endif
377  else
378  monitor_items(itemid)%var = total ! overwrite by last put
379  endif
380  endif
381 
382  return
383  end subroutine monitor_put_2d
384 
385  !-----------------------------------------------------------------------------
387  subroutine monitor_put_3d( &
388  itemid, var )
389  use scale_statistics, only: &
390  statistics_total
391  implicit none
392 
393  integer, intent(in) :: itemid
394  real(RP), intent(in) :: var(:,:,:)
395 
396  integer :: dimid
397 
398  real(DP) :: total
399  !---------------------------------------------------------------------------
400 
401  if( itemid <= 0 ) return
402 
403  dimid = monitor_items(itemid)%dimid
404 
405 
406  call statistics_total( monitor_dims(dimid)%KA, monitor_dims(dimid)%KS, monitor_dims(dimid)%KE, &
407  monitor_dims(dimid)%IA, monitor_dims(dimid)%IS, monitor_dims(dimid)%IE, &
408  monitor_dims(dimid)%JA, monitor_dims(dimid)%JS, monitor_dims(dimid)%JE, &
409  var(:,:,:), monitor_items(itemid)%name, & ! (in)
410  monitor_dims(dimid)%volume(:,:,:), monitor_dims(dimid)%total_volume, & ! (in)
411  log_suppress = .true., & ! (in)
412  sum = total ) ! (out)
413 
414  if ( monitor_items(itemid)%flux ) then
415  if ( monitor_items(itemid)%first ) then
416  monitor_items(itemid)%var = total * monitor_dt ! first put
417  monitor_items(itemid)%first = .false.
418  else
419  monitor_items(itemid)%var = monitor_items(itemid)%var + total * monitor_dt ! integrate by last put
420  endif
421  else
422  if ( monitor_usedevation ) then
423  if ( monitor_items(itemid)%first ) then
424  monitor_items(itemid)%var = 0.0_rp
425  monitor_items(itemid)%var0 = total
426  monitor_items(itemid)%first = .false.
427  else
428  monitor_items(itemid)%var = total - monitor_items(itemid)%var0 ! overwrite by last put
429  endif
430  else
431  monitor_items(itemid)%var = total ! overwrite by last put
432  endif
433  endif
434 
435  return
436  end subroutine monitor_put_3d
437 
438  !-----------------------------------------------------------------------------
440  subroutine monitor_in_2d( &
441  var, &
442  name, desc, unit, &
443  ndims, dim_type, &
444  isflux )
445  implicit none
446 
447  real(RP), intent(in) :: var(:,:)
448  character(len=*), intent(in) :: name
449  character(len=*), intent(in) :: desc
450  character(len=*), intent(in) :: unit
451 
452  integer, intent(in), optional :: ndims
453  character(len=*), intent(in), optional :: dim_type
454  logical, intent(in), optional :: isflux
455 
456  integer :: itemid
457  !---------------------------------------------------------------------------
458 
459  call monitor_reg( name, desc, unit, & ! (in)
460  itemid, & ! (out)
461  ndims=ndims, dim_type=dim_type, & ! (in)
462  isflux=isflux ) ! (in)
463  call monitor_put( itemid, var(:,:) )
464 
465  return
466  end subroutine monitor_in_2d
467 
468  !-----------------------------------------------------------------------------
470  subroutine monitor_in_3d( &
471  var, &
472  name, desc, unit, &
473  ndims, dim_type, &
474  isflux )
475  implicit none
476 
477  real(RP), intent(in) :: var(:,:,:)
478  character(len=*), intent(in) :: name
479  character(len=*), intent(in) :: desc
480  character(len=*), intent(in) :: unit
481 
482  integer, intent(in), optional :: ndims
483  character(len=*), intent(in), optional :: dim_type
484  logical, intent(in), optional :: isflux
485 
486  integer :: itemid
487  !---------------------------------------------------------------------------
488 
489  call monitor_reg( name, desc, unit, & ! (in)
490  itemid, & ! (out)
491  ndims=ndims, dim_type=dim_type, & ! (in)
492  isflux=isflux ) ! (in)
493  call monitor_put( itemid, var(:,:,:) )
494 
495  return
496  end subroutine monitor_in_3d
497 
498  !-----------------------------------------------------------------------------
500  subroutine monitor_write( memo, nowstep )
501  implicit none
502  character(len=*), intent(in) :: memo
503  integer , intent(in) :: nowstep
504 
505  logical, save :: firsttime = .true.
506 
507  integer :: n
508  !---------------------------------------------------------------------------
509 
510  if( monitor_nitems == 0 ) return
511 
512  call prof_rapstart('FILE_O_ASCII', 2)
513 
514  if (firsttime) then
515  firsttime = .false.
516  call monitor_writeheader
517  endif
518 
519  if ( monitor_fid > 0 ) then
520 
521  if ( mod(nowstep-1,monitor_step_interval) == 0 ) then
522  log_progress(*) 'output monitor'
523 
524  write(monitor_fid,'(A,i7,A,A4,A)',advance='no') 'STEP=',nowstep,' (',memo,')'
525  do n = 1, monitor_nitems
526  write(monitor_fid,'(A,ES15.8)',advance='no') ' ', monitor_items(n)%var
527  enddo
528  write(monitor_fid,*)
529  endif
530 
531  endif
532 
533  call prof_rapend ('FILE_O_ASCII', 2)
534 
535  return
536  end subroutine monitor_write
537 
538  !-----------------------------------------------------------------------------
540  subroutine monitor_writeheader
541  use scale_prc, only: &
542  prc_abort, &
543  prc_myrank, &
545  implicit none
546 
547  character(len=H_LONG) :: fname
548 
549  logical :: MONITOR_L
550  integer :: ierr
551  integer :: n
552  !---------------------------------------------------------------------------
553 
554  log_newline
555  log_info('MONITOR_writeheader',*) 'Output item list '
556  log_info_cont(*) 'Number of monitor item :', monitor_nreqs
557  log_info_cont('(2A)') 'NAME :description ', &
558  ':UNIT :dimension_type'
559  log_info_cont('(2A)') '=======================================================================', &
560  '==============================='
561  do n = 1, monitor_nitems
562  log_info_cont('(A24,A48,A16,A16)') monitor_items(n)%name, monitor_items(n)%desc, monitor_items(n)%unit, monitor_dims(monitor_items(n)%dimid)%name
563  enddo
564  log_info_cont('(2A)') '=======================================================================', &
565  '==============================='
566 
567  if ( prc_ismaster ) then ! master node
568  monitor_l = .true.
569  else
570  monitor_l = io_log_allnode
571  endif
572 
573  if ( monitor_l ) then
574 
575  !--- Open logfile
576  monitor_fid = io_get_available_fid()
577  call io_make_idstr(fname,trim(monitor_out_basename),'pe',prc_myrank)
578  open( unit = monitor_fid, &
579  file = trim(fname), &
580  form = 'formatted', &
581  iostat = ierr )
582  if ( ierr /= 0 ) then
583  log_error('MONITOR_writeheader',*) 'File open error! :', trim(fname)
584  call prc_abort
585  endif
586 
587  log_newline
588  log_info('MONITOR_writeheader',*) 'Open ASCII file for monitor, name : ', trim(fname)
589 
590  write(monitor_fid,'(A)',advance='no') ' '
591  do n = 1, monitor_nitems
592  write(monitor_fid,'(A16)',advance='no') monitor_items(n)%name
593  enddo
594  write(monitor_fid,*)
595 
596  endif
597 
598  return
599  end subroutine monitor_writeheader
600 
601  !-----------------------------------------------------------------------------
603  subroutine monitor_finalize
604  use scale_prc, only: &
605  prc_myrank
606  implicit none
607 
608  character(len=H_LONG) :: fname
609 
610  integer :: n
611  !---------------------------------------------------------------------------
612 
613  if ( monitor_fid > 0 ) then
614  call io_make_idstr(fname,trim(monitor_out_basename),'pe',prc_myrank)
615 
616  log_newline
617  log_info('MONITOR_finalize',*) 'Close ASCII file for monitor, name : ', trim(fname)
618 
619  close(monitor_fid)
620  endif
621 
622  do n = 1, monitor_ndims
623  if ( monitor_dims(n)%dim_size >= 2 ) deallocate( monitor_dims(n)%area )
624  if ( monitor_dims(n)%dim_size >= 3 ) deallocate( monitor_dims(n)%volume )
625  end do
626  monitor_ndims = 0
627 
628  if ( allocated(monitor_items) ) deallocate( monitor_items )
629  monitor_nitems = 0
630 
631  return
632  end subroutine monitor_finalize
633 
634 end module scale_monitor
subroutine monitor_put_3d(itemid, var)
Put total value to the monitor buffer.
subroutine, public monitor_set_dim(KA, KS, KE, IA, IS, IE, JA, JS, JE, dim_type, dim_size, area, total_area, volume, total_volume)
Set area and volume.
integer, public io_fid_nml
Log file ID (only for output namelist)
Definition: scale_io.F90:57
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:55
subroutine, public monitor_write(memo, nowstep)
Flush monitor buffer to formatted file.
logical, public io_log_allnode
output log for each node?
Definition: scale_io.F90:65
module MONITOR
integer function, public io_get_available_fid()
search & get available file ID
Definition: scale_io.F90:313
module PROCESS
Definition: scale_prc.F90:11
integer, public prc_myrank
process num in local communicator
Definition: scale_prc.F90:89
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:338
subroutine, public prof_rapstart(rapname_base, level)
Start raptime.
Definition: scale_prof.F90:157
subroutine monitor_put_2d(itemid, var)
Put total value to the monitor buffer.
subroutine, public monitor_finalize
Close file.
module profiler
Definition: scale_prof.F90:11
logical, public prc_ismaster
master process in local communicator?
Definition: scale_prc.F90:90
module PRECISION
subroutine monitor_in_2d(var, name, desc, unit, ndims, dim_type, isflux)
Wrapper routine of MONITOR_reg+MONITOR_put.
subroutine, public monitor_setup(dt)
Setup.
subroutine, public io_make_idstr(outstr, instr, ext, rank, isrgn)
generate process specific filename
Definition: scale_io.F90:334
module Statistics
module STDIO
Definition: scale_io.F90:10
subroutine, public monitor_reg(name, desc, unit, itemid, ndims, dim_type, isflux)
Search existing item, or matching check between requested and registered item.
subroutine, public prof_rapend(rapname_base, level)
Save raptime.
Definition: scale_prof.F90:210
integer, public io_fid_log
Log file ID.
Definition: scale_io.F90:56