icb_oce.F90 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. MODULE icb_oce
  2. !!======================================================================
  3. !! *** MODULE icb_oce ***
  4. !! Icebergs: declare variables for iceberg tracking
  5. !!======================================================================
  6. !! History : 3.3 ! 2010-01 (T. Martin & A. Adcroft) Original code
  7. !! - ! 2011-03 (G. Madec) Part conversion to NEMO form
  8. !! - ! Removal of mapping from another grid
  9. !! - ! 2011-04 (S. Alderson) Extensive rewrite ; Split into separate modules
  10. !!----------------------------------------------------------------------
  11. !!
  12. !! Track Icebergs as Lagrangian objects within the model domain
  13. !! Interaction with the other model variables through 'icebergs_gridded'
  14. !!
  15. !! A single iceberg is held as an instance of type 'iceberg'
  16. !! This type defines a linked list, so each instance contains a pointer
  17. !! to the previous and next icebergs in the list
  18. !!
  19. !! Type 'icebergs' is a convenience container for all relevant arrays
  20. !! It contains one pointer to an 'iceberg' instance representing all icebergs in the processor
  21. !!
  22. !! Each iceberg has a position represented as a real cartesian coordinate which is
  23. !! fractional grid cell, centred on T-points; so an iceberg position of (1.0,1.0) lies
  24. !! exactly on the first T-point and the T-cell spans 0.5 to 1.5 in each direction
  25. !!
  26. !! Each iceberg is assigned a unique id even in MPI
  27. !! This consists of an array of integers: the first element is used to label, the second
  28. !! and subsequent elements are used to count the number of times the first element wraps
  29. !! around all possible values within the valid size for this datatype.
  30. !! Labelling is done by starting the first label in each processor (even when only one)
  31. !! as narea, and then incrementing by jpnij (i.e. the total number of processors.
  32. !! This means that the source processor for each iceberg can be identified by arithmetic
  33. !! modulo jpnij.
  34. !!
  35. !!----------------------------------------------------------------------
  36. USE par_oce ! ocean parameters
  37. USE lib_mpp ! MPP library
  38. IMPLICIT NONE
  39. PUBLIC
  40. PUBLIC icb_alloc ! routine called by icb_init in icbini.F90 module
  41. INTEGER, PUBLIC, PARAMETER :: nclasses = 10 !: Number of icebergs classes
  42. INTEGER, PUBLIC, PARAMETER :: nkounts = 3 !: Number of integers combined for unique naming
  43. TYPE, PUBLIC :: icebergs_gridded !: various icebergs properties on model grid
  44. REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: calving ! Calving mass rate (into stored ice) [kg/s]
  45. REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: calving_hflx ! Calving heat flux [heat content of calving] [W/m2]
  46. REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: floating_melt ! Net melting rate to icebergs + bits [kg/s/m^2]
  47. INTEGER , DIMENSION(:,:) , ALLOCATABLE :: maxclass ! maximum class number at calving source point
  48. REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: tmp ! Temporary work space
  49. REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: stored_ice ! Accumulated ice mass flux at calving locations [kg]
  50. REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: stored_heat ! Heat content of stored ice [J]
  51. END TYPE icebergs_gridded
  52. TYPE, PUBLIC :: point !: properties of an individual iceberg (position, mass, size, etc...)
  53. INTEGER :: year
  54. REAL(wp) :: xi , yj , zk ! iceberg coordinates in the (i,j) referential (global) and deepest level affected
  55. REAL(wp) :: e1 , e2 ! horizontal scale factors at the iceberg position
  56. REAL(wp) :: lon, lat, day ! geographic position
  57. REAL(wp) :: mass, thickness, width, length, uvel, vvel ! iceberg physical properties
  58. REAL(wp) :: ssu, ssv, ui, vi, ua, va, ssh_x, ssh_y, sst, sss, cn, hi ! properties of iceberg environment
  59. REAL(wp) :: mass_of_bits, heat_density
  60. INTEGER :: kb ! icb bottom level
  61. END TYPE point
  62. TYPE, PUBLIC :: iceberg !: linked list defining all the icebergs present in the model domain
  63. TYPE(iceberg), POINTER :: prev=>NULL(), next=>NULL() ! pointers to previous and next unique icebergs in linked list
  64. INTEGER, DIMENSION(nkounts) :: number ! variables which do not change for this iceberg
  65. REAL(wp) :: mass_scaling ! - - - -
  66. TYPE(point), POINTER :: current_point => NULL() ! variables which change with time are held in a separate type
  67. END TYPE iceberg
  68. TYPE(icebergs_gridded), POINTER :: berg_grid !: master instance of gridded iceberg type
  69. TYPE(iceberg) , POINTER :: first_berg => NULL() !: master instance of linked list iceberg type
  70. ! !!! parameters controlling iceberg characteristics and modelling
  71. REAL(wp) :: berg_dt !: Time-step between iceberg CALLs (should make adaptive?)
  72. REAL(wp), DIMENSION(:), ALLOCATABLE :: first_width, first_length !:
  73. LOGICAL :: l_restarted_bergs=.FALSE. ! Indicate whether we read state from a restart or not
  74. ! ! arbitrary numbers for diawri entry
  75. REAL(wp), DIMENSION(nclasses), PUBLIC :: class_num=(/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
  76. ! Extra arrays with bigger halo, needed when interpolating forcing onto iceberg position
  77. ! particularly for MPP when iceberg can lie inside T grid but outside U, V, or f grid
  78. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssu_e, ssv_e
  79. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: sst_e, sss_e, fr_e
  80. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ua_e, va_e
  81. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssh_e
  82. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: tmask_e, umask_e, vmask_e
  83. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: virtual_area, virtual_area_e
  84. REAl(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: rlon_e, rlat_e, ff_e
  85. REAl(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: uoce_e, voce_e, toce_e, e3t_e
  86. !
  87. #if defined key_si3 || defined key_cice
  88. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: hi_e, ui_e, vi_e
  89. #endif
  90. !!gm almost all those PARAM ARE defined in NEMO
  91. REAL(wp), PUBLIC, PARAMETER :: pp_rho_ice = 916.7_wp !: Density of fresh ice @ 0oC [kg/m^3]
  92. REAL(wp), PUBLIC, PARAMETER :: pp_rho_water = 999.8_wp !: Density of fresh water @ 0oC [kg/m^3]
  93. REAL(wp), PUBLIC, PARAMETER :: pp_rho_air = 1.1_wp !: Density of air @ 0oC [kg/m^3]
  94. REAL(wp), PUBLIC, PARAMETER :: pp_rho_seawater = 1025._wp !: Approx. density of surface sea water @ 0oC [kg/m^3]
  95. !!gm end
  96. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_av = 1.3_wp !: (Vertical) Drag coefficient between bergs and atmos
  97. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_ah = 0.0055_wp !: (lateral ) Drag coefficient between bergs and atmos
  98. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wv = 0.9_wp !: (Vertical) Drag coefficient between bergs and ocean
  99. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wh = 0.0012_wp !: (lateral ) Drag coefficient between bergs and ocean
  100. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_iv = 0.9_wp !: (Vertical) Drag coefficient between bergs and sea-ice
  101. !TOM> no horizontal drag for sea ice! real, PARAMETER :: pp_Cd_ih=0.0012 ! (lateral) Drag coeff. between bergs and sea-ice
  102. ! !!* namberg namelist parameters (and defaults) **
  103. LOGICAL , PUBLIC :: ln_bergdia !: Calculate budgets
  104. INTEGER , PUBLIC :: nn_verbose_level !: Turn on debugging when level > 0
  105. INTEGER , PUBLIC :: nn_test_icebergs !: Create icebergs in absence of a restart file from the supplied class nb
  106. REAL(wp), PUBLIC, DIMENSION(4) :: rn_test_box !: lon1,lon2,lat1,lat2 box to create them in
  107. LOGICAL , PUBLIC :: ln_use_calving !: Force use of calving data even with nn_test_icebergs > 0
  108. ! (default is not to use calving data with test bergs)
  109. INTEGER , PUBLIC :: nn_sample_rate !: Timesteps between sampling of position for trajectory storage
  110. INTEGER , PUBLIC :: nn_verbose_write !: timesteps between verbose messages
  111. REAL(wp), PUBLIC :: rn_rho_bergs !: Density of icebergs
  112. REAL(wp), PUBLIC :: rho_berg_1_oce !: convertion factor (thickness to draft) (rn_rho_bergs/pp_rho_seawater)
  113. REAL(wp), PUBLIC :: rn_LoW_ratio !: Initial ratio L/W for newly calved icebergs
  114. REAL(wp), PUBLIC :: rn_bits_erosion_fraction !: Fraction of erosion melt flux to divert to bergy bits
  115. REAL(wp), PUBLIC :: rn_sicn_shift !: Shift of sea-ice concentration in erosion flux modulation (0<sicn_shift<1)
  116. LOGICAL , PUBLIC :: ln_operator_splitting !: Use first order operator splitting for thermodynamics
  117. LOGICAL , PUBLIC :: ln_passive_mode !: iceberg - ocean decoupling
  118. LOGICAL , PUBLIC :: ln_time_average_weight !: Time average the weight on the ocean !!gm I don't understand that !
  119. REAL(wp), PUBLIC :: rn_speed_limit !: CFL speed limit for a berg
  120. LOGICAL , PUBLIC :: ln_M2016, ln_icb_grd !: use Nacho's Merino 2016 work
  121. LOGICAL , PUBLIC :: ln_icb_area_mask !: check icb total area in a cell in grounding scheme
  122. !
  123. ! restart
  124. CHARACTER(len=256), PUBLIC :: cn_icbrst_indir , cn_icbrst_in !: in: restart directory, restart name
  125. CHARACTER(len=256), PUBLIC :: cn_icbrst_outdir, cn_icbrst_out !: out: restart directory, restart name
  126. !
  127. ! ! Mass thresholds between iceberg classes [kg]
  128. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_mass ! Fraction of calving to apply to this class [non-dim]
  129. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_distribution ! Ratio between effective and real iceberg mass (non-dim)
  130. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_mass_scaling ! Total thickness of newly calved bergs [m]
  131. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_thickness ! Single instance of an icebergs type initialised in icebergs_init and updated in icebergs_run
  132. REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: src_calving, src_calving_hflx !: accumulate input ice
  133. INTEGER , PUBLIC , SAVE :: micbkb !: deepest level affected by icebergs
  134. INTEGER , PUBLIC , SAVE :: numicb !: iceberg IO
  135. INTEGER , PUBLIC , SAVE, DIMENSION(nkounts) :: num_bergs !: iceberg counter
  136. INTEGER , PUBLIC , SAVE :: nicbdi, nicbei, nicbdj, nicbej !: processor bounds
  137. REAL(wp), PUBLIC , SAVE :: ricb_left, ricb_right !: cyclical bounds
  138. INTEGER , PUBLIC , SAVE :: nicbpack !: packing integer
  139. INTEGER , PUBLIC , SAVE :: nktberg, nknberg !: helpers
  140. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldpts !: nfold packed points
  141. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbflddest !: nfold destination proc
  142. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldproc !: nfold destination proc
  143. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldnsend !: nfold number of bergs to send to nfold neighbour
  144. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldexpect !: nfold expected number of bergs
  145. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldreq !: nfold message handle (immediate send)
  146. !!----------------------------------------------------------------------
  147. !! NEMO/OCE 4.0 , NEMO Consortium (2018)
  148. !! $Id: icb_oce.F90 14030 2020-12-03 09:26:33Z mathiot $
  149. !! Software governed by the CeCILL license (see ./LICENSE)
  150. !!----------------------------------------------------------------------
  151. CONTAINS
  152. INTEGER FUNCTION icb_alloc()
  153. !!----------------------------------------------------------------------
  154. !! *** ROUTINE icb_alloc ***
  155. !!----------------------------------------------------------------------
  156. INTEGER :: ill
  157. !!----------------------------------------------------------------------
  158. !
  159. icb_alloc = 0
  160. ALLOCATE( berg_grid, STAT=ill )
  161. icb_alloc = icb_alloc + ill
  162. ALLOCATE( berg_grid%calving (jpi,jpj) , berg_grid%calving_hflx (jpi,jpj) , &
  163. & berg_grid%stored_heat(jpi,jpj) , berg_grid%floating_melt(jpi,jpj) , &
  164. & berg_grid%maxclass (jpi,jpj) , berg_grid%stored_ice (jpi,jpj,nclasses) , &
  165. & berg_grid%tmp (jpi,jpj) , STAT=ill)
  166. icb_alloc = icb_alloc + ill
  167. !
  168. ! expanded arrays for bilinear interpolation
  169. ALLOCATE( ssu_e(0:jpi+1,0:jpj+1) , ua_e(0:jpi+1,0:jpj+1) , &
  170. & ssv_e(0:jpi+1,0:jpj+1) , va_e(0:jpi+1,0:jpj+1) , &
  171. #if defined key_si3 || defined key_cice
  172. & ui_e(0:jpi+1,0:jpj+1) , &
  173. & vi_e(0:jpi+1,0:jpj+1) , &
  174. & hi_e(0:jpi+1,0:jpj+1) , &
  175. #endif
  176. & fr_e(0:jpi+1,0:jpj+1) , &
  177. & sst_e(0:jpi+1,0:jpj+1) , ssh_e(0:jpi+1,0:jpj+1) , &
  178. & sss_e(0:jpi+1,0:jpj+1) , &
  179. & first_width(nclasses) , first_length(nclasses) , &
  180. & src_calving (jpi,jpj) , &
  181. & src_calving_hflx(jpi,jpj) , STAT=ill)
  182. icb_alloc = icb_alloc + ill
  183. IF ( ln_M2016 ) THEN
  184. ALLOCATE( uoce_e(0:jpi+1,0:jpj+1,jpk), voce_e(0:jpi+1,0:jpj+1,jpk), &
  185. & toce_e(0:jpi+1,0:jpj+1,jpk), e3t_e(0:jpi+1,0:jpj+1,jpk) , STAT=ill )
  186. icb_alloc = icb_alloc + ill
  187. END IF
  188. !
  189. ALLOCATE( tmask_e(0:jpi+1,0:jpj+1), umask_e(0:jpi+1,0:jpj+1), vmask_e(0:jpi+1,0:jpj+1), &
  190. & rlon_e(0:jpi+1,0:jpj+1) , rlat_e(0:jpi+1,0:jpj+1) , ff_e(0:jpi+1,0:jpj+1) , STAT=ill)
  191. icb_alloc = icb_alloc + ill
  192. ALLOCATE( nicbfldpts(jpi) , nicbflddest(jpi) , nicbfldproc(jpni) , &
  193. & nicbfldnsend(jpni), nicbfldexpect(jpni) , nicbfldreq(jpni), STAT=ill)
  194. icb_alloc = icb_alloc + ill
  195. ALLOCATE( virtual_area (jpi,jpj), virtual_area_e(0:jpi+1,0:jpj+1), STAT=ill )
  196. icb_alloc = icb_alloc + ill
  197. CALL mpp_sum ( 'icb_oce', icb_alloc )
  198. IF( icb_alloc > 0 ) CALL ctl_warn('icb_alloc: allocation of arrays failed')
  199. !
  200. END FUNCTION icb_alloc
  201. !!======================================================================
  202. END MODULE icb_oce