Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
357d6af
add issm fields to history
Feb 9, 2026
03321e6
add ISSM initialization parameters
Feb 11, 2026
81842f0
add issm tile mesh collection
Feb 13, 2026
7799149
add new issm outputs
Feb 16, 2026
820eb10
remove mesh save flag; history works now
Feb 16, 2026
f20df74
rm savemesh comment
Feb 17, 2026
70fbcbb
rm issm_expname, read at runtime
Mar 11, 2026
87b0114
add other issm outputs
Mar 11, 2026
93bc709
rename ice-equiv smb export (mesh)
Mar 12, 2026
19d9a4e
Merge branch 'develop' into feature/agstub/issm-history
gmao-rreichle Mar 13, 2026
a381424
Merge branch 'develop' into feature/agstub/issm-history
gmao-rreichle Mar 23, 2026
3f9682b
initial additions for issm_internals
Apr 6, 2026
c77cfbf
fixes
Apr 6, 2026
ba06a37
comment
Apr 6, 2026
1a76989
update history
Apr 24, 2026
103ef9d
remove ISSM_EXPDIR from LDAS.rc
Apr 29, 2026
2c330d0
Merge pull request #168 from GEOS-ESM/feature/agstub/issm-restarts
agstub Apr 29, 2026
5768e8d
add temporary issm file copy
agstub Apr 30, 2026
f3b361f
add issm checkpoint move to rs
agstub Apr 30, 2026
1b4d6ea
conditional gridded history for issm
May 19, 2026
63ff721
Merge branch 'develop' into feature/agstub/issm-history
May 19, 2026
55f9f8b
fix indent
May 19, 2026
4fc9d47
add issm bcs symlinks
May 19, 2026
a613ac3
fix indentation
May 20, 2026
2fbfbad
include slash in bcs link
May 20, 2026
c2788c0
fix indentation level
May 20, 2026
147a76b
put issm files from input into scratch
May 20, 2026
3b1a01c
fix input file dir path
May 20, 2026
342079e
fix issm cp command
May 26, 2026
7c6d5e9
move issm_mesh.nc to rc_out if exists
May 27, 2026
08c552a
double curly brace on issm copy command
May 27, 2026
59347b7
fix escape seq complaint
May 27, 2026
3e4303b
remove icesmb_issm from time-avg hist collection
Jun 10, 2026
2a456d3
no remap restarts for issm; bootstrap
Jun 18, 2026
eb0105c
Merge branch 'develop' into feature/agstub/issm-history
agstub Jun 18, 2026
f1d395a
make issm bcs also link to mesh file
Jun 19, 2026
ae05720
link issm restarts in case 1
Jun 22, 2026
a82e9d3
update changelog
Jun 26, 2026
dc5e429
add restrictions in issm zoom and restart options
Jun 30, 2026
d424035
copy initial issm rst to outpu rs
agstub Jul 1, 2026
7c1baa0
add with_issm check
Jul 8, 2026
56b7658
init empty issmRstFile str
Jul 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Added support for river routing.
- Added optional NetCDF4 output mode for ObsFcstAna, including NetCDF metadata and runtime context. Changed namelist variable "out_ObsFcstAna" from logical to integer.
- Added support for running ISSM (Ice-Sheet and Sea-level System Model). This includes a new collection in GEOSldas_HIST.rc (tavg24_1d_issm_Nt) as well as additions to the landice gridded collection (tavg24_2d_glac_Nx), and small additions to lenkf_j_template.py and ldas.py for handling ISSM boundary conditions and restarts.

### Changed

Expand Down
19 changes: 19 additions & 0 deletions GEOSldas_App/GEOSldas_HIST.rc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ COLLECTIONS:
# 'const_2d_lnd_Nx'
# 'tavg24_2d_glc_Nx'
# 'tavg24_1d_glc_Nt'
# 'tavg24_1d_issm_Nt'
# 'tavg24_1d_route'
::

Expand Down Expand Up @@ -531,6 +532,10 @@ EASEv2_M36.LM: 1
'ALBNF' , 'LANDICE' , 'ALBNF_GL' ,
'ASNOW_GL' , 'LANDICE' ,
'DELTS' , 'LANDICE' ,
'ICESMB' , 'LANDICE' ,
>>>HIST_ISSM<<< 'ICESURF' , 'LANDICE' ,
>>>HIST_ISSM<<< 'ICETHICK' , 'LANDICE' ,
>>>HIST_ISSM<<< 'ICEVEL' , 'LANDICE' ,
'DNICFLX' , 'LANDICE' ,
'EVAPOUT' , 'LANDICE' ,
'QH' , 'LANDICE' ,
Expand Down Expand Up @@ -597,4 +602,18 @@ EASEv2_M36.LM: 1
'QINFLOW' , 'ROUTE' ,
'QRUNOFF_CAT' , 'ROUTE' ,
::

