stopar.F90 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. MODULE stopar
  2. !!======================================================================
  3. !! *** MODULE stopar ***
  4. !! Stochastic parameters : definition and time stepping
  5. !!=====================================================================
  6. !! History : 3.3 ! 2011-10 (J.-M. Brankart) Original code
  7. !!----------------------------------------------------------------------
  8. !!----------------------------------------------------------------------
  9. !! sto_par : update the stochastic parameters
  10. !! sto_par_init : define the stochastic parameterization
  11. !! sto_rst_read : read restart file for stochastic parameters
  12. !! sto_rst_write : write restart file for stochastic parameters
  13. !! sto_par_white : fill input array with white Gaussian noise
  14. !! sto_par_flt : apply horizontal Laplacian filter to input array
  15. !!----------------------------------------------------------------------
  16. USE storng ! random number generator (external module)
  17. USE par_oce ! ocean parameters
  18. USE dom_oce ! ocean space and time domain variables
  19. USE lbclnk ! lateral boundary conditions (or mpp link)
  20. USE in_out_manager ! I/O manager
  21. USE iom ! I/O module
  22. USE lib_mpp
  23. IMPLICIT NONE
  24. PRIVATE
  25. PUBLIC sto_par_init ! called by nemogcm.F90
  26. PUBLIC sto_par ! called by step.F90
  27. PUBLIC sto_rst_write ! called by step.F90
  28. LOGICAL :: ln_rststo = .FALSE. ! restart stochastic parameters from restart file
  29. LOGICAL :: ln_rstseed = .FALSE. ! read seed of RNG from restart file
  30. CHARACTER(len=32) :: cn_storst_in = "restart_sto" ! suffix of sto restart name (input)
  31. CHARACTER(len=32) :: cn_storst_out = "restart_sto" ! suffix of sto restart name (output)
  32. INTEGER :: numstor, numstow ! logical unit for restart (read and write)
  33. INTEGER :: jpsto2d = 0 ! number of 2D stochastic parameters
  34. INTEGER :: jpsto3d = 0 ! number of 3D stochastic parameters
  35. REAL(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: sto2d ! 2D stochastic parameters
  36. REAL(wp), PUBLIC, DIMENSION(:,:,:,:), ALLOCATABLE :: sto3d ! 3D stochastic parameters
  37. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: sto_tmp ! temporary workspace
  38. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: sto2d_abc ! a, b, c parameters (for 2D arrays)
  39. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: sto3d_abc ! a, b, c parameters (for 3D arrays)
  40. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto2d_ave ! mean value (for 2D arrays)
  41. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto3d_ave ! mean value (for 3D arrays)
  42. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto2d_std ! standard deviation (for 2D arrays)
  43. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto3d_std ! standard deviation (for 3D arrays)
  44. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto2d_lim ! limitation factor (for 2D arrays)
  45. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto3d_lim ! limitation factor (for 3D arrays)
  46. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto2d_tcor ! time correlation (for 2D arrays)
  47. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto3d_tcor ! time correlation (for 3D arrays)
  48. INTEGER, DIMENSION(:), ALLOCATABLE :: sto2d_ord ! order of autoregressive process
  49. INTEGER, DIMENSION(:), ALLOCATABLE :: sto3d_ord ! order of autoregressive process
  50. CHARACTER(len=1), DIMENSION(:), ALLOCATABLE :: sto2d_typ ! nature of grid point (T, U, V, W, F, I)
  51. CHARACTER(len=1), DIMENSION(:), ALLOCATABLE :: sto3d_typ ! nature of grid point (T, U, V, W, F, I)
  52. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto2d_sgn ! control of the sign accross the north fold
  53. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto3d_sgn ! control of the sign accross the north fold
  54. INTEGER, DIMENSION(:), ALLOCATABLE :: sto2d_flt ! number of passes of Laplacian filter
  55. INTEGER, DIMENSION(:), ALLOCATABLE :: sto3d_flt ! number of passes of Laplacian filter
  56. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto2d_fac ! factor to restore std after filtering
  57. REAL(wp), DIMENSION(:), ALLOCATABLE :: sto3d_fac ! factor to restore std after filtering
  58. LOGICAL, PUBLIC :: ln_sto_ldf = .FALSE. ! stochastic lateral diffusion
  59. INTEGER, PUBLIC :: jsto_ldf ! index of lateral diffusion stochastic parameter
  60. REAL(wp) :: rn_ldf_std ! lateral diffusion standard deviation (in percent)
  61. REAL(wp) :: rn_ldf_tcor ! lateral diffusion correlation timescale (in timesteps)
  62. LOGICAL, PUBLIC :: ln_sto_hpg = .FALSE. ! stochastic horizontal pressure gradient
  63. INTEGER, PUBLIC :: jsto_hpgi ! index of stochastic hpg parameter (i direction)
  64. INTEGER, PUBLIC :: jsto_hpgj ! index of stochastic hpg parameter (j direction)
  65. REAL(wp) :: rn_hpg_std ! density gradient standard deviation (in percent)
  66. REAL(wp) :: rn_hpg_tcor ! density gradient correlation timescale (in timesteps)
  67. LOGICAL, PUBLIC :: ln_sto_pstar = .FALSE. ! stochastic ice strength
  68. INTEGER, PUBLIC :: jsto_pstar ! index of stochastic ice strength
  69. REAL(wp), PUBLIC:: rn_pstar_std ! ice strength standard deviation (in percent)
  70. REAL(wp) :: rn_pstar_tcor ! ice strength correlation timescale (in timesteps)
  71. INTEGER :: nn_pstar_flt = 0 ! number of passes of Laplacian filter
  72. INTEGER :: nn_pstar_ord = 1 ! order of autoregressive processes
  73. LOGICAL, PUBLIC :: ln_sto_trd = .FALSE. ! stochastic model trend
  74. INTEGER, PUBLIC :: jsto_trd ! index of stochastic trend parameter
  75. REAL(wp) :: rn_trd_std ! trend standard deviation (in percent)
  76. REAL(wp) :: rn_trd_tcor ! trend correlation timescale (in timesteps)
  77. LOGICAL, PUBLIC :: ln_sto_eos = .FALSE. ! stochastic equation of state
  78. INTEGER, PUBLIC :: nn_sto_eos = 1 ! number of degrees of freedom in stochastic equation of state
  79. INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: jsto_eosi ! index of stochastic eos parameter (i direction)
  80. INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: jsto_eosj ! index of stochastic eos parameter (j direction)
  81. INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: jsto_eosk ! index of stochastic eos parameter (k direction)
  82. REAL(wp) :: rn_eos_stdxy ! random walk horz. standard deviation (in grid points)
  83. REAL(wp) :: rn_eos_stdz ! random walk vert. standard deviation (in grid points)
  84. REAL(wp) :: rn_eos_tcor ! random walk correlation timescale (in timesteps)
  85. REAL(wp) :: rn_eos_lim = 3.0_wp ! limitation factor
  86. INTEGER :: nn_eos_flt = 0 ! number of passes of Laplacian filter
  87. INTEGER :: nn_eos_ord = 1 ! order of autoregressive processes
  88. LOGICAL, PUBLIC :: ln_sto_trc = .FALSE. ! stochastic tracer dynamics
  89. INTEGER, PUBLIC :: nn_sto_trc = 1 ! number of degrees of freedom in stochastic tracer dynamics
  90. INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: jsto_trci ! index of stochastic trc parameter (i direction)
  91. INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: jsto_trcj ! index of stochastic trc parameter (j direction)
  92. INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: jsto_trck ! index of stochastic trc parameter (k direction)
  93. REAL(wp) :: rn_trc_stdxy ! random walk horz. standard deviation (in grid points)
  94. REAL(wp) :: rn_trc_stdz ! random walk vert. standard deviation (in grid points)
  95. REAL(wp) :: rn_trc_tcor ! random walk correlation timescale (in timesteps)
  96. REAL(wp) :: rn_trc_lim = 3.0_wp ! limitation factor
  97. INTEGER :: nn_trc_flt = 0 ! number of passes of Laplacian filter
  98. INTEGER :: nn_trc_ord = 1 ! order of autoregressive processes
  99. !!----------------------------------------------------------------------
  100. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  101. !! $Id: dynhpg.F90 2528 2010-12-27 17:33:53Z rblod $
  102. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  103. !!----------------------------------------------------------------------
  104. CONTAINS
  105. SUBROUTINE sto_par( kt )
  106. !!----------------------------------------------------------------------
  107. !! *** ROUTINE sto_par ***
  108. !!
  109. !! ** Purpose : update the stochastic parameters
  110. !!
  111. !! ** Method : model basic stochastic parameters
  112. !! as a first order autoregressive process AR(1),
  113. !! governed by the equation:
  114. !! X(t) = a * X(t-1) + b * w + c
  115. !! where the parameters a, b and c are related
  116. !! to expected value, standard deviation
  117. !! and time correlation (all stationary in time) by:
  118. !! E [X(t)] = c / ( 1 - a )
  119. !! STD [X(t)] = b / SQRT( 1 - a * a )
  120. !! COR [X(t),X(t-k)] = a ** k
  121. !! and w is a Gaussian white noise.
  122. !!
  123. !! Higher order autoregressive proces can be optionally generated
  124. !! by replacing the white noise by a lower order process.
  125. !!
  126. !! 1) The statistics of the stochastic parameters (X) are assumed
  127. !! constant in space (homogeneous) and time (stationary).
  128. !! This could be generalized by replacing the constant
  129. !! a, b, c parameters by functions of space and time.
  130. !!
  131. !! 2) The computation is performed independently for every model
  132. !! grid point, which corresponds to assume that the stochastic
  133. !! parameters are uncorrelated in space.
  134. !! This could be generalized by including a spatial filter: Y = Filt[ X ]
  135. !! (possibly non-homgeneous and non-stationary) in the computation,
  136. !! or by solving an elliptic equation: L[ Y ] = X.
  137. !!
  138. !! 3) The stochastic model for the parameters could also
  139. !! be generalized to depend on the current state of the ocean (not done here).
  140. !!----------------------------------------------------------------------
  141. INTEGER, INTENT( in ) :: kt ! ocean time-step index
  142. !!
  143. INTEGER :: ji, jj, jk, jsto, jflt
  144. REAL(wp) :: stomax
  145. !
  146. ! Update 2D stochastic arrays
  147. !
  148. DO jsto = 1, jpsto2d
  149. ! Store array from previous time step
  150. sto_tmp(:,:) = sto2d(:,:,jsto)
  151. IF ( sto2d_ord(jsto) == 1 ) THEN
  152. ! Draw new random numbers from N(0,1) --> w
  153. CALL sto_par_white( sto2d(:,:,jsto) )
  154. ! Apply horizontal Laplacian filter to w
  155. DO jflt = 1, sto2d_flt(jsto)
  156. CALL lbc_lnk( sto2d(:,:,jsto), sto2d_typ(jsto), sto2d_sgn(jsto) )
  157. CALL sto_par_flt( sto2d(:,:,jsto) )
  158. END DO
  159. ! Factor to restore standard deviation after filtering
  160. sto2d(:,:,jsto) = sto2d(:,:,jsto) * sto2d_fac(jsto)
  161. ELSE
  162. ! Use previous process (one order lower) instead of white noise
  163. sto2d(:,:,jsto) = sto2d(:,:,jsto-1)
  164. ENDIF
  165. ! Multiply white noise (or lower order process) by b --> b * w
  166. sto2d(:,:,jsto) = sto2d(:,:,jsto) * sto2d_abc(jsto,2)
  167. ! Update autoregressive processes --> a * X(t-1) + b * w
  168. sto2d(:,:,jsto) = sto2d(:,:,jsto) + sto_tmp(:,:) * sto2d_abc(jsto,1)
  169. ! Add parameter c --> a * X(t-1) + b * w + c
  170. sto2d(:,:,jsto) = sto2d(:,:,jsto) + sto2d_abc(jsto,3)
  171. ! Limit random parameter anomalies to std times the limitation factor
  172. stomax = sto2d_std(jsto) * sto2d_lim(jsto)
  173. sto2d(:,:,jsto) = sto2d(:,:,jsto) - sto2d_ave(jsto)
  174. sto2d(:,:,jsto) = SIGN(MIN(stomax,ABS(sto2d(:,:,jsto))),sto2d(:,:,jsto))
  175. sto2d(:,:,jsto) = sto2d(:,:,jsto) + sto2d_ave(jsto)
  176. ! Lateral boundary conditions on sto2d
  177. CALL lbc_lnk( sto2d(:,:,jsto), sto2d_typ(jsto), sto2d_sgn(jsto) )
  178. END DO
  179. !
  180. ! Update 3D stochastic arrays
  181. !
  182. DO jsto = 1, jpsto3d
  183. DO jk = 1, jpk
  184. ! Store array from previous time step
  185. sto_tmp(:,:) = sto3d(:,:,jk,jsto)
  186. IF ( sto3d_ord(jsto) == 1 ) THEN
  187. ! Draw new random numbers from N(0,1) --> w
  188. CALL sto_par_white( sto3d(:,:,jk,jsto) )
  189. ! Apply horizontal Laplacian filter to w
  190. DO jflt = 1, sto3d_flt(jsto)
  191. CALL lbc_lnk( sto3d(:,:,jk,jsto), sto3d_typ(jsto), sto3d_sgn(jsto) )
  192. CALL sto_par_flt( sto3d(:,:,jk,jsto) )
  193. END DO
  194. ! Factor to restore standard deviation after filtering
  195. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) * sto3d_fac(jsto)
  196. ELSE
  197. ! Use previous process (one order lower) instead of white noise
  198. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto-1)
  199. ENDIF
  200. ! Multiply white noise by b --> b * w
  201. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) * sto3d_abc(jsto,2)
  202. ! Update autoregressive processes --> a * X(t-1) + b * w
  203. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) + sto_tmp(:,:) * sto3d_abc(jsto,1)
  204. ! Add parameter c --> a * X(t-1) + b * w + c
  205. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) + sto3d_abc(jsto,3)
  206. ! Limit random parameters anomalies to std times the limitation factor
  207. stomax = sto3d_std(jsto) * sto3d_lim(jsto)
  208. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) - sto3d_ave(jsto)
  209. sto3d(:,:,jk,jsto) = SIGN(MIN(stomax,ABS(sto3d(:,:,jk,jsto))),sto3d(:,:,jk,jsto))
  210. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) + sto3d_ave(jsto)
  211. END DO
  212. ! Lateral boundary conditions on sto3d
  213. CALL lbc_lnk( sto3d(:,:,:,jsto), sto3d_typ(jsto), sto3d_sgn(jsto) )
  214. END DO
  215. END SUBROUTINE sto_par
  216. SUBROUTINE sto_par_init
  217. !!----------------------------------------------------------------------
  218. !! *** ROUTINE sto_par_init ***
  219. !!
  220. !! ** Purpose : define the stochastic parameterization
  221. !!----------------------------------------------------------------------
  222. NAMELIST/namsto/ ln_sto_ldf, rn_ldf_std, rn_ldf_tcor, &
  223. & ln_sto_hpg, rn_hpg_std, rn_hpg_tcor, &
  224. & ln_sto_pstar, rn_pstar_std, rn_pstar_tcor, nn_pstar_flt, nn_pstar_ord, &
  225. & ln_sto_trd, rn_trd_std, rn_trd_tcor, &
  226. & ln_sto_eos, nn_sto_eos, rn_eos_stdxy, rn_eos_stdz, &
  227. & rn_eos_tcor, nn_eos_ord, nn_eos_flt, rn_eos_lim, &
  228. & ln_sto_trc, nn_sto_trc, rn_trc_stdxy, rn_trc_stdz, &
  229. & rn_trc_tcor, nn_trc_ord, nn_trc_flt, rn_trc_lim, &
  230. & ln_rststo, ln_rstseed, cn_storst_in, cn_storst_out
  231. !!----------------------------------------------------------------------
  232. INTEGER :: jsto, jmem, jarea, jdof, jord, jordm1, jk, jflt
  233. INTEGER(KIND=8) :: zseed1, zseed2, zseed3, zseed4
  234. REAL(wp) :: rinflate
  235. INTEGER :: ios ! Local integer output status for namelist read
  236. ! Read namsto namelist : stochastic parameterization
  237. REWIND( numnam_ref ) ! Namelist namdyn_adv in reference namelist : Momentum advection scheme
  238. READ ( numnam_ref, namsto, IOSTAT = ios, ERR = 901)
  239. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsto in reference namelist', lwp )
  240. REWIND( numnam_cfg ) ! Namelist namdyn_adv in configuration namelist : Momentum advection scheme
  241. READ ( numnam_cfg, namsto, IOSTAT = ios, ERR = 902 )
  242. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namsto in configuration namelist', lwp )
  243. IF(lwm) WRITE ( numond, namsto )
  244. !IF(ln_ens_rst_in) cn_storst_in = cn_mem//cn_storst_in
  245. ! Parameter print
  246. IF(lwp) THEN
  247. WRITE(numout,*)
  248. WRITE(numout,*) 'sto_par_init : stochastic parameterization'
  249. WRITE(numout,*) '~~~~~~~~~~~~'
  250. WRITE(numout,*) ' Namelist namsto : stochastic parameterization'
  251. WRITE(numout,*) ' restart stochastic parameters ln_rststo = ', ln_rststo
  252. WRITE(numout,*) ' read seed of RNG from restart file ln_rstseed = ', ln_rstseed
  253. WRITE(numout,*) ' suffix of sto restart name (input) cn_storst_in = ', cn_storst_in
  254. WRITE(numout,*) ' suffix of sto restart name (output) cn_storst_out = ', cn_storst_out
  255. ! WRITE(numout,*) ' stochastic lateral diffusion ln_sto_ldf = ', ln_sto_ldf
  256. ! WRITE(numout,*) ' lateral diffusion std (in percent) rn_ldf_std = ', rn_ldf_std
  257. ! WRITE(numout,*) ' lateral diffusion tcor (in timesteps) rn_ldf_tcor = ', rn_ldf_tcor
  258. ! WRITE(numout,*) ' stochastic horizontal pressure gradient ln_sto_hpg = ', ln_sto_hpg
  259. ! WRITE(numout,*) ' density gradient std (in percent) rn_hpg_std = ', rn_hpg_std
  260. ! WRITE(numout,*) ' density gradient tcor (in timesteps) rn_hpg_tcor = ', rn_hpg_tcor
  261. ! WRITE(numout,*) ' stochastic ice strength ln_sto_pstar = ', ln_sto_pstar
  262. ! WRITE(numout,*) ' ice strength std (in percent) rn_pstar_std = ', rn_pstar_std
  263. ! WRITE(numout,*) ' ice strength tcor (in timesteps) rn_pstar_tcor = ', rn_pstar_tcor
  264. ! WRITE(numout,*) ' order of autoregressive processes nn_pstar_ord = ', nn_pstar_ord
  265. ! WRITE(numout,*) ' passes of Laplacian filter nn_pstar_flt = ', nn_pstar_flt
  266. !WRITE(numout,*) ' stochastic trend ln_sto_trd = ', ln_sto_trd
  267. !WRITE(numout,*) ' trend std (in percent) rn_trd_std = ', rn_trd_std
  268. !WRITE(numout,*) ' trend tcor (in timesteps) rn_trd_tcor = ', rn_trd_tcor
  269. WRITE(numout,*) ' stochastic equation of state ln_sto_eos = ', ln_sto_eos
  270. WRITE(numout,*) ' number of degrees of freedom nn_sto_eos = ', nn_sto_eos
  271. WRITE(numout,*) ' random walk horz. std (in grid points) rn_eos_stdxy = ', rn_eos_stdxy
  272. WRITE(numout,*) ' random walk vert. std (in grid points) rn_eos_stdz = ', rn_eos_stdz
  273. WRITE(numout,*) ' random walk tcor (in timesteps) rn_eos_tcor = ', rn_eos_tcor
  274. WRITE(numout,*) ' order of autoregressive processes nn_eos_ord = ', nn_eos_ord
  275. WRITE(numout,*) ' passes of Laplacian filter nn_eos_flt = ', nn_eos_flt
  276. WRITE(numout,*) ' limitation factor rn_eos_lim = ', rn_eos_lim
  277. ! WRITE(numout,*) ' stochastic tracers dynamics ln_sto_trc = ', ln_sto_trc
  278. ! WRITE(numout,*) ' number of degrees of freedom nn_sto_trc = ', nn_sto_trc
  279. ! WRITE(numout,*) ' random walk horz. std (in grid points) rn_trc_stdxy = ', rn_trc_stdxy
  280. ! WRITE(numout,*) ' random walk vert. std (in grid points) rn_trc_stdz = ', rn_trc_stdz
  281. ! WRITE(numout,*) ' random walk tcor (in timesteps) rn_trc_tcor = ', rn_trc_tcor
  282. ! WRITE(numout,*) ' order of autoregressive processes nn_trc_ord = ', nn_trc_ord
  283. ! WRITE(numout,*) ' passes of Laplacian filter nn_trc_flt = ', nn_trc_flt
  284. ! WRITE(numout,*) ' limitation factor rn_trc_lim = ', rn_trc_lim
  285. ENDIF
  286. IF(lwp) WRITE(numout,*)
  287. IF(lwp) WRITE(numout,*) ' stochastic parameterization :'
  288. ! Set number of 2D stochastic arrays
  289. jpsto2d = 0
  290. IF( ln_sto_ldf ) THEN
  291. IF(lwp) WRITE(numout,*) ' - stochastic lateral diffusion'
  292. jpsto2d = jpsto2d + 1
  293. jsto_ldf = jpsto2d
  294. ENDIF
  295. IF( ln_sto_pstar ) THEN
  296. IF(lwp) WRITE(numout,*) ' - stochastic ice strength'
  297. jpsto2d = jpsto2d + 1 * nn_pstar_ord
  298. jsto_pstar = jpsto2d
  299. ENDIF
  300. IF( ln_sto_eos ) THEN
  301. IF ( lk_agrif ) CALL ctl_stop('EOS stochastic parametrization is not compatible with AGRIF')
  302. IF(lwp) WRITE(numout,*) ' - stochastic equation of state'
  303. ALLOCATE(jsto_eosi(nn_sto_eos))
  304. ALLOCATE(jsto_eosj(nn_sto_eos))
  305. ALLOCATE(jsto_eosk(nn_sto_eos))
  306. DO jdof = 1, nn_sto_eos
  307. jpsto2d = jpsto2d + 3 * nn_eos_ord
  308. jsto_eosi(jdof) = jpsto2d - 2 * nn_eos_ord
  309. jsto_eosj(jdof) = jpsto2d - 1 * nn_eos_ord
  310. jsto_eosk(jdof) = jpsto2d
  311. END DO
  312. ELSE
  313. nn_sto_eos = 0
  314. ENDIF
  315. IF( ln_sto_trc ) THEN
  316. IF(lwp) WRITE(numout,*) ' - stochastic tracers dynamics'
  317. ALLOCATE(jsto_trci(nn_sto_trc))
  318. ALLOCATE(jsto_trcj(nn_sto_trc))
  319. ALLOCATE(jsto_trck(nn_sto_trc))
  320. DO jdof = 1, nn_sto_trc
  321. jpsto2d = jpsto2d + 3 * nn_trc_ord
  322. jsto_trci(jdof) = jpsto2d - 2 * nn_trc_ord
  323. jsto_trcj(jdof) = jpsto2d - 1 * nn_trc_ord
  324. jsto_trck(jdof) = jpsto2d
  325. END DO
  326. ELSE
  327. nn_sto_trc = 0
  328. ENDIF
  329. ! Set number of 3D stochastic arrays
  330. jpsto3d = 0
  331. IF( ln_sto_hpg ) THEN
  332. IF(lwp) WRITE(numout,*) ' - stochastic horizontal pressure gradient'
  333. jpsto3d = jpsto3d + 2
  334. jsto_hpgi = jpsto3d - 1
  335. jsto_hpgj = jpsto3d
  336. ENDIF
  337. IF( ln_sto_trd ) THEN
  338. IF(lwp) WRITE(numout,*) ' - stochastic trend'
  339. jpsto3d = jpsto3d + 1
  340. jsto_trd = jpsto3d
  341. ENDIF
  342. ! Allocate 2D stochastic arrays
  343. IF ( jpsto2d > 0 ) THEN
  344. ALLOCATE ( sto2d(jpi,jpj,jpsto2d) )
  345. ALLOCATE ( sto2d_abc(jpsto2d,3) )
  346. ALLOCATE ( sto2d_ave(jpsto2d) )
  347. ALLOCATE ( sto2d_std(jpsto2d) )
  348. ALLOCATE ( sto2d_lim(jpsto2d) )
  349. ALLOCATE ( sto2d_tcor(jpsto2d) )
  350. ALLOCATE ( sto2d_ord(jpsto2d) )
  351. ALLOCATE ( sto2d_typ(jpsto2d) )
  352. ALLOCATE ( sto2d_sgn(jpsto2d) )
  353. ALLOCATE ( sto2d_flt(jpsto2d) )
  354. ALLOCATE ( sto2d_fac(jpsto2d) )
  355. ENDIF
  356. ! Allocate 3D stochastic arrays
  357. IF ( jpsto3d > 0 ) THEN
  358. ALLOCATE ( sto3d(jpi,jpj,jpk,jpsto3d) )
  359. ALLOCATE ( sto3d_abc(jpsto3d,3) )
  360. ALLOCATE ( sto3d_ave(jpsto3d) )
  361. ALLOCATE ( sto3d_std(jpsto3d) )
  362. ALLOCATE ( sto3d_lim(jpsto3d) )
  363. ALLOCATE ( sto3d_tcor(jpsto3d) )
  364. ALLOCATE ( sto3d_ord(jpsto3d) )
  365. ALLOCATE ( sto3d_typ(jpsto3d) )
  366. ALLOCATE ( sto3d_sgn(jpsto3d) )
  367. ALLOCATE ( sto3d_flt(jpsto3d) )
  368. ALLOCATE ( sto3d_fac(jpsto3d) )
  369. ENDIF
  370. ! Allocate temporary workspace
  371. IF ( jpsto2d > 0 .OR. jpsto3d > 0 ) THEN
  372. ALLOCATE ( sto_tmp(jpi,jpj) ) ; sto_tmp(:,:) = 0._wp
  373. ENDIF
  374. ! 1) For every stochastic parameter:
  375. ! ----------------------------------
  376. ! - set nature of grid point and control of the sign
  377. ! across the north fold (sto2d_typ, sto2d_sgn)
  378. ! - set number of passes of Laplacian filter (sto2d_flt)
  379. ! - set order of every autoregressive process (sto2d_ord)
  380. DO jsto = 1, jpsto2d
  381. sto2d_typ(jsto) = 'T'
  382. sto2d_sgn(jsto) = 1._wp
  383. sto2d_flt(jsto) = 0
  384. sto2d_ord(jsto) = 1
  385. DO jord = 0, nn_pstar_ord-1
  386. IF ( jsto+jord == jsto_pstar ) THEN ! Stochastic ice strength (ave=1)
  387. sto2d_ord(jsto) = nn_pstar_ord - jord
  388. sto2d_flt(jsto) = nn_pstar_flt
  389. ENDIF
  390. ENDDO
  391. DO jdof = 1, nn_sto_eos
  392. DO jord = 0, nn_eos_ord-1
  393. IF ( jsto+jord == jsto_eosi(jdof) ) THEN ! Stochastic equation of state i (ave=0)
  394. sto2d_ord(jsto) = nn_eos_ord - jord
  395. sto2d_sgn(jsto) = -1._wp
  396. sto2d_flt(jsto) = nn_eos_flt
  397. ENDIF
  398. IF ( jsto+jord == jsto_eosj(jdof) ) THEN ! Stochastic equation of state j (ave=0)
  399. sto2d_ord(jsto) = nn_eos_ord - jord
  400. sto2d_sgn(jsto) = -1._wp
  401. sto2d_flt(jsto) = nn_eos_flt
  402. ENDIF
  403. IF ( jsto+jord == jsto_eosk(jdof) ) THEN ! Stochastic equation of state k (ave=0)
  404. sto2d_ord(jsto) = nn_eos_ord - jord
  405. sto2d_flt(jsto) = nn_eos_flt
  406. ENDIF
  407. END DO
  408. END DO
  409. DO jdof = 1, nn_sto_trc
  410. DO jord = 0, nn_trc_ord-1
  411. IF ( jsto+jord == jsto_trci(jdof) ) THEN ! Stochastic tracers dynamics i (ave=0)
  412. sto2d_ord(jsto) = nn_trc_ord - jord
  413. sto2d_sgn(jsto) = -1._wp
  414. sto2d_flt(jsto) = nn_trc_flt
  415. ENDIF
  416. IF ( jsto+jord == jsto_trcj(jdof) ) THEN ! Stochastic tracers dynamics j (ave=0)
  417. sto2d_ord(jsto) = nn_trc_ord - jord
  418. sto2d_sgn(jsto) = -1._wp
  419. sto2d_flt(jsto) = nn_trc_flt
  420. ENDIF
  421. IF ( jsto+jord == jsto_trck(jdof) ) THEN ! Stochastic tracers dynamics k (ave=0)
  422. sto2d_ord(jsto) = nn_trc_ord - jord
  423. sto2d_flt(jsto) = nn_trc_flt
  424. ENDIF
  425. END DO
  426. END DO
  427. sto2d_fac(jsto) = sto_par_flt_fac ( sto2d_flt(jsto) )
  428. END DO
  429. !
  430. DO jsto = 1, jpsto3d
  431. sto3d_typ(jsto) = 'T'
  432. sto3d_sgn(jsto) = 1._wp
  433. sto3d_flt(jsto) = 0
  434. sto3d_ord(jsto) = 1
  435. IF ( jsto == jsto_hpgi ) THEN ! Stochastic density gradient i (ave=1)
  436. sto3d_typ(jsto) = 'U'
  437. ENDIF
  438. IF ( jsto == jsto_hpgj ) THEN ! Stochastic density gradient j (ave=1)
  439. sto3d_typ(jsto) = 'V'
  440. ENDIF
  441. sto3d_fac(jsto) = sto_par_flt_fac ( sto3d_flt(jsto) )
  442. END DO
  443. ! 2) For every stochastic parameter:
  444. ! ----------------------------------
  445. ! set average, standard deviation and time correlation
  446. DO jsto = 1, jpsto2d
  447. sto2d_ave(jsto) = 0._wp
  448. sto2d_std(jsto) = 1._wp
  449. sto2d_tcor(jsto) = 1._wp
  450. sto2d_lim(jsto) = 3._wp
  451. IF ( jsto == jsto_ldf ) THEN ! Stochastic lateral diffusion (ave=1)
  452. sto2d_ave(jsto) = 1._wp
  453. sto2d_std(jsto) = rn_ldf_std
  454. sto2d_tcor(jsto) = rn_ldf_tcor
  455. ENDIF
  456. DO jord = 0, nn_pstar_ord-1
  457. IF ( jsto+jord == jsto_pstar ) THEN ! Stochastic ice strength (ave=1)
  458. sto2d_std(jsto) = 1._wp
  459. sto2d_tcor(jsto) = rn_pstar_tcor
  460. ENDIF
  461. ENDDO
  462. DO jdof = 1, nn_sto_eos
  463. DO jord = 0, nn_eos_ord-1
  464. IF ( jsto+jord == jsto_eosi(jdof) ) THEN ! Stochastic equation of state i (ave=0)
  465. sto2d_std(jsto) = rn_eos_stdxy
  466. sto2d_tcor(jsto) = rn_eos_tcor
  467. sto2d_lim(jsto) = rn_eos_lim
  468. ENDIF
  469. IF ( jsto+jord == jsto_eosj(jdof) ) THEN ! Stochastic equation of state j (ave=0)
  470. sto2d_std(jsto) = rn_eos_stdxy
  471. sto2d_tcor(jsto) = rn_eos_tcor
  472. sto2d_lim(jsto) = rn_eos_lim
  473. ENDIF
  474. IF ( jsto+jord == jsto_eosk(jdof) ) THEN ! Stochastic equation of state k (ave=0)
  475. sto2d_std(jsto) = rn_eos_stdz
  476. sto2d_tcor(jsto) = rn_eos_tcor
  477. sto2d_lim(jsto) = rn_eos_lim
  478. ENDIF
  479. END DO
  480. END DO
  481. DO jdof = 1, nn_sto_trc
  482. DO jord = 0, nn_trc_ord-1
  483. IF ( jsto+jord == jsto_trci(jdof) ) THEN ! Stochastic tracer dynamics i (ave=0)
  484. sto2d_std(jsto) = rn_trc_stdxy
  485. sto2d_tcor(jsto) = rn_trc_tcor
  486. sto2d_lim(jsto) = rn_trc_lim
  487. ENDIF
  488. IF ( jsto+jord == jsto_trcj(jdof) ) THEN ! Stochastic tracer dynamics j (ave=0)
  489. sto2d_std(jsto) = rn_trc_stdxy
  490. sto2d_tcor(jsto) = rn_trc_tcor
  491. sto2d_lim(jsto) = rn_trc_lim
  492. ENDIF
  493. IF ( jsto+jord == jsto_trck(jdof) ) THEN ! Stochastic tracer dynamics k (ave=0)
  494. sto2d_std(jsto) = rn_trc_stdz
  495. sto2d_tcor(jsto) = rn_trc_tcor
  496. sto2d_lim(jsto) = rn_trc_lim
  497. ENDIF
  498. END DO
  499. END DO
  500. END DO
  501. !
  502. DO jsto = 1, jpsto3d
  503. sto3d_ave(jsto) = 0._wp
  504. sto3d_std(jsto) = 1._wp
  505. sto3d_tcor(jsto) = 1._wp
  506. sto3d_lim(jsto) = 3._wp
  507. IF ( jsto == jsto_hpgi ) THEN ! Stochastic density gradient i (ave=1)
  508. sto3d_ave(jsto) = 1._wp
  509. sto3d_std(jsto) = rn_hpg_std
  510. sto3d_tcor(jsto) = rn_hpg_tcor
  511. ENDIF
  512. IF ( jsto == jsto_hpgj ) THEN ! Stochastic density gradient j (ave=1)
  513. sto3d_ave(jsto) = 1._wp
  514. sto3d_std(jsto) = rn_hpg_std
  515. sto3d_tcor(jsto) = rn_hpg_tcor
  516. ENDIF
  517. IF ( jsto == jsto_trd ) THEN ! Stochastic trend (ave=1)
  518. sto3d_ave(jsto) = 1._wp
  519. sto3d_std(jsto) = rn_trd_std
  520. sto3d_tcor(jsto) = rn_trd_tcor
  521. ENDIF
  522. END DO
  523. ! 3) For every stochastic parameter:
  524. ! ----------------------------------
  525. ! - compute parameters (a, b, c) of the AR1 autoregressive process
  526. ! from expected value (ave), standard deviation (std)
  527. ! and time correlation (tcor):
  528. ! a = EXP ( - 1 / tcor ) --> sto2d_abc(:,1)
  529. ! b = std * SQRT( 1 - a * a ) --> sto2d_abc(:,2)
  530. ! c = ave * ( 1 - a ) --> sto2d_abc(:,3)
  531. ! - for higher order processes (ARn, n>1), use approximate formula
  532. ! for the b parameter (valid for tcor>>1 time step)
  533. DO jsto = 1, jpsto2d
  534. IF ( sto2d_tcor(jsto) == 0._wp ) THEN
  535. sto2d_abc(jsto,1) = 0._wp
  536. ELSE
  537. sto2d_abc(jsto,1) = EXP ( - 1._wp / sto2d_tcor(jsto) )
  538. ENDIF
  539. IF ( sto2d_ord(jsto) == 1 ) THEN ! Exact formula for 1st order process
  540. rinflate = sto2d_std(jsto)
  541. ELSE
  542. ! Approximate formula, valid for tcor >> 1
  543. jordm1 = sto2d_ord(jsto) - 1
  544. rinflate = SQRT ( REAL( jordm1 , wp ) / REAL( 2*(2*jordm1-1) , wp ) )
  545. ENDIF
  546. sto2d_abc(jsto,2) = rinflate * SQRT ( 1._wp - sto2d_abc(jsto,1) &
  547. * sto2d_abc(jsto,1) )
  548. sto2d_abc(jsto,3) = sto2d_ave(jsto) * ( 1._wp - sto2d_abc(jsto,1) )
  549. END DO
  550. !
  551. DO jsto = 1, jpsto3d
  552. IF ( sto3d_tcor(jsto) == 0._wp ) THEN
  553. sto3d_abc(jsto,1) = 0._wp
  554. ELSE
  555. sto3d_abc(jsto,1) = EXP ( - 1._wp / sto3d_tcor(jsto) )
  556. ENDIF
  557. IF ( sto3d_ord(jsto) == 1 ) THEN ! Exact formula for 1st order process
  558. rinflate = sto3d_std(jsto)
  559. ELSE
  560. ! Approximate formula, valid for tcor >> 1
  561. jordm1 = sto3d_ord(jsto) - 1
  562. rinflate = SQRT ( REAL( jordm1 , wp ) / REAL( 2*(2*jordm1-1) , wp ) )
  563. ENDIF
  564. sto3d_abc(jsto,2) = rinflate * SQRT ( 1._wp - sto3d_abc(jsto,1) &
  565. * sto3d_abc(jsto,1) )
  566. sto3d_abc(jsto,3) = sto3d_ave(jsto) * ( 1._wp - sto3d_abc(jsto,1) )
  567. END DO
  568. ! 4) Initialize seeds for random number generator
  569. ! -----------------------------------------------
  570. ! using different seeds for different processors (jarea)
  571. ! and different ensemble members (jmem)
  572. CALL kiss_reset( )
  573. DO jarea = 1, narea
  574. !DO jmem = 0, nmember
  575. zseed1 = kiss() ; zseed2 = kiss() ; zseed3 = kiss() ; zseed4 = kiss()
  576. !END DO
  577. END DO
  578. CALL kiss_seed( zseed1, zseed2, zseed3, zseed4 )
  579. ! 5) Initialize stochastic parameters to: ave + std * w
  580. ! -----------------------------------------------------
  581. DO jsto = 1, jpsto2d
  582. ! Draw random numbers from N(0,1) --> w
  583. CALL sto_par_white( sto2d(:,:,jsto) )
  584. ! Apply horizontal Laplacian filter to w
  585. DO jflt = 1, sto2d_flt(jsto)
  586. CALL lbc_lnk( sto2d(:,:,jsto), sto2d_typ(jsto), sto2d_sgn(jsto) )
  587. CALL sto_par_flt( sto2d(:,:,jsto) )
  588. END DO
  589. ! Factor to restore standard deviation after filtering
  590. sto2d(:,:,jsto) = sto2d(:,:,jsto) * sto2d_fac(jsto)
  591. ! Limit random parameter to the limitation factor
  592. sto2d(:,:,jsto) = SIGN(MIN(sto2d_lim(jsto),ABS(sto2d(:,:,jsto))),sto2d(:,:,jsto))
  593. ! Multiply by standard devation and add average value
  594. sto2d(:,:,jsto) = sto2d(:,:,jsto) * sto2d_std(jsto) + sto2d_ave(jsto)
  595. END DO
  596. !
  597. DO jsto = 1, jpsto3d
  598. DO jk = 1, jpk
  599. ! Draw random numbers from N(0,1) --> w
  600. CALL sto_par_white( sto3d(:,:,jk,jsto) )
  601. ! Apply horizontal Laplacian filter to w
  602. DO jflt = 1, sto3d_flt(jsto)
  603. CALL lbc_lnk( sto3d(:,:,jk,jsto), sto3d_typ(jsto), sto3d_sgn(jsto) )
  604. CALL sto_par_flt( sto3d(:,:,jk,jsto) )
  605. END DO
  606. ! Factor to restore standard deviation after filtering
  607. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) * sto3d_fac(jsto)
  608. ! Limit random parameter to the limitation factor
  609. sto3d(:,:,jk,jsto) = SIGN(MIN(sto3d_lim(jsto),ABS(sto3d(:,:,jk,jsto))),sto3d(:,:,jk,jsto))
  610. ! Multiply by standard devation and add average value
  611. sto3d(:,:,jk,jsto) = sto3d(:,:,jk,jsto) * sto3d_std(jsto) + sto3d_ave(jsto)
  612. END DO
  613. END DO
  614. ! 6) Restart stochastic parameters from file
  615. ! ------------------------------------------
  616. IF( ln_rststo ) CALL sto_rst_read
  617. END SUBROUTINE sto_par_init
  618. SUBROUTINE sto_rst_read
  619. !!----------------------------------------------------------------------
  620. !! *** ROUTINE sto_rst_read ***
  621. !!
  622. !! ** Purpose : read stochastic parameters from restart file
  623. !!----------------------------------------------------------------------
  624. INTEGER :: jsto, jseed
  625. INTEGER(KIND=8) :: ziseed(4) ! RNG seeds in integer type
  626. REAL(KIND=8) :: zrseed(4) ! RNG seeds in real type (with same bits to save in restart)
  627. CHARACTER(LEN=9) :: clsto2d='sto2d_000' ! stochastic parameter variable name
  628. CHARACTER(LEN=9) :: clsto3d='sto3d_000' ! stochastic parameter variable name
  629. CHARACTER(LEN=10) :: clseed='seed0_0000' ! seed variable name
  630. IF ( jpsto2d > 0 .OR. jpsto3d > 0 ) THEN
  631. IF(lwp) THEN
  632. WRITE(numout,*)
  633. WRITE(numout,*) 'sto_rst_read : read stochastic parameters from restart file'
  634. WRITE(numout,*) '~~~~~~~~~~~~'
  635. ENDIF
  636. ! Open the restart file
  637. CALL iom_open( cn_storst_in, numstor, kiolib = jprstlib )
  638. ! Get stochastic parameters from restart file:
  639. ! 2D stochastic parameters
  640. DO jsto = 1 , jpsto2d
  641. WRITE(clsto2d(7:9),'(i3.3)') jsto
  642. CALL iom_get( numstor, jpdom_autoglo, clsto2d , sto2d(:,:,jsto) )
  643. END DO
  644. ! 3D stochastic parameters
  645. DO jsto = 1 , jpsto3d
  646. WRITE(clsto3d(7:9),'(i3.3)') jsto
  647. CALL iom_get( numstor, jpdom_autoglo, clsto3d , sto3d(:,:,:,jsto) )
  648. END DO
  649. IF (ln_rstseed) THEN
  650. ! Get saved state of the random number generator
  651. DO jseed = 1 , 4
  652. WRITE(clseed(5:5) ,'(i1.1)') jseed
  653. WRITE(clseed(7:10),'(i4.4)') narea
  654. CALL iom_get( numstor, clseed , zrseed(jseed) )
  655. END DO
  656. ziseed = TRANSFER( zrseed , ziseed)
  657. CALL kiss_seed( ziseed(1) , ziseed(2) , ziseed(3) , ziseed(4) )
  658. ENDIF
  659. ! Close the restart file
  660. CALL iom_close( numstor )
  661. ENDIF
  662. END SUBROUTINE sto_rst_read
  663. SUBROUTINE sto_rst_write( kt )
  664. !!----------------------------------------------------------------------
  665. !! *** ROUTINE sto_rst_write ***
  666. !!
  667. !! ** Purpose : write stochastic parameters in restart file
  668. !!----------------------------------------------------------------------
  669. INTEGER, INTENT(in) :: kt ! ocean time-step
  670. !!
  671. INTEGER :: jsto, jseed
  672. INTEGER(KIND=8) :: ziseed(4) ! RNG seeds in integer type
  673. REAL(KIND=8) :: zrseed(4) ! RNG seeds in real type (with same bits to save in restart)
  674. CHARACTER(LEN=20) :: clkt ! ocean time-step defined as a character
  675. CHARACTER(LEN=50) :: clname ! restart file name
  676. CHARACTER(LEN=9) :: clsto2d='sto2d_000' ! stochastic parameter variable name
  677. CHARACTER(LEN=9) :: clsto3d='sto3d_000' ! stochastic parameter variable name
  678. CHARACTER(LEN=10) :: clseed='seed0_0000' ! seed variable name
  679. IF ( jpsto2d > 0 .OR. jpsto3d > 0 ) THEN
  680. IF( kt == nitrst .OR. kt == nitend ) THEN
  681. IF(lwp) THEN
  682. WRITE(numout,*)
  683. WRITE(numout,*) 'sto_rst_write : write stochastic parameters in restart file'
  684. WRITE(numout,*) '~~~~~~~~~~~~~'
  685. ENDIF
  686. ENDIF
  687. ! Put stochastic parameters in restart files
  688. ! (as opened at previous timestep, see below)
  689. IF( kt > nit000) THEN
  690. IF( kt == nitrst .OR. kt == nitend ) THEN
  691. ! get and save current state of the random number generator
  692. CALL kiss_state( ziseed(1) , ziseed(2) , ziseed(3) , ziseed(4) )
  693. zrseed = TRANSFER( ziseed , zrseed)
  694. DO jseed = 1 , 4
  695. WRITE(clseed(5:5) ,'(i1.1)') jseed
  696. WRITE(clseed(7:10),'(i4.4)') narea
  697. CALL iom_rstput( kt, nitrst, numstow, clseed , zrseed(jseed) )
  698. END DO
  699. ! 2D stochastic parameters
  700. DO jsto = 1 , jpsto2d
  701. WRITE(clsto2d(7:9),'(i3.3)') jsto
  702. CALL iom_rstput( kt, nitrst, numstow, clsto2d , sto2d(:,:,jsto) )
  703. END DO
  704. ! 3D stochastic parameters
  705. DO jsto = 1 , jpsto3d
  706. WRITE(clsto3d(7:9),'(i3.3)') jsto
  707. CALL iom_rstput( kt, nitrst, numstow, clsto3d , sto3d(:,:,:,jsto) )
  708. END DO
  709. ! close the restart file
  710. CALL iom_close( numstow )
  711. ENDIF
  712. ENDIF
  713. ! Open the restart file one timestep before writing restart
  714. IF( kt < nitend) THEN
  715. IF( kt == nitrst - 1 .OR. nstock == 1 .OR. kt == nitend-1 ) THEN
  716. ! create the filename
  717. IF( nitrst > 999999999 ) THEN ; WRITE(clkt, * ) nitrst
  718. ELSE ; WRITE(clkt, '(i8.8)') nitrst
  719. ENDIF
  720. clname = TRIM(cexper)//"_"//TRIM(ADJUSTL(clkt))//"_"//TRIM(cn_storst_out)
  721. ! print information
  722. IF(lwp) THEN
  723. WRITE(numout,*) ' open stochastic parameters restart file: '//clname
  724. IF( kt == nitrst - 1 ) THEN
  725. WRITE(numout,*) ' kt = nitrst - 1 = ', kt
  726. ELSE
  727. WRITE(numout,*) ' kt = ' , kt
  728. ENDIF
  729. ENDIF
  730. ! open the restart file
  731. CALL iom_open( clname, numstow, ldwrt = .TRUE., kiolib = jprstlib )
  732. ENDIF
  733. ENDIF
  734. ENDIF
  735. END SUBROUTINE sto_rst_write
  736. SUBROUTINE sto_par_white( psto )
  737. !!----------------------------------------------------------------------
  738. !! *** ROUTINE sto_par_white ***
  739. !!
  740. !! ** Purpose : fill input array with white Gaussian noise
  741. !!----------------------------------------------------------------------
  742. REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: psto
  743. !!
  744. INTEGER :: ji, jj
  745. REAL(KIND=8) :: gran ! Gaussian random number (forced KIND=8 as in kiss_gaussian)
  746. DO jj = 1, jpj
  747. DO ji = 1, jpi
  748. CALL kiss_gaussian( gran )
  749. psto(ji,jj) = gran
  750. END DO
  751. END DO
  752. END SUBROUTINE sto_par_white
  753. SUBROUTINE sto_par_flt( psto )
  754. !!----------------------------------------------------------------------
  755. !! *** ROUTINE sto_par_flt ***
  756. !!
  757. !! ** Purpose : apply horizontal Laplacian filter to input array
  758. !!----------------------------------------------------------------------
  759. REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: psto
  760. !!
  761. INTEGER :: ji, jj
  762. DO jj = 2, jpj-1
  763. DO ji = 2, jpi-1
  764. psto(ji,jj) = 0.5_wp * psto(ji,jj) + 0.125_wp * &
  765. & ( psto(ji-1,jj) + psto(ji+1,jj) + &
  766. & psto(ji,jj-1) + psto(ji,jj+1) )
  767. END DO
  768. END DO
  769. END SUBROUTINE sto_par_flt
  770. FUNCTION sto_par_flt_fac( kpasses )
  771. !!----------------------------------------------------------------------
  772. !! *** FUNCTION sto_par_flt_fac ***
  773. !!
  774. !! ** Purpose : compute factor to restore standard deviation
  775. !! as a function of the number of passes
  776. !! of the Laplacian filter
  777. !!----------------------------------------------------------------------
  778. INTEGER, INTENT(in) :: kpasses
  779. REAL(wp) :: sto_par_flt_fac
  780. !!
  781. INTEGER :: jpasses, ji, jj, jflti, jfltj
  782. INTEGER, DIMENSION(-1:1,-1:1) :: pflt0
  783. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: pfltb
  784. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: pflta
  785. REAL(wp) :: ratio
  786. pflt0(-1,-1) = 0 ; pflt0(-1,0) = 1 ; pflt0(-1,1) = 0
  787. pflt0( 0,-1) = 1 ; pflt0( 0,0) = 4 ; pflt0( 0,1) = 1
  788. pflt0( 1,-1) = 0 ; pflt0( 1,0) = 1 ; pflt0( 1,1) = 0
  789. ALLOCATE(pfltb(-kpasses-1:kpasses+1,-kpasses-1:kpasses+1))
  790. ALLOCATE(pflta(-kpasses-1:kpasses+1,-kpasses-1:kpasses+1))
  791. pfltb(:,:) = 0
  792. pfltb(0,0) = 1
  793. DO jpasses = 1, kpasses
  794. pflta(:,:) = 0
  795. DO jflti= -1, 1
  796. DO jfltj= -1, 1
  797. DO ji= -kpasses, kpasses
  798. DO jj= -kpasses, kpasses
  799. pflta(ji,jj) = pflta(ji,jj) + pfltb(ji+jflti,jj+jfltj) * pflt0(jflti,jfltj)
  800. ENDDO
  801. ENDDO
  802. ENDDO
  803. ENDDO
  804. pfltb(:,:) = pflta(:,:)
  805. ENDDO
  806. ratio = SUM(pfltb(:,:))
  807. ratio = ratio * ratio / SUM(pfltb(:,:)*pfltb(:,:))
  808. ratio = SQRT(ratio)
  809. DEALLOCATE(pfltb,pflta)
  810. sto_par_flt_fac = ratio
  811. END FUNCTION sto_par_flt_fac
  812. END MODULE stopar