Skip to content

Commit d11acb8

Browse files
authored
Merge pull request #753 from GEOS-ESM/develop
Sync develop into main
2 parents 91c183c + d4ec019 commit d11acb8

File tree

34 files changed

+3867
-1740
lines changed

34 files changed

+3867
-1740
lines changed

GEOSagcm_GridComp/GEOSphysics_GridComp/GEOSsurface_GridComp/GEOSlake_GridComp/GEOS_LakeGridComp.F90

Lines changed: 154 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
! $Id$
22

3+
#define _DEALLOC(A) \
4+
if(associated(A))then; \
5+
if(MAPL_ShmInitialized)then; \
6+
call MAPL_SyncSharedMemory(rc=STATUS); \
7+
call MAPL_DeAllocNodeArray(A,rc=STATUS); \
8+
else; \
9+
deallocate(A,stat=STATUS); \
10+
endif; \
11+
_VERIFY(STATUS); \
12+
NULLIFY(A); \
13+
endif
14+
315
#include "MAPL_Generic.h"
416

517

@@ -25,7 +37,13 @@ module GEOS_LakeGridCompMod
2537
integer, parameter :: NUM_SUBTILES = 2
2638

2739
type lake_state
28-
integer:: CHOOSEMOSFC
40+
private
41+
integer:: CHOOSEMOSFC
42+
logical :: InitDone
43+
logical, pointer :: mask(:) => null()
44+
real :: tol_frice
45+
character(len=ESMF_MAXSTR) :: sstfile
46+
character(len=ESMF_MAXSTR) :: DataFrtFile
2947
end type lake_state
3048

3149
type lake_state_wrap
@@ -854,6 +872,7 @@ subroutine SetServices ( GC, RC )
854872

855873
allocate(mystate,stat=status)
856874
VERIFY_(status)
875+
mystate%InitDone = .false.
857876
call MAPL_GetResource (MAPL, SURFRC, label = 'SURFRC:', default = 'GEOS_SurfaceGridComp.rc', RC=STATUS) ; VERIFY_(STATUS)
858877
SCF = ESMF_ConfigCreate(rc=status) ; VERIFY_(STATUS)
859878
call ESMF_ConfigLoadFile (SCF,SURFRC,rc=status) ; VERIFY_(STATUS)
@@ -914,8 +933,6 @@ subroutine RUN1 ( GC, IMPORT, EXPORT, CLOCK, RC )
914933

915934
type (MAPL_MetaComp), pointer :: MAPL
916935
type (ESMF_State ) :: INTERNAL
917-
type (ESMF_Alarm ) :: ALARM
918-
type (ESMF_Config ) :: CF
919936

920937
! pointers to export
921938

@@ -1553,6 +1570,13 @@ subroutine LAKECORE(NT,RC)
15531570
real, parameter :: LAKECAP = (MAPL_RHOWTR*MAPL_CAPWTR*LAKEDEPTH )
15541571
real, parameter :: LAKEICECAP = (MAPL_RHOWTR*MAPL_CAPWTR*LAKEICEDEPTH )
15551572

1573+
logical :: datalake
1574+
integer :: dlk
1575+
real, allocatable :: DATA_SST(:), DATA_FR(:)
1576+
character(len=ESMF_MAXSTR) :: maskfile
1577+
real, parameter :: Tfreeze = MAPL_TICE - 1.8
1578+
type(lake_state_wrap) :: wrap
1579+
type(lake_state), pointer :: mystate
15561580

