icbini.F90 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. MODULE icbini
  2. !!======================================================================
  3. !! *** MODULE icbini ***
  4. !! Icebergs: initialise variables for iceberg tracking
  5. !!======================================================================
  6. !! History : - ! 2010-01 (T. Martin & A. Adcroft) Original code
  7. !! 3.3 ! 2011-03 (G. Madec) Part conversion to NEMO form ; Removal of mapping from another grid
  8. !! - ! 2011-04 (S. Alderson) Split into separate modules ; Restore restart routines
  9. !! - ! 2011-05 (S. Alderson) generate_test_icebergs restored ; new forcing arrays with extra halo ;
  10. !! - ! north fold exchange arrays added
  11. !!----------------------------------------------------------------------
  12. !!----------------------------------------------------------------------
  13. !! icb_init : initialise icebergs
  14. !! icb_ini_gen : generate test icebergs
  15. !! icb_nam : read iceberg namelist
  16. !!----------------------------------------------------------------------
  17. USE dom_oce ! ocean domain
  18. USE in_out_manager ! IO routines and numout in particular
  19. USE lib_mpp ! mpi library and lk_mpp in particular
  20. USE sbc_oce ! ocean : surface boundary condition
  21. USE sbc_ice ! sea-ice: surface boundary condition
  22. USE iom ! IOM library
  23. USE fldread ! field read
  24. USE lbclnk ! lateral boundary condition - MPP link
  25. !
  26. USE icb_oce ! define iceberg arrays
  27. USE icbutl ! iceberg utility routines
  28. USE icbrst ! iceberg restart routines
  29. USE icbtrj ! iceberg trajectory I/O routines
  30. USE icbdia ! iceberg budget routines
  31. IMPLICIT NONE
  32. PRIVATE
  33. PUBLIC icb_init ! routine called in nemogcm.F90 module
  34. CHARACTER(len=100) :: cn_dir = './' !: Root directory for location of icb files
  35. TYPE(FLD_N) :: sn_icb !: information about the calving file to be read
  36. TYPE(FLD), PUBLIC, ALLOCATABLE , DIMENSION(:) :: sf_icb !: structure: file information, fields read
  37. !: used in icbini and icbstp
  38. !!----------------------------------------------------------------------
  39. !! NEMO/OPA 3.3 , NEMO Consortium (2011)
  40. !! $Id: icbini.F90 2355 2015-05-20 07:11:50Z ufla $
  41. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  42. !!----------------------------------------------------------------------
  43. CONTAINS
  44. SUBROUTINE icb_init( pdt, kt )
  45. !!----------------------------------------------------------------------
  46. !! *** ROUTINE dom_init ***
  47. !!
  48. !! ** Purpose : iceberg initialization.
  49. !!
  50. !! ** Method : - read the iceberg namelist
  51. !! - find non-overlapping processor interior since we can only
  52. !! have one instance of a particular iceberg
  53. !! - calculate the destinations for north fold exchanges
  54. !! - setup either test icebergs or calving file
  55. !!----------------------------------------------------------------------
  56. REAL(wp), INTENT(in) :: pdt ! iceberg time-step (rdt*nn_fsbc)
  57. INTEGER , INTENT(in) :: kt ! time step number
  58. !
  59. INTEGER :: ji, jj, jn ! dummy loop indices
  60. INTEGER :: i1, i2, i3 ! local integers
  61. INTEGER :: ii, inum, ivar ! - -
  62. INTEGER :: istat1, istat2, istat3 ! - -
  63. CHARACTER(len=300) :: cl_sdist ! local character
  64. !!----------------------------------------------------------------------
  65. !
  66. CALL icb_nam ! Read and print namelist parameters
  67. !
  68. IF( .NOT. ln_icebergs ) RETURN
  69. ! ! allocate gridded fields
  70. IF( icb_alloc() /= 0 ) CALL ctl_stop( 'STOP', 'icb_alloc : unable to allocate arrays' )
  71. ! ! open ascii output file or files for iceberg status information
  72. ! ! note that we choose to do this on all processors since we cannot
  73. ! ! predict where icebergs will be ahead of time
  74. CALL ctl_opn( numicb, 'icebergs.stat', 'REPLACE', 'FORMATTED', 'SEQUENTIAL', -1, numout, lwp, narea )
  75. ! set parameters (mostly from namelist)
  76. !
  77. berg_dt = pdt
  78. first_width (:) = SQRT( rn_initial_mass(:) / ( rn_LoW_ratio * rn_rho_bergs * rn_initial_thickness(:) ) )
  79. first_length(:) = rn_LoW_ratio * first_width(:)
  80. berg_grid%calving (:,:) = 0._wp
  81. berg_grid%calving_hflx (:,:) = 0._wp
  82. berg_grid%stored_heat (:,:) = 0._wp
  83. berg_grid%floating_melt(:,:) = 0._wp
  84. berg_grid%maxclass (:,:) = nclasses
  85. berg_grid%stored_ice (:,:,:) = 0._wp
  86. berg_grid%tmp (:,:) = 0._wp
  87. src_calving (:,:) = 0._wp
  88. src_calving_hflx (:,:) = 0._wp
  89. ! ! domain for icebergs
  90. IF( lk_mpp .AND. jpni == 1 ) CALL ctl_stop( 'icbinit: having ONE processor in x currently does not work' )
  91. ! NB: the issue here is simply that cyclic east-west boundary condition have not been coded in mpp case
  92. ! for the north fold we work out which points communicate by asking
  93. ! lbc_lnk to pass processor number (valid even in single processor case)
  94. ! borrow src_calving arrays for this
  95. !
  96. ! pack i and j together using a scaling of a power of 10
  97. nicbpack = 10000
  98. IF( jpiglo >= nicbpack ) CALL ctl_stop( 'icbini: processor index packing failure' )
  99. nicbfldproc(:) = -1
  100. DO jj = 1, jpj
  101. DO ji = 1, jpi
  102. src_calving_hflx(ji,jj) = narea
  103. src_calving (ji,jj) = nicbpack * mjg(jj) + mig(ji)
  104. END DO
  105. END DO
  106. CALL lbc_lnk( src_calving_hflx, 'T', 1._wp )
  107. CALL lbc_lnk( src_calving , 'T', 1._wp )
  108. ! work out interior of processor from exchange array
  109. ! first entry with narea for this processor is left hand interior index
  110. ! last entry is right hand interior index
  111. jj = jpj/2
  112. nicbdi = -1
  113. nicbei = -1
  114. DO ji = 1, jpi
  115. i3 = INT( src_calving(ji,jj) )
  116. i2 = INT( i3/nicbpack )
  117. i1 = i3 - i2*nicbpack
  118. i3 = INT( src_calving_hflx(ji,jj) )
  119. IF( i1 == mig(ji) .AND. i3 == narea ) THEN
  120. IF( nicbdi < 0 ) THEN ; nicbdi = ji
  121. ELSE ; nicbei = ji
  122. ENDIF
  123. ENDIF
  124. END DO
  125. !
  126. ! repeat for j direction
  127. ji = jpi/2
  128. nicbdj = -1
  129. nicbej = -1
  130. DO jj = 1, jpj
  131. i3 = INT( src_calving(ji,jj) )
  132. i2 = INT( i3/nicbpack )
  133. i1 = i3 - i2*nicbpack
  134. i3 = INT( src_calving_hflx(ji,jj) )
  135. IF( i2 == mjg(jj) .AND. i3 == narea ) THEN
  136. IF( nicbdj < 0 ) THEN ; nicbdj = jj
  137. ELSE ; nicbej = jj
  138. ENDIF
  139. ENDIF
  140. END DO
  141. !
  142. ! special for east-west boundary exchange we save the destination index
  143. i1 = MAX( nicbdi-1, 1)
  144. i3 = INT( src_calving(i1,jpj/2) )
  145. jj = INT( i3/nicbpack )
  146. ricb_left = REAL( i3 - nicbpack*jj, wp )
  147. i1 = MIN( nicbei+1, jpi )
  148. i3 = INT( src_calving(i1,jpj/2) )
  149. jj = INT( i3/nicbpack )
  150. ricb_right = REAL( i3 - nicbpack*jj, wp )
  151. ! north fold
  152. IF( npolj > 0 ) THEN
  153. !
  154. ! icebergs in row nicbej+1 get passed across fold
  155. nicbfldpts(:) = INT( src_calving(:,nicbej+1) )
  156. nicbflddest(:) = INT( src_calving_hflx(:,nicbej+1) )
  157. !
  158. ! work out list of unique processors to talk to
  159. ! pack them into a fixed size array where empty slots are marked by a -1
  160. DO ji = nicbdi, nicbei
  161. ii = nicbflddest(ji)
  162. IF( ii .GT. 0 ) THEN ! Needed because land suppression can mean
  163. ! that unused points are not set in edge haloes
  164. DO jn = 1, jpni
  165. ! work along array until we find an empty slot
  166. IF( nicbfldproc(jn) == -1 ) THEN
  167. nicbfldproc(jn) = ii
  168. EXIT !!gm EXIT should be avoided: use DO WHILE expression instead
  169. ENDIF
  170. ! before we find an empty slot, we may find processor number is already here so we exit
  171. IF( nicbfldproc(jn) == ii ) EXIT
  172. END DO
  173. ENDIF
  174. END DO
  175. ENDIF
  176. !
  177. IF( nn_verbose_level > 0) THEN
  178. WRITE(numicb,*) 'processor ', narea
  179. WRITE(numicb,*) 'jpi, jpj ', jpi, jpj
  180. WRITE(numicb,*) 'nldi, nlei ', nldi, nlei
  181. WRITE(numicb,*) 'nldj, nlej ', nldj, nlej
  182. WRITE(numicb,*) 'berg i interior ', nicbdi, nicbei
  183. WRITE(numicb,*) 'berg j interior ', nicbdj, nicbej
  184. WRITE(numicb,*) 'berg left ', ricb_left
  185. WRITE(numicb,*) 'berg right ', ricb_right
  186. jj = jpj/2
  187. WRITE(numicb,*) "central j line:"
  188. WRITE(numicb,*) "i processor"
  189. WRITE(numicb,*) (INT(src_calving_hflx(ji,jj)), ji=1,jpi)
  190. WRITE(numicb,*) "i point"
  191. WRITE(numicb,*) (INT(src_calving(ji,jj)), ji=1,jpi)
  192. ji = jpi/2
  193. WRITE(numicb,*) "central i line:"
  194. WRITE(numicb,*) "j processor"
  195. WRITE(numicb,*) (INT(src_calving_hflx(ji,jj)), jj=1,jpj)
  196. WRITE(numicb,*) "j point"
  197. WRITE(numicb,*) (INT(src_calving(ji,jj)), jj=1,jpj)
  198. IF( npolj > 0 ) THEN
  199. WRITE(numicb,*) 'north fold destination points '
  200. WRITE(numicb,*) nicbfldpts
  201. WRITE(numicb,*) 'north fold destination procs '
  202. WRITE(numicb,*) nicbflddest
  203. WRITE(numicb,*) 'north fold destination proclist '
  204. WRITE(numicb,*) nicbfldproc
  205. ENDIF
  206. CALL flush(numicb)
  207. ENDIF
  208. src_calving (:,:) = 0._wp
  209. src_calving_hflx(:,:) = 0._wp
  210. ! assign each new iceberg with a unique number constructed from the processor number
  211. ! and incremented by the total number of processors
  212. num_bergs(:) = 0
  213. num_bergs(1) = narea - jpnij
  214. ! when not generating test icebergs we need to setup calving file
  215. IF( nn_test_icebergs < 0 ) THEN
  216. !
  217. ! maximum distribution class array does not change in time so read it once
  218. cl_sdist = TRIM( cn_dir )//TRIM( sn_icb%clname )
  219. CALL iom_open ( cl_sdist, inum ) ! open file
  220. ivar = iom_varid( inum, 'maxclass', ldstop=.FALSE. )
  221. IF( ivar > 0 ) THEN
  222. CALL iom_get ( inum, jpdom_data, 'maxclass', src_calving ) ! read the max distribution array
  223. berg_grid%maxclass(:,:) = INT( src_calving )
  224. src_calving(:,:) = 0._wp
  225. ENDIF
  226. CALL iom_close( inum ) ! close file
  227. !
  228. WRITE(numicb,*)
  229. WRITE(numicb,*) ' calving read in a file'
  230. ALLOCATE( sf_icb(1), STAT=istat1 ) ! Create sf_icb structure (calving)
  231. ALLOCATE( sf_icb(1)%fnow(jpi,jpj,1), STAT=istat2 )
  232. ALLOCATE( sf_icb(1)%fdta(jpi,jpj,1,2), STAT=istat3 )
  233. IF( istat1+istat2+istat3 > 0 ) THEN
  234. CALL ctl_stop( 'sbc_icb: unable to allocate sf_icb structure' ) ; RETURN
  235. ENDIF
  236. ! ! fill sf_icb with the namelist (sn_icb) and control print
  237. CALL fld_fill( sf_icb, (/ sn_icb /), cn_dir, 'icb_init', 'read calving data', 'namicb' )
  238. !
  239. ENDIF
  240. IF( .NOT.ln_rstart ) THEN
  241. IF( nn_test_icebergs > 0 ) CALL icb_ini_gen()
  242. ELSE
  243. IF( nn_test_icebergs > 0 ) THEN
  244. CALL icb_ini_gen()
  245. ELSE
  246. CALL icb_rst_read()
  247. l_restarted_bergs = .TRUE.
  248. ENDIF
  249. ENDIF
  250. !
  251. IF( nn_sample_rate .GT. 0 ) CALL icb_trj_init( nitend )
  252. !
  253. CALL icb_dia_init()
  254. !
  255. IF( nn_verbose_level >= 2 ) CALL icb_utl_print('icb_init, initial status', nit000-1)
  256. !
  257. END SUBROUTINE icb_init
  258. SUBROUTINE icb_ini_gen()
  259. !!----------------------------------------------------------------------
  260. !! *** ROUTINE icb_ini_gen ***
  261. !!
  262. !! ** Purpose : iceberg generation
  263. !!
  264. !! ** Method : - at each grid point of the test box supplied in the namelist
  265. !! generate an iceberg in one class determined by the value of
  266. !! parameter nn_test_icebergs
  267. !!----------------------------------------------------------------------
  268. INTEGER :: ji, jj, ibergs
  269. TYPE(iceberg) :: localberg ! NOT a pointer but an actual local variable
  270. TYPE(point) :: localpt
  271. INTEGER :: iyr, imon, iday, ihr, imin, isec
  272. INTEGER :: iberg
  273. !!----------------------------------------------------------------------
  274. ! For convenience
  275. iberg = nn_test_icebergs
  276. ! call get_date(Time, iyr, imon, iday, ihr, imin, isec)
  277. ! Convert nemo time variables from dom_oce into local versions
  278. iyr = nyear
  279. imon = nmonth
  280. iday = nday
  281. ihr = INT(nsec_day/3600)
  282. imin = INT((nsec_day-ihr*3600)/60)
  283. isec = nsec_day - ihr*3600 - imin*60
  284. ! no overlap for icebergs since we want only one instance of each across the whole domain
  285. ! so restrict area of interest
  286. ! use tmask here because tmask_i has been doctored on one side of the north fold line
  287. DO jj = nicbdj, nicbej
  288. DO ji = nicbdi, nicbei
  289. IF( tmask(ji,jj,1) > 0._wp .AND. &
  290. rn_test_box(1) < glamt(ji,jj) .AND. glamt(ji,jj) < rn_test_box(2) .AND. &
  291. rn_test_box(3) < gphit(ji,jj) .AND. gphit(ji,jj) < rn_test_box(4) ) THEN
  292. localberg%mass_scaling = rn_mass_scaling(iberg)
  293. localpt%xi = REAL( mig(ji), wp )
  294. localpt%yj = REAL( mjg(jj), wp )
  295. localpt%lon = icb_utl_bilin(glamt, localpt%xi, localpt%yj, 'T' )
  296. localpt%lat = icb_utl_bilin(gphit, localpt%xi, localpt%yj, 'T' )
  297. localpt%mass = rn_initial_mass (iberg)
  298. localpt%thickness = rn_initial_thickness(iberg)
  299. localpt%width = first_width (iberg)
  300. localpt%length = first_length(iberg)
  301. localpt%year = iyr
  302. localpt%day = REAL(iday,wp)+(REAL(ihr,wp)+REAL(imin,wp)/60._wp)/24._wp
  303. localpt%mass_of_bits = 0._wp
  304. localpt%heat_density = 0._wp
  305. localpt%uvel = 0._wp
  306. localpt%vvel = 0._wp
  307. CALL icb_utl_incr()
  308. localberg%number(:) = num_bergs(:)
  309. call icb_utl_add(localberg, localpt)
  310. ENDIF
  311. END DO
  312. END DO
  313. !
  314. ibergs = icb_utl_count()
  315. IF( lk_mpp ) CALL mpp_sum(ibergs)
  316. WRITE(numicb,'(a,i6,a)') 'diamonds, icb_ini_gen: ',ibergs,' were generated'
  317. !
  318. END SUBROUTINE icb_ini_gen
  319. SUBROUTINE icb_nam
  320. !!----------------------------------------------------------------------
  321. !! *** ROUTINE icb_nam ***
  322. !!
  323. !! ** Purpose : read iceberg namelist and print the variables.
  324. !!
  325. !! ** input : - namberg namelist
  326. !!----------------------------------------------------------------------
  327. INTEGER :: jn ! dummy loop indices
  328. INTEGER :: ios ! Local integer output status for namelist read
  329. REAL(wp) :: zfact ! local scalar
  330. !
  331. NAMELIST/namberg/ ln_icebergs , ln_bergdia , nn_sample_rate , rn_initial_mass , &
  332. & rn_distribution, rn_mass_scaling, rn_initial_thickness, nn_verbose_write , &
  333. & rn_rho_bergs , rn_LoW_ratio , nn_verbose_level , ln_operator_splitting, &
  334. & rn_bits_erosion_fraction , rn_sicn_shift , ln_passive_mode , &
  335. & ln_time_average_weight , nn_test_icebergs , rn_test_box , &
  336. & rn_speed_limit , cn_dir, sn_icb
  337. !!----------------------------------------------------------------------
  338. #if !defined key_agrif
  339. REWIND( numnam_ref ) ! Namelist namberg in reference namelist : Iceberg parameters
  340. READ ( numnam_ref, namberg, IOSTAT = ios, ERR = 901)
  341. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namberg in reference namelist', lwp )
  342. REWIND( numnam_cfg ) ! Namelist namberg in configuration namelist : Iceberg parameters
  343. READ ( numnam_cfg, namberg, IOSTAT = ios, ERR = 902 )
  344. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namberg in configuration namelist', lwp )
  345. IF(lwm) WRITE ( numond, namberg )
  346. #else
  347. IF(lwp) THEN
  348. WRITE(numout,*)
  349. WRITE(numout,*) 'icbini : AGRIF is not compatible with namelist namberg : '
  350. WRITE(numout,*) ' definition of rn_initial_mass(nclasses) with nclasses as PARAMETER '
  351. WRITE(numout,*) ' namelist namberg not read'
  352. ENDIF
  353. ln_icebergs = .false.
  354. #endif
  355. IF( .NOT. ln_icebergs ) THEN ! no icebergs
  356. IF(lwp) THEN
  357. WRITE(numout,*)
  358. WRITE(numout,*) 'icbini : Namelist namberg ln_icebergs = F , NO icebergs used'
  359. WRITE(numout,*) '~~~~~~~~ '
  360. ENDIF
  361. RETURN
  362. ENDIF
  363. IF( nn_test_icebergs > nclasses ) THEN
  364. IF(lwp) WRITE(numout,*) 'Resetting nn_test_icebergs to ', nclasses
  365. nn_test_icebergs = nclasses
  366. ENDIF
  367. zfact = SUM( rn_distribution )
  368. IF( zfact < 1._wp ) THEN
  369. IF( zfact <= 0._wp ) THEN
  370. ELSE
  371. rn_distribution(:) = rn_distribution(:) / zfact
  372. CALL ctl_warn( 'icb_nam: sum of berg input distribution not equal to one and so RESCALED' )
  373. ENDIF
  374. ENDIF
  375. ! IF( lk_lim3 .AND. ln_icebergs ) THEN
  376. ! CALL ctl_stop( 'icb_nam: the use of ICB with LIM3 not allowed. ice thickness missing in ICB' )
  377. ! ENDIF
  378. IF(lwp) THEN ! control print
  379. WRITE(numout,*)
  380. WRITE(numout,*) 'icb_nam : iceberg initialization through namberg namelist read'
  381. WRITE(numout,*) '~~~~~~~~ '
  382. WRITE(numout,*) ' Calculate budgets ln_bergdia = ', ln_bergdia
  383. WRITE(numout,*) ' Period between sampling of position for trajectory storage nn_sample_rate = ', nn_sample_rate
  384. WRITE(numout,*) ' Mass thresholds between iceberg classes (kg) rn_initial_mass ='
  385. DO jn=1,nclasses
  386. WRITE(numout,'(a,f15.2)') ' ',rn_initial_mass(jn)
  387. ENDDO
  388. WRITE(numout,*) ' Fraction of calving to apply to this class (non-dim) rn_distribution ='
  389. DO jn = 1, nclasses
  390. WRITE(numout,'(a,f10.2)') ' ',rn_distribution(jn)
  391. END DO
  392. WRITE(numout,*) ' Ratio between effective and real iceberg mass (non-dim) rn_mass_scaling = '
  393. DO jn = 1, nclasses
  394. WRITE(numout,'(a,f10.2)') ' ',rn_mass_scaling(jn)
  395. END DO
  396. WRITE(numout,*) ' Total thickness of newly calved bergs (m) rn_initial_thickness = '
  397. DO jn = 1, nclasses
  398. WRITE(numout,'(a,f10.2)') ' ',rn_initial_thickness(jn)
  399. END DO
  400. WRITE(numout,*) ' Timesteps between verbose messages nn_verbose_write = ', nn_verbose_write
  401. WRITE(numout,*) ' Density of icebergs rn_rho_bergs = ', rn_rho_bergs
  402. WRITE(numout,*) ' Initial ratio L/W for newly calved icebergs rn_LoW_ratio = ', rn_LoW_ratio
  403. WRITE(numout,*) ' Turn on more verbose output level = ', nn_verbose_level
  404. WRITE(numout,*) ' Use first order operator splitting for thermodynamics ', &
  405. & 'use_operator_splitting = ', ln_operator_splitting
  406. WRITE(numout,*) ' Fraction of erosion melt flux to divert to bergy bits ', &
  407. & 'bits_erosion_fraction = ', rn_bits_erosion_fraction
  408. WRITE(numout,*) ' Shift of sea-ice concentration in erosion flux modulation ', &
  409. & '(0<sicn_shift<1) rn_sicn_shift = ', rn_sicn_shift
  410. WRITE(numout,*) ' Do not add freshwater flux from icebergs to ocean ', &
  411. & ' passive_mode = ', ln_passive_mode
  412. WRITE(numout,*) ' Time average the weight on the ocean time_average_weight = ', ln_time_average_weight
  413. WRITE(numout,*) ' Create icebergs in absence of a restart file nn_test_icebergs = ', nn_test_icebergs
  414. WRITE(numout,*) ' in lon/lat box = ', rn_test_box
  415. WRITE(numout,*) ' CFL speed limit for a berg speed_limit = ', rn_speed_limit
  416. WRITE(numout,*) ' Writing Iceberg status information to icebergs.stat file '
  417. ENDIF
  418. !
  419. END SUBROUTINE icb_nam
  420. !!======================================================================
  421. END MODULE icbini