LCOV - code coverage report
Current view: top level - icepack/columnphysics - icepack_zsalinity.F90 (source / functions) Hit Total Coverage
Test: 201120-001611:d95a4f35ee:7:first,base,travis,decomp,reprosum,io,quick Lines: 0 405 0.00 %
Date: 2020-11-20 04:33:54 Functions: 0 7 0.00 %

          Line data    Source code
       1             : !=======================================================================
       2             : !
       3             : ! Vertical salinity (trcrn(nt_bgc_S)) is solved on the bio grid (bgrid and igrid)
       4             : ! with domain defined by the dynamic brine height (trcrn(nt_fbri) * vicen/aicen).
       5             : ! The CICE Bitz and Lipscomb thermodynamics is solved on the cgrid with height
       6             : ! vicen/aicen.
       7             : ! Gravity drainage is parameterized as nonlinear advection
       8             : ! Flushing is incorporated in the boundary changes and a darcy flow. 
       9             : ! (see Jeffery et al., JGR, 2011).  
      10             : !
      11             : ! authors: Nicole Jeffery, LANL
      12             : !          Elizabeth C. Hunke, LANL
      13             : !
      14             :       module icepack_zsalinity
      15             : 
      16             :       use icepack_kinds
      17             :       use icepack_parameters, only: c0, c1, c2, p001, p5, puny, rhow, depressT, gravit
      18             :       use icepack_parameters, only: rhosi, min_salin, salt_loss
      19             :       use icepack_parameters, only: l_skS, grid_oS, l_sk
      20             :       use icepack_parameters, only: dts_b
      21             :       use icepack_tracers, only: nt_sice
      22             :       use icepack_zbgc_shared, only: remap_zbgc
      23             :       use icepack_zbgc_shared, only: Ra_c, k_o, viscos_dynamic, thinS, Dm, exp_h
      24             :       use icepack_warnings, only: warnstr, icepack_warnings_add
      25             :       use icepack_warnings, only: icepack_warnings_setabort, icepack_warnings_aborted
      26             : 
      27             :       use icepack_brine, only: calculate_drho
      28             :       use icepack_therm_shared, only: calculate_Tin_from_qin
      29             : 
      30             :       implicit none
      31             : 
      32             :       private
      33             :       public :: zsalinity
      34             : 
      35             :       real (kind=dbl_kind), parameter :: & 
      36             :          max_salin = 200.0_dbl_kind, & !(ppt) maximum bulk salinity
      37             :          lapidus_g = 0.3_dbl_kind      ! constant for artificial 
      38             :                                        ! viscosity/diffusion during growth
      39             : !        lapidus_m = 0.007_dbl_kind    ! constant for artificial diffusion during melt
      40             : 
      41             : !=======================================================================
      42             : 
      43             :       contains
      44             : 
      45             : !=======================================================================
      46             : 
      47           0 :       subroutine zsalinity (n_cat,              dt,           &
      48           0 :                             nilyr,              bgrid,        &
      49           0 :                             cgrid,              igrid,        &
      50           0 :                             trcrn_S,            trcrn_q,      &
      51           0 :                             trcrn_Si,           ntrcr,        &
      52             :                             fbri,                             &
      53           0 :                             bSin,               bTin,         &
      54           0 :                             bphin,              iphin,        &
      55           0 :                             ikin,               hbr_old,      &
      56             :                             hbrin,              hin,          &
      57           0 :                             hin_old,            iDin,         &
      58           0 :                             darcy_V,            brine_sal,    &
      59           0 :                             brine_rho,          ibrine_sal,   &
      60           0 :                             ibrine_rho,         dh_direct,    &
      61             :                             Rayleigh_criteria,                &
      62             :                             first_ice,          sss,          &
      63             :                             sst,                dh_top,       &
      64             :                             dh_bot,                           &
      65             :                             fzsal,                            &
      66             :                             fzsal_g,            bphi_min,     &
      67             :                             nblyr,              vicen,        &
      68             :                             aicen,              zsal_tot) 
      69             :              
      70             :       integer (kind=int_kind), intent(in) :: &
      71             :          nilyr         , & ! number of ice layers
      72             :          nblyr         , & ! number of bio layers
      73             :          ntrcr         , & ! number of tracers
      74             :          n_cat             ! category number 
      75             :                     
      76             :       real (kind=dbl_kind), dimension (nblyr+2), intent(in) :: &
      77             :          bgrid              ! biology nondimensional vertical grid points
      78             : 
      79             :       real (kind=dbl_kind), dimension (nblyr+1), intent(in) :: &
      80             :          igrid              ! biology vertical interface points
      81             :  
      82             :       real (kind=dbl_kind), dimension (nilyr+1), intent(in) :: &
      83             :          cgrid              ! CICE vertical coordinate   
      84             : 
      85             :       real (kind=dbl_kind), intent(in) :: &
      86             :          sss           , & ! ocean salinity (ppt)
      87             :          sst           , & ! ocean temperature (oC)
      88             :          hin_old       , & ! old ice thickness (m)
      89             :          dh_top        , & ! brine change in top and bottom for diagnostics (m)
      90             :          dh_bot        , & ! minimum porosity
      91             :          darcy_V       , & ! darcy velocity (m/s)
      92             :          dt            , & ! time step
      93             :          fbri          , & ! ratio of brine height to ice thickness
      94             :          hbr_old       , & ! old brine height  (m)
      95             :          hin           , & ! new ice thickness (m)
      96             :          hbrin         , & ! new brine height  (m)
      97             :          vicen         , & ! ice volume (m)
      98             :          aicen         , & ! ice area (m)
      99             :          bphi_min      , & !
     100             :          dh_direct         ! flooded or runoff amount (m)
     101             : 
     102             :       real (kind=dbl_kind), intent(inout) :: &
     103             :          zsal_tot      , & ! tot salinity (psu*rhosi*total vol ice)
     104             :          fzsal         , & ! total flux of salt out of ice over timestep(kg/m^2/s)
     105             :          fzsal_g           ! gravity drainage flux of salt over timestep(kg/m^2/s)
     106             : 
     107             :       real (kind=dbl_kind), dimension (nblyr+2), intent(inout) :: &
     108             :          bTin          , & ! Ice Temperature ^oC (on bio grid)
     109             :          bphin             ! Ice porosity (on bio grid)
     110             : 
     111             :       real (kind=dbl_kind), dimension (nblyr+2), intent(inout) :: &
     112             :          bSin          , & ! Ice salinity ppt (on bio  grid)
     113             :          brine_sal     , & ! brine salinity (ppt)
     114             :          brine_rho         ! brine density  (kg/m^3)
     115             : 
     116             :       real (kind=dbl_kind), dimension (nblyr), &
     117             :          intent(inout) :: &
     118             :          trcrn_S           ! salinity tracer ppt (on bio grid)
     119             : 
     120             :       real (kind=dbl_kind), dimension (nilyr), &
     121             :          intent(inout) :: &
     122             :          trcrn_q       , & ! enthalpy tracer 
     123             :          trcrn_Si          ! salinity on CICE grid
     124             : 
     125             :       logical (kind=log_kind), intent(inout) :: &
     126             :          Rayleigh_criteria ! .true. if minimun ice thickness (Ra_c)  was reached 
     127             :       
     128             :       logical (kind=log_kind), intent(in) :: &
     129             :          first_ice         ! for first category ice only .true. 
     130             :                            !initialized values should be used 
     131             : 
     132             :       real (kind=dbl_kind), dimension (nblyr+1), intent(out) :: &
     133             :          iDin          , & ! Diffusivity on the igrid   (1/s)
     134             :          ikin              ! permeability on the igrid 
     135             : 
     136             :       real (kind=dbl_kind), dimension (nblyr+1), intent(inout) :: &
     137             :          iphin         , & ! porosity on the igrid 
     138             :          ibrine_rho    , & ! brine rho on interface  
     139             :          ibrine_sal        ! brine sal on interface   
     140             :          
     141             :       ! local variables
     142             : 
     143             :       real (kind=dbl_kind) :: &
     144           0 :          fzsaln        , & ! category flux of salt out of ice over timestep(kg/m^2/s)
     145           0 :          fzsaln_g      , & ! category gravity drainage flux of salt over timestep(kg/m^2/s)
     146           0 :          zsal_totn         ! total salt content
     147             : 
     148             :       character(len=*),parameter :: subname='(zsalinity)'
     149             : 
     150             :          call solve_zsalinity     (nilyr, nblyr, n_cat, dt,          &
     151             :                                    bgrid,      cgrid,    igrid,      &
     152             :                                    trcrn_S,            trcrn_q,      &
     153             :                                    trcrn_Si,           ntrcr,        &
     154             :                                    bSin,               bTin,         &
     155             :                                    bphin,              iphin,        &
     156             :                                    ikin,               hbr_old,      &
     157             :                                    hbrin,              hin,          &
     158             :                                    hin_old,            iDin,         &
     159             :                                    darcy_V,            brine_sal,    &
     160             :                                    brine_rho,          ibrine_sal,   &
     161             :                                    ibrine_rho,         dh_direct,    &
     162             :                                    Rayleigh_criteria,                &
     163             :                                    first_ice,          sss,          &
     164             :                                    sst,                dh_top,       &
     165             :                                    dh_bot,                           &
     166             :                                    fzsaln,                           &
     167           0 :                                    fzsaln_g,           bphi_min)
     168           0 :          if (icepack_warnings_aborted(subname)) return
     169             : 
     170           0 :          zsal_totn = c0
     171             : 
     172             :          call column_sum_zsal    (zsal_totn,          nblyr,      &
     173             :                                   vicen,              trcrn_S,    &
     174           0 :                                   fbri)
     175           0 :          if (icepack_warnings_aborted(subname)) return
     176             : 
     177             :          call merge_zsal_fluxes (aicen, &
     178             :                                  zsal_totn,          zsal_tot,       &
     179             :                                  fzsal,              fzsaln,         &
     180           0 :                                  fzsal_g,            fzsaln_g)            
     181           0 :          if (icepack_warnings_aborted(subname)) return
     182             : 
     183             :       end subroutine zsalinity
     184             : 
     185             : !=======================================================================
     186             : !
     187             : ! update vertical salinity 
     188             : ! 
     189           0 :       subroutine solve_zsalinity  (nilyr,              nblyr,        &
     190             :                                    n_cat,              dt,           &
     191           0 :                                    bgrid,    cgrid,    igrid,        &
     192           0 :                                    trcrn_S,            trcrn_q,      &
     193           0 :                                    trcrn_Si,           ntrcr,        &
     194           0 :                                    bSin,               bTin,         &
     195           0 :                                    bphin,              iphin,        &
     196           0 :                                    ikin,               hbr_old,      &
     197             :                                    hbrin,              hin,          &
     198           0 :                                    hin_old,            iDin,         &
     199           0 :                                    darcy_V,            brine_sal,    &
     200           0 :                                    brine_rho,          ibrine_sal,   &
     201           0 :                                    ibrine_rho,         dh_direct,    &
     202             :                                    Rayleigh_criteria,                &
     203             :                                    first_ice,          sss,          &
     204             :                                    sst,                dh_top,       &
     205             :                                    dh_bot,                           &  
     206             :                                    fzsaln,                           &
     207             :                                    fzsaln_g,           bphi_min)
     208             : 
     209             :       integer (kind=int_kind), intent(in) :: &
     210             :          nilyr,          & ! number of ice layers
     211             :          nblyr,          & ! number of bio layers
     212             :          ntrcr,          & ! number of tracers
     213             :          n_cat             ! category number 
     214             :                     
     215             :       real (kind=dbl_kind), intent(in) :: &
     216             :          dt                ! time step
     217             : 
     218             :       real (kind=dbl_kind), dimension (nblyr+2), intent(in) :: &
     219             :          bgrid              ! biology nondimensional vertical grid points
     220             : 
     221             :       real (kind=dbl_kind), dimension (nblyr+1), intent(in) :: &
     222             :          igrid              ! biology vertical interface points
     223             :  
     224             :       real (kind=dbl_kind), dimension (nilyr+1), intent(in) :: &
     225             :          cgrid              ! CICE vertical coordinate   
     226             : 
     227             :       real (kind=dbl_kind), intent(in) :: &
     228             :          sss           , & ! ocean salinity (ppt)
     229             :          sst           , & ! ocean temperature (oC)
     230             :          hin_old       , & ! old ice thickness (m)
     231             :          dh_top        , & ! brine change in top and bottom for diagnostics (m)
     232             :          dh_bot        , &
     233             :          darcy_V    
     234             : 
     235             :       real (kind=dbl_kind), intent(in) :: &
     236             :          hbr_old       , & ! old brine height  (m)
     237             :          hin           , & ! new ice thickness (m)
     238             :          hbrin         , & ! new brine height  (m)
     239             :          bphi_min      , & !
     240             :          dh_direct         ! flooded or runoff amount (m)
     241             :  
     242             :       real (kind=dbl_kind), intent(out) :: &
     243             :          fzsaln        , & ! total flux of salt out of ice over timestep(kg/m^2/s)
     244             :          fzsaln_g          ! gravity drainage flux of salt  over timestep(kg/m^2/s)
     245             : 
     246             :       real (kind=dbl_kind), dimension (nblyr+2), intent(inout) :: &
     247             :          bTin          , & ! Ice Temperature ^oC (on bio grid)
     248             :          bphin             ! Ice porosity (on bio grid)
     249             : 
     250             :       real (kind=dbl_kind), dimension (nblyr+2), intent(inout) :: &
     251             :          bSin          , & ! Ice salinity ppt (on bio  grid)
     252             :          brine_sal     , & ! brine salinity (ppt)
     253             :          brine_rho         ! brine density  (kg/m^3)
     254             : 
     255             :       real (kind=dbl_kind), dimension (nblyr), &
     256             :          intent(inout) :: &
     257             :          trcrn_S           ! salinity tracer ppt (on bio grid)
     258             : 
     259             :       real (kind=dbl_kind), dimension (nilyr), &
     260             :          intent(inout) :: &
     261             :          trcrn_q       , & ! enthalpy tracer 
     262             :          trcrn_Si          ! salinity on CICE grid
     263             : 
     264             :       logical (kind=log_kind), intent(inout) :: &
     265             :          Rayleigh_criteria ! .true. if minimun ice thickness (Ra_c)  was reached 
     266             :       
     267             :       logical (kind=log_kind), intent(in) :: &
     268             :          first_ice         ! for first category ice only .true. 
     269             :                            !initialized values should be used 
     270             : 
     271             :       real (kind=dbl_kind), dimension (nblyr+1), intent(out) :: &
     272             :          iDin          , & ! Diffusivity on the igrid   (1/s)
     273             :          ikin              ! permeability on the igrid 
     274             : 
     275             :       real (kind=dbl_kind), dimension (nblyr+1), intent(inout) :: &
     276             :          iphin         , & ! porosity on the igrid 
     277             :          ibrine_rho    , & ! brine rho on interface  
     278             :          ibrine_sal        ! brine sal on interface   
     279             :          
     280             :       ! local variables
     281             : 
     282             :       integer (kind=int_kind) :: &
     283             :          k, nint        ! vertical biology layer index 
     284             : 
     285             :       real (kind=dbl_kind) :: &
     286           0 :          surface_S         ! salinity of ice above hin > hbrin
     287             :       
     288             :       real (kind=dbl_kind), dimension(2) :: &
     289           0 :          S_bot           
     290             : 
     291             :       real (kind=dbl_kind) :: &
     292           0 :          Tmlts         , & ! melting temperature
     293           0 :          dts               ! local timestep (s)
     294             : 
     295             :       logical (kind=log_kind) :: &
     296             :          Rayleigh
     297             :      
     298             :       real (kind=dbl_kind):: &
     299           0 :          Ttemp             ! initial temp profile on the CICE grid
     300             : 
     301             :       real (kind=dbl_kind), dimension (ntrcr+2) :: &
     302           0 :          trtmp0        , & ! temporary, remapped tracers     !need extra 
     303           0 :          trtmp             ! temporary, remapped tracers     !
     304             : 
     305             :       logical (kind=log_kind) :: &
     306             :          cflag
     307             : 
     308             :       character(len=*),parameter :: subname='(solve_zsalinity)'
     309             : 
     310             :       !-----------------------------------------------------------------
     311             :       ! Initialize
     312             :       !-----------------------------------------------------------------
     313             : 
     314           0 :       dts = dts_b
     315           0 :       nint = max(1,INT(dt/dts))  
     316           0 :       dts = dt/nint
     317             : 
     318             :       !----------------------------------------------------------------
     319             :       ! Update boundary conditions
     320             :       !----------------------------------------------------------------
     321             :          
     322           0 :       surface_S = min_salin
     323             : 
     324           0 :       Rayleigh = .true.
     325           0 :       if (n_cat == 1 .AND. hbr_old < Ra_c) then
     326           0 :          Rayleigh = Rayleigh_criteria ! only category 1 ice can be false 
     327             :       endif
     328             : 
     329           0 :       if (dh_bot + darcy_V*dt > c0) then  
     330             :             
     331           0 :          bSin     (nblyr+2) = sss
     332           0 :          bTin     (nblyr+2) = sst
     333           0 :          brine_sal(nblyr+2) = sss 
     334           0 :          brine_rho(nblyr+2) = rhow
     335           0 :          bphin    (nblyr+2) = c1 
     336           0 :          S_bot    (1)       = c0
     337           0 :          S_bot    (2)       = c1  
     338             :    
     339             :       ! bottom melt
     340             :       else  
     341           0 :          bSin (nblyr+2) = bSin(nblyr+1)  
     342           0 :          Tmlts          =  -bSin(nblyr+2)* depressT 
     343           0 :          bTin (nblyr+2) = bTin(nblyr+1)
     344           0 :          bphin(nblyr+2) = iphin(nblyr+1)
     345           0 :          S_bot(1)       = c1
     346           0 :          S_bot(2)       = c0
     347             :       endif
     348             : 
     349           0 :       if (abs(dh_top) > puny .AND. abs(darcy_V) > puny) then 
     350           0 :          bSin(1) = max(min_salin,-(brine_rho(2)*brine_sal(2)/rhosi &
     351             :                  * darcy_V*dt - (dh_top + darcy_V*dt/bphi_min - dh_direct)*min_salin &
     352           0 :                  + max(c0,-dh_direct) * sss  )/dh_top)
     353           0 :          brine_sal(1) = brine_sal(2)
     354           0 :          brine_rho(1) = brine_rho(2)
     355           0 :          bphin(1) = bphi_min
     356             :       else
     357           0 :          bSin(1) = min_salin
     358             :       endif
     359             :             
     360             :       !-----------------------------------------------------------------
     361             :       ! Solve for S using CICE T.  If solve_zsal = .true., then couple back
     362             :       ! to the thermodynamics
     363             :       !-----------------------------------------------------------------
     364             : 
     365             :       call solve_S_dt (cflag,         nblyr,         &
     366             :                        nint         , dts          , &
     367             :                        bSin         , bTin         , &
     368             :                        bphin        , iphin        , &
     369             :                        igrid        , bgrid        , &
     370             :                        ikin         ,                &
     371             :                        hbr_old      , hbrin        , &
     372             :                        hin_old      , &
     373             :                        iDin         , darcy_V      , &
     374             :                        brine_sal    , Rayleigh     , &
     375             :                        first_ice    , sss          , &
     376             :                        dt           , dh_top       , &
     377             :                        dh_bot       , brine_rho    , &
     378             :                        ibrine_sal   , ibrine_rho   , &
     379             :                        fzsaln       , fzsaln_g     , &
     380           0 :                        S_bot        )
     381           0 :       if (icepack_warnings_aborted(subname)) return
     382             :   
     383           0 :       if (n_cat == 1)   Rayleigh_criteria = Rayleigh
     384             : 
     385           0 :       trtmp0(:) = c0
     386           0 :       trtmp (:) = c0
     387             :        
     388           0 :       do k = 1,nblyr                  ! back to bulk quantity 
     389           0 :             trcrn_S(k) =   bSin(k+1) 
     390           0 :             trtmp0(nt_sice+k-1) = trcrn_S(k)
     391             :       enddo           ! k
     392             : 
     393             :       call remap_zbgc   (nilyr, &
     394             :                          nt_sice,          &
     395           0 :                          trtmp0(1:ntrcr),  &
     396           0 :                          trtmp,            &
     397             :                          1,         nblyr, &
     398             :                          hin,       hbrin, &
     399           0 :                          cgrid(2:nilyr+1), &
     400           0 :                          bgrid(2:nblyr+1), &
     401           0 :                          surface_S )
     402           0 :       if (icepack_warnings_aborted(subname)) return
     403             :                
     404           0 :       do k = 1, nilyr
     405           0 :             Tmlts = -trcrn_Si(k)*depressT
     406             :             Ttemp = min(-(min_salin+puny)*depressT, &
     407           0 :                        calculate_Tin_from_qin(trcrn_q(k),Tmlts)) 
     408           0 :             trcrn_Si(k) = min(-Ttemp/depressT, max(min_salin, &
     409           0 :                                  trtmp(nt_sice+k-1)))
     410           0 :             Tmlts = - trcrn_Si(k)*depressT 
     411             :            ! if (cflag)  trcrn_q(k) = calculate_qin_from_Sin(Ttemp,Tmlts)  
     412             :       enddo ! k
     413             : 
     414             :       end subroutine solve_zsalinity
     415             : 
     416             : !=======================================================================
     417             : !
     418             : !  solves salt continuity explicitly using 
     419             : !  Lax-Wendroff-type scheme (MacCormack)
     420             : !  (Mendez-Nunez and Carroll,  Monthly Weather Review, 1993)
     421             : !
     422             : ! authors     Nicole Jeffery, LANL
     423             : !
     424           0 :       subroutine solve_S_dt          (cflag,  nblyr, nint,          &
     425           0 :                                       dts,    bSin,  bTin,          &
     426           0 :                                       bphin,  iphin, igrid,         &
     427           0 :                                       bgrid,  ikin,  hbri_old,      &
     428             :                                       hbrin,  hice_old,      &
     429           0 :                                       iDin,          darcy_V,       &
     430           0 :                                       brine_sal,     Rayleigh,      &
     431             :                                       first_ice,     sss,           &
     432             :                                       dt,            dht,           &
     433           0 :                                       dhb,           brine_rho,     &
     434           0 :                                       ibrine_sal,    ibrine_rho,    &
     435             :                                       fzsaln,        fzsaln_g,      &
     436             :                                       S_bot          )
     437             : 
     438             :       integer (kind=int_kind), intent(in) :: &
     439             :          nblyr            , & ! number of bio layers
     440             :          nint                 ! number of interations
     441             : 
     442             :       logical (kind=log_kind), intent(out) :: &
     443             :          cflag                ! thin or not
     444             : 
     445             :       real (kind=dbl_kind), intent(in) :: &
     446             :          dt               , & ! timestep (s)
     447             :          dts              , & ! local timestep (s)
     448             :          sss              , & ! sea surface salinity
     449             :          dht              , & ! change in the ice top  (positive for melting)
     450             :          dhb              , & ! change in the ice bottom (positive for freezing)
     451             :          hice_old         , & ! old ice thickness (m)
     452             :          hbri_old         , & ! brine thickness (m) 
     453             :          hbrin            , & ! new brine thickness (m)
     454             :          darcy_V              ! Darcy velocity due to a pressure head (m/s) or melt      
     455             : 
     456             :       real (kind=dbl_kind), intent(out) :: &
     457             :          fzsaln           , & ! salt flux +ive to  ocean (kg/m^2/s)
     458             :          fzsaln_g             ! gravity drainage salt flux +ive to ocean (kg/m^2/s)
     459             : 
     460             :       logical (kind=log_kind), intent(inout) :: &
     461             :          Rayleigh             ! if .true. convection is allowed; if .false. not yet
     462             : 
     463             :       logical (kind=log_kind), intent(in) :: &
     464             :          first_ice
     465             : 
     466             :       real (kind=dbl_kind), dimension (nblyr+2), intent(in) :: &
     467             :          brine_sal        , & ! Internal brine salinity (ppt)
     468             :          brine_rho        , & ! Internal brine density (kg/m^3)
     469             :          bgrid            , & ! biology nondimensional grid layer points 
     470             :          bTin                 ! Temperature of ice layers on bio grid for history (C) 
     471             : 
     472             :       real (kind=dbl_kind), dimension (nblyr+2), intent(inout) :: &
     473             :          bphin            , & ! Porosity of layers
     474             :          bSin                 ! Bulk Salinity (ppt) contains previous timestep
     475             :                               ! and ocean ss
     476             : 
     477             :       real (kind=dbl_kind), dimension (nblyr+1), intent(in) :: &
     478             :          ibrine_rho       , & ! brine rho on interface 
     479             :          ibrine_sal       , & ! brine sal on interface 
     480             :          igrid                ! biology grid interface points 
     481             : 
     482             :       real (kind=dbl_kind), dimension (nblyr+1), intent(inout) :: &
     483             :          iphin                ! Porosity of layers on interface
     484             : 
     485             :       real (kind=dbl_kind), dimension (nblyr+1), intent(out) :: &
     486             :          iDin             , & ! Diffusivity on the igrid (1/s) with minimum bphi condition
     487             :          ikin                 ! permeability on interface
     488             : 
     489             :       real (kind=dbl_kind), dimension (2), intent(in) :: &
     490             :          S_bot
     491             :        
     492             :       ! local variables
     493             : 
     494             :       integer (kind=int_kind) :: &
     495             :          k, m       ! vertical biology layer index 
     496             : 
     497             :       real (kind=dbl_kind), dimension (nblyr+1) :: &
     498           0 :          iDin_p           , & ! Diffusivity on the igrid (1/s)/bphi^3 
     499           0 :          dSbdx            , & ! gradient of brine rho on grid
     500           0 :          drho             , & ! brine difference rho_a-rho_b  (kg/m^3)
     501             : !        Ci_s             , & !
     502           0 :          Ui_s             , & ! interface function
     503             : !        Vi_s             , & ! for conservation check
     504           0 :          ivel
     505             : 
     506             :       real (kind=dbl_kind), dimension (nblyr+2) :: &
     507           0 :          Din_p            , & ! Diffusivity on the igrid (1/s)/bphi^3  
     508           0 :          Sintemp          , & ! initial salinity
     509           0 :          pre_sin          , & ! estimate of  salinity of layers
     510           0 :          pre_sinb         , & ! estimate of  salinity of layers
     511           0 :          bgrid_temp       , & ! biology nondimensional grid layer points 
     512             :                               ! with boundary values 
     513           0 :          Q_s, C_s         , & ! Functions in continuity equation
     514           0 :          V_s, U_s, F_s    
     515             : 
     516             :       real (kind=dbl_kind) :: &
     517           0 :          dh               , & ! (m) change in hbrine over dts
     518           0 :          dbgrid           , & ! ratio of grid space to spacing across boundary 
     519             :                               ! i.e. 1/nilyr/(dbgrid(2)-dbgrid(1))
     520           0 :          lapidus          , & ! artificial viscosity:  use lapidus_g for growth
     521           0 :          Ssum_old,Ssum_new, & ! depth integrated salt before and after timestep
     522           0 :          fluxcorr,          & ! flux correction to prevent S < min_salin
     523           0 :          Ssum_corr,         & ! numerical boundary flux correction
     524           0 :          fluxb            , & ! bottom, top and total boundary flux (g/kg/m^2)
     525           0 :          fluxg            , & ! bottom, top and total gravity drainage flux (g/kg/m^2)
     526           0 :          fluxm            , & ! bottom, top and total molecular diffusion flux (g/kg/m^2)
     527           0 :          sum_old,sum_new  , & ! integrated salinity at t and t+dt
     528           0 :          dh_dt, dS_dt     , &
     529           0 :          Ssum_tmp
     530             : 
     531             :       real (kind=dbl_kind), dimension (nblyr) :: &
     532           0 :          vel              , & ! advective velocity times dt (m)
     533           0 :          lapidus_diff     , & ! lapidus term and 
     534           0 :          flux_corr        , &
     535           0 :          lapA             , &
     536           0 :          lapB    
     537             : 
     538             :       logical (kind=log_kind) :: &   
     539             :          test_conservation       ! test that salt change is balanced by fluxes 
     540             : 
     541             :       character(len=*),parameter :: subname='(solve_S_dt)'
     542             : 
     543             :       !-----------------------------------------------------------------
     544             :       !  Initialize
     545             :       !-----------------------------------------------------------------
     546             : 
     547           0 :       cflag = .false.
     548           0 :       test_conservation = .false. 
     549           0 :       iDin_p(:) = c0   
     550           0 :       Din_p(:) = c0 
     551           0 :       lapA(:) = c1
     552           0 :       lapB(:) = c1
     553           0 :       lapA(nblyr) = c0
     554           0 :       lapB(1) = c0
     555           0 :       V_s(:) = c0
     556           0 :       U_s(:) = c0
     557           0 :       Q_s(:) = c0
     558           0 :       C_s(:) = c0
     559             : !     Ci_s(:) = c0
     560           0 :       F_s(:) = c0
     561           0 :       Ui_s(:) = c0
     562             : !     Vi_s(:) = c0
     563           0 :       ivel(:) = c0
     564           0 :       vel(:) = c0
     565           0 :       dh = c0
     566           0 :       dbgrid = c2
     567           0 :       fzsaln = c0
     568           0 :       fzsaln_g = c0
     569             : 
     570             :       !-----------------------------------------------------------------
     571             :       ! Find brine density gradient for gravity drainage parameterization
     572             :       !-----------------------------------------------------------------
     573             : 
     574             :       call calculate_drho(nblyr, igrid, bgrid,&
     575           0 :                           brine_rho, ibrine_rho, drho)   
     576           0 :       if (icepack_warnings_aborted(subname)) return
     577             : 
     578             :       !-----------------------------------------------------------------
     579             :       ! Calculate bphi diffusivity on the grid points
     580             :       ! rhosi = 919-974 kg/m^2  set in bio_in
     581             :       ! rhow = 1026.0 density of sea water: uses kinematic viscosity (m^2/s) in Q18
     582             :       ! dynamic viscosity  divided by density = kinematic. 
     583             :       !-----------------------------------------------------------------
     584             : 
     585           0 :       do k = 2, nblyr+1
     586           0 :          iDin_p(k) = k_o*gravit*l_skS/viscos_dynamic*drho(k)/(hbri_old**2)
     587           0 :           Din_p(k) = (iDin_p(k)*(igrid(k)-bgrid(k)) &
     588           0 :                    + iDin_p(k-1)*(bgrid(k)-igrid(k-1)))/(igrid(k)-igrid(k-1))
     589             :       enddo                !k
     590             : 
     591             :       !-----------------------------------------------------------------
     592             :       ! Critical Ra_c value is only for the onset of convection in thinS 
     593             :       ! ice and not throughout, therefore I need a flag to indicate the 
     594             :       ! Ra_c was reached for a particular ice block.
     595             :       ! Using a thickness minimum (Ra_c) for simplicity.
     596             :       !-----------------------------------------------------------------
     597             : 
     598           0 :       bgrid_temp(:) = bgrid(:)
     599           0 :       Din_p(nblyr+2) =  iDin_p(nblyr+1)
     600           0 :       if (.NOT. Rayleigh .AND. hbrin < Ra_c) then
     601           0 :          Din_p(:) =  c0  
     602           0 :          iDin_p(:) = c0  
     603             :       else
     604           0 :          Rayleigh = .true.
     605             :       endif
     606             : 
     607             :       if (hbri_old > thinS .AND. hbrin > thinS .and. &
     608           0 :           hice_old > thinS .AND. .NOT. first_ice) then
     609             : 
     610           0 :          cflag = .true.
     611             : 
     612           0 :          bgrid_temp(1) = c0
     613           0 :          bgrid_temp(nblyr+2) = c1
     614           0 :          dbgrid = igrid(2)/(bgrid_temp(2)-bgrid_temp(1))
     615             : 
     616             :          !-----------------------------------
     617             :          ! surface boundary terms
     618             :          !-----------------------------------
     619             :                              
     620           0 :          lapidus = lapidus_g/real(nblyr,kind=dbl_kind)**2
     621           0 :          ivel(1) = dht/hbri_old
     622           0 :          U_s (1) = ivel(1)/dt*dts 
     623           0 :          Ui_s(1) = U_s(1) 
     624             : !        Ci_s(1) = c0
     625           0 :          F_s (1) = brine_rho(2)*brine_sal(2)/rhosi*darcy_V*dts/hbri_old/bSin(1)
     626             : 
     627             :          !-----------------------------------
     628             :          ! bottom boundary terms
     629             :          !-----------------------------------
     630             : 
     631           0 :          ivel(nblyr+1) =  dhb/hbri_old           
     632           0 :          Ui_s(nblyr+1) = ivel(nblyr+1)/dt*dts  
     633           0 :          dSbdx(nblyr) = (ibrine_sal(nblyr+1)*ibrine_rho(nblyr+1) &
     634           0 :                       -  ibrine_sal(nblyr)*ibrine_rho(nblyr)) &
     635           0 :                       / (igrid(nblyr+1)-igrid(nblyr))
     636           0 :          C_s(nblyr+1) = Dm/brine_sal(nblyr+1)/brine_rho(nblyr+1)*dts/hbri_old**2 &
     637           0 :                       * (ibrine_sal(nblyr+1)*ibrine_rho(nblyr+1) &
     638           0 :                       -  ibrine_sal(nblyr)*ibrine_rho(nblyr)) &
     639           0 :                       / (igrid(nblyr+1)-igrid(nblyr))
     640           0 :          F_s(nblyr+1) = darcy_V*dts/hbri_old/bphin(nblyr+1)
     641           0 :          F_s(nblyr+2) = darcy_V*dts/hbri_old/bphin(nblyr+2)  
     642           0 :          vel(nblyr) =(bgrid(nblyr+1)*(dhb) -(bgrid(nblyr+1) - c1)*dht)/hbri_old
     643           0 :          U_s(nblyr+1) = vel(nblyr)/dt*dts  
     644           0 :          V_s(nblyr+1) = Din_p(nblyr+1)/rhosi &
     645           0 :                       * (rhosi/brine_sal(nblyr+1)/brine_rho(nblyr+1))**exp_h &
     646           0 :                       * dts*dSbdx(nblyr) 
     647           0 :          dSbdx(nblyr+1) = (brine_sal(nblyr+2)*brine_rho(nblyr+2) &
     648           0 :                         -  brine_sal(nblyr+1)*brine_rho(nblyr+1)) &
     649           0 :                         / (bgrid(nblyr+2)-bgrid(nblyr+1)+ grid_oS/hbri_old )  
     650           0 :          C_s( nblyr+2) = Dm/brine_sal(nblyr+2)/brine_rho(nblyr+2)*dts/hbri_old**2 &
     651           0 :                        * (brine_sal(nblyr+2)*brine_rho(nblyr+2) & 
     652           0 :                        -  brine_sal(nblyr+1)*brine_rho(nblyr+1)) &
     653           0 :                        / (bgrid(nblyr+2)-bgrid(nblyr+1) + grid_oS/hbri_old ) 
     654           0 :          U_s(nblyr+2) = ivel(nblyr+1)/dt*dts 
     655           0 :          V_s(nblyr+2) = Din_p(nblyr+2)/rhosi &
     656           0 :                       * (bphin(nblyr+1)/bSin(nblyr+2))**exp_h &
     657           0 :                       * dts*dSbdx(nblyr+1)
     658             : !        Ci_s(nblyr+1) = C_s(nblyr+2)
     659             : !        Vi_s(nblyr+1) = V_s(nblyr+2) 
     660           0 :          dh = (dhb-dht)/dt*dts
     661             : 
     662           0 :          do k = 2, nblyr  
     663           0 :             ivel(k) =  (igrid(k)*dhb - (igrid(k)-c1)*dht)/hbri_old
     664           0 :             Ui_s(k) = ivel(k)/dt*dts   
     665             : !           Vi_s(k) = iDin_p(k)/rhosi &
     666             : !                   *(rhosi/ibrine_rho(k)/ibrine_sal(k))**exp_h*dts &
     667             : !                   * (brine_sal(k+1)*brine_rho(k+1) &
     668             : !                   -  brine_sal(k)*brine_rho(k)) &
     669             : !                   / (bgrid(k+1)-bgrid(k)) 
     670           0 :             dSbdx(k-1) = (ibrine_sal(k)*ibrine_rho(k) &
     671           0 :                        -  ibrine_sal(k-1)*ibrine_rho(k-1))/(igrid(k)-igrid(k-1))
     672           0 :             F_s(k) = darcy_V*dts/hbri_old/bphin(k)
     673           0 :             C_s(k) = Dm/brine_sal(k)/brine_rho(k)*dts/hbri_old**2 &
     674           0 :                    * (ibrine_sal(k)*ibrine_rho(k) &
     675           0 :                    -  ibrine_sal(k-1)*ibrine_rho(k-1))/(igrid(k)-igrid(k-1))
     676             : !           Ci_s(k) = Dm/ibrine_sal(k)/ibrine_rho(k)*dts/hbri_old**2 &
     677             : !                   * (brine_sal(k+1)*brine_rho(k+1) &
     678             : !                   -  brine_sal(k)*brine_rho(k))/(bgrid(k+1)-bgrid(k))
     679           0 :             vel(k-1) = (bgrid(k)*(dhb) - (bgrid(k) - c1)* dht)/hbri_old
     680           0 :             U_s(k) = vel(k-1)/dt*dts 
     681           0 :             V_s(k) = Din_p(k)/rhosi &
     682           0 :                    * (rhosi/brine_sal(k)/brine_rho(k))**exp_h*dts*dSbdx(k-1) 
     683           0 :             C_s(2) = c0
     684           0 :             V_s(2) = c0
     685             :          enddo !k
     686             : 
     687             :       !-----------------------------------------------------------------
     688             :       ! Solve
     689             :       !-----------------------------------------------------------------
     690             : 
     691           0 :          do m = 1, nint     
     692             : 
     693           0 :             Sintemp(:) = bSin(:)
     694           0 :             pre_sin(:) = bSin(:)  
     695           0 :             pre_sinb(:) = bSin(:)
     696           0 :             Ssum_old = bSin(nblyr+1)*(igrid(nblyr+1)-igrid(nblyr))
     697             : 
     698             :             ! forward-difference 
     699             : 
     700           0 :             do k = 2, nblyr
     701           0 :                Ssum_old = Ssum_old + bSin(k)*(igrid(k)-igrid(k-1))
     702             : 
     703           0 :                pre_sin(k) =bSin(k) + (Ui_s(k)*(bSin(k+1) - bSin(k)) + &
     704           0 :                  V_s(k+1)*bSin(k+1)**3 - V_s(k)*bSin(k)**3 + &
     705           0 :                  (C_s(k+1)+F_s(k+1))*bSin(k+1)-&
     706           0 :                  (C_s(k)+F_s(k))*bSin(k))/(bgrid_temp(k+1)-bgrid_temp(k)) 
     707             :             enddo    !k
     708             : 
     709           0 :             pre_sin(nblyr+1) = bSin(nblyr+1) + (Ui_s(nblyr+1)*(bSin(nblyr+2) - &
     710           0 :                  bSin(nblyr+1)) +  V_s(nblyr+2)*bSin(nblyr+2)**3 - &
     711           0 :                  V_s(nblyr+1)*bSin(nblyr+1)**3+ (C_s(nblyr+2)+F_s(nblyr+2))*&
     712           0 :                  bSin(nblyr+2)-(C_s(nblyr+1)+F_s(nblyr+1))*bSin(nblyr+1) )/&
     713           0 :                  (bgrid_temp(nblyr+2)- bgrid_temp(nblyr+1))
     714             :               
     715             :             ! backward-difference 
     716             : 
     717           0 :             pre_sinb(2) = p5*(bSin(2) + pre_sin(2) +  (Ui_s(1)&
     718           0 :                   *(pre_sin(2) -pre_sin(1)) + &
     719           0 :                   V_s(2)*pre_sin(2)**3 - &
     720           0 :                   V_s(1)*pre_sin(1)**3 + (C_s(2)+F_s(2))*pre_sin(2)-&
     721           0 :                   (C_s(1)+F_s(1))*pre_sin(1) )/(bgrid_temp(2)-bgrid_temp(1)) )
     722             :               
     723           0 :             do k = nblyr+1, 3, -1  !nblyr+1
     724           0 :                pre_sinb(k) =p5*(bSin(k) + pre_sin(k) +  (Ui_s(k-1)&
     725           0 :                   *(pre_sin(k) - pre_sin(k-1)) + &
     726           0 :                   V_s(k)*pre_sin(k)**3 - &
     727           0 :                   V_s(k-1)*pre_sin(k-1)**3 + (C_s(k)+F_s(k))*pre_sin(k)-&
     728           0 :                   (C_s(k-1)+F_s(k-1))*pre_sin(k-1))/(bgrid_temp(k)-bgrid_temp(k-1)) )
     729             : 
     730           0 :                Q_s(k) = V_s(k)*pre_sin(k)**2 + U_s(k) + C_s(k) + F_s(k) 
     731             :             enddo   !k
     732             : 
     733           0 :             Q_s(2) = V_s(2)*pre_sin(2)**2 + U_s(2) + C_s(2) + F_s(2)
     734           0 :             Q_s(1) = V_s(1)*pre_sin(2)**2 + Ui_s(1) + C_s(1)+ F_s(1)
     735           0 :             Q_s(nblyr+2) = V_s(nblyr+2)*pre_sin(nblyr+1)**2 + & 
     736           0 :             Ui_s(nblyr+1) + C_s(nblyr+2) +  F_s(nblyr+2)
     737             : 
     738             :       !-----------------------------------------------------------------
     739             :       ! Add artificial viscosity   [Lapidus,1967] [Lohner et al, 1985]
     740             :       ! * more for melting ice
     741             :       !-----------------------------------------------------------------
     742             : 
     743           0 :             lapidus_diff(:) = c0
     744           0 :             flux_corr(:) = c0
     745           0 :             Ssum_new = c0
     746           0 :             Ssum_corr = c0
     747           0 :             fluxcorr = c0
     748           0 :             fluxg = c0
     749           0 :             fluxb = c0
     750           0 :             fluxm = c0
     751             : 
     752           0 :             do k = 2, nblyr+1  
     753             : 
     754           0 :                lapidus_diff(k-1) =    lapidus/& ! lapidus/real(nblyr,kind=dbl_kind)**2/&
     755           0 :                   (igrid(k)-igrid(k-1))* &
     756           0 :                   ( lapA(k-1)*ABS(Q_s(k+1)-Q_s(k))*(abs(pre_sinb(k+1))-abs(pre_sinb(k)))/&
     757           0 :                   (bgrid_temp(k+1)-bgrid_temp(k) )**2 - &
     758           0 :                   lapB(k-1)*ABS(Q_s(k)-Q_s(k-1))*(abs(pre_sinb(k))-abs(pre_sinb(k-1)))/&
     759           0 :                   (bgrid_temp(k)-bgrid_temp(k-1))**2)
     760             :                           
     761           0 :                bSin(k) = pre_sinb(k) + lapidus_diff(k-1)
     762             : 
     763           0 :                if (bSin(k) < min_salin) then
     764           0 :                   flux_corr(k-1) = min_salin - bSin(k) !  flux into the ice
     765           0 :                   bSin(k) = min_salin 
     766           0 :                elseif (bSin(k) > -bTin(k)/depressT) then
     767           0 :                   flux_corr(k-1) = bSin(k)+bTin(k)/depressT !  flux into the ice
     768           0 :                   bSin(k) = -bTin(k)/depressT
     769           0 :                elseif (bSin(k) > max_salin) then
     770           0 :                   call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
     771           0 :                   call icepack_warnings_add(subname//' bSin(k) > max_salin')
     772             :                endif
     773             :             
     774           0 :                if (k == nblyr+1) bSin(nblyr+2) = S_bot(1)*bSin(nblyr+1) &
     775           0 :                                                   + S_bot(2)*bSin(nblyr+2) 
     776             : 
     777           0 :                Ssum_new = Ssum_new + bSin(k)*(igrid(k)-igrid(k-1))
     778           0 :                fluxcorr = fluxcorr + (flux_corr(k-1) &
     779           0 :                         + lapidus_diff(k-1))*(igrid(k)-igrid(k-1))
     780             : 
     781             :             enddo   !k
     782             : 
     783           0 :             Ssum_tmp = Ssum_old
     784             : 
     785             :             call calc_salt_fluxes (nint, nblyr, &
     786             :                  Ui_s,   dh,dbgrid,hbri_old,Sintemp,    &
     787             :                  pre_sin,   fluxb,fluxg,fluxm,V_s,    &
     788             :                  C_s,   F_s,   Ssum_corr,fzsaln_g,fzsaln, &
     789           0 :                  Ssum_tmp,dts, Ssum_new)
     790           0 :             if (icepack_warnings_aborted(subname)) return
     791             : 
     792           0 :             if (test_conservation) then
     793             :                call check_conserve_salt(nint, m, dt, &
     794             :                                 Ssum_tmp, Ssum_new, Ssum_corr,&
     795             :                                 fluxcorr, fluxb, fluxg, fluxm, &
     796           0 :                                 hbrin, hbri_old)
     797           0 :                call icepack_warnings_add(subname//' check_conserve_salt fails')
     798           0 :                if (icepack_warnings_aborted(subname)) return
     799             :             endif  ! test_conservation
     800             : 
     801             :          enddo !m
     802             : 
     803             :       else    !  add/melt ice only 
     804             : 
     805           0 :          sum_old = c0
     806           0 :          sum_new = c0
     807           0 :          dh_dt = hbrin-hbri_old
     808           0 :          dS_dt = c0
     809           0 :          if (dh_dt > c0) then 
     810           0 :             dS_dt = sss*dh_dt*salt_loss
     811           0 :             do k = 2, nblyr+1 
     812           0 :                bSin(k) = max(min_salin,(bSin(k)*hbri_old + dS_dt)/hbrin)
     813             :             enddo  !k
     814             :          else
     815           0 :             do k = 2, nblyr+1 
     816           0 :                sum_old = sum_old + bSin(k)*hbri_old*(igrid(k)-igrid(k-1))
     817           0 :                bSin(k) = max(min_salin,bSin(k) * (c1-abs(dh_dt)/hbri_old))
     818           0 :                sum_new = sum_new + bSin(k)*hbrin*(igrid(k)-igrid(k-1))
     819             :             enddo  !k
     820             :          endif
     821           0 :          fzsaln = rhosi*(sum_old-sum_new + dS_dt)*p001/dt   !kg/m^2/s
     822           0 :          fzsaln_g = c0
     823             : 
     824             :       endif  ! (hbri_old > thinS .AND. hbrin > thinS &
     825             :              ! .and.  hice_old > thinS .AND. .NOT. first_ice) 
     826             : 
     827             :       !-----------------------------------------------------------------
     828             :       ! Move this to bgc calculation if using tr_salinity
     829             :       ! Calculate bphin, iphin, ikin, iDin and iDin_N 
     830             :       !-----------------------------------------------------------------
     831             : 
     832           0 :       iDin(:) = c0
     833           0 :       iphin(:)  = c1
     834           0 :       ikin(:) = c0    
     835             : 
     836           0 :       do k = 1, nblyr+1
     837           0 :          if (k < nblyr+1) bphin(k+1) = min(c1,max(puny, &
     838           0 :                           bSin(k+1)*rhosi/(brine_sal(k+1)*brine_rho(k+1)))) 
     839           0 :          if (k == 1) then     
     840           0 :             bphin(k) = min(c1,max(puny, bSin(k)*rhosi/(brine_sal(k)*brine_rho(k))))  
     841           0 :             iphin(k) = bphin(2)
     842           0 :          elseif (k == nblyr+1) then
     843           0 :             iphin(nblyr+1) = bphin(nblyr+1)
     844             :          else
     845           0 :             iphin(k) = min(c1, max(c0,(bphin(k+1) - bphin(k))/(bgrid(k+1) &
     846           0 :                            - bgrid(k))*(igrid(k)-bgrid(k)) + bphin(k)))
     847             :          endif 
     848           0 :          ikin(k) = k_o*iphin(k)**exp_h 
     849             :       enddo    !k
     850             : 
     851           0 :       if (cflag) then
     852             :                
     853           0 :          do k = 2, nblyr+1
     854           0 :             iDin(k) =  iphin(k)*Dm/hbri_old**2  
     855           0 :             if (Rayleigh .AND. hbrin .GE. Ra_c) &
     856           0 :             iDin(k) = iDin(k) + l_sk*ikin(k)*gravit/viscos_dynamic &
     857           0 :                          * drho(k)/hbri_old**2 
     858             :          enddo       !k
     859             :       else   !  .not. cflag
     860           0 :          do k = 2, nblyr+1
     861           0 :             iDin(k) = iphin(k)*Dm/hbri_old**2
     862             :          enddo       !k
     863             :       endif
     864             : 
     865             :       end subroutine solve_S_dt
     866             : 
     867             : !=======================================================================
     868             : !
     869             : ! Calculate salt fluxes
     870             : ! 
     871           0 :       subroutine calc_salt_fluxes (mint, nblyr, &
     872           0 :                                    Ui_s,dh,dbgrid,hbri_old,Sintemp,pre_sin,&
     873           0 :                                    fluxb,fluxg,fluxm,V_s,&
     874           0 :                                    C_s,F_s,Ssum_corr,fzsaln_g,fzsaln,Ssum_old, &
     875             : !                                  fluxcorr,dts, Ssum_new)
     876             :                                    dts, Ssum_new)
     877             : 
     878             :       integer(kind=int_kind), intent(in) :: &
     879             :          nblyr,          & ! number of bio layers
     880             :          mint              ! current iteration
     881             : 
     882             :       real (kind=dbl_kind), intent(in) :: &
     883             :          dts      , & !  halodynamic timesteps (s)
     884             :         ! hbrin    , & ! new brine height after all iterations (m)
     885             :          dh       , &  ! (m) change in hbrine over dts
     886             :          dbgrid   , & ! ratio of grid space to spacing across boundary 
     887             :                       ! ie. 1/nilyr/(dbgrid(2)-dbgrid(1))
     888             : !        fluxcorr , & ! flux correction to ensure S >= min_salin
     889             :          hbri_old     ! initial brine height (m)
     890             : 
     891             :       real (kind=dbl_kind), dimension (nblyr+1), intent(in) :: & 
     892             :          Ui_s         ! interface function
     893             : 
     894             :       real (kind=dbl_kind), dimension (nblyr+2), intent(in) :: &
     895             :          Sintemp  , & ! initial salinity
     896             :          pre_sin  , & ! estimate of salinity of layers
     897             :          C_s      , & ! Functions in continuity equation
     898             :          F_s      , &
     899             :          V_s
     900             : 
     901             :       real (kind=dbl_kind), intent(in) :: &
     902             :          Ssum_old , & ! initial integrated salt content (ppt)/h  
     903             :          Ssum_new     ! next integrated salt content(ppt)/h
     904             : 
     905             :       real (kind=dbl_kind), intent(inout) :: &
     906             :          fzsaln   , & ! total salt flux  out of ice over timestep(kg/m^2/s)
     907             :          fzsaln_g , & ! gravity drainage flux of salt  over timestep(kg/m^2/s)
     908             :          Ssum_corr, & ! boundary flux correction due to numerics
     909             :          fluxb    , & ! total boundary salt flux into the ice (+ into ice)
     910             :          fluxg    , & ! total gravity drainage salt flux into the ice (+ into ice)
     911             :          fluxm        ! total molecular diffusive salt flux into the ice (+ into ice)
     912             : 
     913             :       ! local variables
     914             : 
     915             :       real (kind=dbl_kind) :: &
     916           0 :          Ssum_corr_flux  , & ! numerical boundary flux correction
     917           0 :          fluxb_b, fluxb_t, & ! bottom, top and total boundary flux (g/kg/m^2)
     918           0 :          fluxg_b, fluxg_t, & ! bottom, top and total gravity drainage flux (g/kg/m^2)
     919           0 :          fluxm_b, fluxm_t    ! bottom, top and total molecular diffusion flux (g/kg/m^2)
     920             : 
     921           0 :       real (kind=dbl_kind) :: hin_old, hin_next, dhtmp !, dh
     922             : 
     923             :       character(len=*),parameter :: subname='(calc_salt_fluxes)'
     924             : 
     925           0 :       dhtmp = c1-dh/hbri_old
     926           0 :       hin_next = hbri_old +  real(mint,kind=dbl_kind)*dh
     927           0 :       hin_old  = hbri_old + (real(mint,kind=dbl_kind)-c1)*dh
     928             : 
     929             :       !-----------------------------------------------------------------
     930             :       ! boundary fluxes (positive into the ice)
     931             :       !---------------------------------------------
     932             :       !  without higher order numerics corrections 
     933             :       ! fluxb = (Ui_s(nblyr+1) + F_s(nblyr+2))*Sintemp(nblyr+2)  - (Ui_s(1) + F_s(1))*Sintemp(1)
     934             :       !-----------------------------------------------------------------
     935             : 
     936           0 :       fluxb_b = p5* Ui_s(nblyr+1) * (dhtmp*Sintemp(nblyr+2)*dbgrid &
     937           0 :                                   +        pre_sin(nblyr+1) &
     938           0 :                                   +  dhtmp*Sintemp(nblyr+1)*(c1-dbgrid)) &
     939           0 :               + p5*(F_s(nblyr+2)  *  dhtmp*Sintemp(nblyr+2)*dbgrid &
     940           0 :                   + F_s(nblyr+1)  *       (pre_sin(nblyr+1) &
     941           0 :                                   +  dhtmp*Sintemp(nblyr+1)*(c1-dbgrid)))
     942             : 
     943           0 :       fluxb_t = -p5*Ui_s(1)*(pre_sin(1)*dbgrid +  &
     944           0 :                               dhtmp*Sintemp(2) -  &
     945           0 :                               (dbgrid-c1)*pre_sin(2)) - &
     946           0 :                               p5*(dbgrid*F_s(1)*pre_sin(1) + &
     947           0 :                               F_s(2)*(dhtmp*Sintemp(2) &
     948           0 :                               +(c1-dbgrid)*pre_sin(2)))
     949             : 
     950           0 :       fluxb = fluxb_b + fluxb_t 
     951             : 
     952             :       !-----------------------------------------------------------------
     953             :       ! gravity drainage fluxes (positive into the ice)
     954             :       ! without higher order numerics corrections 
     955             :       ! fluxg =  V_s(nblyr+2)*Sintemp(nblyr+1)**3
     956             :       !-----------------------------------------------------------------
     957             : 
     958             :       fluxg_b =  p5*(dhtmp* dbgrid* &
     959           0 :                                V_s(nblyr+2)*Sintemp(nblyr+1)**3  +  &
     960           0 :                                V_s(nblyr+1)*(pre_sin(nblyr+1)**3 - &
     961             :                                dhtmp*(dbgrid - c1)* &
     962           0 :                                Sintemp(nblyr+1)**3))
     963             :                 
     964           0 :       fluxg_t =  -p5*(dbgrid*V_s(1)*pre_sin(1)**3 + &
     965           0 :                                V_s(2)*(dhtmp*Sintemp(2)**3- &
     966           0 :                                (dbgrid-c1)*pre_sin(2)**3))
     967             :                 
     968           0 :       fluxg =  fluxg_b + fluxg_t
     969             :       
     970             :       !-----------------------------------------------------------------
     971             :       ! diffusion fluxes (positive into the ice)
     972             :       ! without higher order numerics corrections 
     973             :       ! fluxm = C_s(nblyr+2)*Sintemp(nblyr+2)
     974             :       !-----------------------------------------------------------------
     975             : 
     976           0 :       fluxm_b = p5*(dhtmp*C_s(nblyr+2)* Sintemp(nblyr+2)*dbgrid &
     977           0 :                        +  C_s(nblyr+1)*(pre_sin(nblyr+1) &
     978           0 :                   + dhtmp * Sintemp(nblyr+1)*(c1-dbgrid)))
     979             : 
     980           0 :       fluxm_t = -p5 * (C_s(1) *  pre_sin(1)*dbgrid &
     981           0 :               +        C_s(2) * (pre_sin(2)*(c1-dbgrid) + dhtmp*Sintemp(2)))
     982             :            
     983           0 :       fluxm =  fluxm_b + fluxm_t
     984             :               
     985           0 :       Ssum_corr      = (-dh/hbri_old + p5*(dh/hbri_old)**2)*Ssum_old 
     986           0 :       Ssum_corr_flux = dh*Ssum_old/hin_next + Ssum_corr
     987           0 :       Ssum_corr      = Ssum_corr_flux
     988             :           
     989             :       fzsaln_g = fzsaln_g - hin_next *  fluxg_b &
     990           0 :                           * rhosi*p001/dts
     991             :        
     992             :       !approximate fluxes
     993             :       !fzsaln   = fzsaln   - hin_next * (fluxg &
     994             :       !                    + fluxb + fluxm + fluxcorr + Ssum_corr_flux) & 
     995             :       !                    * rhosi*p001/dts  
     996             : 
     997             :       fzsaln   = fzsaln + (Ssum_old*hin_old - Ssum_new*hin_next) &
     998           0 :                           * rhosi*p001/dts  ! positive into the ocean
     999             : 
    1000           0 :       end subroutine calc_salt_fluxes
    1001             : 
    1002             : !=======================================================================
    1003             : ! 
    1004             : ! Test salt conservation:   flux conservative form d(hSin)/dt = -dF(x,Sin)/dx 
    1005             : !  
    1006           0 :       subroutine check_conserve_salt (mmax, mint,     dt, &
    1007             :                                       Ssum_old, Ssum_new, Ssum_corr,        & 
    1008             :                                       fluxcorr, fluxb,    fluxg,     fluxm, &
    1009             :                                       hbrin,    hbri_old)
    1010             : 
    1011             :       integer(kind=int_kind), intent(in) :: &
    1012             :          mint      , & ! current iteration
    1013             :          mmax          ! maximum number of iterations
    1014             : 
    1015             :       real (kind=dbl_kind), intent(in) :: &
    1016             :          dt             , &  ! thermodynamic and halodynamic timesteps (s)
    1017             :          hbrin          , &  ! (m) final brine height 
    1018             :          hbri_old       , &  ! (m) initial brine height
    1019             :          Ssum_old       , &  ! initial integrated salt content
    1020             :          Ssum_new       , &  ! final integrated salt content
    1021             :          fluxcorr       , &  ! flux correction to ensure S >= min_salin
    1022             :          Ssum_corr      , &  ! boundary flux correction due to numerics
    1023             :          fluxb          , &  ! total boundary salt flux into the ice (+ into ice)
    1024             :          fluxg          , &  ! total gravity drainage salt flux into the ice (+ into ice)
    1025             :          fluxm               ! 
    1026             : 
    1027             :      ! local variables
    1028             : 
    1029             :      real (kind=dbl_kind):: &
    1030           0 :          diff2     , & !
    1031           0 :          dsum_flux , & ! salt change in kg/m^2/s
    1032           0 :          flux_tot  , & ! fluxg + fluxb
    1033           0 :          order     , & !
    1034           0 :          dh
    1035             : 
    1036             :      real (kind=dbl_kind), parameter :: &
    1037             :          accuracy = 1.0e-7_dbl_kind ! g/kg/m^2/s difference between boundary fluxes 
    1038             : 
    1039             :      character(len=*),parameter :: subname='(check_conserve_salt)'
    1040             : 
    1041           0 :          dh = (hbrin-hbri_old)/real(mmax,kind=dbl_kind)
    1042             : 
    1043             :          flux_tot = (fluxb + fluxg + fluxm + fluxcorr + Ssum_corr)*&
    1044           0 :                     (hbri_old + (real(mint,kind=dbl_kind))*dh)/dt
    1045             :          dsum_flux =(Ssum_new*(hbri_old + (real(mint,kind=dbl_kind))*dh) - &
    1046             :                      Ssum_old*(hbri_old + (real(mint,kind=dbl_kind)-c1)* &
    1047           0 :                      dh) )/dt
    1048           0 :          order = abs(dh/min(hbri_old,hbrin))
    1049           0 :          if (abs(dsum_flux) > accuracy) then
    1050           0 :            diff2 = abs(dsum_flux - flux_tot)
    1051           0 :            if (diff2 >  puny .AND. diff2 > order ) then 
    1052           0 :               call icepack_warnings_setabort(.true.,__FILE__,__LINE__)
    1053           0 :               write(warnstr,*) subname, 'Poor salt conservation: check_conserve_salt'
    1054           0 :               call icepack_warnings_add(warnstr)
    1055           0 :               write(warnstr,*) subname, 'mint:', mint
    1056           0 :               call icepack_warnings_add(warnstr)
    1057           0 :               write(warnstr,*) subname, 'Ssum_corr',Ssum_corr
    1058           0 :               call icepack_warnings_add(warnstr)
    1059           0 :               write(warnstr,*) subname, 'fluxb,fluxg,fluxm,flux_tot,fluxcorr:'
    1060           0 :               call icepack_warnings_add(warnstr)
    1061           0 :               write(warnstr,*) subname,  fluxb,fluxg,fluxm,flux_tot,fluxcorr
    1062           0 :               call icepack_warnings_add(warnstr)
    1063           0 :               write(warnstr,*) subname, 'fluxg,',fluxg
    1064           0 :               call icepack_warnings_add(warnstr)
    1065           0 :               write(warnstr,*) subname, 'dsum_flux,',dsum_flux
    1066           0 :               call icepack_warnings_add(warnstr)
    1067           0 :               write(warnstr,*) subname, 'Ssum_new,Ssum_old,hbri_old,dh:'
    1068           0 :               call icepack_warnings_add(warnstr)
    1069           0 :               write(warnstr,*) subname,  Ssum_new,Ssum_old,hbri_old,dh
    1070           0 :               call icepack_warnings_add(warnstr)
    1071           0 :               write(warnstr,*) subname, 'diff2,order,puny',diff2,order,puny
    1072           0 :               call icepack_warnings_add(warnstr)
    1073             :            endif
    1074             :          endif
    1075             : 
    1076           0 :      end subroutine check_conserve_salt
    1077             : 
    1078             : !=======================================================================
    1079             : !
    1080             : ! Aggregate flux information from all ice thickness categories
    1081             : !
    1082           0 :       subroutine merge_zsal_fluxes(aicenS,               &
    1083             :                                    zsal_totn,  zsal_tot, & 
    1084             :                                    fzsal,      fzsaln,   &
    1085             :                                    fzsal_g,    fzsaln_g)
    1086             : 
    1087             :       ! single category fluxes
    1088             :       real (kind=dbl_kind), intent(in):: &          
    1089             :           aicenS   , & ! concentration of ice
    1090             :           fzsaln  , &  ! salt flux                       (kg/m**2/s)
    1091             :           fzsaln_g     ! gravity drainage salt flux      (kg/m**2/s)
    1092             : 
    1093             :       real (kind=dbl_kind), intent(in):: &
    1094             :           zsal_totn   ! tot salinity in category (psu*volume*rhosi)
    1095             : 
    1096             :       real (kind=dbl_kind), intent(inout):: &          
    1097             :           zsal_tot, & ! tot salinity (psu*rhosi*total vol ice)
    1098             :           fzsal   , & ! salt flux                       (kg/m**2/s)
    1099             :           fzsal_g     ! gravity drainage salt flux      (kg/m**2/s)
    1100             : 
    1101             :       character(len=*),parameter :: subname='(merge_zsal_fluxes)'
    1102             : 
    1103             :       !-----------------------------------------------------------------
    1104             :       ! Merge fluxes
    1105             :       !-----------------------------------------------------------------
    1106             : 
    1107           0 :       zsal_tot  = zsal_tot + zsal_totn  ! already *aicenS
    1108             : 
    1109             :       ! ocean tot and gravity drainage salt fluxes
    1110           0 :       fzsal    = fzsal   + fzsaln   * aicenS
    1111           0 :       fzsal_g  = fzsal_g + fzsaln_g * aicenS
    1112             : 
    1113           0 :       end subroutine merge_zsal_fluxes
    1114             : 
    1115             : !==========================================================================
    1116             : !
    1117             : ! For each grid cell, sum field over all ice layers.  "Net" refers to  the column
    1118             : ! integration while "avg"  is normalized by the ice thickness
    1119             : 
    1120           0 :       subroutine column_sum_zsal (zsal_totn, nblyr,   &
    1121           0 :                                   vicenS, trcrn_S, fbri)
    1122             : 
    1123             :       integer (kind=int_kind), intent(in) :: &
    1124             :          nblyr         ! number of layers
    1125             : 
    1126             :       real (kind=dbl_kind),  intent(in):: &          
    1127             :          vicenS    , & ! volume of ice (m)
    1128             :          fbri          ! brine height to ice thickness ratio
    1129             : 
    1130             :       real (kind=dbl_kind), dimension (nblyr), intent(in) :: &
    1131             :          trcrn_S       ! input field
    1132             : 
    1133             :       real (kind=dbl_kind), intent(inout) :: &
    1134             :          zsal_totn    ! avg salinity (psu*rhosi*vol of ice)
    1135             : 
    1136             :       ! local variables
    1137             : 
    1138             :       integer (kind=int_kind) :: &
    1139             :            k           ! layer index
    1140             : 
    1141             :       character(len=*),parameter :: subname='(column_sum_zsal)'
    1142             : 
    1143           0 :       do k = 1, nblyr
    1144             :          zsal_totn = zsal_totn &
    1145           0 :                    + rhosi * trcrn_S(k) &
    1146             :                            * fbri  &
    1147           0 :                            * vicenS/real(nblyr,kind=dbl_kind)
    1148             :       enddo ! k
    1149             : 
    1150           0 :       end subroutine column_sum_zsal
    1151             : 
    1152             : !=======================================================================
    1153             : 
    1154             :       end module icepack_zsalinity
    1155             : 
    1156             : !=======================================================================

Generated by: LCOV version 1.14-6-g40580cd