[3614] | 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 | |
---|
| 39 | IMPLICIT NONE |
---|
| 40 | PUBLIC |
---|
| 41 | |
---|
| 42 | PUBLIC icb_alloc ! routine called by icb_init in icbini.F90 module |
---|
| 43 | |
---|
[6140] | 44 | INTEGER, PUBLIC, PARAMETER :: nclasses = 10 !: Number of icebergs classes |
---|
[3614] | 45 | INTEGER, PUBLIC, PARAMETER :: nkounts = 3 !: Number of integers combined for unique naming |
---|
| 46 | |
---|
| 47 | TYPE, PUBLIC :: icebergs_gridded !: various icebergs properties on model grid |
---|
| 48 | REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: calving ! Calving mass rate (into stored ice) [kg/s] |
---|
| 49 | REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: calving_hflx ! Calving heat flux [heat content of calving] [W/m2] |
---|
| 50 | REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: floating_melt ! Net melting rate to icebergs + bits [kg/s/m^2] |
---|
| 51 | INTEGER , DIMENSION(:,:) , ALLOCATABLE :: maxclass ! maximum class number at calving source point |
---|
| 52 | REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: tmp ! Temporary work space |
---|
| 53 | REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: stored_ice ! Accumulated ice mass flux at calving locations [kg] |
---|
| 54 | REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: stored_heat ! Heat content of stored ice [J] |
---|
| 55 | END TYPE icebergs_gridded |
---|
| 56 | |
---|
| 57 | TYPE, PUBLIC :: point !: properties of an individual iceberg (position, mass, size, etc...) |
---|
| 58 | INTEGER :: year |
---|
[14030] | 59 | REAL(wp) :: xi , yj , zk ! iceberg coordinates in the (i,j) referential (global) and deepest level affected |
---|
[13281] | 60 | REAL(wp) :: e1 , e2 ! horizontal scale factors at the iceberg position |
---|
| 61 | REAL(wp) :: lon, lat, day ! geographic position |
---|
| 62 | REAL(wp) :: mass, thickness, width, length, uvel, vvel ! iceberg physical properties |
---|
[14030] | 63 | REAL(wp) :: ssu, ssv, ui, vi, ua, va, ssh_x, ssh_y, sst, sss, cn, hi ! properties of iceberg environment |
---|
[3614] | 64 | REAL(wp) :: mass_of_bits, heat_density |
---|
[14030] | 65 | INTEGER :: kb ! icb bottom level |
---|
[3614] | 66 | END TYPE point |
---|
| 67 | |
---|
| 68 | TYPE, PUBLIC :: iceberg !: linked list defining all the icebergs present in the model domain |
---|
| 69 | TYPE(iceberg), POINTER :: prev=>NULL(), next=>NULL() ! pointers to previous and next unique icebergs in linked list |
---|
| 70 | INTEGER, DIMENSION(nkounts) :: number ! variables which do not change for this iceberg |
---|
| 71 | REAL(wp) :: mass_scaling ! - - - - |
---|
| 72 | TYPE(point), POINTER :: current_point => NULL() ! variables which change with time are held in a separate type |
---|
| 73 | END TYPE iceberg |
---|
| 74 | |
---|
| 75 | |
---|
| 76 | TYPE(icebergs_gridded), POINTER :: berg_grid !: master instance of gridded iceberg type |
---|
| 77 | TYPE(iceberg) , POINTER :: first_berg => NULL() !: master instance of linked list iceberg type |
---|
| 78 | |
---|
| 79 | ! !!! parameters controlling iceberg characteristics and modelling |
---|
| 80 | REAL(wp) :: berg_dt !: Time-step between iceberg CALLs (should make adaptive?) |
---|
| 81 | REAL(wp), DIMENSION(:), ALLOCATABLE :: first_width, first_length !: |
---|
| 82 | LOGICAL :: l_restarted_bergs=.FALSE. ! Indicate whether we read state from a restart or not |
---|
| 83 | ! ! arbitrary numbers for diawri entry |
---|
| 84 | REAL(wp), DIMENSION(nclasses), PUBLIC :: class_num=(/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /) |
---|
| 85 | |
---|
| 86 | ! Extra arrays with bigger halo, needed when interpolating forcing onto iceberg position |
---|
| 87 | ! particularly for MPP when iceberg can lie inside T grid but outside U, V, or f grid |
---|
[14030] | 88 | REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssu_e, ssv_e |
---|
| 89 | REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: sst_e, sss_e, fr_e |
---|
[3614] | 90 | REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ua_e, va_e |
---|
| 91 | REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssh_e |
---|
[10691] | 92 | REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: tmask_e, umask_e, vmask_e |
---|
[14030] | 93 | REAl(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: rlon_e, rlat_e, ff_e |
---|
| 94 | REAl(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: uoce_e, voce_e, toce_e, e3t_e |
---|
| 95 | ! |
---|
[9570] | 96 | #if defined key_si3 || defined key_cice |
---|
[10702] | 97 | REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: hi_e, ui_e, vi_e |
---|
[3614] | 98 | #endif |
---|
| 99 | |
---|
| 100 | !!gm almost all those PARAM ARE defined in NEMO |
---|
| 101 | REAL(wp), PUBLIC, PARAMETER :: pp_rho_ice = 916.7_wp !: Density of fresh ice @ 0oC [kg/m^3] |
---|
| 102 | REAL(wp), PUBLIC, PARAMETER :: pp_rho_water = 999.8_wp !: Density of fresh water @ 0oC [kg/m^3] |
---|
| 103 | REAL(wp), PUBLIC, PARAMETER :: pp_rho_air = 1.1_wp !: Density of air @ 0oC [kg/m^3] |
---|
| 104 | REAL(wp), PUBLIC, PARAMETER :: pp_rho_seawater = 1025._wp !: Approx. density of surface sea water @ 0oC [kg/m^3] |
---|
| 105 | !!gm end |
---|
| 106 | REAL(wp), PUBLIC, PARAMETER :: pp_Cd_av = 1.3_wp !: (Vertical) Drag coefficient between bergs and atmos |
---|
| 107 | REAL(wp), PUBLIC, PARAMETER :: pp_Cd_ah = 0.0055_wp !: (lateral ) Drag coefficient between bergs and atmos |
---|
| 108 | REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wv = 0.9_wp !: (Vertical) Drag coefficient between bergs and ocean |
---|
| 109 | REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wh = 0.0012_wp !: (lateral ) Drag coefficient between bergs and ocean |
---|
| 110 | REAL(wp), PUBLIC, PARAMETER :: pp_Cd_iv = 0.9_wp !: (Vertical) Drag coefficient between bergs and sea-ice |
---|
| 111 | !TOM> no horizontal drag for sea ice! real, PARAMETER :: pp_Cd_ih=0.0012 ! (lateral) Drag coeff. between bergs and sea-ice |
---|
| 112 | |
---|
| 113 | ! !!* namberg namelist parameters (and defaults) ** |
---|
[4147] | 114 | LOGICAL , PUBLIC :: ln_bergdia !: Calculate budgets |
---|
| 115 | INTEGER , PUBLIC :: nn_verbose_level !: Turn on debugging when level > 0 |
---|
| 116 | INTEGER , PUBLIC :: nn_test_icebergs !: Create icebergs in absence of a restart file from the supplied class nb |
---|
| 117 | REAL(wp), PUBLIC, DIMENSION(4) :: rn_test_box !: lon1,lon2,lat1,lat2 box to create them in |
---|
[9932] | 118 | LOGICAL , PUBLIC :: ln_use_calving !: Force use of calving data even with nn_test_icebergs > 0 |
---|
| 119 | ! (default is not to use calving data with test bergs) |
---|
[4147] | 120 | INTEGER , PUBLIC :: nn_sample_rate !: Timesteps between sampling of position for trajectory storage |
---|
| 121 | INTEGER , PUBLIC :: nn_verbose_write !: timesteps between verbose messages |
---|
| 122 | REAL(wp), PUBLIC :: rn_rho_bergs !: Density of icebergs |
---|
[14030] | 123 | REAL(wp), PUBLIC :: rho_berg_1_oce !: convertion factor (thickness to draft) (rn_rho_bergs/pp_rho_seawater) |
---|
[4147] | 124 | REAL(wp), PUBLIC :: rn_LoW_ratio !: Initial ratio L/W for newly calved icebergs |
---|
| 125 | REAL(wp), PUBLIC :: rn_bits_erosion_fraction !: Fraction of erosion melt flux to divert to bergy bits |
---|
| 126 | REAL(wp), PUBLIC :: rn_sicn_shift !: Shift of sea-ice concentration in erosion flux modulation (0<sicn_shift<1) |
---|
| 127 | LOGICAL , PUBLIC :: ln_operator_splitting !: Use first order operator splitting for thermodynamics |
---|
| 128 | LOGICAL , PUBLIC :: ln_passive_mode !: iceberg - ocean decoupling |
---|
| 129 | LOGICAL , PUBLIC :: ln_time_average_weight !: Time average the weight on the ocean !!gm I don't understand that ! |
---|
| 130 | REAL(wp), PUBLIC :: rn_speed_limit !: CFL speed limit for a berg |
---|
[14030] | 131 | LOGICAL , PUBLIC :: ln_M2016, ln_icb_grd !: use Nacho's Merino 2016 work |
---|
[3614] | 132 | ! |
---|
[12472] | 133 | ! restart |
---|
| 134 | CHARACTER(len=256), PUBLIC :: cn_icbrst_indir , cn_icbrst_in !: in: restart directory, restart name |
---|
| 135 | CHARACTER(len=256), PUBLIC :: cn_icbrst_outdir, cn_icbrst_out !: out: restart directory, restart name |
---|
| 136 | ! |
---|
[3614] | 137 | ! ! Mass thresholds between iceberg classes [kg] |
---|
[4147] | 138 | REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_mass ! Fraction of calving to apply to this class [non-dim] |
---|
| 139 | REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_distribution ! Ratio between effective and real iceberg mass (non-dim) |
---|
| 140 | REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_mass_scaling ! Total thickness of newly calved bergs [m] |
---|
| 141 | REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_thickness ! Single instance of an icebergs type initialised in icebergs_init and updated in icebergs_run |
---|
[3614] | 142 | REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: src_calving, src_calving_hflx !: accumulate input ice |
---|
[14030] | 143 | INTEGER , PUBLIC , SAVE :: micbkb !: deepest level affected by icebergs |
---|
[3614] | 144 | INTEGER , PUBLIC , SAVE :: numicb !: iceberg IO |
---|
| 145 | INTEGER , PUBLIC , SAVE, DIMENSION(nkounts) :: num_bergs !: iceberg counter |
---|
| 146 | INTEGER , PUBLIC , SAVE :: nicbdi, nicbei, nicbdj, nicbej !: processor bounds |
---|
| 147 | REAL(wp), PUBLIC , SAVE :: ricb_left, ricb_right !: cyclical bounds |
---|
| 148 | INTEGER , PUBLIC , SAVE :: nicbpack !: packing integer |
---|
| 149 | INTEGER , PUBLIC , SAVE :: nktberg, nknberg !: helpers |
---|
| 150 | INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldpts !: nfold packed points |
---|
| 151 | INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbflddest !: nfold destination proc |
---|
| 152 | INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldproc !: nfold destination proc |
---|
[4990] | 153 | INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldnsend !: nfold number of bergs to send to nfold neighbour |
---|
| 154 | INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldexpect !: nfold expected number of bergs |
---|
| 155 | INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldreq !: nfold message handle (immediate send) |
---|
[3614] | 156 | !!---------------------------------------------------------------------- |
---|
[9598] | 157 | !! NEMO/OCE 4.0 , NEMO Consortium (2018) |
---|
[5215] | 158 | !! $Id$ |
---|
[10068] | 159 | !! Software governed by the CeCILL license (see ./LICENSE) |
---|
[3614] | 160 | !!---------------------------------------------------------------------- |
---|
| 161 | CONTAINS |
---|
| 162 | |
---|
| 163 | INTEGER FUNCTION icb_alloc() |
---|
| 164 | !!---------------------------------------------------------------------- |
---|
| 165 | !! *** ROUTINE icb_alloc *** |
---|
| 166 | !!---------------------------------------------------------------------- |
---|
| 167 | INTEGER :: ill |
---|
| 168 | !!---------------------------------------------------------------------- |
---|
| 169 | ! |
---|
| 170 | icb_alloc = 0 |
---|
[4990] | 171 | ALLOCATE( berg_grid, STAT=ill ) |
---|
| 172 | icb_alloc = icb_alloc + ill |
---|
[4153] | 173 | ALLOCATE( berg_grid%calving (jpi,jpj) , berg_grid%calving_hflx (jpi,jpj) , & |
---|
[3614] | 174 | & berg_grid%stored_heat(jpi,jpj) , berg_grid%floating_melt(jpi,jpj) , & |
---|
| 175 | & berg_grid%maxclass (jpi,jpj) , berg_grid%stored_ice (jpi,jpj,nclasses) , & |
---|
| 176 | & berg_grid%tmp (jpi,jpj) , STAT=ill) |
---|
| 177 | icb_alloc = icb_alloc + ill |
---|
| 178 | ! |
---|
| 179 | ! expanded arrays for bilinear interpolation |
---|
[14030] | 180 | ALLOCATE( ssu_e(0:jpi+1,0:jpj+1) , ua_e(0:jpi+1,0:jpj+1) , & |
---|
| 181 | & ssv_e(0:jpi+1,0:jpj+1) , va_e(0:jpi+1,0:jpj+1) , & |
---|
[9570] | 182 | #if defined key_si3 || defined key_cice |
---|
[3614] | 183 | & ui_e(0:jpi+1,0:jpj+1) , & |
---|
| 184 | & vi_e(0:jpi+1,0:jpj+1) , & |
---|
[10702] | 185 | & hi_e(0:jpi+1,0:jpj+1) , & |
---|
[3614] | 186 | #endif |
---|
[14030] | 187 | & fr_e(0:jpi+1,0:jpj+1) , & |
---|
| 188 | & sst_e(0:jpi+1,0:jpj+1) , ssh_e(0:jpi+1,0:jpj+1) , & |
---|
| 189 | & sss_e(0:jpi+1,0:jpj+1) , & |
---|
[3614] | 190 | & first_width(nclasses) , first_length(nclasses) , & |
---|
| 191 | & src_calving (jpi,jpj) , & |
---|
| 192 | & src_calving_hflx(jpi,jpj) , STAT=ill) |
---|
| 193 | icb_alloc = icb_alloc + ill |
---|
| 194 | |
---|
[14030] | 195 | IF ( ln_M2016 ) THEN |
---|
| 196 | ALLOCATE( uoce_e(0:jpi+1,0:jpj+1,jpk), voce_e(0:jpi+1,0:jpj+1,jpk), & |
---|
| 197 | & toce_e(0:jpi+1,0:jpj+1,jpk), e3t_e(0:jpi+1,0:jpj+1,jpk) , STAT=ill ) |
---|
| 198 | icb_alloc = icb_alloc + ill |
---|
| 199 | END IF |
---|
| 200 | ! |
---|
[10691] | 201 | 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), & |
---|
[14030] | 202 | & 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) |
---|
[10691] | 203 | icb_alloc = icb_alloc + ill |
---|
| 204 | |
---|
[4990] | 205 | ALLOCATE( nicbfldpts(jpi) , nicbflddest(jpi) , nicbfldproc(jpni) , & |
---|
| 206 | & nicbfldnsend(jpni), nicbfldexpect(jpni) , nicbfldreq(jpni), STAT=ill) |
---|
[3614] | 207 | icb_alloc = icb_alloc + ill |
---|
| 208 | |
---|
[10425] | 209 | CALL mpp_sum ( 'icb_oce', icb_alloc ) |
---|
[3614] | 210 | IF( icb_alloc > 0 ) CALL ctl_warn('icb_alloc: allocation of arrays failed') |
---|
| 211 | ! |
---|
| 212 | END FUNCTION icb_alloc |
---|
| 213 | |
---|
| 214 | !!====================================================================== |
---|
| 215 | END MODULE icb_oce |
---|