tavg24_1d_issm_Nt.descr: 'Tile-space,Daily,Time-Averaged,Single-level,ISSM Diagnostics',
tavg24_1d_issm_Nt.nbits: 12,
tavg24_1d_issm_Nt.template: '%y4%m2%d2_%h2%n2z.nc4' ,
tavg24_1d_issm_Nt.mode: 'time-averaged' ,
tavg24_1d_issm_Nt.format: 'CFIO',
tavg24_1d_issm_Nt.frequency: 240000 ,
tavg24_1d_issm_Nt.ref_time: 000000 ,
tavg24_1d_issm_Nt.fields: 'ICESURF' , 'ISSM' ,
'ICETHICK' , 'ISSM' ,
'ICEVX' , 'ISSM' ,
'ICEVY' , 'ISSM' ,
::

# ========================== EOF ==============================================================
72 changes: 67 additions & 5 deletions GEOSldas_App/ldas.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,12 @@ def __init__(self, cmdLineArgs):
self.bcs_dir_land = ''
self.bcs_dir_geom = ''
self.bcs_dir_landshared = ''
self.bcs_dir_landiceshared = ''
self.tile_types = ''
self.with_land = False
self.with_landice = False
self.run_route = 0
self.with_issm = False
self.adas_expdir = ''

# assert necessary optional arguments in command line if exeinp file does not exsit
Expand Down Expand Up @@ -234,6 +236,10 @@ def __init__(self, cmdLineArgs):
assert int(self.ExeInputs['LSM_CHOICE']) <= 2, "\nLSM_CHOICE=3 (Catchment-CN4.5) is no longer supported. Please set LSM_CHOICE to 1 (Catchment) or 2 (Catchment-CN4.0)"
if "20" in self.tile_types :
self.with_landice = True

if self.with_landice == True:
if int(self.ExeInputs.get('DO_ISSM'))==1:
self.with_issm = True

self.run_route = int(self.ExeInputs.get('RUN_ROUTE',0))

Expand Down Expand Up @@ -261,6 +267,8 @@ def __init__(self, cmdLineArgs):
self.bcs_dir_land = self.ExeInputs['BCS_PATH']+ '/land/' + self.ExeInputs['BCS_RESOLUTION']+'/'
self.bcs_dir_geom = self.ExeInputs['BCS_PATH']+ '/geometry/' + self.ExeInputs['BCS_RESOLUTION']+'/'
self.bcs_dir_landshared = self.ExeInputs['BCS_PATH']+ '/land/shared/'
self.bcs_dir_landiceshared = self.ExeInputs['BCS_PATH']+ '/landice/shared/'


# make sure MET_PATH and RESTART_PATH have trailing '/'
if self.ExeInputs['MET_PATH'][-1] != '/':
Expand Down Expand Up @@ -448,6 +456,11 @@ def __init__(self, cmdLineArgs):
routeRstFile=self.in_rstdir+'/'+tmpFile
assert os.path.isfile(routeRstFile), 'route_internal_rst file [%s] does not exist!' %(routeRstFile)

if self.with_issm:
tmpFile=self.ExeInputs['RESTART_ID']+'.issm_internal_rst.'+y4m2d2_h2m2
issmRstFile=self.in_rstdir+'/'+tmpFile
assert os.path.isfile(issmRstFile), 'issm_internal_rst file [%s] does not exist!' %(issmRstFile)

# DEAL WITH mwRTM input from exec
self.assim = True if self.ExeInputs.get('LAND_ASSIM', 'NO').upper() == 'YES' and self.with_land else False
# verify mwrtm file
Expand Down Expand Up @@ -767,6 +780,9 @@ def createLnRstBc(self) :
# if running routing, make sure domain is global
if self.run_route>0 and self.isZoomIn:
exit( "Must have global domain to run routing model, RUN_ROUTE=" + self.run_route )
# if running ISSM, make sure domain is global
if self.with_issm and self.isZoomIn:
exit( "Must have global domain to run ISSM (DO_ISSM: 1)")

