Skip to content
Snippets Groups Projects
Select Git revision
  • 184e2b95c665d3a9e1eb9cb23493ae164f57f2ac
  • master default protected
  • debug_summertime_expulsion
3 results

mo_mass.f90

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    mo_mass.f90 8.76 KiB
    !>
    !! Regulates mass transfers and their results.
    !!
    !! Ultimately all processes which involve a mass flux should be stored here.
    !!
    !!
    !! @author Philipp Griewank
    !!
    !!  COPYRIGHT
    !!
    !! This file is part of SAMSIM.
    !!
    !!  SAMSIM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
    !!
    !!  SAMSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    !!
    !!  You should have received a copy of the GNU General Public License along with SAMSIM. If not, see <http://www.gnu.org/licenses/>.
    ! 
    !!
    !!
    !!
    !! @par Revision History
    !! Begin implementing Expulsion by Philipp Griewank, IMPRS (2010-08-24)
    !!
    MODULE mo_mass
    
      USE mo_parameters,       ONLY:wp,rho_l,c_l
      USE mo_thermo_functions, ONLY:func_S_br
      USE mo_functions,        ONLY:func_sat_O2
      IMPLICIT NONE
    
      PUBLIC :: mass_transfer,expulsion_flux,bgc_advection
    
    
    CONTAINS
    
      !>
      !! Calculates the effects of mass transfers on H_abs and S_abs.
      !!
      !! The effects of brine displaced by expulsion, flushing or drainage expansion lead to changes in mass, salt ans enthalpy.
      !! This subroutine calculates the effects on S_abs and H_abs.
      !! A very simple upwind strategy is employed, Brine from below has T and S_br of the lower layer, and brine from above T and S_br of the upper layer.
      !! To avoid negative salinity, the maximum amount of advective salt is the total salt content of the layer.
      !! The amount of mass transfered is calculated in other subroutines.
      !! 
      !! This subroutine was started as a quick and dirty way to simulate the bottom freezing experiment described in Notz 2005 p. 85
      !! IMPORTANT: Before this subroutine expelled brine was removed from the system and its effects were determined in subroutine expulsion.
      !! S_bu must be up to date!
      !!
      !! @par Revision History
      !! Brought to life by Philipp Griewank, IMPRS (2010-08-24) \n
      !! Modified to work with all processes by Philipp Griewank, IMPRS (2010-11-27)
      SUBROUTINE mass_transfer (Nlayer,N_active,T,H_abs,S_abs,S_bu,T_bottom,S_bu_bottom,fl_m)
    
        IMPLICIT NONE
    
        INTEGER,                       INTENT(in)    :: Nlayer, N_active
        REAL(wp),                      INTENT(in)    :: T_bottom,S_bu_bottom
        REAL(wp), DIMENSION(Nlayer),   INTENT(in)    :: T,S_bu
        REAL(wp), DIMENSION(Nlayer),   INTENT(inout) :: H_abs,S_abs
        REAL(wp), DIMENSION(Nlayer+1), INTENT(in)    :: fl_m
        REAL(wp), DIMENSION(Nlayer+1)                :: TT,SS_bu,SS_abs !Same as T and S_bu but expanded to include bottom values
        INTEGER                                      :: k
    
    
        TT(1:N_active)      =  T(1:N_active)
        SS_bu(1:N_active)   =  S_bu(1:N_active)
        SS_abs(1:N_active)  =  S_abs(1:N_active)
    
        TT(N_active+1)      =  T_bottom
        SS_bu(N_active+1)   =  S_bu_bottom
        SS_abs(N_active+1)  =  S_bu_bottom*2000._wp
    
    
    
        DO k = 1,N_active
    
           IF (fl_m(k+1)>0.) THEN
              H_abs(k) =  H_abs(k) +fl_m(k+1)*TT(k+1)*c_l
              S_abs(k) =  S_abs(k) +MIN(fl_m(k+1)*func_S_br(TT(k+1),SS_bu(k+1)), SS_abs(k+1))
           ELSE IF (fl_m(k+1)<0.) THEN
              H_abs(k) =  H_abs(k) +fl_m(k+1)*TT(k)*c_l
              S_abs(k) =  S_abs(k) +MAX(fl_m(k+1)*func_S_br(TT(k),SS_bu(k)), -S_abs(k))
           END IF
    
           IF (fl_m(k)>0.) THEN
              H_abs(k) =  H_abs(k) -fl_m(k)*TT(k)*c_l
              S_abs(k) =  S_abs(k) -MIN(fl_m(k)*func_S_br(TT(k),SS_bu(k)), S_abs(k))
           END IF
        END DO
    
        DO k = 2, N_active
    
           IF (fl_m(k)<0) THEN
              H_abs(k) =  H_abs(k) -fl_m(k)*TT(k-1)*c_l
              S_abs(k) =  S_abs(k) -MAX(fl_m(k)*func_S_br( TT(k-1),SS_bu(k-1)), -S_abs(k-1))
           END IF
        END DO
      END SUBROUTINE mass_transfer
    
    
    
      !>
      !! Generates the fluxes caused by expulsion.
      !!
      !! Brine displaced by expansion of a freezing mushy layer lead to a mass, enthalpy and salt flux.
      !! This subroutine calculates the amount of brine which moves between the layers caused by V_ex and how the mass in the layers changes.
      !! Vary basic assumptions are made. Brine always moves downward (negative), no horizontal movement are allowed and gas pockets can be filled.
      !! The upper boundary layer is not permeable but the bottom one is.
      !! This subroutine was started as a quick and dirty way to simulate the bottom freezing experiment described in Notz 2005 p. 85
      !!
      !! @par Revision History
      !! Brought to life by Philipp Griewank, IMPRS (2010-08-24) \n
      !! Simplified by Philipp Griewank, IMPRS (2010-11-27)
      !! edited by Niels Fuchs, UHH (2024-05-03), added brine mass removal from H_abs
      SUBROUTINE expulsion_flux (thick,V_ex,Nlayer,N_active,psi_g,fl_m,m, H_abs)
    
        INTEGER,                        INTENT(in)    :: Nlayer, N_active
        REAL(wp), DIMENSION(Nlayer),    INTENT(in)    :: V_ex,thick
        REAL(wp), DIMENSION(Nlayer),    INTENT(inout) :: psi_g,m, H_abs
        REAL(wp), DIMENSION(Nlayer+1),  INTENT(out)   :: fl_m
    
        INTEGER::k
    
        H = H_abs(:)/m(:)
        fl_m(1:Nlayer+1)  =  0._wp
        fl_m(2)           = -V_ex(1)*rho_l
        DO k = 2,N_active
           IF (psi_g(k)<0.001) THEN
              fl_m(k+1)   = -V_ex(k)*rho_l+fl_m(k)
           ELSE
              fl_m(k+1)   = -MAX((V_ex(k)-psi_g(k)*thick(k))*rho_l    ,0.0_wp)
              psi_g(k)    =  MAX((psi_g(k)*thick(k)-V_ex(k))/thick(k) ,0.0_wp)
           END IF
        END DO
    
        DO k = 1,N_active
           m(k) =  m(k) +fl_m(k+1)-fl_m(k)
           H_abs(k) = H_abs(k) + (fl_m(k+1)-fl_m(k))*H(k) ! exp. brine mass must be removed from H_abs, temperature loss is calculated in mass transfer subs.
        END DO
    
      END SUBROUTINE expulsion_flux
    
      !>
      !! Calculates how the brine fluxes stored in fl_brine_bgc advect bgc tracers
      !!
      !! A very simple upwind strategy is employed.
      !! To avoid negative tracer densities, the maximum amount of advection is restricted to the current tracer content in a layer divided by three.
      !! Three is chosen as a limit as currently each layer can have a maximum of three flows leaving the layer (to the layer above, the layer below, and the lowest layer).
      !! The advection scheme is likely overly diffusive, but given the limitations we are working with (e.g. changing brine volumes) nothing more sophisticated can be applied easily.
      !! 
      !! For gases it might make sense to limit the brine density to saturation value in advecting brine, to take bubble formation into account. This needs to be specified in bgc_advection, and is a first attempt (both scientifically and code wise) which should be used with caution!
      !!
      !! @par Revision History
      !! Brought to life by Philipp Griewank, IMPRS (2014-02-10)
      SUBROUTINE bgc_advection (Nlayer,N_active,N_bgc,fl_brine_bgc,bgc_abs,psi_l,thick,bgc_bottom)
    
        IMPLICIT NONE
    
        INTEGER,                                INTENT(in)    :: Nlayer,N_active,N_bgc
        REAL(wp), DIMENSION(Nlayer),            INTENT(in)    :: psi_l,thick
        REAL(wp), DIMENSION(N_bgc),             INTENT(in)    :: bgc_bottom
        REAL(wp), DIMENSION(Nlayer+1,Nlayer+1), INTENT(in)    :: fl_brine_bgc
        REAL(wp), DIMENSION(Nlayer,N_bgc),      INTENT(inout) :: bgc_abs
        REAL(wp), DIMENSION(Nlayer,N_bgc)                     :: bgc_temp
        REAL(wp), DIMENSION(Nlayer,N_bgc)                     :: bgc_br
        REAL(wp), DIMENSION(N_bgc)                            :: flux
        INTEGER                                      ::k,i,j
    
        bgc_temp = bgc_abs
    
        !Calculating brine concentration of advecting brine, saturation limitations must be included manually!
        DO k = 1,N_active
           bgc_br(k,:)  =  bgc_abs(k,:)/(MAX(psi_l(k)*thick(k)*rho_l,0.000000000000001_wp))
           
           !How to limit the first tracer to the oxygen saturation limit
           !sat_O2 = func_sat_O2(T(k),S_abs(k)/m(k))
           !bgc_br(k,1) = MIN(bgc_br(k,1),1.25*sat_O2)
        END DO
    
        !Internal flows
        DO i = 1,N_active
           DO j = 1,N_active
              DO k = 1,N_bgc
                 IF (fl_brine_bgc(i,j)*bgc_br(i,k) > bgc_abs(i,k)/3._wp) THEN
                 END IF
                 flux(k)      = MIN(fl_brine_bgc(i,j)*bgc_br(i,k),bgc_abs(i,k)/3._wp)
              END DO
              bgc_temp(i,:) = bgc_temp(i,:) - flux(:)
              bgc_temp(j,:) = bgc_temp(j,:) + flux(:)
    
           END DO
        END DO
    
        !Flows which leave the domain
        DO i = 1,N_active
           j = N_active+1
           DO k = 1,N_bgc
              flux(k)      = MIN(fl_brine_bgc(i,j)*bgc_br(i,k),bgc_abs(i,k)/3._wp)
           END DO
           bgc_temp(i,:) = bgc_temp(i,:) - flux(:)
        END DO
    
        !Flows which enter the domain
        i = N_active+1
        DO j = 1,N_active
           DO k = 1,N_bgc
              flux(k)      = fl_brine_bgc(i,j)*bgc_bottom(k)
           END DO
           bgc_temp(j,:) = bgc_temp(j,:) + flux(:)
        END DO
    
        bgc_abs = bgc_temp 
      END SUBROUTINE bgc_advection
    
    
    
    END MODULE mo_mass