15571581
! Begin...
15581582
!----------
@@ -1713,6 +1737,80 @@ subroutine LAKECORE(NT,RC)
17131737
if(associated(QST )) QST = 0.0
17141738
if(associated(HLWUP )) HLWUP = ALW
17151739
if(associated(LWNDSRF)) LWNDSRF = LWDNSRF - ALW
1740+
! datalake addition
1741+
!==================
1742+
1743+
! check resource if datalake is enabled
1744+
call MAPL_GetResource ( MAPL, DLK, Label="DATALAKE:", DEFAULT=0, RC=STATUS)
1745+
VERIFY_(STATUS)
1746+
DATALAKE = (DLK /= 0)
1747+
1748+
call ESMF_UserCompGetInternalState(gc,'lake_private',wrap,status)
1749+
VERIFY_(status)
1750+
mystate => wrap%ptr
1751+
1752+
! Initialize a mask where we could apply the SST/FR from Reynolds/Ostia
1753+
if (.not. associated(mystate%mask)) then
1754+
allocate(mystate%mask(NT), stat=status); VERIFY_(STATUS)
1755+
mystate%mask = .false.
1756+
end if
1757+
1758+
if (datalake) then
1759+
1760+
! next section is done only once. We do it here since the Initalize
1761+
! method of this component defaults to MAPL_GenericInitialize
1762+
1763+
if (.not. mystate%InitDone) then
1764+
mystate%InitDone = .true.
1765+
call MAPL_GetResource ( MAPL, mystate%sstfile, &
1766+
Label="LAKE_SST_FILE:", DEFAULT="sst.data", RC=STATUS)
1767+
VERIFY_(STATUS)
1768+
call MAPL_GetResource ( MAPL, mystate%dataFrtFile, &
1769+
Label="LAKE_FRT_FILE:", DEFAULT="fraci.data", RC=STATUS)
1770+
VERIFY_(STATUS)
1771+
call MAPL_GetResource ( MAPL, mystate%tol_frice, &
1772+
Label="LAKE_TOL_FRICE:", DEFAULT=1.0e-2, RC=STATUS)
1773+
VERIFY_(STATUS)
1774+
1775+
call MAPL_GetResource ( MAPL, MASKFILE, &
1776+
Label="DATALAKE_MASK_FILE:", DEFAULT="DataLakeMask.data", RC=STATUS)
1777+
VERIFY_(STATUS)
1778+
1779+
!ALT: For now we are reading the entire mask from a file
1780+
! we might decide later to use a different strategy (for example
1781+
! Santha suggested lat-lon based description)
1782+
1783+
call DataLakeReadMask(MAPL, mystate%mask, &
1784+
maskfile, RC=status)
1785+
VERIFY_(STATUS)
1786+
end if
1787+
1788+
1789+
allocate(DATA_SST(NT), DATA_FR(NT), stat=status); VERIFY_(STATUS)
1790+
call MAPL_ReadForcing(MAPL, 'SST', mystate%sstfile,&
1791+
CURRENT_TIME, DATA_SST, RC=STATUS)
1792+
VERIFY_(STATUS)
1793+
call MAPL_ReadForcing(MAPL, 'FR', mystate%dataFrtFile,&
1794+
CURRENT_TIME, DATA_FR, RC=STATUS)
1795+
VERIFY_(STATUS)
1796+
1797+
do I=1,NT
1798+
if(mystate%mask(i)) then
1799+
! we are operating over the 'observed' lake: Great Lakes and Caspian Sea (set by mask)
1800+
TS(I,WATER) = DATA_SST(I)
1801+
TS(I,ICE) = Tfreeze
1802+
if (data_fr(i) > mystate%tol_frice) then !have lake ice
1803+
FR(I,WATER) = 1.0-DATA_FR(I)
1804+
FR(I,ICE) = DATA_FR(I)
1805+
else
1806+
FR(I,WATER) = 1.0
1807+
FR(I,ICE) = 0.0
1808+
end if
1809+
end if
1810+
end do
1811+
1812+
deallocate(DATA_SST, DATA_FR)
1813+
end if
17161814

17171815
do N=1,NUM_SUBTILES
17181816
CFT = (CH(:,N)/CTATM)
@@ -1749,7 +1847,7 @@ subroutine LAKECORE(NT,RC)
17491847
! Update surface temperature and moisture
17501848
!----------------------------------------
17511849

1752-
TS(:,N) = TS(:,N) + DTS
1850+
where(.not.mystate%mask) TS(:,N) = TS(:,N) + DTS
17531851
DQS = GEOS_QSAT(TS(:,N), PS, RAMP=0.0, PASCALS=.TRUE.) - QS(:,N)
17541852
QS(:,N) = QS(:,N) + DQS
17551853

@@ -1773,6 +1871,10 @@ subroutine LAKECORE(NT,RC)
17731871
! Update Ice fraction
17741872
!--------------------
17751873
do I=1,NT
1874+
!$ if(mystate%mask(i)) cycle
1875+
if(mystate%mask(i)) then
1876+
cycle
1877+
end if
17761878
if (TS(I,ICE)>MAPL_TICE .and. FR(I,ICE)>0.0) then
17771879
! MELT
17781880
FR(I,WATER) = 1.0
@@ -1919,6 +2021,54 @@ end subroutine ALBLAKEICE
19192021

