m_parameters.F90 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. ! File: m_parameters.F90
  2. !
  3. ! Created: 6 August 2010
  4. !
  5. ! Last modified: 6/8/2010
  6. !
  7. ! Author: Pavel Sakov
  8. ! NERSC
  9. !
  10. ! Purpose: Provide a simpl nml list-based parameter input into EnKF.
  11. !
  12. ! Description: Provides code for reading parameters from a specified
  13. ! parameter file.
  14. !
  15. ! Modifications: none
  16. module m_parameters
  17. #if defined(QMPI)
  18. use qmpi
  19. #else
  20. use qmpi_fake
  21. #endif
  22. implicit none
  23. integer, parameter, private :: STRLEN = 512
  24. integer, parameter, private :: FID = 101
  25. character(STRLEN), public :: PRMFNAME = "NONE"
  26. integer, public :: ENSSIZE = 0
  27. namelist /ensemble/ ENSSIZE
  28. character(STRLEN), public :: METHODTAG = "NONE"
  29. namelist /method/ METHODTAG
  30. real, public :: LOCRAD = 0.0d0
  31. character(STRLEN), public :: LOCFUNTAG = "GASPARI-COHN"
  32. namelist /localisation/ LOCRAD, LOCFUNTAG
  33. real, public :: INFL = 1.0d0
  34. real, public :: RFACTOR1 = 1.0d0
  35. real, public :: RFACTOR2 = 1.0d0
  36. real, public :: KFACTOR = 2.0d0
  37. namelist /moderation/ INFL, RFACTOR1, RFACTOR2, KFACTOR
  38. character(STRLEN), public :: JMAPFNAME = "NONE"
  39. character(STRLEN), public :: POINTFNAME = "NONE"
  40. character(STRLEN), public :: MEANSSHFNAME = "NONE"
  41. namelist /files/ JMAPFNAME, POINTFNAME, MEANSSHFNAME
  42. integer, parameter, private :: NPRMESTMAX = 10
  43. integer :: nprmest = 0
  44. character(STRLEN), dimension(NPRMESTMAX), public :: PRMESTNAME
  45. real, dimension(NPRMESTMAX), public :: PRMINFL
  46. namelist /prmest/ PRMESTNAME, PRMINFL
  47. public prm_read, prm_describe, prm_print, prm_getinfl, prm_prmestexists, ucase
  48. contains
  49. subroutine prm_read
  50. integer :: ios, i
  51. call getarg(1, PRMFNAME)
  52. if (master) then
  53. print *, 'EnKF: reading parameters from "', trim(PRMFNAME), '":'
  54. end if
  55. open(unit = FID, file = trim(PRMFNAME), form = "formatted",&
  56. status = "old", iostat = ios)
  57. if (ios /= 0) then
  58. if (master) then
  59. print *, 'ERROR: could not open "', trim(PRMFNAME), '", iostatus =', ios
  60. stop
  61. end if
  62. end if
  63. read(unit = FID, nml = method, iostat = ios)
  64. if (ios /= 0) then
  65. if (master) then
  66. print *, 'ERROR: "', trim(PRMFNAME), '": could not read namelist "method"'
  67. end if
  68. stop
  69. end if
  70. rewind(FID)
  71. read(unit = FID, nml = ensemble, iostat = ios)
  72. if (ios /= 0) then
  73. if (master) then
  74. print *, 'ERROR: "', trim(PRMFNAME), '": could not read namelist "ensemble"'
  75. end if
  76. stop
  77. end if
  78. rewind(FID)
  79. read(unit = FID, nml = localisation, iostat = ios)
  80. if (ios /= 0) then
  81. if (master) then
  82. print *, 'ERROR: "', trim(PRMFNAME), '": could not read namelist "localisation"'
  83. end if
  84. stop
  85. end if
  86. rewind(FID)
  87. read(unit = FID, nml = moderation, iostat = ios)
  88. if (ios /= 0) then
  89. if (master) then
  90. print *, 'ERROR: "', trim(PRMFNAME), '": could not read namelist "moderation"'
  91. end if
  92. stop
  93. end if
  94. rewind(FID)
  95. read(unit = FID, nml = files, iostat = ios)
  96. if (ios /= 0) then
  97. if (master) then
  98. print *, 'ERROR: "', trim(PRMFNAME), '": could not read namelist "files"'
  99. end if
  100. stop
  101. end if
  102. rewind(FID)
  103. do i = 1, NPRMESTMAX
  104. PRMESTNAME(i) = ""
  105. end do
  106. read(unit = FID, nml = prmest, iostat = ios)
  107. if (ios /= 0) then
  108. if (master) then
  109. print *, 'ERROR: "', trim(PRMFNAME), '": could not read namelist "prmest"'
  110. end if
  111. stop
  112. end if
  113. do i = 1, NPRMESTMAX
  114. if (PRMESTNAME(i) == "") then
  115. nprmest = i - 1
  116. exit
  117. end if
  118. end do
  119. rewind(FID)
  120. close(FID)
  121. call ucase(METHODTAG)
  122. call ucase(LOCFUNTAG)
  123. end subroutine prm_read
  124. subroutine prm_describe
  125. if (.not. master) then
  126. return
  127. end if
  128. print '(a)', ' Example of EnKF parameter file:'
  129. print *
  130. print '(a)', '&method'
  131. print '(a)', ' methodtag = "DEnKF"'
  132. print '(a)', '/'
  133. print '(a)', '&ensemble'
  134. print '(a)', ' enssize = 0'
  135. print '(a)', '/'
  136. print '(a)', '&localisation'
  137. print '(a)', ' locfuntag = "Gaspari-Cohn"'
  138. print '(a)', ' locrad = 300.0'
  139. print '(a)', '/'
  140. print '(a)', '&moderation'
  141. print '(a)', ' infl = 1.01 (<number>)'
  142. print '(a)', ' rfactor1 = 1.0 (<number>)'
  143. print '(a)', ' rfactor2 = 2.0 (<number>)'
  144. print '(a)', ' kfactor = 2.0 (<number>)'
  145. print '(a)', '/'
  146. print '(a)', '&files'
  147. print '(a)', ' jmapfname = "jmap.txt" (<file name>)'
  148. print '(a)', ' pointfname = "point2nc.txt" (<file name>)'
  149. print '(a)', ' meansshfname = "meanssh.uf" (<file name>)'
  150. print *
  151. print '(a)', 'Parameter options:'
  152. print '(a)', ' method = "EnKF" | "DEnKF"*'
  153. print '(a)', ' enssize = <number> (0* to use all available states)'
  154. print '(a)', ' locfuntag = "Gaspari-Cohn"* | "Step" | "None"'
  155. print '(a)', ' locrad = <support radius in km>'
  156. print '(a)', ' infl = <multiple, for ensemble anomalies> (* 1.0)'
  157. print '(a)', ' rfactor1 = <obs. error variance multiple> (* 1.0)'
  158. print '(a)', ' rfactor2 = <additional multiple for updating ens. anomalies> (* 1.0)'
  159. print '(a)', ' kfactor = <max. allowed increment in terms of ensemble spread> (* 2.0)'
  160. print '(a)', ' jmapfname* = <file with j remapping> (* none)'
  161. print '(a)', ' pointfname* = <file with point coordinates> (* none)'
  162. print '(a)', ' meansshfname* = <file with mean SSH> (* none)'
  163. end subroutine prm_describe
  164. subroutine prm_print
  165. integer :: i
  166. if (.not. master) then
  167. return
  168. end if
  169. print '(a)', ' EnKF parameters:'
  170. print '(a)', ' method:'
  171. print '(a, a, a)', ' methodtag = "', trim(METHODTAG), '"'
  172. print '(a)', ' ensemble:'
  173. print '(a, i0)', ' enssize = ', ENSSIZE
  174. print '(a)', ' localisation:'
  175. print '(a, f5.0)', ' locrad = ', LOCRAD
  176. print '(a, a, a)', ' locfuntag = "', trim(LOCFUNTAG), '"'
  177. print '(a)', ' moderation:'
  178. print '(a, f5.3)', ' infl = ', INFL
  179. print '(a, f3.1)', ' rfactor1 = ', RFACTOR1
  180. print '(a, f3.1)', ' rfactor2 = ', RFACTOR2
  181. print '(a, f3.1)', ' kfactor = ', KFACTOR
  182. print '(a)', ' files:'
  183. print '(a, a, a)', ' jmapfname = "', trim(JMAPFNAME), '"'
  184. print '(a, a, a)', ' pointfname = "', trim(POINTFNAME), '"'
  185. print '(a, a, a)', ' meansshfname = "', trim(MEANSSHFNAME), '"'
  186. print '(a, i0, a)', ' prmest: ', nprmest, ' fields'
  187. do i = 1, nprmest
  188. print '(a, a, a, f5.3)', ' prmestname = "', trim(PRMESTNAME(i)), '", infl = ', PRMINFL(i)
  189. end do
  190. print *
  191. end subroutine prm_print
  192. function prm_getinfl(fldname)
  193. real :: prm_getinfl
  194. character(*), intent(in) :: fldname
  195. integer :: i
  196. prm_getinfl = INFL
  197. do i = 1, nprmest
  198. if (trim(fldname) == PRMESTNAME(i)) then
  199. prm_getinfl = PRMINFL(i)
  200. print '(a, a, a, f5.3)', ' "', trim(fldname), '": using inflation = ', prm_getinfl
  201. return
  202. end if
  203. end do
  204. end function prm_getinfl
  205. function prm_prmestexists(varname)
  206. logical :: prm_prmestexists
  207. character(*), intent(in) :: varname
  208. integer :: i
  209. prm_prmestexists = .false.
  210. do i = 1, nprmest
  211. if (trim(varname) == PRMESTNAME(i)) then
  212. prm_prmestexists = .true.
  213. return
  214. end if
  215. end do
  216. end function prm_prmestexists
  217. ! Shift a character string to upper case.
  218. !
  219. subroutine ucase(string)
  220. character(*) :: string
  221. integer :: i
  222. do i = 1, len(string)
  223. if (string(i:i) >= 'a' .and. string(i:i) <= 'z') then
  224. string(i:i) = achar (iachar ( string(i:i) ) - 32)
  225. end if
  226. end do
  227. end subroutine ucase
  228. end module m_parameters