gtool5 Fortran 90/95 Library 1.0.0-rc5
日本語
Loading...
Searching...
No Matches
dc_trace.f90
Go to the documentation of this file.
1! -*- mode: f90; coding: utf-8 -*-
2!-----------------------------------------------------------------------
3! Copyright (c) 2000-2026 Gtool Development Group. All rights reserved.
4!-----------------------------------------------------------------------
151 use dc_types, only: token, string
152 ! MPI ライブラリ
153 ! MPI library
154 !
155 use mpi
156 implicit none
157 private
158 logical, save :: lfirst = .true.
159 ! 初回フラグ
160 integer, save, public :: dbg = -1 ! SetDebug で設定された
161 ! デバッグメッセージの
162 ! 出力される装置番号です。
163 integer, save :: level = 0 ! サブルーチンレベル
164 integer, parameter :: trace_stack_size = 128
165 ! 最大階層数
166 character(TOKEN), save:: table(trace_stack_size)
167 ! 階層⇔プログラム名
168 character(STRING), save, allocatable:: called_subname(:), &
169 & called_subname_tmp(:)
170 ! 既に一度呼ばれており,
171 ! *version* 引数を指定している
172 ! 副プログラム名を格納する配列
173 character(7):: head ! 行頭文字
174 character(2), parameter :: indent = '| ' ! 字下げ文字
175 character(2), parameter :: meshead = '|-' ! DbgMessage 用行頭文字
177 public:: sublevel, datadump
178 interface debug
179 module procedure dctracedebug
180 end interface
181 interface datadump
182 module procedure datad1dump, datad2dump, datad3dump
183 end interface
184contains
202 integer function sublevel() result(result)
203 result = level
204 end function sublevel
237 subroutine dbg_scratch(on)
238 logical, intent(in):: on
239 integer, save:: saved_dbg = -1
240 logical:: x, p
241 character(80):: line
242 integer:: ios
243 continue
244 if (on) then
245 if (dbg < 0) return
246 saved_dbg = dbg
247 ! 有効な 1 〜 99 の装置番号の内の大きめの値を設定 (?)
248 dbg = 98
249 do
250 inquire(unit=dbg, exist=x, opened=p)
251 ! 装置番号 dbg が接続可能で、かつ未接続の場合
252 if (x .and. .not. p) then
253 ! 装置番号 deg をスクラッチファイルとして開く。
254 ! ※ スクラッチファイルとは、特殊な外部ファイルである。
255 ! これは名前なしの一時ファイルであり、開いている
256 ! 間だけ存在する。つまり、プログラムが終了すると
257 ! 存在しなくなる。
258 open(unit=dbg, status='SCRATCH')
259 ! 開く事が出来ればそれで終了。
260 return
261 endif
262 ! 装置番号 dbg が利用不可、または利用済の場合は 0 以下に
263 ! なるまで dbg - 1 して繰り返す。
264 dbg = dbg - 1
265 if (dbg < 0) exit
266 enddo
267 ! 装置番号 dbg が開けない場合、dbg と saved_dbg を初期化
268 dbg = saved_dbg
269 saved_dbg = -1
270 else
271 ! 以前に装置番号 dbg = 98〜0 でスクラッチファイルを開けてい
272 ! なければそれで終了
273 if (saved_dbg < 0) return
274 ! 装置番号 dbg に接続されたスクラッチファイルをその開始位置
275 ! に位置付ける。エラーが生じたら「100 continue」へ
276 rewind(dbg, err=100)
277 do
278 ! 装置番号 dbg に接続されたスクラッチファイルの一行を
279 ! line へ
280 read(dbg, '(A)', iostat=ios) line
281 if (ios /= 0) exit
282 ! line を装置番号 saved_dbg へ書き出す。
283 write(saved_dbg, '(A)', iostat=ios) trim(line)
284 if (ios /= 0) exit
285 enddo
286 100 continue
287 close(dbg, iostat=ios)
288 ! 最後に dbg と saved_dbg を初期化
289 dbg = saved_dbg
290 saved_dbg = -1
291 endif
292 end subroutine dbg_scratch
339 subroutine setdebug(debug)
340 use dc_types, only: stdout, stderr
341 implicit none
342 integer, intent(in), optional:: debug
343 integer:: ios
344 logical:: initflag_mpi
345 character(4):: myrank_str_mpi
346 integer:: myrank_mpi, err_mpi
347 continue
348 call mpi_initialized(initflag_mpi, err_mpi)
349 if ( initflag_mpi ) then
350 call mpi_comm_rank(mpi_comm_world, myrank_mpi, err_mpi)
351 if ( myrank_mpi > 9999 ) then
352 head = '#rOVER#'
353 else
354 write(unit=myrank_str_mpi, fmt="(i4.4)") myrank_mpi
355 head = '#r' // myrank_str_mpi // '#'
356 end if
357 else
358 head = '#'
359 end if
360 if (present(debug)) then
361 ! debug が与えられる時は装置番号として deg を用いる。
362 dbg = debug
363 write(dbg, "(A, 'SetDebug: dbg =', i4)", iostat=ios) &
364 & trim(head), dbg
365 if (ios == 0) return
366 else
367 ! debug が与えられ無い時は装置番号 0 (標準エラー出力)
368 dbg = stderr
369 write(dbg, "(A, 'SetDebug: dbg = ', I0)", iostat=ios) trim(head), dbg
370 if (ios == 0) return
371 ! 装置番号 0 への出力が失敗したら装置番号 6 (標準出力)
372 dbg = stdout
373 write(dbg, "(A, 'SetDebug: dbg = ', I0)", iostat=ios) trim(head), dbg
374 if (ios == 0) return
375 endif
376 ! 例外処理として dbg の初期化
377 dbg = -1
378 end subroutine setdebug
396 subroutine dctracedebug(dbg_mode)
397 logical, intent(out):: dbg_mode
398 dbg_mode = dbg >= 0
399 end subroutine dctracedebug
401 subroutine initialize
402 table(:) = ' '
403 lfirst = .false.
404 end subroutine initialize
474 subroutine beginsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca, &
475 & version)
476 use dc_types, only: string, dp
477 use dc_string, only: cprintf, strinclude
478 character(*), intent(in) :: name
479 character(*), intent(in), optional:: fmt
480 integer, intent(in), optional:: i(:), n(:)
481 real, intent(in), optional:: r(:)
482 real(dp), intent(in), optional:: d(:)
483 logical, intent(in), optional:: l(:)
484 character(*), intent(in), optional:: c1, c2, c3
485 character(*), intent(in), optional:: ca(:)
486 character(*), intent(in), optional:: version
487 character(STRING) :: cbuf
488 character(STRING) :: name_ver
489 logical :: dbg_mode, print_version
490 integer :: alloc_size
491 continue
492 if ( dbg < 0 ) return
493 if (lfirst) call initialize
494 call debug( dbg_mode )
495 if ( dbg_mode ) then
496 name_ver = name
497 print_version = .false.
498 !---------------------------------
499 ! Print Version check
500 if (present(version)) then
501 if (.not. allocated(called_subname)) then
502 allocate(called_subname(1))
503 called_subname(1) = name
504 print_version = .true.
505 else
506 if (.not. strinclude(called_subname, trim(name))) then
507 alloc_size = size(called_subname)
508 allocate(called_subname_tmp(alloc_size))
509 called_subname_tmp = called_subname
510 deallocate(called_subname)
511 allocate(called_subname(alloc_size + 1))
512 called_subname(1:alloc_size) = called_subname_tmp
513 deallocate(called_subname_tmp)
514 called_subname(alloc_size + 1) = name
515 print_version = .true.
516 end if
517 end if
518 if (print_version) then
519 name_ver = cprintf('%c version=<%c>', &
520 & c1=trim(name), c2=trim(version))
521 end if
522 end if
523 !---------------------------------
524 ! Print Debug message
525 if (present(fmt)) then
526 cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
527 write(dbg, "(A, A, 'call ', A, ' : ', A)") trim(head), &
528 & repeat(indent, level), trim(name_ver), trim(cbuf)
529 else
530 write(dbg, "(A, A, 'call ',A)") trim(head), &
531 & repeat(indent, level), trim(name_ver)
532 endif
533 endif
534 ! call errtra ! --- for Fujitsu debug
535 if (level > size(table)) return
536 level = level + 1
537 table(level) = name
538 end subroutine beginsub
598 subroutine endsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca)
599 use dc_types, only: dp
600 use dc_string, only: cprintf
601 character(*), intent(in) :: name
602 character(*), intent(in), optional:: fmt
603 integer, intent(in), optional:: i(:), n(:)
604 real, intent(in), optional:: r(:)
605 real(dp), intent(in), optional:: d(:)
606 logical, intent(in), optional:: l(:)
607 character(*), intent(in), optional:: c1, c2, c3
608 character(*), intent(in), optional:: ca(:)
609 character(STRING):: cbuf
610 logical:: debug_mode
611 continue
612 if ( dbg < 0 ) return
613 if (lfirst) call initialize
614 ! call errtra ! --- for Fujitsu debug
615 if (level <= 0) then
616 write(*, "(A, 'Warning EndSub[',A,'] without BeginSub')") &
617 & trim(head), trim(name)
618 else if (name /= table(level)) then
619 write(*, "(A, 'Warning EndSub[',A,'] but tos[',A,']')") &
620 & trim(head), trim(name), trim(table(level))
621 else
622 level = level - 1
623 endif
624 call debug( debug_mode )
625 if ( debug_mode ) then
626 if (present(fmt)) then
627 cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
628 write(dbg, "(A, A, 'end ', A, ' : ', A)") trim(head), &
629 & repeat(indent, level), trim(name), trim(cbuf)
630 else
631 write(dbg, "(A, A, 'end ', A)") trim(head), &
632 & repeat(indent, level), trim(name)
633 endif
634 endif
635 end subroutine endsub
679 subroutine dbgmessage(fmt, i, r, d, L, n, c1, c2, c3, ca)
680 use dc_types, only: string, dp
681 use dc_string, only: cprintf, tochar
682 character(*), intent(in) :: fmt
683 integer, intent(in), optional:: i(:), n(:)
684 real, intent(in), optional:: r(:)
685 real(dp), intent(in), optional:: d(:)
686 logical, intent(in), optional:: l(:)
687 character(*), intent(in), optional:: c1, c2, c3
688 character(*), intent(in), optional:: ca(:)
689 character(STRING):: cbuf
690 character(STRING):: meshead_tmp
691 integer :: meshead_len
692 continue
693 if ( dbg < 0 ) return
694 cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
695 if (level < 1) then
696 meshead_tmp = ''
697 meshead_len = 0
698 else
699 meshead_tmp = meshead
700 meshead_len = len(meshead)
701 endif
702 write(dbg, "(A, A, A, A)") &
703 & trim(head), repeat( indent, max(level-1, 0) ), &
704 & meshead_tmp(1:meshead_len), trim(cbuf)
705 end subroutine dbgmessage
743 subroutine datad1dump(header, d, strlen, multi)
744 use dc_types, only: string, dp
745 use dc_string, only: tochar
746 character(*), intent(in) :: header
747 real(DP), intent(in) :: d(:)
748 integer, intent(in), optional:: strlen
749 integer, intent(in), optional:: multi(:)
750 integer :: i, j
751 character(STRING):: unit ! データ文字列
752 character(STRING):: unitbuf ! データ文字列バッファ
753 integer :: ucur ! unit に書かれた文字数
754 character(STRING):: cbuf ! read/write 文のバッファ
755 integer :: stat ! ステータス
756 logical :: first ! 1つ目のデータかどうか
757 integer :: begini ! 1つ目のデータの添字
758 integer :: endi ! 最後のデータの添字
759 character(STRING):: cmulti ! 次元添字用文字列
760 character(STRING):: cout ! 出力する文字列
761 character(STRING):: meshead_tmp
762 integer :: meshead_len
763 continue
764 if ( dbg < 0 ) return
765 ! 初期化
766 unit = ''
767 unitbuf = ''
768 ucur = 0
769 stat = 0
770 first = .true.
771 cmulti = ''
772 ! デバッグメッセージヘッダの作成。
773 if (level < 1) then
774 meshead_tmp = ''
775 meshead_len = 0
776 else
777 meshead_tmp = meshead
778 meshead_len = len(meshead)
779 endif
780 ! 次元添字用文字列を作成
781 if (present(multi)) then
782 do j = 1, size(multi)
783 cmulti = trim(cmulti) // ', ' // trim( tochar( multi(j) ) )
784 enddo
785 endif
786 i = 1
787 dim_1_loop : do
788 if (first) begini = i
789 endi = i
790 write(cbuf, "(g40.20)") d(i)
791 if (.not. first) cbuf = ', ' // adjustl(cbuf(1:254))
792 unitbuf = unit
793 call append(unit, ucur, trim(adjustl(cbuf)), stat, strlen)
794 if ( stat /= 0 .or. i == size( d(:) ) ) then
795 ! 一回目は、文字数オーバーでもそのまま出力。
796 if (first) then
797 cout = header // '(' &
798 & // trim(tochar(begini)) &
799 & // trim(cmulti) &
800 & // ')=' // trim(unit)
801 ! 二回目以降は、オーバーしたものは次回へ
802 elseif (stat /= 0 .and. begini == endi-1) then
803 cout = header // '(' &
804 & // trim(tochar(begini)) &
805 & // trim(cmulti) &
806 & // ')='// trim(unitbuf)
807 ! 1つ巻戻す
808 i = i - 1
809 elseif (stat /= 0 .and. begini /= endi-1) then
810 cout = header // '(' &
811 & // trim(tochar(begini)) // '-' &
812 & // trim(tochar(endi-1)) &
813 & // trim(cmulti) &
814 & // ')=' // trim(unitbuf)
815 ! 1つ巻戻す
816 i = i - 1
817 ! i が size(d) まで到達した場合もそのまま出力。
818 elseif ( i == size( d(:) ) ) then
819 cout = header // '(' &
820 & // trim(tochar(begini)) // '-' &
821 & // trim(tochar(endi)) &
822 & // trim(cmulti) &
823 & // ')='// trim(unit)
824 endif
825 write(dbg, "(A, A, A, A)") &
826 & trim(head), repeat( indent, max(level-1, 0) ), &
827 & meshead_tmp(1:meshead_len), trim(cout)
828 ! unit, unitbuf をクリア
829 unit = ''
830 unitbuf = ''
831 ucur = 0
832 first = .true.
833 else
834 first = .false.
835 endif
836 if (i == size( d(:) ) ) exit dim_1_loop
837 i = i + 1
838 enddo dim_1_loop
839 end subroutine datad1dump
861 subroutine datad2dump(header, d, strlen, multi)
862 use dc_types, only: dp
863 character(*), intent(in) :: header
864 real(DP), intent(in) :: d(:,:)
865 integer, intent(in), optional:: strlen
866 integer, intent(in), optional:: multi(:)
867 integer, allocatable :: total(:)
868 integer :: j
869 continue
870 if ( dbg < 0 ) return
871 if (present(multi)) then
872 allocate( total(size(multi)+1) )
873 total(2:size(multi)+1) = multi(:)
874 else
875 allocate( total(1) )
876 endif
877 do j = 1, size( d(:,:), 2 )
878 total(1) = j
879 call datadump(header, d(:,j), strlen=strlen, multi=total(:))
880 enddo
881 deallocate( total )
882 end subroutine datad2dump
904 subroutine datad3dump(header, d, strlen, multi)
905 use dc_types, only: dp
906 character(*), intent(in) :: header
907 real(DP), intent(in) :: d(:,:,:)
908 integer, intent(in), optional:: strlen
909 integer, intent(in), optional:: multi(:)
910 integer, allocatable :: total(:)
911 integer :: k
912 continue
913 if ( dbg < 0 ) return
914 if (present(multi)) then
915 allocate( total(size(multi)+1) )
916 total(2:size(multi)+1) = multi(:)
917 else
918 allocate( total(1) )
919 endif
920 do k = 1, size( d(:,:,:), 3 )
921 total(1) = k
922 call datadump(header, d(:,:,k), strlen=strlen, multi=total(:))
923 enddo
924 deallocate( total )
925 end subroutine datad3dump
951 subroutine append(unit, ucur, val, stat, strlen)
952 character(*), intent(inout):: unit
953 integer, intent(inout):: ucur
954 character(*), intent(in) :: val
955 integer, intent(out) :: stat
956 integer, intent(in), &
957 & optional :: strlen
958 integer :: wrsz ! val の文字列
959 continue
960 ! unit の最大長を越えた場合には stat = 2 を返す。
961 if (present(strlen)) then
962 if (ucur >= strlen) then
963 stat = 2
964 return
965 endif
966 else
967 if (ucur >= len(unit)) then
968 stat = 2
969 return
970 endif
971 endif
972 ! 正常時の処理。
973 ! unit の長さを越えた場合も考慮して unit に val を付加する。
974 wrsz = min(len(val), len(unit) - ucur)
975 unit(1+ucur: wrsz+ucur) = val(1: wrsz)
976 ucur = ucur + wrsz
977 stat = 0
978 if (wrsz < len(val)) stat = 1
979 end subroutine append
981end module dc_trace
subroutine append(unitx, ucur, val, stat)
Handling character types.
Definition dc_string.f90:83
Debug tracing module.
Definition dc_trace.f90:150
integer function, public sublevel()
Definition dc_trace.f90:203
subroutine, public setdebug(debug)
Definition dc_trace.f90:340
subroutine, public dbgmessage(fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:680
subroutine, public beginsub(name, fmt, i, r, d, l, n, c1, c2, c3, ca, version)
Definition dc_trace.f90:476
subroutine, public dbg_scratch(on)
Definition dc_trace.f90:238
integer, save, public dbg
Definition dc_trace.f90:160
subroutine, public endsub(name, fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:599
Provides kind type parameter values.
Definition dc_types.f90:55
integer, parameter, public stdout
Unit number for Standard OUTPUT
Definition dc_types.f90:117
integer, parameter, public token
Character length for word, token
Definition dc_types.f90:128
integer, parameter, public dp
Double Precision Real number
Definition dc_types.f90:92
integer, parameter, public string
Character length for string
Definition dc_types.f90:137
integer, parameter, public stderr
Unit number for Standard ERROR
Definition dc_types.f90:122