19202022
end subroutine RUN2
19212023

2024+
subroutine DataLakeReadMask(mapl, msk, maskfile, rc)
2025+
implicit none
2026+
! arguments
2027+
type (MAPL_MetaComp), pointer :: MAPL
2028+
logical, intent(INOUT) :: msk(:)
2029+
character(len=*), intent(IN) :: maskfile
2030+
integer, optional, intent(OUT) :: rc
2031+
2032+
! errlog vars
2033+
integer :: status
2034+
character(len=ESMF_MAXSTR), parameter :: Iam='DataLakeReadMask'
2035+
2036+
! local vars
2037+
integer :: unit
2038+
integer, pointer :: tilemask(:) => null()
2039+
type(ESMF_Grid) :: TILEGRID
2040+
type(MAPL_LocStream) :: LOCSTREAM
2041+
integer :: NT
2042+
real, allocatable :: imask(:)
2043+
2044+
! this is the first attempt to read the mask. For now we support binary
2045+
call MAPL_Get(MAPL, LocStream=LOCSTREAM, RC=STATUS)
2046+
VERIFY_(STATUS)
2047+
call MAPL_LocStreamGet(LOCSTREAM, TILEGRID=TILEGRID, RC=STATUS)
2048+
VERIFY_(STATUS)
2049+
2050+
call MAPL_TileMaskGet(tilegrid, tilemask, rc=status)
2051+
VERIFY_(STATUS)
2052+
2053+
nt = size(msk)
2054+
allocate(imask(nt), stat=status)
2055+
2056+
unit = GETFILE( maskfile, form="unformatted", RC=STATUS )
2057+
VERIFY_(STATUS)
2058+
2059+
call MAPL_VarRead(unit, tilegrid, imask, mask=tilemask, rc=status)
2060+
VERIFY_(STATUS)
2061+
2062+
call FREE_FILE(unit, RC=STATUS)
2063+
VERIFY_(STATUS)
2064+
2065+
msk = (imask /= 0.0)
2066+
deallocate(imask)
2067+
_DEALLOC(tilemask)
2068+
2069+
RETURN_(ESMF_SUCCESS)
2070+
end subroutine DataLakeReadMask
2071+
19222072
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
19232073