# update tile domain
if self.isZoomIn:
Expand Down Expand Up @@ -830,7 +846,13 @@ def createLnRstBc(self) :
if ("catchcn" in self.catch):
os.symlink(self.bcs_dir_landshared + 'CO2_MonthlyMean_DiurnalCycle.nc4', \
self.inpdir+'/CO2_MonthlyMean_DiurnalCycle.nc4')


if self.with_issm:
for pattern in ('*.bin', '*.toolkits', '*.nc*'):
for issmbc in glob.glob(self.bcs_dir_landiceshared + pattern):
myISSMBC = self.inpdir+'/'+os.path.basename(issmbc)
os.symlink(issmbc, myISSMBC)

# create and link restart
print ("Creating and linking restart...")
_start = self.begDates[0]
Expand Down Expand Up @@ -910,12 +932,15 @@ def createLnRstBc(self) :
catchRstFile0 = ''
vegdynRstFile0 = ''
landiceRstFile0 = ''
issmRstFile0 = ''

for iens in range(self.nens) :
ensdir = self.ensdirs[iens]
ensid = self.ensids[iens]
myCatchRst = myRstDir+'/'+ self.catch +ensid +'_internal_rst'
myLandiceRst = myRstDir+'/'+ 'landice' +ensid +'_internal_rst'
myVegRst = myRstDir+'/'+ 'vegdyn' +ensid +'_internal_rst'
myCatchRst = myRstDir+'/'+self.catch +ensid +'_internal_rst'
myLandiceRst = myRstDir+'/'+ 'landice' +ensid +'_internal_rst'
myIssmRst = myRstDir+'/'+ 'issm' +ensid +'_internal_rst'
myVegRst = myRstDir+'/'+ 'vegdyn'+ensid +'_internal_rst'
myPertRst = myRstDir+'/'+ 'landpert' +ensid +'_internal_rst'
myRouteRst = myRstDir+'/'+ 'route' +ensid +'_internal_rst'

Expand Down Expand Up @@ -972,11 +997,22 @@ def createLnRstBc(self) :
vegdynRstFile = vegdynRstFile0

landiceRstFile = ''
issmRstFile = ''
if self.with_landice :
if RESTART_str in ['1', '3'] :
landiceRstFile = rstpath+ensdir +'/'+ y4m2+'/'+self.ExeInputs['RESTART_ID']+'.'+'landice_internal_rst.'+y4m2d2_h2m2
if self.with_issm:
issmRstFile = rstpath+ensdir +'/'+ y4m2+'/'+self.ExeInputs['RESTART_ID']+'.'+'issm_internal_rst.'+y4m2d2_h2m2



if RESTART_str in ['2', 'M']:
landiceRstFile = glob.glob(self.exphome+'/'+exp_id+'/mk_restarts/*'+'landice_internal_rst.'+YYYYMMDD+'*')[0]
if self.with_issm and RESTART_str in ['2']:
exit( "Restart '2' not supported when running ISSM (DO_ISSM: 1)")
if self.with_issm and RESTART_str in ['M']:
print("issm_internal_rst will be bootstrapped for Restart 'M' ")


if os.path.isfile(landiceRstFile) :
landiceLocal = self.rstdir+ensdir +'/'+ y4m2+'/'+self.ExeInputs['EXP_ID']+'.landice_internal_rst.'+y4m2d2_h2m2
Expand All @@ -995,6 +1031,17 @@ def createLnRstBc(self) :
else :
landiceRstFile = landiceRstFile0

if self.with_issm:
if os.path.isfile(issmRstFile) :
issmLocal = self.rstdir+ensdir +'/'+ y4m2+'/'+self.ExeInputs['EXP_ID']+'.issm_internal_rst.'+y4m2d2_h2m2
shutil.copy(issmRstFile,issmLocal)
issmRstFile = issmLocal

if '0000' in ensdir :
issmRstFile0 = issmRstFile
else :
issmRstFile = issmRstFile0

routeRstFile = ''
if self.run_route > 0 :
if RESTART_str in ['1', '2'] :
Expand Down Expand Up @@ -1037,6 +1084,11 @@ def createLnRstBc(self) :
print("link route restart: " + myRouteRst)
os.symlink(routeRstFile, myRouteRst)

if self.with_issm:
if RESTART_str in ['1', '3']:
print("link issm restart: " + myIssmRst)
os.symlink(issmRstFile, myIssmRst)

if ( self.has_geos_pert and self.perturb == 1 ):
os.symlink(pertRstFile, myPertRst)

