diff --git a/src/Makefile b/src/Makefile index 77cec390d..ddc265f69 100644 --- a/src/Makefile +++ b/src/Makefile @@ -64,7 +64,7 @@ unittest: $(test_objects) ace.o: global.o output.o string.o fileio.o string.o endf.o error.o cross_section.o: global.o string.o data_structures.o output.o error.o data_structures.o: global.o -endf.o: global.o +endf.o: global.o string.o energy_grid.o: global.o output.o data_structures.o error.o: global.o fileio.o: types.o global.o string.o output.o data_structures.o \ @@ -75,13 +75,13 @@ global.o: types.o logging.o: global.o main.o: global.o fileio.o output.o geometry.o mcnp_random.o \ source.o physics.o cross_section.o data_structures.o \ - ace.o energy_grid.o score.o logging.o + ace.o energy_grid.o score.o logging.o string.o mpi_routines.o: global.o output.o types.o mcnp_random.o source.o \ error.o output.o: global.o types.o data_structures.o endf.o string.o physics.o: types.o global.o mcnp_random.o geometry.o output.o \ - search.o endf.o score.o error.o -score.o: global.o output.o ace.o error.o + search.o endf.o score.o error.o string.o +score.o: global.o output.o ace.o error.o string.o search.o: global.o error.o source.o: global.o mcnp_random.o output.o physics.o string.o: global.o error.o diff --git a/src/ace.f90 b/src/ace.f90 index b18d16051..d30a63ad6 100644 --- a/src/ace.f90 +++ b/src/ace.f90 @@ -5,7 +5,7 @@ module ace use output, only: message use string, only: lower_case use fileio, only: read_line, read_data, skip_lines - use string, only: split_string + use string, only: split_string, str_to_real use data_structures, only: dict_create, dict_add_key, dict_has_key, & & dict_get_key, dict_delete use endf, only: reaction_name diff --git a/src/cross_section.f90 b/src/cross_section.f90 index b1bc1a20a..670697519 100644 --- a/src/cross_section.f90 +++ b/src/cross_section.f90 @@ -1,7 +1,7 @@ module cross_section use global - use string, only: split_string + use string, only: split_string, str_to_int, str_to_real use data_structures, only: dict_create, dict_add_key, dict_get_key use output, only: message use error, only: fatal_error diff --git a/src/endf.f90 b/src/endf.f90 index f496b4582..d87e98d67 100644 --- a/src/endf.f90 +++ b/src/endf.f90 @@ -1,6 +1,7 @@ module endf use global + use string, only: int_to_str contains diff --git a/src/fileio.f90 b/src/fileio.f90 index 4aa799357..1f96d83ef 100644 --- a/src/fileio.f90 +++ b/src/fileio.f90 @@ -2,12 +2,12 @@ module fileio use global use types, only: Cell, Surface, ExtSource, ListKeyValueCI - use string, only: split_string_wl, lower_case, split_string, & - & concatenate, is_number + use string, only: split_string_wl, lower_case, split_string, concatenate, & + is_number, str_to_int, int_to_str, str_to_real use error, only: fatal_error, warning use output, only: message use data_structures, only: dict_create, dict_add_key, dict_get_key, & - & dict_has_key, DICT_NULL, dict_keys, list_size + dict_has_key, DICT_NULL, dict_keys, list_size implicit none diff --git a/src/geometry.f90 b/src/geometry.f90 index cfd4d423c..e0b996db2 100644 --- a/src/geometry.f90 +++ b/src/geometry.f90 @@ -5,6 +5,7 @@ module geometry use output, only: message use error, only: fatal_error use data_structures, only: dict_get_key + use string, only: int_to_str implicit none diff --git a/src/global.f90 b/src/global.f90 index 23fd8f2ea..f3e30fa6a 100644 --- a/src/global.f90 +++ b/src/global.f90 @@ -272,10 +272,6 @@ module global integer, parameter :: VERSION_MINOR = 2 integer, parameter :: VERSION_RELEASE = 2 - interface int_to_str - module procedure int4_to_str, int8_to_str - end interface - contains !=============================================================================== @@ -335,162 +331,4 @@ contains end subroutine free_memory -!=============================================================================== -! INT4_TO_STR converts an integer(4) to a string. -!=============================================================================== - - function int4_to_str(num) result(str) - - integer, intent(in) :: num - character(11) :: str - - write (str, '(I11)') num - str = adjustl(str) - - end function int4_to_str - -!=============================================================================== -! INT8_TO_STR converts an integer(8) to a string. -!=============================================================================== - - function int8_to_str(num) result(str) - - integer(8), intent(in) :: num - character(21) :: str - - write (str, '(I21)') num - str = adjustl(str) - - end function int8_to_str - -!=============================================================================== -! STR_TO_INT converts a string to an integer. -!=============================================================================== - - function str_to_int(str) result(num) - - character(*), intent(in) :: str - integer(8) :: num - - character(5) :: fmt - integer :: w - integer :: ioError - - ! Determine width of string - w = len_trim(str) - - ! Create format specifier for reading string - write(UNIT=fmt, FMT='("(I",I2,")")') w - - ! read string into integer - read(UNIT=str, FMT=fmt, IOSTAT=ioError) num - if (ioError > 0) num = ERROR_INT - - end function str_to_int - -!=============================================================================== -! STR_TO_REAL converts an arbitrary string to a real(8). Generally this function -! is intended for strings for which the exact format is not known. If the format -! of the number is known a priori, the appropriate format descriptor should be -! used in lieu of this routine because of the extra overhead. -! -! Arguments: -! string = character(*) containing number to convert -!=============================================================================== - - function str_to_real(string) result(num) - - character(*), intent(in) :: string - real(8) :: num - - integer :: index_decimal ! index of decimal point - integer :: index_exponent ! index of exponent character - integer :: w ! total field width - integer :: d ! number of digits to right of decimal point - integer :: ioError - - character(8) :: fmt ! format for reading string - character(max_line_len) :: msg ! error message - - ! Determine total field width - w = len_trim(string) - - ! Determine number of digits to right of decimal point - index_decimal = index(string, '.') - index_exponent = max(index(string, 'd'), index(string, 'D'), & - & index(string, 'e'), index(string, 'E')) - if (index_decimal > 0) then - if (index_exponent > 0) then - d = index_exponent - index_decimal - 1 - else - d = w - index_decimal - end if - else - d = 0 - end if - - ! Create format specifier for reading string - write(fmt, '("(E",I2,".",I2,")")') w, d - - ! Read string - read(UNIT=string, FMT=fmt, IOSTAT=ioError) num - if (ioError > 0) num = ERROR_REAL - - end function str_to_real - -!=============================================================================== -! REAL_TO_STR converts a real(8) to a string based on how large the value is and -! how many significant digits are desired. By default, six significants digits -! are used. -!=============================================================================== - - function real_to_str(num, sig_digits) result(string) - - real(8), intent(in) :: num ! number to convert - integer, optional, intent(in) :: sig_digits ! # of significant digits - character(15) :: string ! string returned - - integer :: decimal ! number of places after decimal - integer :: width ! total field width - real(8) :: num2 ! absolute value of number - character(9) :: fmt ! format specifier for writing number - - ! set default field width - width = 15 - - ! set number of places after decimal - if (present(sig_digits)) then - decimal = sig_digits - else - decimal = 6 - end if - - ! Create format specifier for writing character - num2 = abs(num) - if (num2 == ZERO) then - write(fmt, '("(F",I2,".",I2,")")') width, 1 - elseif (num2 < 1.0e-1_8) then - write(fmt, '("(ES",I2,".",I2,")")') width, decimal - 1 - elseif (num2 >= 1.0e-1_8 .and. num2 < 1.0_8) then - write(fmt, '("(F",I2,".",I2,")")') width, decimal - elseif (num2 >= 1.0_8 .and. num2 < 10.0_8) then - write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-1, 0) - elseif (num2 >= 10.0_8 .and. num2 < 100.0_8) then - write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-2, 0) - elseif (num2 >= 100.0_8 .and. num2 < 1000.0_8) then - write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-3, 0) - elseif (num2 >= 100.0_8 .and. num2 < 10000.0_8) then - write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-4, 0) - elseif (num2 >= 10000.0_8 .and. num2 < 100000.0_8) then - write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-5, 0) - else - write(fmt, '("(ES",I2,".",I2,")")') width, decimal - 1 - end if - - ! Write string and left adjust - write(string, fmt) num - string = adjustl(string) - - end function real_to_str - end module global diff --git a/src/main.f90 b/src/main.f90 index acd4a5bb7..71773b42e 100644 --- a/src/main.f90 +++ b/src/main.f90 @@ -16,6 +16,7 @@ program main use score, only: calculate_keff use logging, only: create_log use timing, only: timer_start, timer_stop + use string, only: int_to_str #ifdef MPI use mpi diff --git a/src/output.f90 b/src/output.f90 index f13adcaaa..4eba34009 100644 --- a/src/output.f90 +++ b/src/output.f90 @@ -5,7 +5,7 @@ module output use types, only: Cell, Universe, Surface use data_structures, only: dict_get_key use endf, only: reaction_name - use string, only: upper_case + use string, only: upper_case, int_to_str, real_to_str implicit none diff --git a/src/physics.f90 b/src/physics.f90 index 818afd671..51dd32888 100644 --- a/src/physics.f90 +++ b/src/physics.f90 @@ -10,6 +10,7 @@ module physics use search, only: binary_search use endf, only: reaction_name use score, only: score_tally + use string, only: int_to_str implicit none diff --git a/src/score.f90 b/src/score.f90 index 75bcf50cf..68c2e6a94 100644 --- a/src/score.f90 +++ b/src/score.f90 @@ -5,6 +5,7 @@ module score use error, only: fatal_error use ace, only: get_macro_xs use search, only: binary_search + use string, only: int_to_str #ifdef MPI use mpi @@ -73,8 +74,8 @@ contains call MPI_BCAST(keff, 1, MPI_REAL8, 0, MPI_COMM_WORLD, ierr) #endif -100 format (2X,I4,3X,F7.5) -101 format (2X,I4,3X,F7.5,10X,F7.5,2X,F7.5) +100 format (2X,I4,2X,F8.5) +101 format (2X,I4,2X,F8.5,9X,F8.5,1X,F8.5) end subroutine calculate_keff diff --git a/src/string.f90 b/src/string.f90 index 80f6f294c..7c176789c 100644 --- a/src/string.f90 +++ b/src/string.f90 @@ -5,6 +5,10 @@ module string implicit none + interface int_to_str + module procedure int4_to_str, int8_to_str + end interface + contains !=============================================================================== @@ -200,4 +204,162 @@ contains end function is_number +!=============================================================================== +! INT4_TO_STR converts an integer(4) to a string. +!=============================================================================== + + function int4_to_str(num) result(str) + + integer, intent(in) :: num + character(11) :: str + + write (str, '(I11)') num + str = adjustl(str) + + end function int4_to_str + +!=============================================================================== +! INT8_TO_STR converts an integer(8) to a string. +!=============================================================================== + + function int8_to_str(num) result(str) + + integer(8), intent(in) :: num + character(21) :: str + + write (str, '(I21)') num + str = adjustl(str) + + end function int8_to_str + +!=============================================================================== +! STR_TO_INT converts a string to an integer. +!=============================================================================== + + function str_to_int(str) result(num) + + character(*), intent(in) :: str + integer(8) :: num + + character(5) :: fmt + integer :: w + integer :: ioError + + ! Determine width of string + w = len_trim(str) + + ! Create format specifier for reading string + write(UNIT=fmt, FMT='("(I",I2,")")') w + + ! read string into integer + read(UNIT=str, FMT=fmt, IOSTAT=ioError) num + if (ioError > 0) num = ERROR_INT + + end function str_to_int + +!=============================================================================== +! STR_TO_REAL converts an arbitrary string to a real(8). Generally this function +! is intended for strings for which the exact format is not known. If the format +! of the number is known a priori, the appropriate format descriptor should be +! used in lieu of this routine because of the extra overhead. +! +! Arguments: +! string = character(*) containing number to convert +!=============================================================================== + + function str_to_real(string) result(num) + + character(*), intent(in) :: string + real(8) :: num + + integer :: index_decimal ! index of decimal point + integer :: index_exponent ! index of exponent character + integer :: w ! total field width + integer :: d ! number of digits to right of decimal point + integer :: ioError + + character(8) :: fmt ! format for reading string + character(max_line_len) :: msg ! error message + + ! Determine total field width + w = len_trim(string) + + ! Determine number of digits to right of decimal point + index_decimal = index(string, '.') + index_exponent = max(index(string, 'd'), index(string, 'D'), & + & index(string, 'e'), index(string, 'E')) + if (index_decimal > 0) then + if (index_exponent > 0) then + d = index_exponent - index_decimal - 1 + else + d = w - index_decimal + end if + else + d = 0 + end if + + ! Create format specifier for reading string + write(fmt, '("(E",I2,".",I2,")")') w, d + + ! Read string + read(UNIT=string, FMT=fmt, IOSTAT=ioError) num + if (ioError > 0) num = ERROR_REAL + + end function str_to_real + +!=============================================================================== +! REAL_TO_STR converts a real(8) to a string based on how large the value is and +! how many significant digits are desired. By default, six significants digits +! are used. +!=============================================================================== + + function real_to_str(num, sig_digits) result(string) + + real(8), intent(in) :: num ! number to convert + integer, optional, intent(in) :: sig_digits ! # of significant digits + character(15) :: string ! string returned + + integer :: decimal ! number of places after decimal + integer :: width ! total field width + real(8) :: num2 ! absolute value of number + character(9) :: fmt ! format specifier for writing number + + ! set default field width + width = 15 + + ! set number of places after decimal + if (present(sig_digits)) then + decimal = sig_digits + else + decimal = 6 + end if + + ! Create format specifier for writing character + num2 = abs(num) + if (num2 == ZERO) then + write(fmt, '("(F",I2,".",I2,")")') width, 1 + elseif (num2 < 1.0e-1_8) then + write(fmt, '("(ES",I2,".",I2,")")') width, decimal - 1 + elseif (num2 >= 1.0e-1_8 .and. num2 < 1.0_8) then + write(fmt, '("(F",I2,".",I2,")")') width, decimal + elseif (num2 >= 1.0_8 .and. num2 < 10.0_8) then + write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-1, 0) + elseif (num2 >= 10.0_8 .and. num2 < 100.0_8) then + write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-2, 0) + elseif (num2 >= 100.0_8 .and. num2 < 1000.0_8) then + write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-3, 0) + elseif (num2 >= 100.0_8 .and. num2 < 10000.0_8) then + write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-4, 0) + elseif (num2 >= 10000.0_8 .and. num2 < 100000.0_8) then + write(fmt, '("(F",I2,".",I2,")")') width, max(decimal-5, 0) + else + write(fmt, '("(ES",I2,".",I2,")")') width, decimal - 1 + end if + + ! Write string and left adjust + write(string, fmt) num + string = adjustl(string) + + end function real_to_str + end module string