19242074
end module GEOS_LakeGridCompMod
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#define _ASSERT(cond) if(.not. cond) then; print*, 'ERROR at ', __LINE__; stop; endif
2+
program maskLakes
3+
implicit none
4+
5+
integer, parameter :: HDR_SIZE=14
6+
integer :: header(HDR_SIZE)
7+
real :: hdr(HDR_SIZE)
8+
9+
integer :: nt, nl
10+
integer :: ng
11+
character(len=128), parameter :: filename='mask.bin'
12+
character(len=128), parameter :: tilefile='tile.bin'
13+
real, allocatable :: lats(:), lons(:)
14+
integer, allocatable :: t(:)
15+
real, allocatable :: buffer(:)
16+
real, allocatable :: omask(:,:) ! mask on OSTIA grid
17+
integer :: im, jm
18+
integer :: i, j, n
19+
integer :: status
20+
integer :: unit
21+
real, allocatable :: mask(:)
22+
real :: x0, y0, dx, dy
23+
24+
! read OSTIA mask
25+
unit=10
26+
open(unit=unit, file=filename, form='unformatted')
27+
read(unit) hdr
28+
header = nint(hdr)
29+
im = header(13)
30+
jm = header(14)
31+
print *,'DEBUG: im/jm',im,jm
32+
33+
allocate(omask(im,jm), stat=status)
34+
_ASSERT(status == 0)
35+
read(unit) omask
36+
close(unit)
37+
38+
! process tile file
39+
unit=11
40+
open(unit=unit, file=tilefile, form='unformatted')
41+
read(unit) nt
42+
print *,'DEBUG ntiles ',nt
43+
read(unit) ng
44+
print *,'DEBUG ngrids ',ng
45+
do i=1,ng
46+
! 3 blank read for im, jm, gridname
47+
read(unit)
48+
read(unit)
49+
read(unit)
50+
end do
51+
allocate(buffer(nt), stat=status)
52+
_ASSERT(status == 0)
53+
! get typetype
54+
read(unit) buffer
55+
t = nint(buffer)
56+
nl = count(t==19) ! number of lake tiles
57+
print *,'DEBUG lake points ',nl
58+
allocate(lons(nl), lats(nl), mask(nl), stat=status)
59+
_ASSERT(status == 0)
60+
mask = 0.0
61+
62+
! get X
63+
read(unit) buffer
64+
lons = pack(buffer, t==19)
65+
! get Y
66+
read(unit) buffer
67+
lats = pack(buffer, t==19)
68+
close(unit)
69+
70+
! the OSTIA grid origin is at the pole edge, dateline edge
71+
x0 = -180.0
72+
y0 = -90.0
73+
dx = 360. / im
74+
dy = 180. / jm
75+
76+
! convert tile lat/lon to Ostia grid indices
77+
do n=1,nl
78+
i = nint((lons(n)-x0)/dx - 0.5)
79+
j = nint((lats(n)-y0)/dy -0.5)+1
80+
i = mod(i+im,im)+1
81+
if (i<=0 .or. j<=0) print *,i,j,n,lats(n),lons(n)
82+
if (i>im .or. j>jm) print *,i,j,n,lats(n),lons(n)
83+
_ASSERT(i>0 .and. i<im)
84+
_ASSERT(j>0 .and. j<jm)
85+
86+
if(omask(i,j) /= 0.0) then
87+
mask(n) = 1.0
88+
print *,'DEBUG: masked lake at ',n,lons(n),lats(n)
89+
end if
90+
end do
91+
92+
! some sanity check/prints
93+
print *,'done, processed ',nl,' lake points, found ',count(mask/=0.0)
94+
95+
! ultimately, write mask
96+
unit=12
97+
open(unit=unit, file='lakemask.bin', form='unformatted')
98+
write(unit) mask
99+
close(unit)
100+
101+
! all done
102+
end program maskLakes

GEOSagcm_GridComp/GEOSphysics_GridComp/GEOSsurface_GridComp/GEOSland_GridComp/GEOScatchCN_GridComp/GEOScatchCNCLM40_GridComp/GEOS_CatchCNCLM40GridComp.F90

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5003,7 +5003,7 @@ subroutine Driver ( RC )
50035003

50045004
type(ESMF_Config) :: CF
50055005
type(MAPL_SunOrbit) :: ORBIT
5006-
type(ESMF_Time) :: CURRENT_TIME, StopTime, NextTime
5006+
type(ESMF_Time) :: CURRENT_TIME, StopTime, NextTime, NextRecordTime
50075007
type(ESMF_Time) :: BEFORE
50085008
type(ESMF_Time) :: NOW
50095009
type(ESMF_Time) :: MODELSTART
@@ -5167,6 +5167,10 @@ subroutine Driver ( RC )
51675167
! Variables for FPAR
51685168
! --------------------------
51695169
real , allocatable, dimension (:,:) :: parzone
5170+
5171+
logical :: record
5172+
type(ESMF_Alarm) :: RecordAlarm
5173+
51705174
character(len=ESMF_MAXSTR) :: Co2_CycleFile
51715175

51725176
IAm=trim(COMP_NAME)//"::RUN2::Driver"
@@ -6843,7 +6847,14 @@ subroutine Driver ( RC )
68436847

68446848
! copy CN_restart vars to catch_internal_rst gkw: only do if stopping
68456849
! ------------------------------------------
6846-
if(NextTime == StopTime) then
6850+
record = .false.
6851+
call ESMF_ClockGetAlarm ( CLOCK, alarmname="RecordAlarm001", ALARM=RecordAlarm, RC=STATUS )
6852+
if (status == 0) then
6853+
call ESMF_AlarmGet( RecordAlarm, RingTime=NextRecordTime, _RC)
6854+
if (NextTime == NextRecordTime) record = .true.
6855+
endif
6856+
6857+
if(NextTime == StopTime .or. record ) then
68476858

68486859
call CN_exit(ntiles,nveg,nzone,ityp,fveg,cncol,var_col,cnpft,var_pft)
68496860
i = 1

0 commit comments

Comments
 (0)