#include "rundeck_opts.h"
C23456789012345678901234567890123456789012345678901234567890123456789012
MODULE LAKES 8,5
!@sum LAKES subroutines for Lakes and Rivers
!@auth Gavin Schmidt/Gary Russell
!@ver 1.0 (based on LB265)
USE CONSTANT
, only : grav,bygrav,shw,rhow,lhm,shi,teeny
USE MODEL_COM
, only : im,jm
USE DOMAIN_DECOMP
, only : HALO_UPDATE, GRID,NORTH,SOUTH
USE DOMAIN_DECOMP
, only : WRITE_PARALLEL
#ifdef TRACERS_WATER
USE TRACER_COM
, only : trname,ntm
#endif
IMPLICIT NONE
SAVE
C****
C**** Changes from Model III: MO -> MWL (kg), G0M -> GML (J),
C**** GZM -> TLAKE (deg C)
!@var KDIREC directions for river flow
C**** (0 no flow, 1-8 anti-clockwise from top RH corner
INTEGER, ALLOCATABLE, DIMENSION(:,:) :: KDIREC
!@var RATE rate of river flow downslope (fraction)
!@var DHORZ horizontal distance to downstream box (m)
REAL*8, ALLOCATABLE, DIMENSION(:,:) :: RATE,DHORZ
!@var IFLOW,JFLOW grid box indexes for downstream direction
INTEGER, ALLOCATABLE, DIMENSION (:,:) :: IFLOW,JFLOW
!@param NRVRMX Max No. of specified rivers
INTEGER, PARAMETER :: NRVRMX = 42
!@var NRVR actual No. of specified rivers
INTEGER :: NRVR
!@var IRVRMTH,JRVRMTH indexes for specified river mouths
INTEGER, DIMENSION(NRVRMX) :: IRVRMTH,JRVRMTH
!@var NAMERVR Names of specified rivers
CHARACTER*8, DIMENSION(NRVRMX) :: NAMERVR
!@param MINMLD minimum mixed layer depth in lake (m)
REAL*8, PARAMETER :: MINMLD = 1.
!@param TMAXRHO temperature of maximum density (pure water) (C)
REAL*8, PARAMETER :: TMAXRHO = 4.
!@param KVLAKE lake diffusion constant at mixed layer depth (m^2/s)
REAL*8, PARAMETER :: KVLAKE = 1d-5
!@param TFL freezing temperature for lakes (=0 C)
REAL*8, PARAMETER :: TFL = 0.
!@param AC1LMIN, AC2LMIN minimum ice thickness for lake ice (kg/m^2)
REAL*8, PARAMETER :: AC1LMIN = 0.1, AC2LMIN=0.1 ! (not used)
!@param FLEADLK lead fraction for lakes
REAL*8, PARAMETER :: FLEADLK = 0.
!@param BYZETA reciprocal of solar rad. extinction depth for lake (1/m)
REAL*8, PARAMETER :: BYZETA = 1./0.35d0
!@dbparam river_fac Factor to multiply runoff by to balance sea level
REAL*8 :: river_fac=1. ! default = 1
!@dbparam init_flake used to make sure FLAKE is properly initialised
!@+ when using older restart files
INTEGER :: init_flake=1 ! default = 1
!@dbparam variable_lk 1 if lakes are to be variable
!@+ (temporary variable for development purposes)
INTEGER :: variable_lk=0 ! default = 0
CONTAINS
SUBROUTINE LKSOURC (I0,J0,ROICE,MLAKE,ELAKE,RUN0,FODT,FIDT,SROX 1,3
* ,FSR2,
#ifdef TRACERS_WATER
* TRLAKEL,TRUN0,TREVAP,TRO,TRI,
#endif
* EVAPO,ENRGFO,ACEFO,ACEFI,ENRGFI)
!@sum LKSOURC applies fluxes to lake in ice-covered and ice-free areas
!@auth Gary Russell/Gavin Schmidt
!@ver 1.0
USE MODEL_COM
, only : qcheck
IMPLICIT NONE
!@var MLAKE,ELAKE mass and energy in lake layers (kg,J /m^2)
REAL*8, INTENT(INOUT), DIMENSION(2) :: MLAKE,ELAKE
INTEGER, INTENT(IN) :: I0,J0
REAL*8, INTENT(IN) :: ROICE, EVAPO, RUN0
REAL*8, INTENT(IN) :: FODT, FIDT, SROX(2)
REAL*8, INTENT(OUT) :: ENRGFO, ACEFO, ENRGFI, ACEFI
#ifdef TRACERS_WATER
REAL*8, INTENT(INOUT), DIMENSION(NTM,2) :: TRLAKEL
REAL*8, INTENT(IN), DIMENSION(NTM) :: TRUN0,TREVAP
REAL*8, INTENT(OUT), DIMENSION(NTM) :: TRO,TRI
REAL*8, DIMENSION(NTM) :: DTR2,TRUNO,TRUNI,TRF1,TRF2,FRAC
#ifdef TRACERS_SPECIAL_O18
REAL*8 fracls
INTEGER N
#endif
#endif
!@var emin min energy deficit required before ice forms (J/m^2)
REAL*8, PARAMETER :: emin=-1d-10
REAL*8 ENRGF1, ACEF1, ENRGF2, ACEF2, FHO, FHI, FH0, FH1, FH2, FSR2
REAL*8 ENRGI, ENRGI2, ENRGO, ENRGO2, RUNO, RUNI, TLK2, DM2, DH2
REAL*8 FRATO,FRATI,E2O,E2I
!@var out_line local variable to hold mixed-type output for parallel I/O
character(len=300) :: out_line
C**** initiallize output
ENRGFO=0. ; ACEFO=0. ; ACEFI=0. ; ENRGFI=0.
C**** Calculate heat and mass fluxes to lake
ENRGO = FODT-SROX(1)*FSR2 ! in open water
ENRGO2= +SROX(1)*FSR2 ! in open water, second layer
ENRGI = FIDT-SROX(2)*FSR2 ! under ice
ENRGI2= +SROX(2)*FSR2 ! under ice, second layer
RUNO =-EVAPO
RUNI = RUN0
#ifdef TRACERS_WATER
TRUNO(:)=-TREVAP(:)
TRUNI(:)= TRUN0(:)
FRAC(:)=1.
#ifdef TRACERS_SPECIAL_O18
do n=1,ntm
FRAC(n)=fracls
(n) ! fractionation when freezing
end do
#endif
#endif
C**** Bring up mass from second layer if required/allowed
IF (MLAKE(1)+RUNO.lt.MINMLD*RHOW.and.MLAKE(2).gt.0) THEN
DM2 = MIN(MLAKE(2),MINMLD*RHOW-(MLAKE(1)+RUNO))
DH2 = DM2*(ELAKE(2)+(1.-ROICE)*ENRGO2+ROICE*ENRGI2)/MLAKE(2)
#ifdef TRACERS_WATER
DTR2(:) = DM2*TRLAKEL(:,2)/MLAKE(2)
#endif
ELSE
DM2 = 0.
DH2 = 0.
#ifdef TRACERS_WATER
DTR2(:) = 0.
#endif
END IF
C**** Apply fluxes to 2nd layer
IF (DM2.lt.MLAKE(2)) THEN
MLAKE(2)=MLAKE(2) - DM2
ELAKE(2)=ELAKE(2) - DH2 + (1.-ROICE)*ENRGO2 + ROICE*ENRGI2
#ifdef TRACERS_WATER
TRLAKEL(:,2)=TRLAKEL(:,2) - DTR2(:)
#endif
ELSE
MLAKE(2)=0.
ELAKE(2)=0.
#ifdef TRACERS_WATER
TRLAKEL(:,2)=0.
#endif
END IF
E2O = 0. ; E2I = 0.
C**** Calculate energy in mixed layer (open ocean)
IF (ROICE.LT.1d0) THEN
FHO=ELAKE(1)+ENRGO+DH2-(MLAKE(1)+DM2+RUNO)*TFL*SHW
IF (FHO.LT.emin) THEN ! FLUXES COOL WATER TO FREEZING, FORM ICE
ACEFO =FHO/(TFL*(SHI-SHW)-LHM)
ACEFO =MIN(ACEFO,MAX(MLAKE(1)+DM2+RUNO-MINMLD*RHOW,0d0))
ENRGFO=ACEFO*(TFL*SHI-LHM)
E2O=FHO-ENRGFO
END IF
END IF
IF (ROICE.GT.0) THEN
C**** Calculate energy in mixed layer (under ice)
FHI=ELAKE(1)+DH2+ENRGI-(MLAKE(1)+DM2+RUNI)*TFL*SHW
IF (FHI.LT.emin) THEN ! FLUXES COOL WATER TO FREEZING, FORM ICE
ACEFI =FHI/(TFL*(SHI-SHW)-LHM)
ACEFI =MIN(ACEFI,MAX(MLAKE(1)+DM2+RUNI-MINMLD*RHOW,0d0))
ENRGFI=ACEFI*(TFL*SHI-LHM)
E2I=FHI-ENRGFI
END IF
END IF
#ifdef TRACERS_WATER
TRO(:)=ACEFO*FRAC(:)*TRLAKEL(:,1)/MLAKE(1)
TRI(:)=ACEFI*FRAC(:)*TRLAKEL(:,1)/MLAKE(1)
#endif
C**** Update first layer variables
MLAKE(1)=MLAKE(1)+DM2+(1.-ROICE)*(RUNO -ACEFO)+ROICE*(RUNI-ACEFI)
ELAKE(1)=ELAKE(1)+DH2+(1.-ROICE)*(ENRGO-ENRGFO)+
* ROICE*(ENRGI-ENRGFI)
#ifdef TRACERS_WATER
TRLAKEL(:,1)=TRLAKEL(:,1)+DTR2(:)+(1.-ROICE)*(TRUNO(:)-TRO(:))+
* ROICE*(TRUNI(:)-TRI(:))
#endif
ACEF1=0. ; ACEF2=0. ; ENRGF1=0. ; ENRGF2=0.
C**** Take remaining energy and start to freeze second layer
FH2= ELAKE(1)-MLAKE(1)*TFL*SHW
IF (FH2.LT.emin) THEN
IF (MLAKE(2).gt.0) THEN
C**** FH2=-ACEF2*(TLK2-TFL)*SHW+ACEF2*LHM
TLK2 =ELAKE(2)/(MLAKE(2)*SHW)
ACEF2 =-FH2/(TLK2*SHW-TFL*SHI+LHM)
ACEF2 =MIN(ACEF2,MLAKE(2))
ENRGF2 =ACEF2*(TFL*SHI-LHM)
ELAKE(1)=ELAKE(1)+ACEF2*TLK2*SHW-ENRGF2
ELAKE(2)=ELAKE(2)-ACEF2*TLK2*SHW
MLAKE(2)=MLAKE(2)-ACEF2
END IF
FH1= ELAKE(1)-MLAKE(1)*TFL*SHW
IF (FH1.lt.emin) THEN ! all layer 2 froze, freeze layer 1
ACEF1 =FH1/(TFL*(SHI-SHW)-LHM)
C**** limit freezing if lake is between 50 and 20cm depth
IF (MLAKE(1).lt.0.5d0*RHOW) THEN
ACEF1=MIN(ACEF1,MAX(0.5*(MLAKE(1)-0.2d0*RHOW),0d0))
if (qcheck) print*,"Lake freezing limited",ACEF1/RHOW
* ,MLAKE(1)/RHOW
END IF
ENRGF1 =ACEF1*(TFL*SHI-LHM)
ELAKE(1)=ELAKE(1)-ENRGF1
MLAKE(1)=MLAKE(1)-ACEF1
FH0 =ELAKE(1)-MLAKE(1)*TFL*SHW
IF (FH0.lt.-1d-8) THEN ! max. amount of lake frozen, cool ice
if (qcheck) then
WRITE(out_line,*)
* "Minimum lake level reached: rsi,mlake,elake",i0,j0
* ,roice,mlake(1)/rhow,elake(1)
CALL WRITE_PARALLEL
(trim(out_line), UNIT=6)
endif
ENRGF1 =ENRGF1+FH0
ELAKE(1)=MLAKE(1)*TFL*SHW
END IF
END IF
END IF
#ifdef TRACERS_WATER
TRF1(:) = ACEF1*FRAC(:)*TRLAKEL(:,1)/(MLAKE(1)+ACEF1)
TRLAKEL(:,1)=TRLAKEL(:,1)-TRF1(:)
IF (MLAKE(2).gt.0) THEN
TRF2(:) = MIN(ACEF2*FRAC(:)/(MLAKE(2)+ACEF2),1d0)*TRLAKEL(:,2)
TRLAKEL(:,2)=TRLAKEL(:,2)-TRF2(:)
ELSE ! possibility of complete freezing (and so no frac)
TRF2(:) = TRLAKEL(:,2)
TRLAKEL(:,2) = 0.
END IF
#endif
C**** combine mass and energy fluxes for output
C**** Note that output fluxes are over open water/ice covered fractions
C**** distribute ice fluxes according to flux amounts
FRATO = 1d0
FRATI = 1d0
IF (E2I+E2O.lt.0) THEN
FRATO = E2O/(E2I*ROICE+E2O*(1.-ROICE))
FRATI = E2I/(E2I*ROICE+E2O*(1.-ROICE))
END IF
ACEFO =ACEFO + (ACEF1 +ACEF2 )*FRATO
ACEFI =ACEFI + (ACEF1 +ACEF2 )*FRATI
ENRGFO=ENRGFO+ (ENRGF1+ENRGF2)*FRATO
ENRGFI=ENRGFI+ (ENRGF1+ENRGF2)*FRATI
#ifdef TRACERS_WATER
TRO(:)=TRO(:) + (TRF1(:) + TRF2(:))* FRATO
TRI(:)=TRI(:) + (TRF1(:) + TRF2(:))* FRATI
#endif
RETURN
END SUBROUTINE LKSOURC
SUBROUTINE LKMIX(MLAKE,ELAKE, 1
#ifdef TRACERS_WATER
* TRLAKEL,
#endif
* HLAKE,TKE,ROICE,DTSRC)
!@sum LKMIX calculates mixing and entrainment in lakes
!@auth Gavin Schmidt
!@ver 1.0
IMPLICIT NONE
!@var MLAKE,ELAKE mass and energy in lake layers (kg,J /m^2)
REAL*8, INTENT(INOUT), DIMENSION(2) :: MLAKE,ELAKE
!@var TKE turbulent kinetic energy input at surface of lake (J/m^2)
!@var ROICE ice fraction
REAL*8, INTENT(IN) :: TKE,ROICE
!@var HLAKE sill depth for lake (m)
REAL*8, INTENT(IN) :: HLAKE
!@var DTSRC source time step (s)
REAL*8, INTENT(IN) :: DTSRC
#ifdef TRACERS_WATER
!@var TRLAKEL tracer mass in lake layers (kg/m^2)
REAL*8, INTENT(INOUT), DIMENSION(NTM,2) :: TRLAKEL
REAL*8, DIMENSION(NTM) :: DTML,TR1N,TR2N,TRLT
#endif
!@param MAXRHO,RHO0,BFAC freshwater density function approximation
REAL*8, PARAMETER :: MAXRHO=1d3, RHO0=999.842594d0,
* BFAC=(MAXRHO-RHO0)/16d0
REAL*8 TLK1, TLK2, HLT, MLT, DTK, E1N, E2N, ATKE, H1, H2,
* DRHO, DML, DHML
C**** Only mix if there is a second layer!
IF (MLAKE(2).gt.0) THEN
TLK1=ELAKE(1)/(MLAKE(1)*SHW)
TLK2=ELAKE(2)/(MLAKE(2)*SHW)
HLT=ELAKE(1)+ELAKE(2)
MLT=MLAKE(1)+MLAKE(2)
#ifdef TRACERS_WATER
TRLT(:)=TRLAKEL(:,1)+TRLAKEL(:,2)
#endif
C**** Test for static stability
C**** DRHO=RHO(TLK2)-RHO(TLK1)~=(TLK2-TLK1)*dRHOdT((TLK1+TLK2)/2)
C**** Assumes a parabolic density function going through MAXRHO at
C**** TMAXRHO, and RHO0 at T=0. (reasonable up to about 12 C)
IF ((TMAXRHO-0.5*(TLK1+TLK2))*(TLK2-TLK1).lt.0) THEN
C**** mix uniformly and set MLD to minimum
MLAKE(1)=MIN(MLT,MAX(MINMLD*RHOW,MLT-HLAKE*RHOW))
MLAKE(2)=MLT-MLAKE(1)
ELAKE(1)=HLT*MLAKE(1)/MLT
ELAKE(2)=HLT*MLAKE(2)/MLT
#ifdef TRACERS_WATER
TRLAKEL(:,1)=TRLT(:)*MLAKE(1)/MLT
TRLAKEL(:,2)=TRLT(:)*MLAKE(2)/MLT
#endif
ELSE ! not unstable, implicitly diffuse heat + entrain
C**** reduce mixing if there is ice cover
DTK=2.*KVLAKE*(1.-ROICE)*DTSRC*RHOW**2
E1N=(ELAKE(1)+DTK*HLT/(MLT*MLAKE(2)))/
* (1.+DTK/(MLAKE(1)*MLAKE(2)))
E2N=(ELAKE(2)+DTK*HLT/(MLT*MLAKE(1)))/
* (1.+DTK/(MLAKE(1)*MLAKE(2)))
ELAKE(1)=E1N
ELAKE(2)=E2N
#ifdef TRACERS_WATER
C**** diffuse tracers using same KV as for heat?
TR1N(:)=(TRLAKEL(:,1)+DTK*TRLT(:)/(MLT*MLAKE(2)))/
* (1.+DTK/(MLAKE(1)*MLAKE(2)))
TR2N(:)=(TRLAKEL(:,2)+DTK*TRLT(:)/(MLT*MLAKE(1)))/
* (1.+DTK/(MLAKE(1)*MLAKE(2)))
TRLAKEL(:,1)=TR1N(:)
TRLAKEL(:,2)=TR2N(:)
#endif
C**** entrain deep water if there is available TKE
C**** take a factor of TKE and calculate change in PE
IF (TKE.gt.0) THEN
ATKE=0.2d0*TKE ! 20% of TKE is available for mixing
H1=MLAKE(1)/RHOW
H2=MLAKE(2)/RHOW
DRHO=(TLK2-TLK1)*2d0*BFAC*(TMAXRHO-0.5*(TLK1+TLK2))
DML=ATKE*BYGRAV/(DRHO*0.5*H1)
IF (DML*RHOW.lt.MLAKE(2)) THEN
DHML=DML*ELAKE(2)/H2
ELAKE(1)=ELAKE(1)+DHML
ELAKE(2)=ELAKE(2)-DHML
MLAKE(1)=MLAKE(1)+DML*RHOW
MLAKE(2)=MLAKE(2)-DML*RHOW
#ifdef TRACERS_WATER
DTML(:)=DML*TRLAKEL(:,2)/H2
TRLAKEL(:,1)=TRLAKEL(:,1)+DTML(:)
TRLAKEL(:,2)=TRLAKEL(:,2)-DTML(:)
#endif
ELSE ! entire second layer is entrained
MLAKE(1)=MLT
MLAKE(2)=0
ELAKE(1)=HLT
ELAKE(2)=0
#ifdef TRACERS_WATER
TRLAKEL(:,1)=TRLT(:)
TRLAKEL(:,2)=0.
#endif
END IF
END IF
END IF
END IF
RETURN
C****
END SUBROUTINE LKMIX
END MODULE LAKES
SUBROUTINE ALLOC_LAKES (GRID) 1,3
C23456789012345678901234567890123456789012345678901234567890123456789012
!@SUM To alllocate arrays whose sizes now need to be determined
!@+ at run-time
!@auth Raul Garza-Robles
!@ver 1.0
USE DOMAIN_DECOMP
, only: DIST_GRID, GET
USE MODEL_COM
, only : IM, JM
USE LAKES
, ONLY: RATE, DHORZ,KDIREC,IFLOW,JFLOW
IMPLICIT NONE
TYPE (DIST_GRID), INTENT(IN) :: grid
ALLOCATE ( KDIREC (IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO),
* IFLOW (IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO),
* JFLOW (IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO),
* RATE (IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO),
* DHORZ (IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO)
* )
RETURN
END SUBROUTINE ALLOC_LAKES
SUBROUTINE init_LAKES(inilake,istart) 1,30
!@sum init_LAKES initiallises lake variables
!@auth Gary Russell/Gavin Schmidt
!@ver 1.0
USE FILEMANAGER
USE CONSTANT
, only : rhow,shw,tf,pi,grav
USE MODEL_COM
, only : im,jm,flake0,zatmo,dtsrc,flice,hlake
* ,focean,jday,fearth0
USE DOMAIN_DECOMP
, only : GRID,WRITE_PARALLEL
USE DOMAIN_DECOMP
, only : GET,NORTH,SOUTH,HALO_UPDATE
c*** USE ESMF_MOD, Only : ESMF_HaloDirection
USE GEOM
, only : dxyp,dxv,dyv,dxp,dyp,imaxj
#ifdef TRACERS_WATER
USE TRACER_COM
, only : trw0
USE FLUXES
, only : gtracer
#endif
USE FLUXES
, only : gtemp,mlhc,gtempr
USE SEAICE_COM
, only : rsi
USE PBLCOM
, only : tsavg
USE LAKES
USE LAKES_COM
!USE GHY_COM, only : fearth
USE DIAG_COM
, only : npts,icon_LKM,icon_LKE,title_con,conpt0
USE PARAM
IMPLICIT NONE
INTEGER :: FROM,J_0,J_1,J_0H,J_1H,J_0S,J_1S
LOGICAL :: HAVE_NORTH_POLE, HAVE_SOUTH_POLE
c*** Type (ESMF_HaloDirection) :: direction
Integer :: direction ! ESMF_HaloDirection not yet implemented
LOGICAL, INTENT(IN) :: inilake
INTEGER, INTENT(IN) :: ISTART
!@var I,J,I72,IU,JU,ID,JD loop variables
INTEGER I,J,I72,IU,JU,ID,JD,INM,KD
INTEGER iu_RVR !@var iu_RVR unit number for river direction file
CHARACTER TITLEI*80, CDIREC(IM,JM)*1, CONPT(NPTS)*10
REAL*8 SPMIN,SPMAX,SPEED0,SPEED,DZDH,DZDH1,MLK1
LOGICAL :: QCON(NPTS), T=.TRUE. , F=.FALSE.
!@var out_line local variable to hold mixed-type output for parallel I/O
character(len=300) :: out_line
CALL GET
(GRID, J_STRT = J_0, J_STOP = J_1,
& J_STRT_SKP = J_0S, J_STOP_SKP = J_1S,
& J_STRT_HALO= J_0H, J_STOP_HALO= J_1H,
& HAVE_SOUTH_POLE = HAVE_SOUTH_POLE,
& HAVE_NORTH_POLE = HAVE_NORTH_POLE)
C****
C**** LAKECB MWL Mass of water in lake (kg)
C**** GML Liquid lake enthalpy (J)
C**** TLAKE Temperature of lake surface (C)
C**** HLAKE Lake sill depth (m)
C**** ALAKE Lake surface area (m^2)
C**** TANLK Lake slope (tan(alpha)) (1)
C****
C**** FIXDCB FLAKE0 Original Lake fraction (1)
C****
C**** Get parameters from rundeck
call sync_param
("river_fac",river_fac)
call sync_param
("init_flake",init_flake)
call sync_param
("variable_lk",variable_lk)
C**** initialise FLAKE if requested (i.e. from older restart files)
if ((init_flake.eq.1.and.istart.lt.9) .or. INILAKE) THEN
print*,"Initialising FLAKE from TOPO file..."
FLAKE = FLAKE0
end if
C**** Ensure that HLAKE is a minimum of 1m for FLAKE>0
DO J=J_0, J_1
DO I=1,IM
IF (FLAKE(I,J).gt.0 .and. HLAKE(I,J).lt.1.) THEN
print*,"Warning: Fixing HLAKE",i,j,FLAKE(I,J),FLAKE0(I,J)
* ,HLAKE(I,J),"--> 1m"
HLAKE(I,J)=1.
END IF
END DO
END DO
IF (INILAKE) THEN
C**** Set lake variables from surface temperature
C**** This is just an estimate for the initiallisation
DO J=J_0, J_1
DO I=1,IM
IF (FLAKE(I,J).gt.0) THEN
TLAKE(I,J) = MAX(0d0,TSAVG(I,J)-TF)
MWL(I,J) = RHOW*HLAKE(I,J)*FLAKE(I,J)*DXYP(J)
MLK1 = MINMLD*RHOW*FLAKE(I,J)*DXYP(J)
GML(I,J) = SHW*(MLK1*TLAKE(I,J)
* +(MWL(I,J)-MLK1)*MAX(TLAKE(I,J),4d0))
MLDLK(I,J) = MINMLD
#ifdef TRACERS_WATER
TRLAKE(:,1,I,J)=MLK1*TRW0(:)
TRLAKE(:,2,I,J)=(MWL(I,J)-MLK1)*TRW0(:)
#endif
ELSE
TLAKE(I,J) = 0.
MWL(I,J) = 0.
GML(I,J) = 0.
MLDLK(I,J) = MINMLD
#ifdef TRACERS_WATER
TRLAKE(:,:,I,J)=0.
#endif
END IF
END DO
END DO
END IF
C**** Set fixed geometric variables
C**** TANLK=TAN(ALPHA) = R/H for a conical lake of equivalent volume
DO J=J_0, J_1
DO I=1,IM
IF (FLAKE0(I,J).gt.0) THEN
TANLK(I,J) = SQRT(FLAKE0(I,J)*DXYP(J)/PI)/(3d0*HLAKE(I,J))
ELSE
TANLK(I,J) = 2d3 ! reasonable average value
END IF
END DO
END DO
CALL PRINTLK
("IN")
C**** Set GTEMP arrays for lakes
IF (ISTART.gt.0) THEN
DO J=J_0, J_1
DO I=1,IM
IF (FLAKE(I,J).gt.0) THEN
GTEMP(1,1,I,J)=TLAKE(I,J)
GTEMPR(1,I,J) =TLAKE(I,J)+TF
IF (MWL(I,J).gt.(1d-10+MLDLK(I,J))*RHOW*FLAKE(I,J)*DXYP(J))
* THEN
GTEMP(2,1,I,J)=(GML(I,J)-TLAKE(I,J)*SHW*MLDLK(I,J)*RHOW
* *FLAKE(I,J)*DXYP(J))/(SHW*(MWL(I,J)-MLDLK(I,J)
* *RHOW*FLAKE(I,J)*DXYP(J)))
C**** If starting from a possibly corrupted rsf file, check Tlk2
IF(GTEMP(2,1,I,J)>TLAKE(I,J)+1.and.GTEMP(2,1,I,J)>10) THEN
WRITE(6,*) "Warning: Unphysical Tlk2 fixed",I,J,GTEMP(:
* ,1,I,J)
GTEMP(2,1,I,J)=GTEMP(1,1,I,J) ! set to Tlk1
GML(I,J)=TLAKE(I,J)*SHW*MWL(I,J)
END IF
ELSE
GTEMP(2,1,I,J)=TLAKE(I,J)
END IF
#ifdef TRACERS_WATER
GTRACER(:,1,I,J)=TRLAKE(:,1,I,J)/(MLDLK(I,J)*RHOW*FLAKE(I,J)
* *DXYP(J))
#endif
MLHC(I,J)= SHW*MLDLK(I,J)*RHOW
END IF
END DO
END DO
END IF
C****
C**** Always initiallise River direction and Rate
C**** Read in CDIREC: Number = octant direction, Letter = river mouth
call openunit
("RVR",iu_RVR,.false.,.true.)
READ (iu_RVR,910) TITLEI
WRITE (out_line,*) 'River Direction file read: ',TITLEI
CALL WRITE_PARALLEL
(trim(out_line), UNIT=6)
READ (iu_RVR,910)
DO I72=1,1+(IM-1)/72
DO J=JM, 1, -1
READ (iu_RVR,911) (CDIREC(I,J),I=72*(I72-1)+1,MIN(IM,I72*72))
END DO
END DO
C**** read in named rivers (if any)
READ (iu_RVR,*,END=10)
READ (iu_RVR,'(A80)',END=10) TITLEI
READ (iu_RVR,*,END=10)
IF (TITLEI.eq."Named River Mouths:") THEN
DO I=1,NRVRMX,5
READ(iu_RVR,'(5(A8,1X))') NAMERVR(I:MIN(NRVRMX,I+4))
END DO
END IF
10 call closeunit
(iu_RVR)
C**** Create integral direction array KDIREC from CDIREC
CALL HALO_UPDATE
(GRID, FEARTH0, FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(GRID, FLICE, FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(GRID, FLAKE0, FROM=NORTH+SOUTH) ! fixed
CALL HALO_UPDATE
(GRID, FOCEAN, FROM=NORTH+SOUTH) ! fixed
! Use unusual loop bounds to fill KDIREC in halo
DO J=MAX(1,J_0-1),MIN(JM,J_1+1)
DO I=1,IM
C**** KD: -16 = blank, 0-8 directions >8 named rivers
KD= ICHAR(CDIREC(I,J)) - 48
C**** If land but no ocean, and no direction, print warning
IF ((FEARTH0(I,J)+FLICE(I,J)+FLAKE0(I,J).gt.0) .and.
* FOCEAN(I,J).le.0 .and. (KD.gt.8 .or. KD.lt.0)) THEN
WRITE(6,*) "Land box has no river direction I,J: ",I,J
* ,FOCEAN(I,J),FLICE(I,J),FLAKE0(I,J),FEARTH0(I,J)
END IF
C**** Default direction is down (if ocean box), or no outlet (if not)
C**** Also ensure that all ocean boxes are done properly
IF ((KD.lt.0 .or. KD.gt.8) .or. FOCEAN(I,J).eq.1.) THEN
KDIREC(I,J)=0.
ELSE
KDIREC(I,J) = KD
END IF
C**** Check for specified river mouths
IF (KD.GE.17 .AND. KD.LE.42) THEN
IF (FOCEAN(I,J).le.0) THEN
WRITE(6,*)
* "Warning: Named river outlet must be in ocean",i
* ,j,FOCEAN(I,J),FLICE(I,J),FLAKE0(I,J)
* ,FEARTH0(I,J)
END IF
END IF
END DO
END DO
INM=0
DO J=1,JM
DO I=1,IM
C**** KD: -16 = blank, 0-8 directions >8 named rivers
KD= ICHAR(CDIREC(I,J)) - 48
C**** Check for specified river mouths
IF (KD.GE.17 .AND. KD.LE.42) THEN
INM=INM+1
IRVRMTH(INM)=I
JRVRMTH(INM)=J
IF (CDIREC(I,J).ne.NAMERVR(INM)(1:1)) THEN
WRITE(6,*)
* "Warning: Named river in RVR does not correspond"
* //" with letter in direction file. Please check"
WRITE(6,*) "INM, CDIREC, NAMERVR = ",INM,CDIREC(I,J)
* ," ",NAMERVR(INM)
NAMERVR(INM)=CDIREC(I,J) ! set default
END IF
END IF
END DO
END DO
NRVR=INM
C****
C**** From each box calculate the downstream river box
C****
! odd bounds to fill IFLOW and JFLOW in halo
DO J=MAX(2,J_0H), MIN(JM-1,J_1H)
DO I=1,IM
SELECT CASE (KDIREC(I,J))
CASE (0)
IFLOW(I,J) = I
JFLOW(I,J) = J
DHORZ(I,J) = 0.5*SQRT(DXP(J)*DXP(J)+DYP(J)*DYP(J))
CASE (1)
IFLOW(I,J) = I+1
JFLOW(I,J) = J+1
DHORZ(I,J) = SQRT(DXV(J+1)*DXV(J+1)+DYV(J+1)*DYV(J+1))
! SQRT(DXV(J)*DXV(J)+DYV(J)*DYV(J))
IF(I.eq.IM) IFLOW(I,J) = 1
CASE (2)
IFLOW(I,J) = I
JFLOW(I,J) = J+1
DHORZ(I,J) = DYV(J+1) ! DYV(J)
CASE (3)
IFLOW(I,J) = I-1
JFLOW(I,J) = J+1
DHORZ(I,J) = SQRT(DXV(J+1)*DXV(J+1)+DYV(J+1)*DYV(J+1))
! SQRT(DXV(J)*DXV(J)+DYV(J)*DYV(J))
IF(I.eq.1) IFLOW(I,J) = IM
CASE (4)
IFLOW(I,J) = I-1
JFLOW(I,J) = J
DHORZ(I,J) = DXP(J)
IF(I.eq.1) IFLOW(I,J) = IM
CASE (5)
IFLOW(I,J) = I-1
JFLOW(I,J) = J-1
DHORZ(I,J) = SQRT(DXV(J)*DXV(J)+DYV(J)*DYV(J))
! SQRT(DXV(J-1)*DXV(J-1)+DYV(J-1)*DYV(J-1))
IF(I.eq.1) IFLOW(I,J) = IM
CASE (6)
IFLOW(I,J) = I
JFLOW(I,J) = J-1
DHORZ(I,J) = DYV(J) ! DYV(J-1)
CASE (7)
IFLOW(I,J) = I+1
JFLOW(I,J) = J-1
DHORZ(I,J) = SQRT(DXV(J)*DXV(J)+DYV(J)*DYV(J))
! SQRT(DXV(J-1)*DXV(J-1)+DYV(J-1)*DYV(J-1))
IF(I.eq.IM) IFLOW(I,J) = 1
CASE (8)
IFLOW(I,J) = I+1
JFLOW(I,J) = J
DHORZ(I,J) = DXP(J)
IF(I.eq.IM) IFLOW(I,J) = 1
END SELECT
END DO
END DO
C**** South Pole is a special case
IF (HAVE_SOUTH_POLE) Then
DO I=1,IM
IF(KDIREC(I,1).eq.2) THEN
IFLOW(1,1) = I
JFLOW(1,1) = 2
DHORZ(1,1) = DYV(2) ! DYV(1)
END IF
IF(KDIREC(I,2).eq.6) THEN
IFLOW(I,2) = 1
JFLOW(I,2) = 1
END IF
END DO
END IF
C****
C**** Calculate river flow RATE (per source time step)
C****
CALL HALO_UPDATE
(GRID, zatmo, FROM=NORTH+SOUTH)
SPEED0= .35d0
SPMIN = .15d0
SPMAX = 5.
DZDH1 = .00005
DO JU = J_0, J_1S
DO IU=1,IMAXJ(JU)
IF(KDIREC(IU,JU).gt.0) THEN
JD=JFLOW(IU,JU)
ID=IFLOW(IU,JU)
DZDH = (ZATMO(IU,JU)-ZATMO(ID,JD)) / (GRAV*DHORZ(IU,JU))
ELSE
DZDH = ZATMO(IU,JU) / (GRAV*DHORZ(IU,JU))
END IF
SPEED = SPEED0*DZDH/DZDH1
IF(SPEED.lt.SPMIN) SPEED = SPMIN
IF(SPEED.gt.SPMAX) SPEED = SPMAX
RATE(IU,JU) = DTsrc*SPEED/DHORZ(IU,JU)
END DO
END DO
C**** Set conservation diagnostics for Lake mass and energy
CONPT=CONPT0
CONPT(4)="PREC+LAT M"
CONPT(5)="SURFACE" ; CONPT(8)="RIVERS"
QCON=(/ F, F, F, T, T, F, F, T, T, F, F/)
CALL SET_CON
(QCON,CONPT,"LAK MASS","(KG/M^2) ",
* "(10**-9 KG/SM^2)",1d0,1d9,icon_LKM)
QCON=(/ F, F, F, T, T, F, F, T, T, F, F/)
CALL SET_CON
(QCON,CONPT,"LAK ENRG","(10**3 J/M^2) ",
* "(10**-3 W/M^2) ",1d-3,1d3,icon_LKE)
C**** assume that at the start GHY is in balance with LAKES
SVFLAKE = FLAKE
RETURN
C****
910 FORMAT (A72)
911 FORMAT (72A1)
END SUBROUTINE init_LAKES
SUBROUTINE RIVERF 1,26
!@sum RIVERF transports lake water from each grid box downstream
!@auth Gary Russell/Gavin Schmidt
!@ver 1.0 (based on LB265)
USE CONSTANT
, only : shw,rhow,teeny,bygrav,tf
USE MODEL_COM
, only : im,jm,focean,zatmo,hlake,itlake,itlkice
* ,itocean,itoice,fland,dtsrc
USE DOMAIN_DECOMP
, only : HALO_UPDATE, GRID,NORTH,SOUTH,GET,
* GLOBALSUM, HALO_UPDATE_COLUMN
USE GEOM
, only : dxyp,bydxyp,imaxj
USE DIAG_COM
, only : aij=>aij_loc,ij_ervr,ij_mrvr,ij_f0oc,
* aj=>aj_loc,aregj=>aregj_loc,jreg,j_rvrd,j_ervr,ij_fwoc
USE GHY_COM
, only : fearth
#ifdef TRACERS_WATER
USE TRDIAG_COM
, only : taijn =>taijn_loc , tij_rvr
USE FLUXES
, only : trflowo,gtracer
#endif
USE FLUXES
, only : flowo,eflowo,gtemp,mlhc,gtempr
USE LAKES
, only : kdirec,rate,iflow,jflow,river_fac
USE LAKES_COM
, only : tlake,gml,mwl,mldlk,flake
#ifdef TRACERS_WATER
* ,trlake,ntm
#endif
USE SEAICE_COM
, only : rsi
IMPLICIT NONE
INTEGER :: FROM,J_0,J_1,J_0H,J_1H,J_0S,J_1S,I_0H,I_1H
!@var I,J,IU,JU,ID,JD loop variables
INTEGER I,J,IU,JU,ID,JD,JR,ITYPE
REAL*8 MWLSILL,DMM,DGM,HLK1,DPE,MWLSILLD,FLFAC
REAL*8, DIMENSION(IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO) ::
* FLOW,EFLOW
!@var URATE upstream fractional rate of river flow per time step
!@+ (only for special case)
REAL*8 :: URATE = 1d-6 ! roughly 10 day e-folding time
#ifdef TRACERS_WATER
REAL*8, DIMENSION(NTM) :: DTM
REAL*8, DIMENSION(NTM,IM,GRID%J_STRT_HALO:GRID%J_STOP_HALO)
* :: TRFLOW
#endif
LOGICAL :: rvrfl
C****
C**** LAKECB MWL Liquid lake mass (kg)
C**** GML Liquid lake enthalpy (J)
C**** TLAKE Lake surface temperature (C)
C****
C**** Calculate net mass and energy changes due to river flow
C****
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1,
& J_STRT_SKP =J_0S, J_STOP_SKP =J_1S,
& J_STRT_HALO=J_0H, J_STOP_HALO=J_1H)
FLOW = 0. ; EFLOW = 0.
FLOWO = 0. ; EFLOWO = 0.
#ifdef TRACERS_WATER
TRFLOW = 0.
TRFLOWO = 0.
#endif
CALL HALO_UPDATE
(GRID, FLAND,FROM=NORTH+SOUTH) ! fixed
CALL HALO_UPDATE
(GRID,FOCEAN,FROM=NORTH+SOUTH) ! fixed
CALL HALO_UPDATE
(GRID,FEARTH,FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(GRID, ZATMO,FROM=NORTH+SOUTH) ! fixed
CALL HALO_UPDATE
(GRID, HLAKE,FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(grid, FLAKE,FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(grid, MWL,FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(grid, TLAKE,FROM=NORTH+SOUTH)
CALL HALO_UPDATE
(grid, RATE,FROM=NORTH+SOUTH) ! fixed
#ifdef TRACERS_WATER
CALL HALO_UPDATE_COLUMN
(grid, GTRACER(:,1,:,:),NORTH+SOUTH)
CALL HALO_UPDATE_COLUMN
(grid, TRLAKE(:,1,:,:),NORTH+SOUTH)
CALL HALO_UPDATE
(grid, TAIJN(:,:,TIJ_RVR,:),FROM=NORTH+SOUTH)
#endif
C**** Calculate fluxes downstream if lake mass is above sill height (HLAKE (m))
C**** Also allow flow into ocean fraction of same box if KDIREC=0
C**** SPECIAL CASE: If the downstream box has FLAKE=1 and KDIREC=0 (i.e.
C**** no outlet) then the only way to prevent excess water build up is
C**** to allow a back-flux. Take account of mean topography change as
C**** well. This is mainly an issue for the Caspian and Aral Seas.
C**** Loop now includes polar boxes
! note on MPI fixes: since different PEs can influence the downstream
! accumulation of FLOW etc, we loop on the haloed variables to ensure
! that contributions from the halo are included in FLOW/FLOWO etc.
! If downstream box is outside the interior, cycle - this is dealt with on
! a separate PE
DO JU=MAX(1,J_0H),MIN(JM,J_1H)
DO IU=1,IMAXJ(JU)
IF (KDIREC(IU,JU).gt.0 .or.
* (FLAND(IU,JU).gt.0 .and. FOCEAN(IU,JU).gt.0)) THEN
JD=JFLOW(IU,JU)
ID=IFLOW(IU,JU)
! only calculate for downstream interior boxes.
IF (JD.gt.J_1H .or. JD.lt.J_0H ) CYCLE
C**** MWLSILL/D mass associated with full lake (and downstream)
MWLSILL = RHOW*HLAKE(IU,JU)*FLAKE(IU,JU)*DXYP(JU)
rvrfl=.false.
C**** Check for special case:
IF (KDIREC(ID,JD).eq.0 .and. FLAKE(ID,JD).ge.
& 0.95d0*(FLAKE(ID,JD)+FEARTH(ID,JD))) THEN
MWLSILLD = RHOW*(HLAKE(ID,JD)+BYGRAV*MAX(ZATMO(IU,JU)
* -ZATMO(ID,JD),0d0))*DXYP(JD)*FLAKE(ID,JD)
IF (MWL(ID,JD)-MWLSILLD.gt.0) THEN ! potential back flux
IF (FLAKE(IU,JU).gt.0) THEN
IF (MWL(ID,JD)-MWLSILLD-FLAKE(ID,JD)*DXYP(JD)*(MWL(IU,JU
* )-MWLSILL)/(FLAKE(IU,JU)*DXYP(JU)).gt.0) THEN
DMM=-(MWL(ID,JD)-MWLSILLD-FLAKE(ID,JD)*DXYP(JD)
* *(MWL(IU,JU)-MWLSILL)/(FLAKE(IU,JU)*DXYP(JU)))
* *URATE*DTsrc ! <0
rvrfl=.true.
END IF
ELSE
DMM=-(MWL(ID,JD)-MWLSILLD)*URATE*DTsrc ! <0
rvrfl=.true.
END IF
if (rvrfl) then
DGM=TLAKE(ID,JD)*DMM*SHW ! TLAKE always defined
#ifdef TRACERS_WATER
DTM(:) = DMM*GTRACER(:,1,ID,JD)
#endif
end if
END IF
END IF
C**** Normal downstream flow
IF(.not.rvrfl .and. MWL(IU,JU).gt.MWLSILL) THEN
rvrfl=.true.
DMM = (MWL(IU,JU)-MWLSILL)*RATE(IU,JU)
IF (MWL(IU,JU)-DMM.lt.1d-6) DMM=MWL(IU,JU)
DMM=MIN(DMM,0.5d0*RHOW*DXYP(JU)) ! minimise 'flood' events!
c IF (FLAKE(IU,JU).gt.0) THEN
c MLM=RHOW*MLDLK(IU,JU)*FLAKE(IU,JU)*DXYP(JU)
c DMM=MIN(DMM,MLM) ! not necessary since MLM>TOTD-HLAKE
c END IF
DGM=TLAKE(IU,JU)*DMM*SHW ! TLAKE always defined
#ifdef TRACERS_WATER
if (flake(iu,ju).gt.0) then
DTM(:) = DMM*GTRACER(:,1,IU,JU)
else
DTM(:) = DMM*TRLAKE(:,1,IU,JU)/MWL(IU,JU)
end if
#endif
END IF
IF (rvrfl) THEN
FLOW(IU,JU) = FLOW(IU,JU) - DMM
EFLOW(IU,JU) = EFLOW(IU,JU) - DGM
#ifdef TRACERS_WATER
TRFLOW(:,IU,JU) = TRFLOW(:,IU,JU) - DTM(:)
#endif
C**** calculate adjustments for poles
IF (JU.eq.1 .or. JU.eq.JM) THEN
FLFAC=IM ! pole exception upstream
ELSEIF (JD.eq.1 .or. JD.eq.JM) THEN
FLFAC=1d0/real(IM) ! pole exception downstream
ELSE
FLFAC=1. ! default
END IF
IF(FOCEAN(ID,JD).le.0.) THEN
DPE=0. ! DMM*(ZATMO(IU,JU)-ZATMO(ID,JD))
FLOW(ID,JD) = FLOW(ID,JD) + DMM *FLFAC
EFLOW(ID,JD) = EFLOW(ID,JD) + (DGM+DPE)*FLFAC
#ifdef TRACERS_WATER
TRFLOW(:,ID,JD)=TRFLOW(:,ID,JD) +DTM(:)*FLFAC
#endif
ELSE ! Save river mouth flow to for output to oceans
C**** DPE: also add potential energy change to ocean.
C**** Normally ocean is at sea level (Duh!), but in some boxes ZATMO
C**** may not be zero if there is land as well, while in the Caspian,
C**** the ocean level is below zero.
C**** Note: this is diasabled until PE of precip is properly calculated
C**** in atmosphere as well. Otherwise, there is an energy imbalance.
DPE=0. ! DMM*(ZATMO(IU,JU)-MIN(0d0,ZATMO(ID,JD)))
C**** possibly adjust mass (not heat) to allow for balancing of sea level
DMM=river_fac*DMM
FLOWO(ID,JD) = FLOWO(ID,JD)+ DMM *FLFAC
EFLOWO(ID,JD)=EFLOWO(ID,JD)+(DGM+DPE)*FLFAC
#ifdef TRACERS_WATER
DTM(:)=river_fac*DTM(:)
TRFLOWO(:,ID,JD)=TRFLOWO(:,ID,JD)+DTM(:)*FLFAC
#endif
C**** accumulate river runoff diags (moved from ground)
AJ(JD,J_RVRD,ITOCEAN)=AJ(JD,J_RVRD,ITOCEAN)+
* (1.-RSI(ID,JD))*DMM*BYDXYP(JD)
AJ(JD,J_ERVR,ITOCEAN)=AJ(JD,J_ERVR,ITOCEAN)+
* (1.-RSI(ID,JD))*(DGM+DPE)*BYDXYP(JD)
AJ(JD,J_RVRD,ITOICE)=AJ(JD,J_RVRD,ITOICE) +
* RSI(ID,JD)*DMM*BYDXYP(JD)
AJ(JD,J_ERVR,ITOICE)=AJ(JD,J_ERVR,ITOICE) +
* RSI(ID,JD)*(DGM+DPE)*BYDXYP(JD)
AIJ(ID,JD,IJ_F0OC)=AIJ(ID,JD,IJ_F0OC)+
* (DGM+DPE)*BYDXYP(JD)
AIJ(ID,JD,IJ_FWOC)=AIJ(ID,JD,IJ_FWOC)+DMM*BYDXYP(JD)
END IF
JR=JREG(ID,JD)
AREGJ(JR,JD,J_RVRD)=AREGJ(JR,JD,J_RVRD)+DMM
AREGJ(JR,JD,J_ERVR)=AREGJ(JR,JD,J_ERVR)+DGM+DPE
AIJ(ID,JD,IJ_MRVR)=AIJ(ID,JD,IJ_MRVR) + DMM
AIJ(ID,JD,IJ_ERVR)=AIJ(ID,JD,IJ_ERVR) + DGM+DPE
#ifdef TRACERS_WATER
TAIJN(ID,JD,TIJ_RVR,:)=TAIJN(ID,JD,TIJ_RVR,:)+DTM(:)
* *BYDXYP(JD)
#endif
END IF
END IF
END DO
END DO
C****
C**** Apply net river flow to continental reservoirs
C****
DO J=J_0, J_1
DO I=1,IMAXJ(J)
IF(FLAND(I,J)+FLAKE(I,J).gt.0.) THEN
MWL(I,J) = MWL(I,J) + FLOW(I,J)
GML(I,J) = GML(I,J) + EFLOW(I,J)
#ifdef TRACERS_WATER
TRLAKE(:,1,I,J) = TRLAKE(:,1,I,J) + TRFLOW(:,I,J)
#endif
C**** remove pathologically small values
IF (MWL(I,J).lt.1d-6) THEN
MWL(I,J)=0.
GML(I,J)=0.
#ifdef TRACERS_WATER
TRLAKE(:,1:2,I,J) = 0.
#endif
END IF
IF (FLAKE(I,J).gt.0) THEN
HLK1=(MLDLK(I,J)*RHOW)*TLAKE(I,J)*SHW
MLDLK(I,J)=MLDLK(I,J)+FLOW(I,J)/(RHOW*FLAKE(I,J)*DXYP(J))
TLAKE(I,J)=(HLK1*FLAKE(I,J)*DXYP(J)+EFLOW(I,J))
* /(MLDLK(I,J)*RHOW*FLAKE(I,J)*DXYP(J)*SHW)
C**** accumulate some diagnostics
AJ(J,J_RVRD,ITLAKE) =AJ(J,J_RVRD,ITLAKE) + FLOW(I,J)*
* BYDXYP(J)*(1.-RSI(I,J))
AJ(J,J_ERVR,ITLAKE) =AJ(J,J_ERVR,ITLAKE) +EFLOW(I,J)*
* BYDXYP(J)*(1.-RSI(I,J))
AJ(J,J_RVRD,ITLKICE)=AJ(J,J_RVRD,ITLKICE)+ FLOW(I,J)*
* BYDXYP(J)*RSI(I,J)
AJ(J,J_ERVR,ITLKICE)=AJ(J,J_ERVR,ITLKICE)+EFLOW(I,J)*
* BYDXYP(J)*RSI(I,J)
ELSE
TLAKE(I,J)=GML(I,J)/(SHW*MWL(I,J)+teeny)
C**** accounting fix to ensure river flow with no lakes is counted
AJ(J,J_RVRD,ITLAKE)=AJ(J,J_RVRD,ITLAKE)+ FLOW(I,J)
* *BYDXYP(J)
AJ(J,J_ERVR,ITLAKE)=AJ(J,J_ERVR,ITLAKE)+EFLOW(I,J)
* *BYDXYP(J)
END IF
END IF
END DO
END DO
CALL PRINTLK
("RV")
C**** Set GTEMP array for lakes
DO J=J_0, J_1
DO I=1,IM
IF (FLAKE(I,J).gt.0) THEN
GTEMP(1,1,I,J)=TLAKE(I,J)
GTEMPR(1,I,J) =TLAKE(I,J)+TF
#ifdef TRACERS_WATER
GTRACER(:,1,I,J)=TRLAKE(:,1,I,J)/(MLDLK(I,J)*RHOW*FLAKE(I,J)
* *DXYP(J))
#endif
MLHC(I,J) = SHW*MLDLK(I,J)*RHOW
END IF
END DO
END DO
RETURN
C****
END SUBROUTINE RIVERF
SUBROUTINE diag_RIVER 1,13
!@sum diag_RIVER prints out the river outflow for various rivers
!@auth Gavin Schmidt
!@ver 1.0
USE CONSTANT
, only : rhow,sday,teeny,undef
USE MODEL_COM
, only : jyear0,amon0,jdate0,jhour0,jyear,amon
* ,jdate,jhour,itime,dtsrc,idacc,itime0,nday,jdpery,jmpery
USE DOMAIN_DECOMP
, only : HALO_UPDATE, GRID,NORTH,SOUTH,
* WRITE_PARALLEL
USE GEOM
, only : bydxyp
USE DIAG_COM
, only : aij,ij_mrvr
#ifdef TRACERS_WATER
USE TRACER_COM
, only : ntm,trname,trw0,n_water,itime_tr0
* ,tr_wd_type,nwater
USE TRDIAG_COM
, only : taijn
USE TRDIAG_COM
, only : tij_rvr,to_per_mil,units_tij,scale_tij
#endif
USE LAKES
, only : irvrmth,jrvrmth,namervr,nrvr
IMPLICIT NONE
REAL*8 RVROUT(6), SCALERVR, DAYS
INTEGER INM,I,N
#ifdef TRACERS_WATER
REAL*8 TRRVOUT(6,NTM)
#endif
!@var out_line local variable to hold mixed-type output for parallel I/O
character(len=300) :: out_line
DAYS=(Itime-Itime0)/REAL(nday,kind=8)
WRITE(out_line,900) JYEAR0,AMON0,JDATE0,JHOUR0,JYEAR,AMON,JDATE,
* JHOUR,ITIME,DAYS
CALL WRITE_PARALLEL
(trim(out_line), UNIT=6)
C**** convert kg/(source time step) to km^3/mon
SCALERVR = 1d-9*SDAY*JDPERY/(JMPERY*RHOW*DTSRC)
DO INM=1,NRVR,6
DO I=1,MIN(6,NRVR+1-INM)
RVROUT(I) = SCALERVR*AIJ(IRVRMTH(I-1+INM),JRVRMTH(I-1+INM)
* ,IJ_MRVR)/IDACC(1)
END DO
WRITE(out_line,901)
* (NAMERVR(I-1+INM),RVROUT(I),I=1,MIN(6,NRVR+1-INM))
CALL WRITE_PARALLEL
(trim(out_line), UNIT=6)
END DO
#ifdef TRACERS_WATER
DO N=1,NTM
if (itime.ge.itime_tr0(n) .and. tr_wd_TYPE(n).eq.nWater) then
WRITE(out_line,*) "River outflow tracer concentration "
* ,trim(units_tij(tij_rvr,n)),":",TRNAME(N)
CALL WRITE_PARALLEL
(trim(out_line), UNIT=6)
DO INM=1,NRVR,6
DO I=1,MIN(6,NRVR+1-INM)
IF (AIJ(IRVRMTH(I-1+INM),JRVRMTH(I-1+INM),IJ_MRVR).gt.0)
* THEN
if (to_per_mil(n).gt.0) then
c TRRVOUT(I,N)=1d3*(TAIJN(IRVRMTH(I-1+INM),JRVRMTH(I-1
c * +INM),TIJ_RVR,N)/(trw0(n)*AIJ(IRVRMTH(I-1+INM)
c * ,JRVRMTH(I-1+INM),IJ_MRVR)*BYDXYP(JRVRMTH(I-1+INM
c * ))) -1.)
if (TAIJN(IRVRMTH(I-1+INM),JRVRMTH(I-1+INM),TIJ_RVR
* ,N_water).gt.0) then
TRRVOUT(I,N)=1d3*(TAIJN(IRVRMTH(I-1+INM),JRVRMTH(I-1
* +INM),TIJ_RVR,N)/(trw0(n)*TAIJN(IRVRMTH(I-1+INM)
* ,JRVRMTH(I-1+INM),TIJ_RVR,N_water))-1.)
else
TRRVOUT(I,N)=undef
endif
else
TRRVOUT(I,N)=scale_tij(TIJ_RVR,n)*TAIJN(IRVRMTH(I-1+INM)
* ,JRVRMTH(I-1+INM),TIJ_RVR,N)/(AIJ(IRVRMTH(I-1+INM)
* ,JRVRMTH(I-1+INM),IJ_MRVR)*BYDXYP(JRVRMTH(I-1+INM))
* +teeny)
end if
ELSE
TRRVOUT(I,N)=undef
END IF
END DO
WRITE(out_line,901) (NAMERVR(I-1+INM),TRRVOUT(I,N),
* I=1,MIN(6,NRVR+1-INM))
CALL WRITE_PARALLEL
(trim(out_line), UNIT=6)
END DO
end if
END DO
#endif
RETURN
C****
900 FORMAT ('1* River Outflow (km^3/mon) ** From:',I6,A6,I2,', Hr'
* ,I3,6X,'To:',I6,A6,I2,', Hr',I3,' Model-Time:',I9,5X
* ,'Dif:',F7.2,' Days')
901 FORMAT (' ',A8,':',F8.3,5X,A8,':',F8.3,5X,A8,':',F8.3,5X,
* A8,':',F8.3,5X,A8,':',F8.3,5X,A8,':',F8.3)
END SUBROUTINE diag_RIVER
SUBROUTINE CHECKL (SUBR) 1,13
!@sum CHECKL checks whether the lake variables are reasonable.
!@auth Gavin Schmidt/Gary Russell
!@ver 1.0 (based on LB265)
USE CONSTANT
, only : rhow
USE MODEL_COM
, only : im,jm,hlake,qcheck
USE DOMAIN_DECOMP
, only : HALO_UPDATE, GET, GRID,NORTH,SOUTH
USE GEOM
, only : dxyp,imaxj
#ifdef TRACERS_WATER
USE TRACER_COM
, only : ntm, trname, t_qlimit
#endif
USE LAKES
USE LAKES_COM
USE GHY_COM
, only : fearth
IMPLICIT NONE
INTEGER :: FROM,J_0,J_1,J_0H,J_1H,J_0S,J_1S,I_0H,I_1H
INTEGER I,J,N !@var I,J loop variables
CHARACTER*6, INTENT(IN) :: SUBR
LOGICAL QCHECKL
#ifdef TRACERS_WATER
integer :: imax,jmax
real*8 relerr,errmax
#endif
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1,
& J_STRT_SKP=J_0S, J_STOP_SKP=J_1S)
C**** Check for NaN/INF in lake data CALL CHECK3(MWL,IM,JM,1,SUBR,'mwl')
CALL CHECK3
(GML,IM,JM,1,SUBR,'gml')
CALL CHECK3
(MLDLK,IM,JM,1,SUBR,'mld')
CALL CHECK3
(TLAKE,IM,JM,1,SUBR,'tlk')
QCHECKL = .FALSE.
DO J=J_0S, J_1S
DO I=1,IM
IF(FEARTH(I,J).gt.0.) THEN
C**** check for negative mass
IF (MWL(I,J).lt.0 .or. MLDLK(I,J).lt.0) THEN
WRITE(6,*) 'After ',SUBR,': I,J,TSL,MWL,GML,MLD=',
* I,J,TLAKE(I,J),MWL(I,J),GML(I,J),MLDLK(I,J)
QCHECKL = .TRUE.
END IF
C**** check for reasonable lake surface temps
IF (TLAKE(I,J).ge.50 .or. TLAKE(I,J).lt.-0.5) THEN
WRITE(6,*) 'After ',SUBR,': I,J,TSL=',I,J,TLAKE(I,J)
if (TLAKE(I,J).lt.-5.and.FLAKE(I,J).gt.0) QCHECKL = .TRUE.
END IF
END IF
C**** Check total lake mass ( <0.4 m, >20x orig depth)
IF(FLAKE(I,J).gt.0.) THEN
IF(MWL(I,J).lt.0.4d0*RHOW*DXYP(J)*FLAKE(I,J)) THEN
WRITE (6,*) 'After ',SUBR,
* ': I,J,FLAKE,HLAKE,lake level low=',I,J,FLAKE(I,J),
* HLAKE(I,J),MWL(I,J)/(RHOW*DXYP(J)*FLAKE(I,J))
END IF
IF(MWL(I,J).gt.RHOW*MAX(20.*HLAKE(I,J),3d1)*DXYP(J)*FLAKE(I,J)
* )THEN
WRITE (6,*) 'After ',SUBR,
* ': I,J,FLAKE,HLAKE,lake level high=',I,J,FLAKE(I,J),
* HLAKE(I,J),MWL(I,J)/(RHOW*DXYP(J)*FLAKE(I,J))
END IF
END IF
END DO
END DO
#ifdef TRACERS_WATER
do n=1,ntm
C**** Check for neg tracers in lake
if (t_qlimit(n)) then
do j=J_0, J_1
do i=1,imaxj(j)
if (fearth(i,j).gt.0) then
if (trlake(n,1,i,j).lt.0 .or. trlake(n,2,i,j).lt.0) then
print*,"Neg tracer in lake after ",SUBR,i,j,trname(n)
* ,trlake(n,:,i,j)
QCHECKL=.TRUE.
end if
end if
end do
end do
end if
C**** Check conservation of water tracers in lake
if (trname(n).eq.'Water') then
errmax = 0. ; imax=1 ; jmax=1
do j=J_0, J_1
do i=1,imaxj(j)
if (fearth(i,j).gt.0) then
if (flake(i,j).gt.0) then
relerr=max(
* abs(trlake(n,1,i,j)-mldlk(i,j)*rhow*flake(i,j)
* *dxyp(j))/trlake(n,1,i,j),abs(trlake(n,1,i,j)
* +trlake(n,2,i,j)-mwl(i,j))/(trlake(n,1,i,j)
* +trlake(n,2,i,j)))
else
if ((mwl(i,j).eq.0 .and. trlake(n,1,i,j)+trlake(n,2,i,j)
* .gt.0) .or. (mwl(i,j).gt.0 .and. trlake(n,1,i,j)
* +trlake(n,2,i,j).eq.0)) then
print*,"CHECKL ",SUBR,i,j,mwl(i,j),trlake(n,1:2,i,j)
relerr=0.
else
if (mwl(i,j).gt.1d-20) then
relerr=abs(trlake(n,1,i,j)
* +trlake(n,2,i,j)-mwl(i,j))/(trlake(n,1,i,j)
* +trlake(n,2,i,j))
else
if (mwl(i,j).gt.0) print*,"CHECKL2 ",SUBR,i,j,mwl(i
* ,j),trlake(n,1:2,i,j)
relerr=0.
end if
end if
end if
if (relerr.gt.errmax) then
imax=i ; jmax=j ; errmax=relerr
end if
end if
end do
end do
print*,"Relative error in lake mass after ",trim(subr),":"
* ,imax,jmax,errmax,trlake(n,:,imax,jmax),mldlk(imax,jmax)
* *rhow*flake(imax,jmax)*dxyp(jmax),mwl(imax,jmax)
* -mldlk(imax,jmax)*rhow*flake(imax,jmax)*dxyp(jmax)
end if
end do
#endif
IF (QCHECKL)
& call stop_model
('CHECKL: Lake variables out of bounds',255)
RETURN
C****
END SUBROUTINE CHECKL
SUBROUTINE daily_LAKE 1,14
!@sum daily_LAKE does lake things at the beginning of every day
!@auth G. Schmidt
!@ver 1.0
USE CONSTANT
, only : rhow,by3,pi,lhm,shi,shw,teeny,tf
USE MODEL_COM
, only : im,fland,flice,focean,itlake,itlkice,hlake
USE LAKES
, only : kdirec,minmld,variable_lk
USE LAKES_COM
, only : mwl,flake,tanlk,mldlk,tlake,gml,svflake
#ifdef TRACERS_WATER
* ,trlake,ntm
#endif
USE SEAICE_COM
, only : rsi,msi,hsi,snowi
#ifdef TRACERS_WATER
* ,trsi
#endif
USE SEAICE
, only : ace1i,xsi,ac2oim
USE GEOM
, only : dxyp,imaxj,bydxyp
USE GHY_COM
, only : fearth
USE FLUXES
, only : dmwldf,dgml,gtemp,mlhc,gtempr
#ifdef TRACERS_WATER
* ,dtrl,gtracer
#endif
USE DIAG_COM
, only : aj=>aj_loc,j_run,j_erun,j_imelt,j_hmelt,
* aregj=>aregj_loc,jreg
USE DOMAIN_DECOMP
, only : HALO_UPDATE, GET, GRID,NORTH,SOUTH,
* GLOBALSUM
IMPLICIT NONE
integer i,j,J_0,J_1,jr,itm
real*8 new_flake,sumh,msinew,snownew,frac,fmsi2,fmsi3
* ,fmsi4,fhsi2,fhsi3,fhsi4,imlt,hmlt,plake,plkic,hlk
* ,frsat,new_MLD,hlkic
#ifdef TRACERS_WATER
* ,hlk2,ftsi2(ntm),ftsi3(ntm),ftsi4(ntm),sumt,dtr(ntm)
& ,tottr(ntm)
#endif
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1)
C**** Experimental code: not yet fully functional
C**** Update lake fraction as a function of lake mass at end of day
C**** Assume lake is conical
C**** => A = pi*(h*tanlk)^2, M=(1/3)*pi*rho*h*(h*tanlk)^2
C****
SVFLAKE=FLAKE ! save for ghy purposes
if (variable_lk .ne. 0) then
DO J=J_0, J_1
DO I=1,IMAXJ(J)
JR=JREG(I,J)
IF (FLAKE(I,J)+FEARTH(I,J).gt.0 .and.FOCEAN(I,J).eq.0) THEN
PLAKE=FLAKE(I,J)*(1.-RSI(I,J))
PLKIC=FLAKE(I,J)* RSI(I,J)
new_flake=min(0.95d0*(FLAKE(I,J)+FEARTH(I,J)),(9d0*PI
* *(TANLK(I,J)*MWL(I,J)/RHOW)**2)**BY3/DXYP(J))
C**** hack to prevent lakes fooding the snow in GHY
C**** (do not flood more than 4.9% of land per day)
new_flake=min( new_flake, FLAKE(I,J)+.049d0*FEARTH(I,J) )
hlk=0.
hlkic=0.
if (new_flake.gt.0) then
hlk=MWL(I,J)/(RHOW*new_flake*DXYP(J))
hlkic=(MSI(I,J)+SNOWI(I,J)+ACE1I)*RSI(I,J)/RHOW
end if
if (new_flake.ne.FLAKE(I,J)) THEN ! something to do
IF (FLAKE(I,J).eq.0) HLAKE(I,J)=MAX(1d0,HLAKE(I,J))
IF (new_flake.gt.0 .and. (hlk.gt.0.4 .or. (hlk.gt.0.2 .and
* . hlk+hlkic.gt.0.4)) ) THEN ! new or surviving lake
HLAKE(I,J)=MAX(HLAKE(I,J),1d0) ! in case it wasn't set
C**** adjust for fearth changes
FRSAT=0.
IF (new_flake.gt.FLAKE(I,J)) THEN ! some water used to saturate
if (MWL(I,J).gt.DMWLDF(I,J)*(new_flake
* -FLAKE(I,J))*DXYP(J)) THEN
FRSAT=DMWLDF(I,J)*(new_flake-FLAKE(I,J))*DXYP(J)
* /MWL(I,J)
MWL(I,J)=MWL(I,J)*(1.-FRSAT)
C**** calculate associated energy/tracer transfer
DGML(I,J)=FRSAT*GML(I,J)
GML(I,J)=GML(I,J)*(1.-FRSAT)
#ifdef TRACERS_WATER
DTRL(:,I,J)=FRSAT*(TRLAKE(:,1,I,J)+TRLAKE(:,2,I,J))
TRLAKE(:,:,I,J)=TRLAKE(:,:,I,J)*(1.-FRSAT)
#endif
MLDLK(I,J)=MLDLK(I,J)*(1.-FRSAT)
C**** save some diags
AJ(J, J_RUN,ITLAKE) =AJ(J, J_RUN,ITLAKE) +PLAKE*
* DMWLDF(I,J)*(new_flake-FLAKE(I,J))
AJ(J, J_RUN,ITLKICE)=AJ(J, J_RUN,ITLKICE)+PLKIC*
* DMWLDF(I,J)*(new_flake-FLAKE(I,J))
AJ(J,J_ERUN,ITLAKE) =AJ(J,J_ERUN,ITLAKE) +PLAKE*
* DGML(I,J)*BYDXYP(J)
AJ(J,J_ERUN,ITLKICE)=AJ(J,J_ERUN,ITLKICE)+PLKIC*
* DGML(I,J)*BYDXYP(J)
else
C**** this is just here to see whether this ever happens.
print*,"dont saturate",i,j,(DMWLDF(I,J)*(new_flake
* -FLAKE(I,J))*DXYP(J))/MWL(I,J),MWL(I,J)
* ,(DMWLDF(I,J)*(new_flake-FLAKE(I,J))*DXYP(J))
* ,(new_flake-FLAKE(I,J))
call stop_model
('Not enough water for saturation'
* ,255)
end if
END IF
C**** conserve lake ice
IF (RSI(I,J)*FLAKE(I,J).gt.new_flake) THEN ! crunch ice up
SUMH=PLKIC*SUM(HSI(:,I,J))
FRAC=PLKIC/new_flake
SNOWNEW=SNOWI(I,J)*FRAC
MSINEW=(MSI(I,J)+ACE1I)*FRAC-ACE1I
RSI(I,J)=1.
C**** all tracers --> tracer*FRAC, then adjust layering
FMSI3=ACE1I*(FRAC-1d0) ! kg/m2 flux over new fraction
FMSI2=FMSI3*XSI(1)
FMSI4=FMSI3*XSI(4)
FHSI2=FMSI2*HSI(1,I,J)/(XSI(1)*(ACE1I+SNOWI(I,J)))
IF (FMSI3.LT.FRAC*XSI(2)*(ACE1I+SNOWI(I,J))) THEN
FHSI3=FMSI3*HSI(2,I,J)/(XSI(2)*(ACE1I+SNOWI(I,J)))
ELSE
FHSI3=HSI(2,I,J)*FRAC+(FMSI3-FRAC*XSI(2)*(ACE1I
* +SNOWI(I,J)))*HSI(1,I,J)/(XSI(1)*(ACE1I
* +SNOWI(I,J)))
END IF
IF (FMSI4.LT.FRAC*XSI(3)*MSI(I,J)) THEN
FHSI4=FMSI4*HSI(3,I,J)/(XSI(3)*MSI(I,J))
ELSE
FHSI4=HSI(3,I,J)*FRAC+(FMSI4-FRAC*XSI(3)*MSI(I,J))
* *FHSI3/FMSI3
END IF
HSI(1,I,J)=HSI(1,I,J)*(ACE1I+SNOWNEW)/
* (ACE1I+SNOWI(I,J))
HSI(2,I,J)=HSI(2,I,J)*FRAC+FHSI2-FHSI3
HSI(3,I,J)=HSI(3,I,J)*FRAC+FHSI3-FHSI4
HSI(4,I,J)=HSI(4,I,J)*FRAC +FHSI4
#ifdef TRACERS_WATER
sumt=rsi(i,j)*flake(I,j)*sum(trsi(1,:,i,j))
FTSI2(:)=FMSI2*TRSI(:,1,I,J)/(XSI(1)*(ACE1I+SNOWI(I,J)
* ))
IF (FMSI3.LT.FRAC*XSI(2)*(ACE1I+SNOWI(I,J))) THEN
FTSI3(:)=FMSI3*TRSI(:,2,I,J)/(XSI(2)*(ACE1I+SNOWI(I
* ,J)))
ELSE
FTSI3(:)=TRSI(:,2,I,J)*FRAC+(FMSI3-FRAC*XSI(2)
* *(ACE1I+SNOWI(I,J)))*TRSI(:,1,I,J)/(XSI(1)
* *(ACE1I+SNOWI(I,J)))
END IF
IF (FMSI4.LT.FRAC*XSI(3)*MSI(I,J)) THEN
FTSI4(:)=FMSI4*TRSI(:,3,I,J)/(XSI(3)*MSI(I,J))
ELSE
FTSI4(:)=TRSI(:,3,I,J)*FRAC+(FMSI4-FRAC*XSI(3)*MSI(I
* ,J))*FTSI3(:)/FMSI3
END IF
TRSI(:,1,I,J)=TRSI(:,1,I,J)*(ACE1I+SNOWNEW)/
* (ACE1I+SNOWI(I,J))
TRSI(:,2,I,J)=TRSI(:,2,I,J)*FRAC+FTSI2(:)-FTSI3(:)
TRSI(:,3,I,J)=TRSI(:,3,I,J)*FRAC+FTSI3(:)-FTSI4(:)
TRSI(:,4,I,J)=TRSI(:,4,I,J)*FRAC +FTSI4(:)
#endif
MSI(I,J)=MSINEW
SNOWI(I,J)=SNOWNEW
ELSE
RSI(I,J)=PLKIC/new_flake
END IF
C**** adjust layering if necessary
HLK=MWL(I,J)/(RHOW*new_flake*DXYP(J))
new_MLD=MIN(MAX(MINMLD,HLK-HLAKE(I,J)),HLK)
IF (MLDLK(I,J)*FLAKE(I,J).lt.new_flake*new_MLD) THEN
IF (FLAKE(I,J).eq.0 .or. HLK.le.new_MLD) THEN ! new or shallow lake
MLDLK(I,J)=new_MLD
#ifdef TRACERS_WATER
TOTTR(:)=TRLAKE(:,1,I,J)+TRLAKE(:,2,I,J)
TRLAKE(:,2,I,J)=TOTTR(:)*(HLK-MLDLK(I,J))/HLK
TRLAKE(:,1,I,J)=TOTTR(:)* MLDLK(I,J) /HLK
#endif
ELSE
#ifdef TRACERS_WATER
DTR(:)=TRLAKE(:,2,I,J)*(new_flake*new_MLD-MLDLK(I
* ,J)*FLAKE(I,J))/(HLK*new_flake-MLDLK(I,J)
* *FLAKE(I,J))
TRLAKE(:,1,I,J)=TRLAKE(:,1,I,J)+DTR(:)
TRLAKE(:,2,I,J)=TRLAKE(:,2,I,J)-DTR(:)
#endif
MLDLK(I,J)=new_MLD
END IF
ELSE
MLDLK(I,J)=MLDLK(I,J)*FLAKE(I,J)/new_flake
END IF
C**** adjust land surface fractions
FLAKE(I,J)=new_flake
FLAND(I,J)=1.-FLAKE(I,J)
FEARTH(I,J)=FLAND(I,J)-FLICE(I,J)
ELSE
C**** remove/do not create lakes that are too small
IF (FLAKE(I,J).gt.0) THEN
C**** transfer lake ice mass/energy for accounting purposes
IMLT=ACE1I+MSI(I,J)+SNOWI(I,J)
HMLT=SUM(HSI(:,I,J))
MWL(I,J)=MWL(I,J)+PLKIC*IMLT*DXYP(J)
GML(I,J)=GML(I,J)+PLKIC*HMLT*DXYP(J)
#ifdef TRACERS_WATER
DO ITM=1,NTM
TRLAKE(ITM,1,I,J)=TRLAKE(ITM,1,I,J)+TRLAKE(ITM,2,I,J
* )+RSI(I,J)*FLAKE(I,J)*SUM(TRSI(ITM,:,I,J))
* *DXYP(J)
TRSI(ITM,:,I,J)=0.
END DO
#endif
C**** save some diags
AJ(J,J_IMELT,ITLKICE)=AJ(J,J_IMELT,ITLKICE)+PLKIC*IMLT
AJ(J,J_HMELT,ITLKICE)=AJ(J,J_IMELT,ITLKICE)+PLKIC*HMLT
C**** Accumulate regional diagnostics
AREGJ(JR,J,J_IMELT)=AREGJ(JR,J,J_IMELT)+PLKIC*IMLT
* *DXYP(J)
AREGJ(JR,J,J_HMELT)=AREGJ(JR,J,J_HMELT)+PLKIC*HMLT
* *DXYP(J)
C****
RSI(I,J)=0.
SNOWI(I,J)=0.
HSI(1:2,I,J)=-LHM*XSI(1:2)*ACE1I
HSI(3:4,I,J)=-LHM*XSI(3:4)*AC2OIM
MSI(I,J)=AC2OIM
TLAKE(I,J)=GML(I,J)/(SHW*MWL(I,J)+teeny)
MLDLK(I,J)=MINMLD
FLAKE(I,J)=0.
FLAND(I,J)=1.
FEARTH(I,J)=FLAND(I,J)-FLICE(I,J)
END IF
END IF
END IF
END IF
END DO
END DO
end if
C****
CALL PRINTLK
("DY")
C**** Set GTEMP array for lakes
DO J=J_0, J_1
DO I=1,IMAXJ(J)
IF (FLAKE(I,J).gt.0) THEN
GTEMP(1,1,I,J)=TLAKE(I,J)
GTEMPR(1,I,J) =TLAKE(I,J)+TF
#ifdef TRACERS_WATER
GTRACER(:,1,I,J)=TRLAKE(:,1,I,J)/(MLDLK(I,J)*RHOW*FLAKE(I,J)
* *DXYP(J))
#endif
MLHC(I,J) = SHW*MLDLK(I,J)*RHOW
END IF
END DO
END DO
C****
RETURN
END SUBROUTINE daily_LAKE
SUBROUTINE PRECIP_LK 1,10
!@sum PRECIP_LK driver for applying precipitation/melt to lake fraction
!@auth Gavin Schmidt
!@ver 1.0
USE CONSTANT
, only : rhow,shw,teeny,tf
USE MODEL_COM
, only : im,jm,flice,itlake,itlkice
USE DOMAIN_DECOMP
, only : HALO_UPDATE, GRID,GET,NORTH,SOUTH
USE GEOM
, only : imaxj,dxyp,bydxyp
USE SEAICE_COM
, only : rsi
USE LAKES_COM
, only : mwl,gml,tlake,mldlk,flake
#ifdef TRACERS_WATER
* ,trlake,ntm
#endif
USE FLUXES
, only : runpsi,runoli,prec,eprec,gtemp,melti,emelti,
* gtempr
#ifdef TRACERS_WATER
* ,trunpsi,trunoli,trprec,gtracer,trmelti
#endif
USE DIAG_COM
, only : aj=>aj_loc,j_run,aij=>aij_loc,ij_lk
IMPLICIT NONE
REAL*8 PRCP,ENRGP,PLICE,PLKICE,RUN0,ERUN0,POLAKE,HLK1
INTEGER :: FROM,J_0,J_1,J_0H,J_1H,J_0S,J_1S,I_0H,I_1H
INTEGER I,J,ITYPE
#ifdef TRACERS_WATER
REAL*8, DIMENSION(NTM) :: TRUN0
#endif
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1,
& J_STRT_SKP=J_0S, J_STOP_SKP=J_1S)
CALL PRINTLK
("PR")
DO J=J_0, J_1
DO I=1,IMAXJ(J)
IF (FLAKE(I,J)+FLICE(I,J).gt.0) THEN
POLAKE=(1.-RSI(I,J))*FLAKE(I,J)
PLKICE=RSI(I,J)*FLAKE(I,J)
PLICE=FLICE(I,J)
PRCP=PREC(I,J)
ENRGP=EPREC(I,J) ! energy of precipitation
C**** calculate fluxes over whole box
RUN0 =POLAKE*PRCP + PLKICE* RUNPSI(I,J) + PLICE* RUNOLI(I,J)
ERUN0=POLAKE*ENRGP ! PLKICE*ERUNPSI(I,J) + PLICE*ERUNOLI(I,J) =0
C**** simelt is given as kg, so divide by area
IF (FLAKE(I,J).gt.0) THEN
RUN0 =RUN0+ MELTI(I,J)*BYDXYP(J)
ERUN0=ERUN0+EMELTI(I,J)*BYDXYP(J)
END IF
MWL(I,J) = MWL(I,J) + RUN0*DXYP(J)
GML(I,J) = GML(I,J) + ERUN0*DXYP(J)
#ifdef TRACERS_WATER
TRUN0(:) = POLAKE*TRPREC(:,I,J)*BYDXYP(J)
* + PLKICE*TRUNPSI(:,I,J) + PLICE *TRUNOLI(:,I,J)
IF (FLAKE(I,J).gt.0) TRUN0(:)=TRUN0(:)+TRMELTI(:,I,J)*BYDXYP(J)
TRLAKE(:,1,I,J)=TRLAKE(:,1,I,J) + TRUN0(:)*DXYP(J)
#endif
IF (FLAKE(I,J).gt.0) THEN
HLK1=TLAKE(I,J)*MLDLK(I,J)*RHOW*SHW
MLDLK(I,J)=MLDLK(I,J) + RUN0/(FLAKE(I,J)*RHOW)
TLAKE(I,J)=(HLK1*FLAKE(I,J)+ERUN0)/(MLDLK(I,J)*FLAKE(I,J)
* *RHOW*SHW)
GTEMP(1,1,I,J)=TLAKE(I,J)
GTEMPR(1,I,J) =TLAKE(I,J)+TF
IF (MWL(I,J).gt.(1d-10+MLDLK(I,J))*RHOW*FLAKE(I,J)*DXYP(J))
* THEN
GTEMP(2,1,I,J)=(GML(I,J)-TLAKE(I,J)*SHW*MLDLK(I,J)*RHOW
* *FLAKE(I,J)*DXYP(J))/(SHW*(MWL(I,J)-MLDLK(I,J)
* *RHOW*FLAKE(I,J)*DXYP(J)))
ELSE
GTEMP(2,1,I,J)=TLAKE(I,J)
END IF
#ifdef TRACERS_WATER
GTRACER(:,1,I,J)=TRLAKE(:,1,I,J)/(MLDLK(I,J)*RHOW*FLAKE(I,J)
* *DXYP(J))
#endif
AJ(J,J_RUN,ITLAKE) =AJ(J,J_RUN,ITLAKE) -PLICE*RUNOLI(I,J)
* *(1.-RSI(I,J))
AJ(J,J_RUN,ITLKICE)=AJ(J,J_RUN,ITLKICE)-PLICE*RUNOLI(I,J)
* *RSI(I,J)
ELSE
TLAKE(I,J)=GML(I,J)/(MWL(I,J)*SHW+teeny)
C**** accounting fix to ensure runoff with no lakes is counted
C**** no regional diagnostics required
AJ(J,J_RUN,ITLAKE) =AJ(J,J_RUN,ITLAKE)-PLICE*RUNOLI(I,J)
END IF
C**** save area diag
AIJ(I,J,IJ_LK) = AIJ(I,J,IJ_LK) + FLAKE(I,J)
END IF
END DO
END DO
RETURN
C****
END SUBROUTINE PRECIP_LK
SUBROUTINE GROUND_LK 1,16
!@sum GROUND_LK driver for applying surface fluxes to lake fraction
!@auth Gavin Schmidt
!@ver 1.0
!@calls
USE CONSTANT
, only : rhow,shw,teeny,tf
USE MODEL_COM
, only : im,jm,flice,fland,hlake
* ,dtsrc,itlake,itlkice
USE DOMAIN_DECOMP
, only : GRID, GET,GLOBALSUM, HALO_UPDATE,
* NORTH,SOUTH
USE GEOM
, only : imaxj,dxyp
USE FLUXES
, only : runosi, erunosi, e0, evapor, dmsi, dhsi, dssi,
* runoli, runoe, erunoe, solar, dmua, dmva, gtemp, gtempr
#ifdef TRACERS_WATER
* ,trunoli,trunoe,trevapor,dtrsi,trunosi,gtracer
#ifdef TRACERS_DRYDEP
* ,trdrydep
#endif
#endif
USE SEAICE_COM
, only : rsi
USE DIAG_COM
, only : aj=>aj_loc,aregj=>aregj_loc,jreg,j_wtr1
* ,j_wtr2,j_run,j_erun
USE LAKES_COM
, only : mwl,gml,tlake,mldlk,flake
#ifdef TRACERS_WATER
* ,trlake,ntm
USE TRDIAG_COM
,only: taijn=>taijn_loc , tij_lk1,tij_lk2
#endif
USE LAKES
, only : lkmix,lksourc,byzeta,minmld
USE GHY_COM
, only : fearth
IMPLICIT NONE
C**** grid box variables
REAL*8 ROICE, POLAKE, PLKICE, PEARTH, PLICE
!@var MLAKE,ELAKE mass and energy /m^2 for lake model layers
REAL*8, DIMENSION(2) :: MLAKE,ELAKE
C**** fluxes
REAL*8 EVAPO, FIDT, FODT, RUN0, ERUN0, RUNLI, RUNE, ERUNE,
* HLK1,TLK1,TLK2,TKE,SROX(2),FSR2, U2RHO
C**** output from LKSOURC
REAL*8 ENRGFO, ACEFO, ACEFI, ENRGFI
#ifdef TRACERS_WATER
REAL*8, DIMENSION(NTM) :: TRUN0,TRO,TRI,TREVAP,TOTTRL
REAL*8, DIMENSION(NTM,2) :: TRLAKEL
#endif
INTEGER I,J,JR
INTEGER :: J_0,J_1,J_0S,J_1S
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1,
& J_STRT_SKP=J_0S, J_STOP_SKP=J_1S)
CALL PRINTLK
("GR")
DO J=J_0, J_1
DO I=1,IMAXJ(J)
JR=JREG(I,J)
ROICE=RSI(I,J)
PLKICE=FLAKE(I,J)*ROICE
POLAKE=FLAKE(I,J)*(1.-ROICE)
C**** Add land ice and surface runoff to lake variables
IF (FLAND(I,J).gt.0) THEN
PLICE =FLICE(I,J)
PEARTH=FEARTH(I,J)
RUNLI=RUNOLI(I,J)
RUNE =RUNOE(I,J)
ERUNE=ERUNOE(I,J)
C**** calculate flux over whole box
RUN0 =RUNLI*PLICE + RUNE*PEARTH
ERUN0= ERUNE*PEARTH
MWL(I,J) = MWL(I,J) + RUN0*DXYP(J)
GML(I,J) = GML(I,J) +ERUN0*DXYP(J)
#ifdef TRACERS_WATER
TRLAKE(:,1,I,J)=TRLAKE(:,1,I,J)+
* (TRUNOLI(:,I,J)*PLICE+TRUNOE(:,I,J)*PEARTH)*DXYP(J)
#endif
IF (FLAKE(I,J).gt.0) THEN
HLK1=TLAKE(I,J)*MLDLK(I,J)*RHOW*SHW
MLDLK(I,J)=MLDLK(I,J) + RUN0/(FLAKE(I,J)*RHOW)
TLAKE(I,J)=(HLK1*FLAKE(I,J)+ERUN0)/(MLDLK(I,J)*FLAKE(I,J)
* *RHOW*SHW)
#ifdef TRACERS_WATER
GTRACER(:,1,I,J)=TRLAKE(:,1,I,J)/(MLDLK(I,J)*RHOW*FLAKE(I,J)
* *DXYP(J))
#endif
AJ(J,J_RUN,ITLAKE)=AJ(J,J_RUN,ITLAKE)-
* (RUNE*PEARTH+RUNLI*PLICE)*(1.-RSI(I,J))
AJ(J,J_RUN,ITLKICE)=AJ(J,J_RUN,ITLKICE)-
* (RUNE*PEARTH+RUNLI*PLICE)*RSI(I,J)
AJ(J,J_ERUN,ITLAKE )=AJ(J,J_ERUN,ITLAKE )-ERUNE*PEARTH*
* (1.-RSI(I,J))
AJ(J,J_ERUN,ITLKICE)=AJ(J,J_ERUN,ITLKICE)-ERUNE*PEARTH*
* RSI(I,J)
ELSE
TLAKE(I,J)=GML(I,J)/(MWL(I,J)*SHW+teeny)
C**** accounting fix to ensure runoff with no lakes is counted
C**** no regional diagnostics required
AJ(J,J_RUN,ITLAKE)=AJ(J,J_RUN,ITLAKE)-
* (RUNE*PEARTH+RUNLI*PLICE)
AJ(J,J_ERUN,ITLAKE )=AJ(J,J_ERUN,ITLAKE )-ERUNE*PEARTH
END IF
END IF
IF (FLAKE(I,J).gt.0) THEN
TLK1 =TLAKE(I,J)
EVAPO=EVAPOR(I,J,1) ! evap/dew over open lake (kg/m^2)
FODT =E0(I,J,1) ! net heat over open lake (J/m^2)
SROX(1)=SOLAR(1,I,J) ! solar radiation open lake (J/m^2)
SROX(2)=SOLAR(3,I,J) ! solar radiation through ice (J/m^2)
FSR2 =EXP(-MLDLK(I,J)*BYZETA)
C**** get ice-ocean fluxes from sea ice routine (over ice fraction)
RUN0 =RUNOSI(I,J) ! includes ACE2M + basal term
FIDT =ERUNOSI(I,J)
C**** calculate kg/m^2, J/m^2 from saved variables
MLAKE(1)=MLDLK(I,J)*RHOW
MLAKE(2)=MAX(MWL(I,J)/(FLAKE(I,J)*DXYP(J))-MLAKE(1),0d0)
ELAKE(1)=TLK1*SHW*MLAKE(1)
ELAKE(2)=GML(I,J)/(FLAKE(I,J)*DXYP(J))-ELAKE(1)
#ifdef TRACERS_WATER
TRLAKEL(:,:)=TRLAKE(:,:,I,J)/(FLAKE(I,J)*DXYP(J))
TRUN0(:)=TRUNOSI(:,I,J)
TREVAP(:)=TREVAPOR(:,1,I,J)
#ifdef TRACERS_DRYDEP
* -trdrydep(:,1,i,j)
#endif
#endif
IF (MLAKE(2).lt.1d-10) THEN
MLAKE(1)=MLAKE(1)+MLAKE(2)
MLAKE(2)=0.
ELAKE(1)=ELAKE(1)+ELAKE(2)
ELAKE(2)=0.
#ifdef TRACERS_WATER
TRLAKEL(:,1)=TRLAKEL(:,1)+TRLAKEL(:,2)
TRLAKEL(:,2)=0.
#endif
END IF
C**** Limit FSR2 in the case of thin second layer
FSR2=MIN(FSR2,MLAKE(2)/(MLAKE(1)+MLAKE(2)))
C**** Apply fluxes and calculate the amount of frazil ice formation
CALL LKSOURC
(I,J,ROICE,MLAKE,ELAKE,RUN0,FODT,FIDT,SROX,FSR2,
#ifdef TRACERS_WATER
* TRLAKEL,TRUN0,TREVAP,TRO,TRI,
#endif
* EVAPO,ENRGFO,ACEFO,ACEFI,ENRGFI)
C**** Mixing and entrainment
C**** Calculate turbulent kinetic energy for lake
c U2rho=(1.-ROICE)*SQRT(DMUA(I,J,1)**2+DMVA(I,J,1)**2)/DTSRC
c TKE=0.5 * (19.3)^(2/3) * U2rho /rhoair ! (m/s)^2
TKE=0. ! 3.6d0*U2rho/rhoair*MLAKE(1) ! (J/m^2)
CALL LKMIX
(MLAKE,ELAKE,
#ifdef TRACERS_WATER
* TRLAKEL,
#endif
* HLAKE(I,J),TKE,ROICE,DTSRC)
C**** Resave prognostic variables
MWL(I,J) =(MLAKE(1)+MLAKE(2))*(FLAKE(I,J)*DXYP(J))
GML(I,J) =(ELAKE(1)+ELAKE(2))*(FLAKE(I,J)*DXYP(J))
MLDLK(I,J)= MLAKE(1)/RHOW
IF (MLAKE(2).eq.0.) MLDLK(I,J)=MIN(MINMLD,MLDLK(I,J))
TLAKE(I,J)= ELAKE(1)/(SHW*MLAKE(1))
IF (MLAKE(2).gt.0) THEN
TLK2 = ELAKE(2)/(SHW*MLAKE(2))
ELSE
TLK2 = TLAKE(I,J)
END IF
#ifdef TRACERS_WATER
IF (MLAKE(2).eq.0. .and. MLAKE(1)-MLDLK(I,J)*RHOW.gt.1d-10) THEN
TOTTRL(:)=TRLAKEL(:,1)
TRLAKEL(:,2)=(MLAKE(1)-MLDLK(I,J)*RHOW)*TRLAKEL(:,1)/MLAKE(1)
TRLAKEL(:,1)=TOTTRL(:)-TRLAKEL(:,2)
END IF
TRLAKE(:,:,I,J)=TRLAKEL(:,:)*(FLAKE(I,J)*DXYP(J))
GTRACER(:,1,I,J)=TRLAKEL(:,1)/(MLDLK(I,J)*RHOW)
#endif
GTEMP(1,1,I,J)=TLAKE(I,J)
GTEMP(2,1,I,J)=TLK2 ! diagnostic only
GTEMPR(1,I,J) =TLAKE(I,J)+TF
C**** Open lake diagnostics
AJ(J,J_WTR1, ITLAKE)=AJ(J,J_WTR1, ITLAKE)+MLAKE(1)*POLAKE
AJ(J,J_WTR2, ITLAKE)=AJ(J,J_WTR2, ITLAKE)+MLAKE(2)*POLAKE
C**** Ice-covered ocean diagnostics
AJ(J,J_WTR1, ITLKICE)=AJ(J,J_WTR1, ITLKICE)+MLAKE(1)*PLKICE
AJ(J,J_WTR2, ITLKICE)=AJ(J,J_WTR2, ITLKICE)+MLAKE(2)*PLKICE
C**** regional diags
AREGJ(JR,J,J_WTR1)=AREGJ(JR,J,J_WTR1)+
* MLAKE(1)*FLAKE(I,J)*DXYP(J)
AREGJ(JR,J,J_WTR2)=AREGJ(JR,J,J_WTR2)+
* MLAKE(2)*FLAKE(I,J)*DXYP(J)
#ifdef TRACERS_WATER
C**** tracer diagnostics
TAIJN(I,J,tij_lk1,:)=TAIJN(I,J,tij_lk1,:)+TRLAKEL(:,1) !*PLKICE?
TAIJN(I,J,tij_lk2,:)=TAIJN(I,J,tij_lk2,:)+TRLAKEL(:,2) !*PLKICE?
#endif
C**** Store mass and energy fluxes for formation of sea ice
DMSI(1,I,J)=ACEFO
DMSI(2,I,J)=ACEFI
DHSI(1,I,J)=ENRGFO
DHSI(2,I,J)=ENRGFI
DSSI(:,I,J)=0. ! always zero salinity
#ifdef TRACERS_WATER
DTRSI(:,1,I,J)=TRO(:)
DTRSI(:,2,I,J)=TRI(:)
#endif
END IF
END DO ! i loop
END DO ! j loop
CALL PRINTLK
("G2")
RETURN
C****
END SUBROUTINE GROUND_LK
SUBROUTINE PRINTLK(STR) 6,8
!@sum PRINTLK print out selected diagnostics from specified lakes
!@auth Gavin Schmidt
!@ver 1.0
USE CONSTANT
, only : lhm,byshi,rhow,shw
USE MODEL_COM
, only : qcheck
USE GEOM
, only : dxyp
USE LAKES_COM
, only : tlake,mwl,mldlk,gml,flake
USE SEAICE
, only : xsi,ace1i,rhoi
USE SEAICE_COM
, only : rsi,hsi,msi,snowi
USE DOMAIN_DECOMP
, only : GRID, GET
IMPLICIT NONE
CHARACTER*2, INTENT(IN) :: STR
INTEGER, PARAMETER :: NDIAG=4
INTEGER I,J,N, J_0, J_1
INTEGER, DIMENSION(NDIAG) :: IDIAG = (/41, 66, 12, 31/),
* JDIAG = (/27, 15, 36, 41/)
REAL*8 HLK2,TLK2, TSIL(4)
IF (.NOT.QCHECK) RETURN
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1)
DO N=1,NDIAG
I=IDIAG(N)
J=JDIAG(N)
if (J.lt. J_0 .or. J.gt. J_1) CYCLE
IF (FLAKE(I,J).gt.0) THEN
HLK2 = MWL(I,J)/(RHOW*FLAKE(I,J)*DXYP(J)) - MLDLK(I,J)
IF (HLK2.gt.0) THEN
TLK2 = (GML(I,J)/(SHW*RHOW*FLAKE(I,J)*DXYP(J)) -
* TLAKE(I,J)*MLDLK(I,J))/HLK2
ELSE
TLK2=0.
END IF
TSIL(:)=0.
IF (RSI(I,J).gt.0) THEN
TSIL(1:2) = (HSI(1:2,I,J)/(XSI(1:2)*(ACE1I+SNOWI(I,J)))+LHM)
* *BYSHI
TSIL(3:4) = (HSI(3:4,I,J)/(XSI(3:4)*MSI(I,J))+LHM)*BYSHI
END IF
WRITE(99,*) STR,I,J,FLAKE(I,J),TLAKE(I,J),TLK2,MLDLK(I,J),HLK2
* ,RSI(I,J),MSI(I,J)/RHOI,SNOWI(I,J)/RHOW,TSIL(1:4)
ELSE
WRITE(99,*) STR,I,J,TLAKE(I,J),MWL(I,J)
END IF
END DO
RETURN
END SUBROUTINE PRINTLK
SUBROUTINE conserv_LKM(LKM),5
!@sum conserv_LKM calculates zonal lake mass
!@auth Gary Russell/Gavin Schmidt
!@ver 1.0
USE MODEL_COM
, only : im,jm,fland,fim
USE DOMAIN_DECOMP
, only : GRID, GET
USE GEOM
, only : imaxj,bydxyp
USE LAKES_COM
, only : mwl,flake
IMPLICIT NONE
REAL*8, DIMENSION(GRID%J_STRT_HALO:GRID%J_STOP_HALO) :: LKM
INTEGER :: I,J
INTEGER :: J_0,J_1,J_0S,J_1S
LOGICAL :: HAVE_SOUTH_POLE, HAVE_NORTH_POLE
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1,
& J_STRT_SKP=J_0S, J_STOP_SKP=J_1S,
& HAVE_SOUTH_POLE = HAVE_SOUTH_POLE,
& HAVE_NORTH_POLE = HAVE_NORTH_POLE )
C****
C**** LAKE MASS (kg/m^2)
C****
DO J=J_0, J_1
LKM(J)=0.
DO I=1,IMAXJ(J)
IF (FLAND(I,J)+FLAKE(I,J).gt.0) LKM(J)=LKM(J)+MWL(I,J)
END DO
LKM(J)=LKM(J)*BYDXYP(J)
END DO
IF (HAVE_SOUTH_POLE) LKM(1) =FIM*LKM(1)
IF (HAVE_NORTH_POLE) LKM(JM)=FIM*LKM(JM)
RETURN
END SUBROUTINE conserv_LKM
SUBROUTINE conserv_LKE(LKE),5
!@sum conserv_LKE calculates zonal lake energy
!@auth Gary Russell/Gavin Schmidt
!@ver 1.0
USE MODEL_COM
, only : im,jm,zatmo,fim,fland
USE DOMAIN_DECOMP
, only : GRID, GET
USE GEOM
, only : imaxj,bydxyp
USE LAKES_COM
, only : gml,mwl,flake
IMPLICIT NONE
REAL*8, DIMENSION(GRID%J_STRT_HALO:GRID%J_STOP_HALO) :: LKE
INTEGER :: I,J
INTEGER :: FROM,J_0,J_1,J_0S,J_1S
LOGICAL :: HAVE_SOUTH_POLE, HAVE_NORTH_POLE
CALL GET
(grid, J_STRT=J_0, J_STOP=J_1,
& J_STRT_SKP=J_0S, J_STOP_SKP=J_1S,
& HAVE_SOUTH_POLE=HAVE_SOUTH_POLE,
& HAVE_NORTH_POLE=HAVE_NORTH_POLE)
C****
C**** LAKE ENERGY (J/m^2) (includes potential energy (DISABLED))
C****
DO J=J_0, J_1
LKE(J)=0.
DO I=1,IMAXJ(J)
IF (FLAND(I,J)+FLAKE(I,J).gt.0) LKE(J)=LKE(J)+GML(I,J)
c * +ZATMO(I,J)*MWL(I,J)
END DO
LKE(J)=LKE(J)*BYDXYP(J)
END DO
IF (HAVE_SOUTH_POLE) LKE(1)=FIM*LKE(1)
IF (HAVE_NORTH_POLE) LKE(JM)=FIM*LKE(JM)
RETURN
END SUBROUTINE conserv_LKE