asminc.F90 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. MODULE asminc
  2. !!======================================================================
  3. !! *** MODULE asminc ***
  4. !! Assimilation increment : Apply an increment generated by data
  5. !! assimilation
  6. !!======================================================================
  7. !! History : ! 2007-03 (M. Martin) Met Office version
  8. !! ! 2007-04 (A. Weaver) calc_date original code
  9. !! ! 2007-04 (A. Weaver) Merge with OPAVAR/NEMOVAR
  10. !! NEMO 3.3 ! 2010-05 (D. Lea) Update to work with NEMO v3.2
  11. !! - ! 2010-05 (D. Lea) add calc_month_len routine based on day_init
  12. !! 3.4 ! 2012-10 (A. Weaver and K. Mogensen) Fix for direct initialization
  13. !!----------------------------------------------------------------------
  14. !!----------------------------------------------------------------------
  15. !! 'key_asminc' : Switch on the assimilation increment interface
  16. !!----------------------------------------------------------------------
  17. !! asm_inc_init : Initialize the increment arrays and IAU weights
  18. !! calc_date : Compute the calendar date YYYYMMDD on a given step
  19. !! tra_asm_inc : Apply the tracer (T and S) increments
  20. !! dyn_asm_inc : Apply the dynamic (u and v) increments
  21. !! ssh_asm_inc : Apply the SSH increment
  22. !! seaice_asm_inc : Apply the seaice increment
  23. !!----------------------------------------------------------------------
  24. USE wrk_nemo ! Memory Allocation
  25. USE par_oce ! Ocean space and time domain variables
  26. USE dom_oce ! Ocean space and time domain
  27. USE domvvl ! domain: variable volume level
  28. USE oce ! Dynamics and active tracers defined in memory
  29. USE ldfdyn_oce ! ocean dynamics: lateral physics
  30. USE eosbn2 ! Equation of state - in situ and potential density
  31. USE zpshde ! Partial step : Horizontal Derivative
  32. USE iom ! Library to read input files
  33. USE asmpar ! Parameters for the assmilation interface
  34. USE c1d ! 1D initialization
  35. USE in_out_manager ! I/O manager
  36. USE lib_mpp ! MPP library
  37. #if defined key_lim2
  38. USE ice_2 ! LIM2
  39. #endif
  40. USE sbc_oce ! Surface boundary condition variables.
  41. IMPLICIT NONE
  42. PRIVATE
  43. PUBLIC asm_inc_init !: Initialize the increment arrays and IAU weights
  44. PUBLIC calc_date !: Compute the calendar date YYYYMMDD on a given step
  45. PUBLIC tra_asm_inc !: Apply the tracer (T and S) increments
  46. PUBLIC dyn_asm_inc !: Apply the dynamic (u and v) increments
  47. PUBLIC ssh_asm_inc !: Apply the SSH increment
  48. PUBLIC seaice_asm_inc !: Apply the seaice increment
  49. #if defined key_asminc
  50. LOGICAL, PUBLIC, PARAMETER :: lk_asminc = .TRUE. !: Logical switch for assimilation increment interface
  51. #else
  52. LOGICAL, PUBLIC, PARAMETER :: lk_asminc = .FALSE. !: No assimilation increments
  53. #endif
  54. LOGICAL, PUBLIC :: ln_bkgwri = .FALSE. !: No output of the background state fields
  55. LOGICAL, PUBLIC :: ln_asmiau = .FALSE. !: No applying forcing with an assimilation increment
  56. LOGICAL, PUBLIC :: ln_asmdin = .FALSE. !: No direct initialization
  57. LOGICAL, PUBLIC :: ln_trainc = .FALSE. !: No tracer (T and S) assimilation increments
  58. LOGICAL, PUBLIC :: ln_dyninc = .FALSE. !: No dynamics (u and v) assimilation increments
  59. LOGICAL, PUBLIC :: ln_sshinc = .FALSE. !: No sea surface height assimilation increment
  60. LOGICAL, PUBLIC :: ln_seaiceinc !: No sea ice concentration increment
  61. LOGICAL, PUBLIC :: ln_salfix = .FALSE. !: Apply minimum salinity check
  62. LOGICAL, PUBLIC :: ln_temnofreeze = .FALSE. !: Don't allow the temperature to drop below freezing
  63. INTEGER, PUBLIC :: nn_divdmp !: Apply divergence damping filter nn_divdmp times
  64. REAL(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: t_bkg , s_bkg !: Background temperature and salinity
  65. REAL(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: u_bkg , v_bkg !: Background u- & v- velocity components
  66. REAL(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: t_bkginc, s_bkginc !: Increment to the background T & S
  67. REAL(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: u_bkginc, v_bkginc !: Increment to the u- & v-components
  68. REAL(wp), PUBLIC, DIMENSION(:) , ALLOCATABLE :: wgtiau !: IAU weights for each time step
  69. #if defined key_asminc
  70. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssh_iau !: IAU-weighted sea surface height increment
  71. #endif
  72. ! !!! time steps relative to the cycle interval [0,nitend-nit000-1]
  73. INTEGER , PUBLIC :: nitbkg !: Time step of the background state used in the Jb term
  74. INTEGER , PUBLIC :: nitdin !: Time step of the background state for direct initialization
  75. INTEGER , PUBLIC :: nitiaustr !: Time step of the start of the IAU interval
  76. INTEGER , PUBLIC :: nitiaufin !: Time step of the end of the IAU interval
  77. !
  78. INTEGER , PUBLIC :: niaufn !: Type of IAU weighing function: = 0 Constant weighting
  79. ! !: = 1 Linear hat-like, centred in middle of IAU interval
  80. REAL(wp), PUBLIC :: salfixmin !: Ensure that the salinity is larger than this value if (ln_salfix)
  81. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: ssh_bkg, ssh_bkginc ! Background sea surface height and its increment
  82. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: seaice_bkginc ! Increment to the background sea ice conc
  83. #if defined key_cice && defined key_asminc
  84. REAL(wp), DIMENSION(:,:), ALLOCATABLE :: ndaice_da ! ice increment tendency into CICE
  85. #endif
  86. !! * Substitutions
  87. # include "domzgr_substitute.h90"
  88. # include "ldfdyn_substitute.h90"
  89. # include "vectopt_loop_substitute.h90"
  90. !!----------------------------------------------------------------------
  91. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  92. !! $Id: asminc.F90 5540 2015-07-02 15:11:23Z jchanut $
  93. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  94. !!----------------------------------------------------------------------
  95. CONTAINS
  96. SUBROUTINE asm_inc_init
  97. !!----------------------------------------------------------------------
  98. !! *** ROUTINE asm_inc_init ***
  99. !!
  100. !! ** Purpose : Initialize the assimilation increment and IAU weights.
  101. !!
  102. !! ** Method : Initialize the assimilation increment and IAU weights.
  103. !!
  104. !! ** Action :
  105. !!----------------------------------------------------------------------
  106. INTEGER :: ji, jj, jk, jt ! dummy loop indices
  107. INTEGER :: imid, inum ! local integers
  108. INTEGER :: ios ! Local integer output status for namelist read
  109. INTEGER :: iiauper ! Number of time steps in the IAU period
  110. INTEGER :: icycper ! Number of time steps in the cycle
  111. INTEGER :: iitend_date ! Date YYYYMMDD of final time step
  112. INTEGER :: iitbkg_date ! Date YYYYMMDD of background time step for Jb term
  113. INTEGER :: iitdin_date ! Date YYYYMMDD of background time step for DI
  114. INTEGER :: iitiaustr_date ! Date YYYYMMDD of IAU interval start time step
  115. INTEGER :: iitiaufin_date ! Date YYYYMMDD of IAU interval final time step
  116. !
  117. REAL(wp) :: znorm ! Normalization factor for IAU weights
  118. REAL(wp) :: ztotwgt ! Value of time-integrated IAU weights (should be equal to one)
  119. REAL(wp) :: z_inc_dateb ! Start date of interval on which increment is valid
  120. REAL(wp) :: z_inc_datef ! End date of interval on which increment is valid
  121. REAL(wp) :: zdate_bkg ! Date in background state file for DI
  122. REAL(wp) :: zdate_inc ! Time axis in increments file
  123. !
  124. REAL(wp), POINTER, DIMENSION(:,:) :: hdiv ! 2D workspace
  125. !!
  126. NAMELIST/nam_asminc/ ln_bkgwri, &
  127. & ln_trainc, ln_dyninc, ln_sshinc, &
  128. & ln_asmdin, ln_asmiau, &
  129. & nitbkg, nitdin, nitiaustr, nitiaufin, niaufn, &
  130. & ln_salfix, salfixmin, nn_divdmp
  131. !!----------------------------------------------------------------------
  132. !-----------------------------------------------------------------------
  133. ! Read Namelist nam_asminc : assimilation increment interface
  134. !-----------------------------------------------------------------------
  135. ln_seaiceinc = .FALSE.
  136. ln_temnofreeze = .FALSE.
  137. REWIND( numnam_ref ) ! Namelist nam_asminc in reference namelist : Assimilation increment
  138. READ ( numnam_ref, nam_asminc, IOSTAT = ios, ERR = 901)
  139. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'nam_asminc in reference namelist', lwp )
  140. REWIND( numnam_cfg ) ! Namelist nam_asminc in configuration namelist : Assimilation increment
  141. READ ( numnam_cfg, nam_asminc, IOSTAT = ios, ERR = 902 )
  142. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'nam_asminc in configuration namelist', lwp )
  143. IF(lwm) WRITE ( numond, nam_asminc )
  144. ! Control print
  145. IF(lwp) THEN
  146. WRITE(numout,*)
  147. WRITE(numout,*) 'asm_inc_init : Assimilation increment initialization :'
  148. WRITE(numout,*) '~~~~~~~~~~~~'
  149. WRITE(numout,*) ' Namelist namasm : set assimilation increment parameters'
  150. WRITE(numout,*) ' Logical switch for writing out background state ln_bkgwri = ', ln_bkgwri
  151. WRITE(numout,*) ' Logical switch for applying tracer increments ln_trainc = ', ln_trainc
  152. WRITE(numout,*) ' Logical switch for applying velocity increments ln_dyninc = ', ln_dyninc
  153. WRITE(numout,*) ' Logical switch for applying SSH increments ln_sshinc = ', ln_sshinc
  154. WRITE(numout,*) ' Logical switch for Direct Initialization (DI) ln_asmdin = ', ln_asmdin
  155. WRITE(numout,*) ' Logical switch for applying sea ice increments ln_seaiceinc = ', ln_seaiceinc
  156. WRITE(numout,*) ' Logical switch for Incremental Analysis Updating (IAU) ln_asmiau = ', ln_asmiau
  157. WRITE(numout,*) ' Timestep of background in [0,nitend-nit000-1] nitbkg = ', nitbkg
  158. WRITE(numout,*) ' Timestep of background for DI in [0,nitend-nit000-1] nitdin = ', nitdin
  159. WRITE(numout,*) ' Timestep of start of IAU interval in [0,nitend-nit000-1] nitiaustr = ', nitiaustr
  160. WRITE(numout,*) ' Timestep of end of IAU interval in [0,nitend-nit000-1] nitiaufin = ', nitiaufin
  161. WRITE(numout,*) ' Type of IAU weighting function niaufn = ', niaufn
  162. WRITE(numout,*) ' Logical switch for ensuring that the sa > salfixmin ln_salfix = ', ln_salfix
  163. WRITE(numout,*) ' Minimum salinity after applying the increments salfixmin = ', salfixmin
  164. ENDIF
  165. nitbkg_r = nitbkg + nit000 - 1 ! Background time referenced to nit000
  166. nitdin_r = nitdin + nit000 - 1 ! Background time for DI referenced to nit000
  167. nitiaustr_r = nitiaustr + nit000 - 1 ! Start of IAU interval referenced to nit000
  168. nitiaufin_r = nitiaufin + nit000 - 1 ! End of IAU interval referenced to nit000
  169. iiauper = nitiaufin_r - nitiaustr_r + 1 ! IAU interval length
  170. icycper = nitend - nit000 + 1 ! Cycle interval length
  171. CALL calc_date( nit000, nitend , ndate0, iitend_date ) ! Date of final time step
  172. CALL calc_date( nit000, nitbkg_r , ndate0, iitbkg_date ) ! Background time for Jb referenced to ndate0
  173. CALL calc_date( nit000, nitdin_r , ndate0, iitdin_date ) ! Background time for DI referenced to ndate0
  174. CALL calc_date( nit000, nitiaustr_r, ndate0, iitiaustr_date ) ! IAU start time referenced to ndate0
  175. CALL calc_date( nit000, nitiaufin_r, ndate0, iitiaufin_date ) ! IAU end time referenced to ndate0
  176. !
  177. IF(lwp) THEN
  178. WRITE(numout,*)
  179. WRITE(numout,*) ' Time steps referenced to current cycle:'
  180. WRITE(numout,*) ' iitrst = ', nit000 - 1
  181. WRITE(numout,*) ' nit000 = ', nit000
  182. WRITE(numout,*) ' nitend = ', nitend
  183. WRITE(numout,*) ' nitbkg_r = ', nitbkg_r
  184. WRITE(numout,*) ' nitdin_r = ', nitdin_r
  185. WRITE(numout,*) ' nitiaustr_r = ', nitiaustr_r
  186. WRITE(numout,*) ' nitiaufin_r = ', nitiaufin_r
  187. WRITE(numout,*)
  188. WRITE(numout,*) ' Dates referenced to current cycle:'
  189. WRITE(numout,*) ' ndastp = ', ndastp
  190. WRITE(numout,*) ' ndate0 = ', ndate0
  191. WRITE(numout,*) ' iitend_date = ', iitend_date
  192. WRITE(numout,*) ' iitbkg_date = ', iitbkg_date
  193. WRITE(numout,*) ' iitdin_date = ', iitdin_date
  194. WRITE(numout,*) ' iitiaustr_date = ', iitiaustr_date
  195. WRITE(numout,*) ' iitiaufin_date = ', iitiaufin_date
  196. ENDIF
  197. IF ( nacc /= 0 ) &
  198. & CALL ctl_stop( ' nacc /= 0 and key_asminc :', &
  199. & ' Assimilation increments have only been implemented', &
  200. & ' for synchronous time stepping' )
  201. IF ( ( ln_asmdin ).AND.( ln_asmiau ) ) &
  202. & CALL ctl_stop( ' ln_asmdin and ln_asmiau :', &
  203. & ' Choose Direct Initialization OR Incremental Analysis Updating')
  204. IF ( ( ( .NOT. ln_asmdin ).AND.( .NOT. ln_asmiau ) ) &
  205. .AND.( ( ln_trainc ).OR.( ln_dyninc ).OR.( ln_sshinc ) .OR. ( ln_seaiceinc) )) &
  206. & CALL ctl_stop( ' One or more of ln_trainc, ln_dyninc, ln_sshinc and ln_seaiceinc is set to .true.', &
  207. & ' but ln_asmdin and ln_asmiau are both set to .false. :', &
  208. & ' Inconsistent options')
  209. IF ( ( niaufn /= 0 ).AND.( niaufn /= 1 ) ) &
  210. & CALL ctl_stop( ' niaufn /= 0 or niaufn /=1 :', &
  211. & ' Type IAU weighting function is invalid')
  212. IF ( ( .NOT. ln_trainc ).AND.( .NOT. ln_dyninc ).AND.( .NOT. ln_sshinc ).AND.( .NOT. ln_seaiceinc ) &
  213. & ) &
  214. & CALL ctl_warn( ' ln_trainc, ln_dyninc, ln_sshinc and ln_seaiceinc are set to .false. :', &
  215. & ' The assimilation increments are not applied')
  216. IF ( ( ln_asmiau ).AND.( nitiaustr == nitiaufin ) ) &
  217. & CALL ctl_stop( ' nitiaustr = nitiaufin :', &
  218. & ' IAU interval is of zero length')
  219. IF ( ( ln_asmiau ).AND.( ( nitiaustr_r < nit000 ).OR.( nitiaufin_r > nitend ) ) ) &
  220. & CALL ctl_stop( ' nitiaustr or nitiaufin :', &
  221. & ' IAU starting or final time step is outside the cycle interval', &
  222. & ' Valid range nit000 to nitend')
  223. IF ( ( nitbkg_r < nit000 - 1 ).OR.( nitbkg_r > nitend ) ) &
  224. & CALL ctl_stop( ' nitbkg :', &
  225. & ' Background time step is outside the cycle interval')
  226. IF ( ( nitdin_r < nit000 - 1 ).OR.( nitdin_r > nitend ) ) &
  227. & CALL ctl_stop( ' nitdin :', &
  228. & ' Background time step for Direct Initialization is outside', &
  229. & ' the cycle interval')
  230. IF ( nstop > 0 ) RETURN ! if there are any errors then go no further
  231. !--------------------------------------------------------------------
  232. ! Initialize the Incremental Analysis Updating weighting function
  233. !--------------------------------------------------------------------
  234. IF ( ln_asmiau ) THEN
  235. ALLOCATE( wgtiau( icycper ) )
  236. wgtiau(:) = 0.0
  237. IF ( niaufn == 0 ) THEN
  238. !---------------------------------------------------------
  239. ! Constant IAU forcing
  240. !---------------------------------------------------------
  241. DO jt = 1, iiauper
  242. wgtiau(jt+nitiaustr-1) = 1.0 / REAL( iiauper )
  243. END DO
  244. ELSEIF ( niaufn == 1 ) THEN
  245. !---------------------------------------------------------
  246. ! Linear hat-like, centred in middle of IAU interval
  247. !---------------------------------------------------------
  248. ! Compute the normalization factor
  249. znorm = 0.0
  250. IF ( MOD( iiauper, 2 ) == 0 ) THEN ! Even number of time steps in IAU interval
  251. imid = iiauper / 2
  252. DO jt = 1, imid
  253. znorm = znorm + REAL( jt )
  254. END DO
  255. znorm = 2.0 * znorm
  256. ELSE ! Odd number of time steps in IAU interval
  257. imid = ( iiauper + 1 ) / 2
  258. DO jt = 1, imid - 1
  259. znorm = znorm + REAL( jt )
  260. END DO
  261. znorm = 2.0 * znorm + REAL( imid )
  262. ENDIF
  263. znorm = 1.0 / znorm
  264. DO jt = 1, imid - 1
  265. wgtiau(jt+nitiaustr-1) = REAL( jt ) * znorm
  266. END DO
  267. DO jt = imid, iiauper
  268. wgtiau(jt+nitiaustr-1) = REAL( iiauper - jt + 1 ) * znorm
  269. END DO
  270. ENDIF
  271. ! Test that the integral of the weights over the weighting interval equals 1
  272. IF(lwp) THEN
  273. WRITE(numout,*)
  274. WRITE(numout,*) 'asm_inc_init : IAU weights'
  275. WRITE(numout,*) '~~~~~~~~~~~~'
  276. WRITE(numout,*) ' time step IAU weight'
  277. WRITE(numout,*) ' ========= ====================='
  278. ztotwgt = 0.0
  279. DO jt = 1, icycper
  280. ztotwgt = ztotwgt + wgtiau(jt)
  281. WRITE(numout,*) ' ', jt, ' ', wgtiau(jt)
  282. END DO
  283. WRITE(numout,*) ' ==================================='
  284. WRITE(numout,*) ' Time-integrated weight = ', ztotwgt
  285. WRITE(numout,*) ' ==================================='
  286. ENDIF
  287. ENDIF
  288. !--------------------------------------------------------------------
  289. ! Allocate and initialize the increment arrays
  290. !--------------------------------------------------------------------
  291. ALLOCATE( t_bkginc(jpi,jpj,jpk) )
  292. ALLOCATE( s_bkginc(jpi,jpj,jpk) )
  293. ALLOCATE( u_bkginc(jpi,jpj,jpk) )
  294. ALLOCATE( v_bkginc(jpi,jpj,jpk) )
  295. ALLOCATE( ssh_bkginc(jpi,jpj) )
  296. ALLOCATE( seaice_bkginc(jpi,jpj))
  297. #if defined key_asminc
  298. ALLOCATE( ssh_iau(jpi,jpj) )
  299. #endif
  300. #if defined key_cice && defined key_asminc
  301. ALLOCATE( ndaice_da(jpi,jpj) )
  302. #endif
  303. t_bkginc(:,:,:) = 0.0
  304. s_bkginc(:,:,:) = 0.0
  305. u_bkginc(:,:,:) = 0.0
  306. v_bkginc(:,:,:) = 0.0
  307. ssh_bkginc(:,:) = 0.0
  308. seaice_bkginc(:,:) = 0.0
  309. #if defined key_asminc
  310. ssh_iau(:,:) = 0.0
  311. #endif
  312. #if defined key_cice && defined key_asminc
  313. ndaice_da(:,:) = 0.0
  314. #endif
  315. IF ( ( ln_trainc ).OR.( ln_dyninc ).OR.( ln_sshinc ).OR.( ln_seaiceinc ) ) THEN
  316. !--------------------------------------------------------------------
  317. ! Read the increments from file
  318. !--------------------------------------------------------------------
  319. CALL iom_open( c_asminc, inum )
  320. CALL iom_get( inum, 'time', zdate_inc )
  321. CALL iom_get( inum, 'z_inc_dateb', z_inc_dateb )
  322. CALL iom_get( inum, 'z_inc_datef', z_inc_datef )
  323. z_inc_dateb = zdate_inc
  324. z_inc_datef = zdate_inc
  325. IF(lwp) THEN
  326. WRITE(numout,*)
  327. WRITE(numout,*) 'asm_inc_init : Assimilation increments valid ', &
  328. & ' between dates ', NINT( z_inc_dateb ),' and ', &
  329. & NINT( z_inc_datef )
  330. WRITE(numout,*) '~~~~~~~~~~~~'
  331. ENDIF
  332. IF ( ( NINT( z_inc_dateb ) < ndastp ) &
  333. & .OR.( NINT( z_inc_datef ) > iitend_date ) ) &
  334. & CALL ctl_warn( ' Validity time of assimilation increments is ', &
  335. & ' outside the assimilation interval' )
  336. IF ( ( ln_asmdin ).AND.( NINT( zdate_inc ) /= iitdin_date ) ) &
  337. & CALL ctl_warn( ' Validity time of assimilation increments does ', &
  338. & ' not agree with Direct Initialization time' )
  339. IF ( ln_trainc ) THEN
  340. CALL iom_get( inum, jpdom_autoglo, 'bckint', t_bkginc, 1 )
  341. CALL iom_get( inum, jpdom_autoglo, 'bckins', s_bkginc, 1 )
  342. ! Apply the masks
  343. t_bkginc(:,:,:) = t_bkginc(:,:,:) * tmask(:,:,:)
  344. s_bkginc(:,:,:) = s_bkginc(:,:,:) * tmask(:,:,:)
  345. ! Set missing increments to 0.0 rather than 1e+20
  346. ! to allow for differences in masks
  347. WHERE( ABS( t_bkginc(:,:,:) ) > 1.0e+10 ) t_bkginc(:,:,:) = 0.0
  348. WHERE( ABS( s_bkginc(:,:,:) ) > 1.0e+10 ) s_bkginc(:,:,:) = 0.0
  349. ENDIF
  350. IF ( ln_dyninc ) THEN
  351. CALL iom_get( inum, jpdom_autoglo, 'bckinu', u_bkginc, 1 )
  352. CALL iom_get( inum, jpdom_autoglo, 'bckinv', v_bkginc, 1 )
  353. ! Apply the masks
  354. u_bkginc(:,:,:) = u_bkginc(:,:,:) * umask(:,:,:)
  355. v_bkginc(:,:,:) = v_bkginc(:,:,:) * vmask(:,:,:)
  356. ! Set missing increments to 0.0 rather than 1e+20
  357. ! to allow for differences in masks
  358. WHERE( ABS( u_bkginc(:,:,:) ) > 1.0e+10 ) u_bkginc(:,:,:) = 0.0
  359. WHERE( ABS( v_bkginc(:,:,:) ) > 1.0e+10 ) v_bkginc(:,:,:) = 0.0
  360. ENDIF
  361. IF ( ln_sshinc ) THEN
  362. CALL iom_get( inum, jpdom_autoglo, 'bckineta', ssh_bkginc, 1 )
  363. ! Apply the masks
  364. ssh_bkginc(:,:) = ssh_bkginc(:,:) * tmask(:,:,1)
  365. ! Set missing increments to 0.0 rather than 1e+20
  366. ! to allow for differences in masks
  367. WHERE( ABS( ssh_bkginc(:,:) ) > 1.0e+10 ) ssh_bkginc(:,:) = 0.0
  368. ENDIF
  369. IF ( ln_seaiceinc ) THEN
  370. CALL iom_get( inum, jpdom_autoglo, 'bckinseaice', seaice_bkginc, 1 )
  371. ! Apply the masks
  372. seaice_bkginc(:,:) = seaice_bkginc(:,:) * tmask(:,:,1)
  373. ! Set missing increments to 0.0 rather than 1e+20
  374. ! to allow for differences in masks
  375. WHERE( ABS( seaice_bkginc(:,:) ) > 1.0e+10 ) seaice_bkginc(:,:) = 0.0
  376. ENDIF
  377. CALL iom_close( inum )
  378. ENDIF
  379. !-----------------------------------------------------------------------
  380. ! Apply divergence damping filter
  381. !-----------------------------------------------------------------------
  382. IF ( ln_dyninc .AND. nn_divdmp > 0 ) THEN
  383. CALL wrk_alloc(jpi,jpj,hdiv)
  384. DO jt = 1, nn_divdmp
  385. DO jk = 1, jpkm1
  386. hdiv(:,:) = 0._wp
  387. DO jj = 2, jpjm1
  388. DO ji = fs_2, fs_jpim1 ! vector opt.
  389. hdiv(ji,jj) = &
  390. ( e2u(ji ,jj ) * fse3u(ji ,jj ,jk) * u_bkginc(ji ,jj ,jk) &
  391. - e2u(ji-1,jj ) * fse3u(ji-1,jj ,jk) * u_bkginc(ji-1,jj ,jk) &
  392. + e1v(ji ,jj ) * fse3v(ji ,jj ,jk) * v_bkginc(ji ,jj ,jk) &
  393. - e1v(ji ,jj-1) * fse3v(ji ,jj-1,jk) * v_bkginc(ji ,jj-1,jk) ) &
  394. / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
  395. END DO
  396. END DO
  397. CALL lbc_lnk( hdiv, 'T', 1. ) ! lateral boundary cond. (no sign change)
  398. DO jj = 2, jpjm1
  399. DO ji = fs_2, fs_jpim1 ! vector opt.
  400. u_bkginc(ji,jj,jk) = u_bkginc(ji,jj,jk) + 0.2_wp * ( e1t(ji+1,jj)*e2t(ji+1,jj) * hdiv(ji+1,jj) &
  401. - e1t(ji ,jj)*e2t(ji ,jj) * hdiv(ji ,jj) ) &
  402. / e1u(ji,jj) * umask(ji,jj,jk)
  403. v_bkginc(ji,jj,jk) = v_bkginc(ji,jj,jk) + 0.2_wp * ( e1t(ji,jj+1)*e2t(ji,jj+1) * hdiv(ji,jj+1) &
  404. - e1t(ji,jj )*e2t(ji,jj ) * hdiv(ji,jj ) ) &
  405. / e2v(ji,jj) * vmask(ji,jj,jk)
  406. END DO
  407. END DO
  408. END DO
  409. END DO
  410. CALL wrk_dealloc(jpi,jpj,hdiv)
  411. ENDIF
  412. !-----------------------------------------------------------------------
  413. ! Allocate and initialize the background state arrays
  414. !-----------------------------------------------------------------------
  415. IF ( ln_asmdin ) THEN
  416. ALLOCATE( t_bkg(jpi,jpj,jpk) )
  417. ALLOCATE( s_bkg(jpi,jpj,jpk) )
  418. ALLOCATE( u_bkg(jpi,jpj,jpk) )
  419. ALLOCATE( v_bkg(jpi,jpj,jpk) )
  420. ALLOCATE( ssh_bkg(jpi,jpj) )
  421. t_bkg(:,:,:) = 0.0
  422. s_bkg(:,:,:) = 0.0
  423. u_bkg(:,:,:) = 0.0
  424. v_bkg(:,:,:) = 0.0
  425. ssh_bkg(:,:) = 0.0
  426. !--------------------------------------------------------------------
  427. ! Read from file the background state at analysis time
  428. !--------------------------------------------------------------------
  429. CALL iom_open( c_asmdin, inum )
  430. CALL iom_get( inum, 'rdastp', zdate_bkg )
  431. IF(lwp) THEN
  432. WRITE(numout,*)
  433. WRITE(numout,*) 'asm_inc_init : Assimilation background state valid at : ', &
  434. & NINT( zdate_bkg )
  435. WRITE(numout,*) '~~~~~~~~~~~~'
  436. ENDIF
  437. IF ( NINT( zdate_bkg ) /= iitdin_date ) &
  438. & CALL ctl_warn( ' Validity time of assimilation background state does', &
  439. & ' not agree with Direct Initialization time' )
  440. IF ( ln_trainc ) THEN
  441. CALL iom_get( inum, jpdom_autoglo, 'tn', t_bkg )
  442. CALL iom_get( inum, jpdom_autoglo, 'sn', s_bkg )
  443. t_bkg(:,:,:) = t_bkg(:,:,:) * tmask(:,:,:)
  444. s_bkg(:,:,:) = s_bkg(:,:,:) * tmask(:,:,:)
  445. ENDIF
  446. IF ( ln_dyninc ) THEN
  447. CALL iom_get( inum, jpdom_autoglo, 'un', u_bkg )
  448. CALL iom_get( inum, jpdom_autoglo, 'vn', v_bkg )
  449. u_bkg(:,:,:) = u_bkg(:,:,:) * umask(:,:,:)
  450. v_bkg(:,:,:) = v_bkg(:,:,:) * vmask(:,:,:)
  451. ENDIF
  452. IF ( ln_sshinc ) THEN
  453. CALL iom_get( inum, jpdom_autoglo, 'sshn', ssh_bkg )
  454. ssh_bkg(:,:) = ssh_bkg(:,:) * tmask(:,:,1)
  455. ENDIF
  456. CALL iom_close( inum )
  457. ENDIF
  458. !
  459. END SUBROUTINE asm_inc_init
  460. SUBROUTINE calc_date( kit000, kt, kdate0, kdate )
  461. !!----------------------------------------------------------------------
  462. !! *** ROUTINE calc_date ***
  463. !!
  464. !! ** Purpose : Compute the calendar date YYYYMMDD at a given time step.
  465. !!
  466. !! ** Method : Compute the calendar date YYYYMMDD at a given time step.
  467. !!
  468. !! ** Action :
  469. !!----------------------------------------------------------------------
  470. INTEGER, INTENT(IN) :: kit000 ! Initial time step
  471. INTEGER, INTENT(IN) :: kt ! Current time step referenced to kit000
  472. INTEGER, INTENT(IN) :: kdate0 ! Initial date
  473. INTEGER, INTENT(OUT) :: kdate ! Current date reference to kdate0
  474. !
  475. INTEGER :: iyea0 ! Initial year
  476. INTEGER :: imon0 ! Initial month
  477. INTEGER :: iday0 ! Initial day
  478. INTEGER :: iyea ! Current year
  479. INTEGER :: imon ! Current month
  480. INTEGER :: iday ! Current day
  481. INTEGER :: idaystp ! Number of days between initial and current date
  482. INTEGER :: idaycnt ! Day counter
  483. INTEGER, DIMENSION(12) :: imonth_len !: length in days of the months of the current year
  484. !-----------------------------------------------------------------------
  485. ! Compute the calendar date YYYYMMDD
  486. !-----------------------------------------------------------------------
  487. ! Initial date
  488. iyea0 = kdate0 / 10000
  489. imon0 = ( kdate0 - ( iyea0 * 10000 ) ) / 100
  490. iday0 = kdate0 - ( iyea0 * 10000 ) - ( imon0 * 100 )
  491. ! Check that kt >= kit000 - 1
  492. IF ( kt < kit000 - 1 ) CALL ctl_stop( ' kt must be >= kit000 - 1')
  493. ! If kt = kit000 - 1 then set the date to the restart date
  494. IF ( kt == kit000 - 1 ) THEN
  495. kdate = ndastp
  496. RETURN
  497. ENDIF
  498. ! Compute the number of days from the initial date
  499. idaystp = INT( REAL( kt - kit000 ) * rdt / 86400. )
  500. iday = iday0
  501. imon = imon0
  502. iyea = iyea0
  503. idaycnt = 0
  504. CALL calc_month_len( iyea, imonth_len )
  505. DO WHILE ( idaycnt < idaystp )
  506. iday = iday + 1
  507. IF ( iday > imonth_len(imon) ) THEN
  508. iday = 1
  509. imon = imon + 1
  510. ENDIF
  511. IF ( imon > 12 ) THEN
  512. imon = 1
  513. iyea = iyea + 1
  514. CALL calc_month_len( iyea, imonth_len ) ! update month lengths
  515. ENDIF
  516. idaycnt = idaycnt + 1
  517. END DO
  518. !
  519. kdate = iyea * 10000 + imon * 100 + iday
  520. !
  521. END SUBROUTINE
  522. SUBROUTINE calc_month_len( iyear, imonth_len )
  523. !!----------------------------------------------------------------------
  524. !! *** ROUTINE calc_month_len ***
  525. !!
  526. !! ** Purpose : Compute the number of days in a months given a year.
  527. !!
  528. !! ** Method :
  529. !!----------------------------------------------------------------------
  530. INTEGER, DIMENSION(12) :: imonth_len !: length in days of the months of the current year
  531. INTEGER :: iyear !: year
  532. !!----------------------------------------------------------------------
  533. !
  534. ! length of the month of the current year (from nleapy, read in namelist)
  535. IF ( nleapy < 2 ) THEN
  536. imonth_len(:) = (/ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 /)
  537. IF ( nleapy == 1 ) THEN ! we are using calendar with leap years
  538. IF ( MOD(iyear, 4) == 0 .AND. ( MOD(iyear, 400) == 0 .OR. MOD(iyear, 100) /= 0 ) ) THEN
  539. imonth_len(2) = 29
  540. ENDIF
  541. ENDIF
  542. ELSE
  543. imonth_len(:) = nleapy ! all months with nleapy days per year
  544. ENDIF
  545. !
  546. END SUBROUTINE
  547. SUBROUTINE tra_asm_inc( kt )
  548. !!----------------------------------------------------------------------
  549. !! *** ROUTINE tra_asm_inc ***
  550. !!
  551. !! ** Purpose : Apply the tracer (T and S) assimilation increments
  552. !!
  553. !! ** Method : Direct initialization or Incremental Analysis Updating
  554. !!
  555. !! ** Action :
  556. !!----------------------------------------------------------------------
  557. INTEGER, INTENT(IN) :: kt ! Current time step
  558. !
  559. INTEGER :: ji,jj,jk
  560. INTEGER :: it
  561. REAL(wp) :: zincwgt ! IAU weight for current time step
  562. REAL (wp), DIMENSION(jpi,jpj,jpk) :: fzptnz ! 3d freezing point values
  563. !!----------------------------------------------------------------------
  564. ! freezing point calculation taken from oc_fz_pt (but calculated for all depths)
  565. ! used to prevent the applied increments taking the temperature below the local freezing point
  566. DO jk = 1, jpkm1
  567. CALL eos_fzp( tsn(:,:,jk,jp_sal), fzptnz(:,:,jk), fsdept(:,:,jk) )
  568. END DO
  569. IF ( ln_asmiau ) THEN
  570. !--------------------------------------------------------------------
  571. ! Incremental Analysis Updating
  572. !--------------------------------------------------------------------
  573. IF ( ( kt >= nitiaustr_r ).AND.( kt <= nitiaufin_r ) ) THEN
  574. it = kt - nit000 + 1
  575. zincwgt = wgtiau(it) / rdt ! IAU weight for the current time step
  576. IF(lwp) THEN
  577. WRITE(numout,*)
  578. WRITE(numout,*) 'tra_asm_inc : Tracer IAU at time step = ', kt,' with IAU weight = ', wgtiau(it)
  579. WRITE(numout,*) '~~~~~~~~~~~~'
  580. ENDIF
  581. ! Update the tracer tendencies
  582. DO jk = 1, jpkm1
  583. IF (ln_temnofreeze) THEN
  584. ! Do not apply negative increments if the temperature will fall below freezing
  585. WHERE(t_bkginc(:,:,jk) > 0.0_wp .OR. &
  586. & tsn(:,:,jk,jp_tem) + tsa(:,:,jk,jp_tem) + t_bkginc(:,:,jk) * wgtiau(it) > fzptnz(:,:,jk) )
  587. tsa(:,:,jk,jp_tem) = tsa(:,:,jk,jp_tem) + t_bkginc(:,:,jk) * zincwgt
  588. END WHERE
  589. ELSE
  590. tsa(:,:,jk,jp_tem) = tsa(:,:,jk,jp_tem) + t_bkginc(:,:,jk) * zincwgt
  591. ENDIF
  592. IF (ln_salfix) THEN
  593. ! Do not apply negative increments if the salinity will fall below a specified
  594. ! minimum value salfixmin
  595. WHERE(s_bkginc(:,:,jk) > 0.0_wp .OR. &
  596. & tsn(:,:,jk,jp_sal) + tsa(:,:,jk,jp_sal) + s_bkginc(:,:,jk) * wgtiau(it) > salfixmin )
  597. tsa(:,:,jk,jp_sal) = tsa(:,:,jk,jp_sal) + s_bkginc(:,:,jk) * zincwgt
  598. END WHERE
  599. ELSE
  600. tsa(:,:,jk,jp_sal) = tsa(:,:,jk,jp_sal) + s_bkginc(:,:,jk) * zincwgt
  601. ENDIF
  602. END DO
  603. ENDIF
  604. IF ( kt == nitiaufin_r + 1 ) THEN ! For bias crcn to work
  605. DEALLOCATE( t_bkginc )
  606. DEALLOCATE( s_bkginc )
  607. ENDIF
  608. ELSEIF ( ln_asmdin ) THEN
  609. !--------------------------------------------------------------------
  610. ! Direct Initialization
  611. !--------------------------------------------------------------------
  612. IF ( kt == nitdin_r ) THEN
  613. neuler = 0 ! Force Euler forward step
  614. ! Initialize the now fields with the background + increment
  615. IF (ln_temnofreeze) THEN
  616. ! Do not apply negative increments if the temperature will fall below freezing
  617. WHERE( t_bkginc(:,:,:) > 0.0_wp .OR. tsn(:,:,:,jp_tem) + t_bkginc(:,:,:) > fzptnz(:,:,:) )
  618. tsn(:,:,:,jp_tem) = t_bkg(:,:,:) + t_bkginc(:,:,:)
  619. END WHERE
  620. ELSE
  621. tsn(:,:,:,jp_tem) = t_bkg(:,:,:) + t_bkginc(:,:,:)
  622. ENDIF
  623. IF (ln_salfix) THEN
  624. ! Do not apply negative increments if the salinity will fall below a specified
  625. ! minimum value salfixmin
  626. WHERE( s_bkginc(:,:,:) > 0.0_wp .OR. tsn(:,:,:,jp_sal) + s_bkginc(:,:,:) > salfixmin )
  627. tsn(:,:,:,jp_sal) = s_bkg(:,:,:) + s_bkginc(:,:,:)
  628. END WHERE
  629. ELSE
  630. tsn(:,:,:,jp_sal) = s_bkg(:,:,:) + s_bkginc(:,:,:)
  631. ENDIF
  632. tsb(:,:,:,:) = tsn(:,:,:,:) ! Update before fields
  633. CALL eos( tsb, rhd, rhop, gdept_0(:,:,:) ) ! Before potential and in situ densities
  634. !!gm fabien
  635. ! CALL eos( tsb, rhd, rhop ) ! Before potential and in situ densities
  636. !!gm
  637. IF( ln_zps .AND. .NOT. lk_c1d .AND. .NOT. ln_isfcav) &
  638. & CALL zps_hde ( kt, jpts, tsb, gtsu, gtsv, & ! Partial steps: before horizontal gradient
  639. & rhd, gru , grv ) ! of t, s, rd at the last ocean level
  640. IF( ln_zps .AND. .NOT. lk_c1d .AND. ln_isfcav) &
  641. & CALL zps_hde_isf( nit000, jpts, tsb, gtsu, gtsv, & ! Partial steps for top cell (ISF)
  642. & rhd, gru , grv , aru , arv , gzu , gzv , ge3ru , ge3rv , &
  643. & gtui, gtvi, grui, grvi, arui, arvi, gzui, gzvi, ge3rui, ge3rvi ) ! of t, s, rd at the last ocean level
  644. #if defined key_zdfkpp
  645. CALL eos( tsn, rhd, fsdept_n(:,:,:) ) ! Compute rhd
  646. !!gm fabien CALL eos( tsn, rhd ) ! Compute rhd
  647. #endif
  648. DEALLOCATE( t_bkginc )
  649. DEALLOCATE( s_bkginc )
  650. DEALLOCATE( t_bkg )
  651. DEALLOCATE( s_bkg )
  652. ENDIF
  653. !
  654. ENDIF
  655. ! Perhaps the following call should be in step
  656. IF ( ln_seaiceinc ) CALL seaice_asm_inc ( kt ) ! apply sea ice concentration increment
  657. !
  658. END SUBROUTINE tra_asm_inc
  659. SUBROUTINE dyn_asm_inc( kt )
  660. !!----------------------------------------------------------------------
  661. !! *** ROUTINE dyn_asm_inc ***
  662. !!
  663. !! ** Purpose : Apply the dynamics (u and v) assimilation increments.
  664. !!
  665. !! ** Method : Direct initialization or Incremental Analysis Updating.
  666. !!
  667. !! ** Action :
  668. !!----------------------------------------------------------------------
  669. INTEGER, INTENT(IN) :: kt ! Current time step
  670. !
  671. INTEGER :: jk
  672. INTEGER :: it
  673. REAL(wp) :: zincwgt ! IAU weight for current time step
  674. !!----------------------------------------------------------------------
  675. IF ( ln_asmiau ) THEN
  676. !--------------------------------------------------------------------
  677. ! Incremental Analysis Updating
  678. !--------------------------------------------------------------------
  679. IF ( ( kt >= nitiaustr_r ).AND.( kt <= nitiaufin_r ) ) THEN
  680. it = kt - nit000 + 1
  681. zincwgt = wgtiau(it) / rdt ! IAU weight for the current time step
  682. IF(lwp) THEN
  683. WRITE(numout,*)
  684. WRITE(numout,*) 'dyn_asm_inc : Dynamics IAU at time step = ', &
  685. & kt,' with IAU weight = ', wgtiau(it)
  686. WRITE(numout,*) '~~~~~~~~~~~~'
  687. ENDIF
  688. ! Update the dynamic tendencies
  689. DO jk = 1, jpkm1
  690. ua(:,:,jk) = ua(:,:,jk) + u_bkginc(:,:,jk) * zincwgt
  691. va(:,:,jk) = va(:,:,jk) + v_bkginc(:,:,jk) * zincwgt
  692. END DO
  693. IF ( kt == nitiaufin_r ) THEN
  694. DEALLOCATE( u_bkginc )
  695. DEALLOCATE( v_bkginc )
  696. ENDIF
  697. ENDIF
  698. ELSEIF ( ln_asmdin ) THEN
  699. !--------------------------------------------------------------------
  700. ! Direct Initialization
  701. !--------------------------------------------------------------------
  702. IF ( kt == nitdin_r ) THEN
  703. neuler = 0 ! Force Euler forward step
  704. ! Initialize the now fields with the background + increment
  705. un(:,:,:) = u_bkg(:,:,:) + u_bkginc(:,:,:)
  706. vn(:,:,:) = v_bkg(:,:,:) + v_bkginc(:,:,:)
  707. ub(:,:,:) = un(:,:,:) ! Update before fields
  708. vb(:,:,:) = vn(:,:,:)
  709. DEALLOCATE( u_bkg )
  710. DEALLOCATE( v_bkg )
  711. DEALLOCATE( u_bkginc )
  712. DEALLOCATE( v_bkginc )
  713. ENDIF
  714. !
  715. ENDIF
  716. !
  717. END SUBROUTINE dyn_asm_inc
  718. SUBROUTINE ssh_asm_inc( kt )
  719. !!----------------------------------------------------------------------
  720. !! *** ROUTINE ssh_asm_inc ***
  721. !!
  722. !! ** Purpose : Apply the sea surface height assimilation increment.
  723. !!
  724. !! ** Method : Direct initialization or Incremental Analysis Updating.
  725. !!
  726. !! ** Action :
  727. !!----------------------------------------------------------------------
  728. INTEGER, INTENT(IN) :: kt ! Current time step
  729. !
  730. INTEGER :: it
  731. INTEGER :: jk
  732. REAL(wp) :: zincwgt ! IAU weight for current time step
  733. !!----------------------------------------------------------------------
  734. IF ( ln_asmiau ) THEN
  735. !--------------------------------------------------------------------
  736. ! Incremental Analysis Updating
  737. !--------------------------------------------------------------------
  738. IF ( ( kt >= nitiaustr_r ).AND.( kt <= nitiaufin_r ) ) THEN
  739. it = kt - nit000 + 1
  740. zincwgt = wgtiau(it) / rdt ! IAU weight for the current time step
  741. IF(lwp) THEN
  742. WRITE(numout,*)
  743. WRITE(numout,*) 'ssh_asm_inc : SSH IAU at time step = ', &
  744. & kt,' with IAU weight = ', wgtiau(it)
  745. WRITE(numout,*) '~~~~~~~~~~~~'
  746. ENDIF
  747. ! Save the tendency associated with the IAU weighted SSH increment
  748. ! (applied in dynspg.*)
  749. #if defined key_asminc
  750. ssh_iau(:,:) = ssh_bkginc(:,:) * zincwgt
  751. #endif
  752. IF ( kt == nitiaufin_r ) THEN
  753. DEALLOCATE( ssh_bkginc )
  754. ENDIF
  755. #if defined key_asminc
  756. ELSE IF( kt == nitiaufin_r+1 ) THEN
  757. !
  758. ssh_iau(:,:) = 0._wp
  759. !
  760. #endif
  761. ENDIF
  762. ELSEIF ( ln_asmdin ) THEN
  763. !--------------------------------------------------------------------
  764. ! Direct Initialization
  765. !--------------------------------------------------------------------
  766. IF ( kt == nitdin_r ) THEN
  767. neuler = 0 ! Force Euler forward step
  768. ! Initialize the now fields the background + increment
  769. sshn(:,:) = ssh_bkg(:,:) + ssh_bkginc(:,:)
  770. ! Update before fields
  771. sshb(:,:) = sshn(:,:)
  772. IF( lk_vvl ) THEN
  773. DO jk = 1, jpk
  774. fse3t_b(:,:,jk) = fse3t_n(:,:,jk)
  775. END DO
  776. ENDIF
  777. DEALLOCATE( ssh_bkg )
  778. DEALLOCATE( ssh_bkginc )
  779. ENDIF
  780. !
  781. ENDIF
  782. !
  783. END SUBROUTINE ssh_asm_inc
  784. SUBROUTINE seaice_asm_inc( kt, kindic )
  785. !!----------------------------------------------------------------------
  786. !! *** ROUTINE seaice_asm_inc ***
  787. !!
  788. !! ** Purpose : Apply the sea ice assimilation increment.
  789. !!
  790. !! ** Method : Direct initialization or Incremental Analysis Updating.
  791. !!
  792. !! ** Action :
  793. !!
  794. !!----------------------------------------------------------------------
  795. IMPLICIT NONE
  796. !
  797. INTEGER, INTENT(in) :: kt ! Current time step
  798. INTEGER, INTENT(in), OPTIONAL :: kindic ! flag for disabling the deallocation
  799. !
  800. INTEGER :: it
  801. REAL(wp) :: zincwgt ! IAU weight for current time step
  802. #if defined key_lim2
  803. REAL(wp), DIMENSION(jpi,jpj) :: zofrld, zohicif, zseaicendg, zhicifinc ! LIM
  804. REAL(wp) :: zhicifmin = 0.5_wp ! ice minimum depth in metres
  805. #endif
  806. !!----------------------------------------------------------------------
  807. IF ( ln_asmiau ) THEN
  808. !--------------------------------------------------------------------
  809. ! Incremental Analysis Updating
  810. !--------------------------------------------------------------------
  811. IF ( ( kt >= nitiaustr_r ).AND.( kt <= nitiaufin_r ) ) THEN
  812. it = kt - nit000 + 1
  813. zincwgt = wgtiau(it) ! IAU weight for the current time step
  814. ! note this is not a tendency so should not be divided by rdt (as with the tracer and other increments)
  815. IF(lwp) THEN
  816. WRITE(numout,*)
  817. WRITE(numout,*) 'seaice_asm_inc : sea ice conc IAU at time step = ', &
  818. & kt,' with IAU weight = ', wgtiau(it)
  819. WRITE(numout,*) '~~~~~~~~~~~~'
  820. ENDIF
  821. ! Sea-ice : LIM-3 case (to add)
  822. #if defined key_lim2
  823. ! Sea-ice : LIM-2 case
  824. zofrld (:,:) = frld(:,:)
  825. zohicif(:,:) = hicif(:,:)
  826. !
  827. frld = MIN( MAX( frld (:,:) - seaice_bkginc(:,:) * zincwgt, 0.0_wp), 1.0_wp)
  828. pfrld = MIN( MAX( pfrld(:,:) - seaice_bkginc(:,:) * zincwgt, 0.0_wp), 1.0_wp)
  829. fr_i(:,:) = 1.0_wp - frld(:,:) ! adjust ice fraction
  830. !
  831. zseaicendg(:,:) = zofrld(:,:) - frld(:,:) ! find out actual sea ice nudge applied
  832. !
  833. ! Nudge sea ice depth to bring it up to a required minimum depth
  834. WHERE( zseaicendg(:,:) > 0.0_wp .AND. hicif(:,:) < zhicifmin )
  835. zhicifinc(:,:) = (zhicifmin - hicif(:,:)) * zincwgt
  836. ELSEWHERE
  837. zhicifinc(:,:) = 0.0_wp
  838. END WHERE
  839. !
  840. ! nudge ice depth
  841. hicif (:,:) = hicif (:,:) + zhicifinc(:,:)
  842. phicif(:,:) = phicif(:,:) + zhicifinc(:,:)
  843. !
  844. ! seaice salinity balancing (to add)
  845. #endif
  846. #if defined key_cice && defined key_asminc
  847. ! Sea-ice : CICE case. Pass ice increment tendency into CICE
  848. ndaice_da(:,:) = seaice_bkginc(:,:) * zincwgt / rdt
  849. #endif
  850. IF ( kt == nitiaufin_r ) THEN
  851. DEALLOCATE( seaice_bkginc )
  852. ENDIF
  853. ELSE
  854. #if defined key_cice && defined key_asminc
  855. ! Sea-ice : CICE case. Zero ice increment tendency into CICE
  856. ndaice_da(:,:) = 0.0_wp
  857. #endif
  858. ENDIF
  859. ELSEIF ( ln_asmdin ) THEN
  860. !--------------------------------------------------------------------
  861. ! Direct Initialization
  862. !--------------------------------------------------------------------
  863. IF ( kt == nitdin_r ) THEN
  864. neuler = 0 ! Force Euler forward step
  865. ! Sea-ice : LIM-3 case (to add)
  866. #if defined key_lim2
  867. ! Sea-ice : LIM-2 case.
  868. zofrld(:,:)=frld(:,:)
  869. zohicif(:,:)=hicif(:,:)
  870. !
  871. ! Initialize the now fields the background + increment
  872. frld (:,:) = MIN( MAX( frld(:,:) - seaice_bkginc(:,:), 0.0_wp), 1.0_wp)
  873. pfrld(:,:) = frld(:,:)
  874. fr_i (:,:) = 1.0_wp - frld(:,:) ! adjust ice fraction
  875. zseaicendg(:,:) = zofrld(:,:) - frld(:,:) ! find out actual sea ice nudge applied
  876. !
  877. ! Nudge sea ice depth to bring it up to a required minimum depth
  878. WHERE( zseaicendg(:,:) > 0.0_wp .AND. hicif(:,:) < zhicifmin )
  879. zhicifinc(:,:) = (zhicifmin - hicif(:,:)) * zincwgt
  880. ELSEWHERE
  881. zhicifinc(:,:) = 0.0_wp
  882. END WHERE
  883. !
  884. ! nudge ice depth
  885. hicif (:,:) = hicif (:,:) + zhicifinc(:,:)
  886. phicif(:,:) = phicif(:,:)
  887. !
  888. ! seaice salinity balancing (to add)
  889. #endif
  890. #if defined key_cice && defined key_asminc
  891. ! Sea-ice : CICE case. Pass ice increment tendency into CICE
  892. ndaice_da(:,:) = seaice_bkginc(:,:) / rdt
  893. #endif
  894. IF ( .NOT. PRESENT(kindic) ) THEN
  895. DEALLOCATE( seaice_bkginc )
  896. END IF
  897. ELSE
  898. #if defined key_cice && defined key_asminc
  899. ! Sea-ice : CICE case. Zero ice increment tendency into CICE
  900. ndaice_da(:,:) = 0.0_wp
  901. #endif
  902. ENDIF
  903. !#if defined defined key_lim2 || defined key_cice
  904. !
  905. ! IF (ln_seaicebal ) THEN
  906. ! !! balancing salinity increments
  907. ! !! simple case from limflx.F90 (doesn't include a mass flux)
  908. ! !! assumption is that as ice concentration is reduced or increased
  909. ! !! the snow and ice depths remain constant
  910. ! !! note that snow is being created where ice concentration is being increased
  911. ! !! - could be more sophisticated and
  912. ! !! not do this (but would need to alter h_snow)
  913. !
  914. ! usave(:,:,:)=sb(:,:,:) ! use array as a temporary store
  915. !
  916. ! DO jj = 1, jpj
  917. ! DO ji = 1, jpi
  918. ! ! calculate change in ice and snow mass per unit area
  919. ! ! positive values imply adding salt to the ocean (results from ice formation)
  920. ! ! fwf : ice formation and melting
  921. !
  922. ! zfons = ( -nfresh_da(ji,jj)*soce + nfsalt_da(ji,jj) )*rdt
  923. !
  924. ! ! change salinity down to mixed layer depth
  925. ! mld=hmld_kara(ji,jj)
  926. !
  927. ! ! prevent small mld
  928. ! ! less than 10m can cause salinity instability
  929. ! IF (mld < 10) mld=10
  930. !
  931. ! ! set to bottom of a level
  932. ! DO jk = jpk-1, 2, -1
  933. ! IF ((mld > gdepw(ji,jj,jk)) .and. (mld < gdepw(ji,jj,jk+1))) THEN
  934. ! mld=gdepw(ji,jj,jk+1)
  935. ! jkmax=jk
  936. ! ENDIF
  937. ! ENDDO
  938. !
  939. ! ! avoid applying salinity balancing in shallow water or on land
  940. ! !
  941. !
  942. ! ! dsal_ocn (psu kg m^-2) / (kg m^-3 * m)
  943. !
  944. ! dsal_ocn=0.0_wp
  945. ! sal_thresh=5.0_wp ! minimum salinity threshold for salinity balancing
  946. !
  947. ! if (tmask(ji,jj,1) > 0 .AND. tmask(ji,jj,jkmax) > 0 ) &
  948. ! dsal_ocn = zfons / (rhop(ji,jj,1) * mld)
  949. !
  950. ! ! put increments in for levels in the mixed layer
  951. ! ! but prevent salinity below a threshold value
  952. !
  953. ! DO jk = 1, jkmax
  954. !
  955. ! IF (dsal_ocn > 0.0_wp .or. sb(ji,jj,jk)+dsal_ocn > sal_thresh) THEN
  956. ! sb(ji,jj,jk) = sb(ji,jj,jk) + dsal_ocn
  957. ! sn(ji,jj,jk) = sn(ji,jj,jk) + dsal_ocn
  958. ! ENDIF
  959. !
  960. ! ENDDO
  961. !
  962. ! ! ! salt exchanges at the ice/ocean interface
  963. ! ! zpmess = zfons / rdt_ice ! rdt_ice is ice timestep
  964. ! !
  965. ! !! Adjust fsalt. A +ve fsalt means adding salt to ocean
  966. ! !! fsalt(ji,jj) = fsalt(ji,jj) + zpmess ! adjust fsalt
  967. ! !!
  968. ! !! emps(ji,jj) = emps(ji,jj) + zpmess ! or adjust emps (see icestp1d)
  969. ! !! ! E-P (kg m-2 s-2)
  970. ! ! emp(ji,jj) = emp(ji,jj) + zpmess ! E-P (kg m-2 s-2)
  971. ! ENDDO !ji
  972. ! ENDDO !jj!
  973. !
  974. ! ENDIF !ln_seaicebal
  975. !
  976. !#endif
  977. ENDIF
  978. END SUBROUTINE seaice_asm_inc
  979. !!======================================================================
  980. END MODULE asminc