Forked from
Consortium Members / UKMO / GOSI / GOSI
261 commits behind the upstream repository.
-
Guillaume Samson authored89746a6d
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
icb_oce.F90 15.07 KiB
MODULE icb_oce
!!======================================================================
!! *** MODULE icb_oce ***
!! Icebergs: declare variables for iceberg tracking
!!======================================================================
!! History : 3.3 ! 2010-01 (T. Martin & A. Adcroft) Original code
!! - ! 2011-03 (G. Madec) Part conversion to NEMO form
!! - ! Removal of mapping from another grid
!! - ! 2011-04 (S. Alderson) Extensive rewrite ; Split into separate modules
!!----------------------------------------------------------------------
!!
!! Track Icebergs as Lagrangian objects within the model domain
!! Interaction with the other model variables through 'icebergs_gridded'
!!
!! A single iceberg is held as an instance of type 'iceberg'
!! This type defines a linked list, so each instance contains a pointer
!! to the previous and next icebergs in the list
!!
!! Type 'icebergs' is a convenience container for all relevant arrays
!! It contains one pointer to an 'iceberg' instance representing all icebergs in the processor
!!
!! Each iceberg has a position represented as a real cartesian coordinate which is
!! fractional grid cell, centred on T-points; so an iceberg position of (1.0,1.0) lies
!! exactly on the first T-point and the T-cell spans 0.5 to 1.5 in each direction
!!
!! Each iceberg is assigned a unique id even in MPI
!! This consists of an array of integers: the first element is used to label, the second
!! and subsequent elements are used to count the number of times the first element wraps
!! around all possible values within the valid size for this datatype.
!! Labelling is done by starting the first label in each processor (even when only one)
!! as narea, and then incrementing by jpnij (i.e. the total number of processors.
!! This means that the source processor for each iceberg can be identified by arithmetic
!! modulo jpnij.
!!
!!----------------------------------------------------------------------
USE par_oce ! ocean parameters
USE lib_mpp ! MPP library
IMPLICIT NONE
PUBLIC
PUBLIC icb_alloc ! routine called by icb_init in icbini.F90 module
INTEGER, PUBLIC, PARAMETER :: nclasses = 10 !: Number of icebergs classes
INTEGER, PUBLIC, PARAMETER :: nkounts = 3 !: Number of integers combined for unique naming
TYPE, PUBLIC :: icebergs_gridded !: various icebergs properties on model grid
REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: calving ! Calving mass rate (into stored ice) [kg/s]
REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: calving_hflx ! Calving heat flux [heat content of calving] [W/m2]
REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: floating_melt ! Net melting rate to icebergs + bits [kg/s/m^2]
INTEGER , DIMENSION(:,:) , ALLOCATABLE :: maxclass ! maximum class number at calving source point
REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: tmp ! Temporary work space
REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: stored_ice ! Accumulated ice mass flux at calving locations [kg]
REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: stored_heat ! Heat content of stored ice [J]
END TYPE icebergs_gridded
TYPE, PUBLIC :: point !: properties of an individual iceberg (position, mass, size, etc...)
INTEGER :: year
REAL(wp) :: xi , yj , zk ! iceberg coordinates in the (i,j) referential (global) and deepest level affected
REAL(wp) :: e1 , e2 ! horizontal scale factors at the iceberg position
REAL(wp) :: lon, lat, day ! geographic position
REAL(wp) :: mass, thickness, width, length, uvel, vvel ! iceberg physical properties
REAL(wp) :: ssu, ssv, ui, vi, ua, va, ssh_x, ssh_y, sst, sss, cn, hi ! properties of iceberg environment
REAL(wp) :: mass_of_bits, heat_density
INTEGER :: kb ! icb bottom level
END TYPE point
TYPE, PUBLIC :: iceberg !: linked list defining all the icebergs present in the model domain
TYPE(iceberg), POINTER :: prev=>NULL(), next=>NULL() ! pointers to previous and next unique icebergs in linked list
INTEGER, DIMENSION(nkounts) :: number ! variables which do not change for this iceberg
REAL(wp) :: mass_scaling ! - - - -
TYPE(point), POINTER :: current_point => NULL() ! variables which change with time are held in a separate type
END TYPE iceberg
TYPE(icebergs_gridded), POINTER :: berg_grid !: master instance of gridded iceberg type
TYPE(iceberg) , POINTER :: first_berg => NULL() !: master instance of linked list iceberg type
! !!! parameters controlling iceberg characteristics and modelling
REAL(wp) :: berg_dt !: Time-step between iceberg CALLs (should make adaptive?)
REAL(wp), DIMENSION(:), ALLOCATABLE :: first_width, first_length !:
LOGICAL :: l_restarted_bergs=.FALSE. ! Indicate whether we read state from a restart or not
! ! arbitrary numbers for diawri entry
REAL(wp), DIMENSION(nclasses), PUBLIC :: class_num=(/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
! Extra arrays with bigger halo, needed when interpolating forcing onto iceberg position
! particularly for MPP when iceberg can lie inside T grid but outside U, V, or f grid
REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssu_e, ssv_e
REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: sst_e, sss_e, fr_e
REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ua_e, va_e
REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: ssh_e
REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: tmask_e, umask_e, vmask_e
REAl(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: rlon_e, rlat_e, ff_e
REAl(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE :: uoce_e, voce_e, toce_e, e3t_e
!
#if defined key_si3 || defined key_cice
REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE :: hi_e, ui_e, vi_e
#endif
!!gm almost all those PARAM ARE defined in NEMO
REAL(wp), PUBLIC, PARAMETER :: pp_rho_ice = 916.7_wp !: Density of fresh ice @ 0oC [kg/m^3]
REAL(wp), PUBLIC, PARAMETER :: pp_rho_water = 999.8_wp !: Density of fresh water @ 0oC [kg/m^3]
REAL(wp), PUBLIC, PARAMETER :: pp_rho_air = 1.1_wp !: Density of air @ 0oC [kg/m^3]
REAL(wp), PUBLIC, PARAMETER :: pp_rho_seawater = 1025._wp !: Approx. density of surface sea water @ 0oC [kg/m^3]
!!gm end
REAL(wp), PUBLIC, PARAMETER :: pp_Cd_av = 1.3_wp !: (Vertical) Drag coefficient between bergs and atmos
REAL(wp), PUBLIC, PARAMETER :: pp_Cd_ah = 0.0055_wp !: (lateral ) Drag coefficient between bergs and atmos
REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wv = 0.9_wp !: (Vertical) Drag coefficient between bergs and ocean
REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wh = 0.0012_wp !: (lateral ) Drag coefficient between bergs and ocean
REAL(wp), PUBLIC, PARAMETER :: pp_Cd_iv = 0.9_wp !: (Vertical) Drag coefficient between bergs and sea-ice
!TOM> no horizontal drag for sea ice! real, PARAMETER :: pp_Cd_ih=0.0012 ! (lateral) Drag coeff. between bergs and sea-ice
! !!* namberg namelist parameters (and defaults) **
LOGICAL , PUBLIC :: ln_bergdia !: Calculate budgets
INTEGER , PUBLIC :: nn_verbose_level !: Turn on debugging when level > 0
INTEGER , PUBLIC :: nn_test_icebergs !: Create icebergs in absence of a restart file from the supplied class nb
REAL(wp), PUBLIC, DIMENSION(4) :: rn_test_box !: lon1,lon2,lat1,lat2 box to create them in
LOGICAL , PUBLIC :: ln_use_calving !: Force use of calving data even with nn_test_icebergs > 0
! (default is not to use calving data with test bergs)
INTEGER , PUBLIC :: nn_sample_rate !: Timesteps between sampling of position for trajectory storage
INTEGER , PUBLIC :: nn_verbose_write !: timesteps between verbose messages
REAL(wp), PUBLIC :: rn_rho_bergs !: Density of icebergs
REAL(wp), PUBLIC :: rho_berg_1_oce !: convertion factor (thickness to draft) (rn_rho_bergs/pp_rho_seawater)
REAL(wp), PUBLIC :: rn_LoW_ratio !: Initial ratio L/W for newly calved icebergs
REAL(wp), PUBLIC :: rn_bits_erosion_fraction !: Fraction of erosion melt flux to divert to bergy bits
REAL(wp), PUBLIC :: rn_sicn_shift !: Shift of sea-ice concentration in erosion flux modulation (0<sicn_shift<1)
LOGICAL , PUBLIC :: ln_operator_splitting !: Use first order operator splitting for thermodynamics
LOGICAL , PUBLIC :: ln_passive_mode !: iceberg - ocean decoupling
LOGICAL , PUBLIC :: ln_time_average_weight !: Time average the weight on the ocean !!gm I don't understand that !
REAL(wp), PUBLIC :: rn_speed_limit !: CFL speed limit for a berg
LOGICAL , PUBLIC :: ln_M2016, ln_icb_grd !: use Nacho's Merino 2016 work
!
! restart
CHARACTER(len=256), PUBLIC :: cn_icbrst_indir , cn_icbrst_in !: in: restart directory, restart name
CHARACTER(len=256), PUBLIC :: cn_icbrst_outdir, cn_icbrst_out !: out: restart directory, restart name
!
! ! Mass thresholds between iceberg classes [kg]
REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_mass ! Fraction of calving to apply to this class [non-dim]
REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_distribution ! Ratio between effective and real iceberg mass (non-dim)
REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_mass_scaling ! Total thickness of newly calved bergs [m]
REAL(wp), DIMENSION(nclasses), PUBLIC :: rn_initial_thickness ! Single instance of an icebergs type initialised in icebergs_init and updated in icebergs_run
REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: src_calving, src_calving_hflx !: accumulate input ice
INTEGER , PUBLIC , SAVE :: micbkb !: deepest level affected by icebergs
INTEGER , PUBLIC , SAVE :: numicb !: iceberg IO
INTEGER , PUBLIC , SAVE, DIMENSION(nkounts) :: num_bergs !: iceberg counter
INTEGER , PUBLIC , SAVE :: nicbdi, nicbei, nicbdj, nicbej !: processor bounds
REAL(wp), PUBLIC , SAVE :: ricb_left, ricb_right !: cyclical bounds
INTEGER , PUBLIC , SAVE :: nicbpack !: packing integer
INTEGER , PUBLIC , SAVE :: nktberg, nknberg !: helpers
INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldpts !: nfold packed points
INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbflddest !: nfold destination proc
INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldproc !: nfold destination proc
INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldnsend !: nfold number of bergs to send to nfold neighbour
INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldexpect !: nfold expected number of bergs
INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:) :: nicbfldreq !: nfold message handle (immediate send)
!!----------------------------------------------------------------------
!! NEMO/OCE 4.0 , NEMO Consortium (2018)
!! $Id: icb_oce.F90 14030 2020-12-03 09:26:33Z mathiot $
!! Software governed by the CeCILL license (see ./LICENSE)
!!----------------------------------------------------------------------
CONTAINS
INTEGER FUNCTION icb_alloc()
!!----------------------------------------------------------------------
!! *** ROUTINE icb_alloc ***
!!----------------------------------------------------------------------
INTEGER :: ill
!!----------------------------------------------------------------------
!
icb_alloc = 0
ALLOCATE( berg_grid, STAT=ill )
icb_alloc = icb_alloc + ill
ALLOCATE( berg_grid%calving (jpi,jpj) , berg_grid%calving_hflx (jpi,jpj) , &
& berg_grid%stored_heat(jpi,jpj) , berg_grid%floating_melt(jpi,jpj) , &
& berg_grid%maxclass (jpi,jpj) , berg_grid%stored_ice (jpi,jpj,nclasses) , &
& berg_grid%tmp (jpi,jpj) , STAT=ill)
icb_alloc = icb_alloc + ill
!
! expanded arrays for bilinear interpolation
ALLOCATE( ssu_e(0:jpi+1,0:jpj+1) , ua_e(0:jpi+1,0:jpj+1) , &
& ssv_e(0:jpi+1,0:jpj+1) , va_e(0:jpi+1,0:jpj+1) , &
#if defined key_si3 || defined key_cice
& ui_e(0:jpi+1,0:jpj+1) , &
& vi_e(0:jpi+1,0:jpj+1) , &
& hi_e(0:jpi+1,0:jpj+1) , &
#endif
& fr_e(0:jpi+1,0:jpj+1) , &
& sst_e(0:jpi+1,0:jpj+1) , ssh_e(0:jpi+1,0:jpj+1) , &
& sss_e(0:jpi+1,0:jpj+1) , &
& first_width(nclasses) , first_length(nclasses) , &
& src_calving (jpi,jpj) , &
& src_calving_hflx(jpi,jpj) , STAT=ill)
icb_alloc = icb_alloc + ill
IF ( ln_M2016 ) THEN
ALLOCATE( uoce_e(0:jpi+1,0:jpj+1,jpk), voce_e(0:jpi+1,0:jpj+1,jpk), &
& toce_e(0:jpi+1,0:jpj+1,jpk), e3t_e(0:jpi+1,0:jpj+1,jpk) , STAT=ill )
icb_alloc = icb_alloc + ill
END IF
!
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), &
& 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)
icb_alloc = icb_alloc + ill
ALLOCATE( nicbfldpts(jpi) , nicbflddest(jpi) , nicbfldproc(jpni) , &
& nicbfldnsend(jpni), nicbfldexpect(jpni) , nicbfldreq(jpni), STAT=ill)
icb_alloc = icb_alloc + ill
CALL mpp_sum ( 'icb_oce', icb_alloc )
IF( icb_alloc > 0 ) CALL ctl_warn('icb_alloc: allocation of arrays failed')
!
END FUNCTION icb_alloc
!!======================================================================
END MODULE icb_oce