icb_oce.F90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 ! iceberg coordinates in the (i,j) referential (global)
  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) :: uo, vo, ui, vi, ua, va, ssh_x, ssh_y, sst, cn, hi ! properties of iceberg environment
  59. REAL(wp) :: mass_of_bits, heat_density
  60. END TYPE point
  61. TYPE, PUBLIC :: iceberg !: linked list defining all the icebergs present in the model domain
  62. TYPE(iceberg), POINTER :: prev=>NULL(), next=>NULL() ! pointers to previous and next unique icebergs in linked list
  63. INTEGER, DIMENSION(nkounts) :: number ! variables which do not change for this iceberg
  64. REAL(wp) :: mass_scaling ! - - - -
  65. TYPE(point), POINTER :: current_point => NULL() ! variables which change with time are held in a separate type
  66. END TYPE iceberg
  67. TYPE(icebergs_gridded), POINTER :: berg_grid !: master instance of gridded iceberg type
  68. TYPE(iceberg) , POINTER :: first_berg => NULL() !: master instance of linked list iceberg type
  69. ! !!! parameters controlling iceberg characteristics and modelling
  70. REAL(wp) :: berg_dt !: Time-step between iceberg CALLs (should make adaptive?)
  71. REAL(wp), DIMENSION(:), ALLOCATABLE :: first_width, first_length !:
  72. LOGICAL :: l_restarted_bergs=.FALSE. ! Indicate whether we read state from a restart or not
  73. ! ! arbitrary numbers for diawri entry
  74. REAL(wp), DIMENSION(nclasses), PUBLIC :: class_num=(/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
  75. ! Extra arrays with bigger halo, needed when interpolating forcing onto iceberg position
  76. ! particularly for MPP when iceberg can lie inside T grid but outside U, V, or f grid
  77. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: uo_e, vo_e
  78. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ff_e, tt_e, fr_e, hicth
  79. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ua_e, va_e
  80. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssh_e
  81. #if defined key_lim2 || defined key_lim3 || defined key_cice
  82. REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ui_e, vi_e
  83. #endif
  84. !!gm almost all those PARAM ARE defined in NEMO
  85. REAL(wp), PUBLIC, PARAMETER :: pp_rho_ice = 916.7_wp !: Density of fresh ice @ 0oC [kg/m^3]
  86. REAL(wp), PUBLIC, PARAMETER :: pp_rho_water = 999.8_wp !: Density of fresh water @ 0oC [kg/m^3]
  87. REAL(wp), PUBLIC, PARAMETER :: pp_rho_air = 1.1_wp !: Density of air @ 0oC [kg/m^3]
  88. REAL(wp), PUBLIC, PARAMETER :: pp_rho_seawater = 1025._wp !: Approx. density of surface sea water @ 0oC [kg/m^3]
  89. !!gm end
  90. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_av = 1.3_wp !: (Vertical) Drag coefficient between bergs and atmos
  91. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_ah = 0.0055_wp !: (lateral ) Drag coefficient between bergs and atmos
  92. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wv = 0.9_wp !: (Vertical) Drag coefficient between bergs and ocean
  93. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wh = 0.0012_wp !: (lateral ) Drag coefficient between bergs and ocean
  94. REAL(wp), PUBLIC, PARAMETER :: pp_Cd_iv = 0.9_wp !: (Vertical) Drag coefficient between bergs and sea-ice
  95. !TOM> no horizontal drag for sea ice! real, PARAMETER :: pp_Cd_ih=0.0012 ! (lateral) Drag coeff. between bergs and sea-ice
  96. ! !!* namberg namelist parameters (and defaults) **
  97. LOGICAL , PUBLIC :: ln_bergdia !: Calculate budgets
  98. INTEGER , PUBLIC :: nn_verbose_level !: Turn on debugging when level > 0
  99. INTEGER , PUBLIC :: nn_test_icebergs !: Create icebergs in absence of a restart file from the supplied class nb
  100. REAL(wp), PUBLIC, DIMENSION(4) :: rn_test_box !: lon1,lon2,lat1,lat2 box to create them in
  101. INTEGER , PUBLIC :: nn_sample_rate !: Timesteps between sampling of position for trajectory storage
  102. INTEGER , PUBLIC :: nn_verbose_write !: timesteps between verbose messages
  103. REAL(wp), PUBLIC :: rn_rho_bergs !: Density of icebergs
  104. REAL(wp), PUBLIC :: rn_LoW_ratio !: Initial ratio L/W for newly calved icebergs
  105. REAL(wp), PUBLIC :: rn_bits_erosion_fraction !: Fraction of erosion melt flux to divert to bergy bits
  106. REAL(wp), PUBLIC :: rn_sicn_shift !: Shift of sea-ice concentration in erosion flux modulation (0<sicn_shift<1)
  107. LOGICAL , PUBLIC :: ln_operator_splitting !: Use first order operator splitting for thermodynamics
  108. LOGICAL , PUBLIC :: ln_passive_mode !: iceberg - ocean decoupling
  109. LOGICAL , PUBLIC :: ln_time_average_weight !: Time average the weight on the ocean !!gm I don't understand that !
  110. REAL(wp), PUBLIC :: rn_speed_limit !: CFL speed limit for a berg
  111. !
  112. ! ! Mass thresholds between iceberg classes [kg]
  113. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_mass ! Fraction of calving to apply to this class [non-dim]
  114. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_distribution ! Ratio between effective and real iceberg mass (non-dim)
  115. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_mass_scaling ! Total thickness of newly calved bergs [m]
  116. REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_thickness ! Single instance of an icebergs type initialised in icebergs_init and updated in icebergs_run
  117. REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: src_calving, src_calving_hflx !: accumulate input ice
  118. INTEGER , PUBLIC , SAVE :: numicb !: iceberg IO
  119. INTEGER , PUBLIC , SAVE, DIMENSION(nkounts) :: num_bergs !: iceberg counter
  120. INTEGER , PUBLIC , SAVE :: nicbdi, nicbei, nicbdj, nicbej !: processor bounds
  121. REAL(wp), PUBLIC , SAVE :: ricb_left, ricb_right !: cyclical bounds
  122. INTEGER , PUBLIC , SAVE :: nicbpack !: packing integer
  123. INTEGER , PUBLIC , SAVE :: nktberg, nknberg !: helpers
  124. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldpts !: nfold packed points
  125. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbflddest !: nfold destination proc
  126. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldproc !: nfold destination proc
  127. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldnsend !: nfold number of bergs to send to nfold neighbour
  128. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldexpect !: nfold expected number of bergs
  129. INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldreq !: nfold message handle (immediate send)
  130. REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: griddata !: work array for icbrst
  131. !!----------------------------------------------------------------------
  132. !! NEMO/OPA 3.3 , NEMO Consortium (2011)
  133. !! $Id: icb_oce.F90 2355 2015-05-20 07:11:50Z ufla $
  134. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  135. !!----------------------------------------------------------------------
  136. CONTAINS
  137. INTEGER FUNCTION icb_alloc()
  138. !!----------------------------------------------------------------------
  139. !! *** ROUTINE icb_alloc ***
  140. !!----------------------------------------------------------------------
  141. INTEGER :: ill
  142. !!----------------------------------------------------------------------
  143. !
  144. icb_alloc = 0
  145. ALLOCATE( berg_grid, STAT=ill )
  146. icb_alloc = icb_alloc + ill
  147. ALLOCATE( berg_grid%calving (jpi,jpj) , berg_grid%calving_hflx (jpi,jpj) , &
  148. & berg_grid%stored_heat(jpi,jpj) , berg_grid%floating_melt(jpi,jpj) , &
  149. & berg_grid%maxclass (jpi,jpj) , berg_grid%stored_ice (jpi,jpj,nclasses) , &
  150. & berg_grid%tmp (jpi,jpj) , STAT=ill)
  151. icb_alloc = icb_alloc + ill
  152. !
  153. ! expanded arrays for bilinear interpolation
  154. ALLOCATE( uo_e(0:jpi+1,0:jpj+1) , ua_e(0:jpi+1,0:jpj+1) , &
  155. & vo_e(0:jpi+1,0:jpj+1) , va_e(0:jpi+1,0:jpj+1) , &
  156. #if defined key_lim2 || defined key_lim3 || defined key_cice
  157. & ui_e(0:jpi+1,0:jpj+1) , &
  158. & vi_e(0:jpi+1,0:jpj+1) , &
  159. #endif
  160. & ff_e(0:jpi+1,0:jpj+1) , fr_e(0:jpi+1,0:jpj+1) , &
  161. & tt_e(0:jpi+1,0:jpj+1) , ssh_e(0:jpi+1,0:jpj+1) , &
  162. & hicth(0:jpi+1,0:jpj+1), &
  163. & first_width(nclasses) , first_length(nclasses) , &
  164. & src_calving (jpi,jpj) , &
  165. & src_calving_hflx(jpi,jpj) , STAT=ill)
  166. icb_alloc = icb_alloc + ill
  167. ALLOCATE( nicbfldpts(jpi) , nicbflddest(jpi) , nicbfldproc(jpni) , &
  168. & nicbfldnsend(jpni), nicbfldexpect(jpni) , nicbfldreq(jpni), STAT=ill)
  169. icb_alloc = icb_alloc + ill
  170. ALLOCATE( griddata(jpi,jpj,1), STAT=ill )
  171. icb_alloc = icb_alloc + ill
  172. IF( lk_mpp ) CALL mpp_sum ( icb_alloc )
  173. IF( icb_alloc > 0 ) CALL ctl_warn('icb_alloc: allocation of arrays failed')
  174. !
  175. END FUNCTION icb_alloc
  176. !!======================================================================
  177. END MODULE icb_oce