Expand Down Expand Up @@ -1189,7 +1241,8 @@ def createRCFiles(self):
+ str(self.ExeInputs['LSM_CHOICE']) + ' ' \
+ str(self.ExeInputs['AEROSOL_DEPOSITION']) + ' ' \
+ str(self.ExeInputs['RUN_IRRIG']) + ' ' \
+ str(self.nens)
+ str(self.nens) + ' ' \
+ str(self.ExeInputs['DO_ISSM'])
print(cmd)
#os.system(cmd)
sp.call(shlex.split(cmd))
Expand Down Expand Up @@ -1298,6 +1351,9 @@ def createRCFiles(self):
if self.with_landice:
rstkey.append('LANDICE')
rstval.append('landice')
if self.with_issm:
rstkey.append('ISSM')
rstval.append('issm')

if self.run_route > 0:
rstkey.append('ROUTE')
Expand Down Expand Up @@ -1336,6 +1392,12 @@ def createRCFiles(self):
valn = val + tmpl_ + '_internal_checkpoint'
ldasrcInp[keyn] = valn

if self.with_issm:
keyn = 'ISSM_INTERNAL_CHECKPOINT_FILE'
valn = 'issm'+tmpl_+'_internal_checkpoint'
ldasrcInp[keyn]= valn


# specify LANDPERT restart file
if (self.perturb == 1):
keyn = 'LANDPERT_INTERNAL_RESTART_FILE'
Expand Down
11 changes: 9 additions & 2 deletions GEOSldas_App/lenkf_j_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@
/bin/cp -f $HOMDIR/*.rc .
/bin/cp -f $HOMDIR/*.nml .

# copy ISSM input files to scratch
/bin/find $EXPDIR/input -maxdepth 1 -name "ISSM*" -exec /bin/cp {{}} . \\;

# move ISSM auxiliary mesh file to rc_out
if (-e $EXPDIR/input/ISSM_MESH.nc) /bin/mv $EXPDIR/input/ISSM_MESH.nc $EXPDIR/output/$EXPDOMAIN/rc_out

set LSMCHOICE = `grep -n -m 1 "LSM_CHOICE" $HOMDIR/LDAS.rc | cut -d':' -f3`

#######################################################################
Expand Down Expand Up @@ -721,7 +727,7 @@
set THISDIR = $EXPDIR/output/$EXPDOMAIN/rs/$ENSDIR/Y${{eYEAR}}/M${{eMON}}/
if (! -e $THISDIR ) mkdir -p $THISDIR

set rstfs = (${{LANDMODEL}} 'landice' 'route')
set rstfs = (${{LANDMODEL}} 'landice' 'route' 'issm')
foreach rstf ( $rstfs )
if (-f ${{rstf}}${{ENSID}}_internal_checkpoint ) then
set tmp_file = $EXPDIR/output/$EXPDOMAIN/rs/$ENSDIR/Y${{eYEAR}}/M${{eMON}}/${{EXPID}}.${{rstf}}_internal_rst.${{eYEAR}}${{eMON}}${{eDAY}}_${{eHour}}${{eMin}}
Expand Down Expand Up @@ -759,8 +765,9 @@
set rstfiles2 = `ls landpert${{ENSID}}_internal_checkpoint.*`
set rstfiles3 = `ls landassim_obspertrseed${{ENSID}}_checkpoint.*`
set rstfiles4 = `ls landice${{ENSID}}_internal_checkpoint.*`
set rstfiles5 = `ls issm${{ENSID}}_internal_checkpoint.*`

foreach rfile ( $rstfiles1 $rstfiles4 )
foreach rfile ( $rstfiles1 $rstfiles4 $rstfiles5 )
set ThisTime = `echo $rfile | rev | cut -d'.' -f2 | rev`
set TY = `echo $ThisTime | cut -c1-4`
set TM = `echo $ThisTime | cut -c5-6`
Expand Down
8 changes: 8 additions & 0 deletions GEOSldas_App/process_hist.csh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ setenv LSM_CHOICE $4
setenv AEROSOL_DEPOSITION $5
setenv RUN_IRRIG $6
setenv NENS $7
setenv DO_ISSM $8


# -------------------------------------------------

Expand Down Expand Up @@ -67,6 +69,12 @@ else
sed -i 's/>>>HIST_IRRIG<<</''/g' $HISTRC
endif

if($DO_ISSM == 0) then
sed -i '/^>>>HIST_ISSM<<</d' $HISTRC
else
sed -i 's/>>>HIST_ISSM<<</''/g' $HISTRC
endif

# for ensemble simulations, set 'GridComp' to ENSAVG

if($NENS > 1) then
Expand Down
Loading