From 68d08a1e10bb22782137fa0d852b1698e2a31520 Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Wed, 11 Feb 2026 12:32:41 -0500 Subject: [PATCH 1/9] exclude tile2pfaf nc4 file which is not a tile file --- GEOSldas_App/ldas.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index bdab4f6..a7f5745 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -296,6 +296,8 @@ def __init__(self, cmdLineArgs): if 'MAPL_' in os.path.basename(f): txt_tile = [f] break + nc4_tmp = glob.glob(inpgeom_ + '*.nc4' + domain_) + nc4_tile = [ item_ for item_ in nc4_tmp if 'tile2pfaf' not in item_ ] nc4_tile = glob.glob(inpgeom_ + '*.nc4' + domain_) if tile_file_format.upper() == 'TXT' : self.ExeInputs['TILING_FILE'] = txt_tile[0] if tile_file_format.upper() == 'DEFAULT' : self.ExeInputs['TILING_FILE'] = (txt_tile+nc4_tile)[-1] From 97e88643a5909e52efc7443884722a60a21f084f Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang <52509753+weiyuan-jiang@users.noreply.github.com> Date: Wed, 11 Feb 2026 14:11:07 -0500 Subject: [PATCH 2/9] remove extra line in ldas.py Removed redundant glob call for nc4_tile. --- GEOSldas_App/ldas.py | 1 - 1 file changed, 1 deletion(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index a7f5745..1503867 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -298,7 +298,6 @@ def __init__(self, cmdLineArgs): break nc4_tmp = glob.glob(inpgeom_ + '*.nc4' + domain_) nc4_tile = [ item_ for item_ in nc4_tmp if 'tile2pfaf' not in item_ ] - nc4_tile = glob.glob(inpgeom_ + '*.nc4' + domain_) if tile_file_format.upper() == 'TXT' : self.ExeInputs['TILING_FILE'] = txt_tile[0] if tile_file_format.upper() == 'DEFAULT' : self.ExeInputs['TILING_FILE'] = (txt_tile+nc4_tile)[-1] From 0618cfc5969d97f2fdb345789cbf8428596e10dd Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Wed, 18 Feb 2026 14:59:20 -0500 Subject: [PATCH 3/9] fix bug to find extention and reorg. assert if domain is wrong --- GEOSldas_App/ldas.py | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index 1503867..3248bfe 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -279,15 +279,30 @@ def __init__(self, cmdLineArgs): inpdir_ = self.bcs_dir_land inpgeom_ = self.bcs_dir_geom - if self.ExeInputs['RESTART'] == '1' : - inp_ = self.ExeInputs['RESTART_PATH']+'/'.join([self.ExeInputs['RESTART_ID'],'output', + + # find restart files and tile files (if necessary) + RESTART_str = str(self.ExeInputs['RESTART']) + + inp_ = self.ExeInputs['RESTART_PATH']+'/'.join([self.ExeInputs['RESTART_ID'],'output', self.ExeInputs['RESTART_DOMAIN'], 'rc_out/']) + if RESTART_str == '1' : + inpdir_ = inp_ + inpgeom_ = inp_ txt_tile = glob.glob(inp_ + '*.domain') if len(txt_tile) > 0: domain_ = '.domain' - inpdir_ = inp_ - inpgeom_ = inp_ - + elif RESTART_str == '2': + txt_tile = glob.glob(inp_ + '*.domain') + assert len(txt_tile) == 0, "RESTART = 2 should restart from global domain" + in_tilefiles_ = glob.glob(inp_+'MAPL_*.til') + if len(in_tilefiles_) == 0 : + nc4_tmp = glob.glob(inp_+'/*.nc4') + in_tilesfile_ = [ item_ for item_ in nc4_tmp if 'tile2pfaf' not in item_ ] + if len(in_tilefiles_) == 0 : + in_tilefiles_ = glob.glob(inp_+'/*.til') + self.in_tilefile =os.path.realpath(in_tilefiles_[0]) + + inpdir_ = os.path.realpath(inpdir_)+'/' inpgeom_ = os.path.realpath(inpgeom_)+'/' @@ -317,7 +332,7 @@ def __init__(self, cmdLineArgs): tmptile = os.path.realpath(self.ExeInputs['TILING_FILE']) extension = os.path.splitext(tmptile)[1] if extension == '.domain': - extension = os.path.splitext(tmptile)[0] + extension = os.path.splitext(os.path.splitext(tmptile)[0])[1] gridname_ ='' if extension == '.til': gridname_ = linecache.getline(tmptile, 3).strip() @@ -348,6 +363,7 @@ def __init__(self, cmdLineArgs): for key,val in _domain_dic.items() : if key in self.ExeInputs : _domain_dic[key]= self.ExeInputs[key] + assert RESTART_str != 2, "Please comment out " + key + " event you set it global" self.domain_def = tempfile.NamedTemporaryFile(mode='w', delete=False) self.domain_def.write('&domain_inputs\n') for key,val in _domain_dic.items() : @@ -360,21 +376,6 @@ def __init__(self, cmdLineArgs): self.domain_def.write('/\n') self.domain_def.close() - # find restart files and tile files (if necessary) - RESTART_str = str(self.ExeInputs['RESTART']) - - if RESTART_str == '2': - inpdir=self.ExeInputs['RESTART_PATH']+self.ExeInputs['RESTART_ID']+'/input/' - in_tilefiles_ = glob.glob(inpdir+'*tile.data') - if len(in_tilefiles_) == 0 : - inpdir=self.ExeInputs['RESTART_PATH']+self.ExeInputs['RESTART_ID']+'/output/'+self.ExeInputs['RESTART_DOMAIN']+'/rc_out/' - in_tilefiles_ = glob.glob(inpdir+'MAPL_*.til') - if len(in_tilefiles_) == 0 : - in_tilefiles_ = glob.glob(inpdir+'/*.til') - if len(in_tilefiles_) == 0 : - in_tilefiles_ = glob.glob(inpdir+'/*.nc4') - self.in_tilefile =os.path.realpath(in_tilefiles_[0]) - if RESTART_str in ['1', '2']: y4m2='Y%4d/M%02d' % (self.begDates[0].year, self.begDates[0].month) y4m2d2_h2m2='%4d%02d%02d_%02d%02d' % (self.begDates[0].year, self.begDates[0].month, From 5cae2f1cdf8888e5ff1ce050eeb4bef044b4bbd3 Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Wed, 18 Feb 2026 15:29:27 -0500 Subject: [PATCH 4/9] fix indent --- GEOSldas_App/ldas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index 3248bfe..bc318e7 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -362,7 +362,7 @@ def __init__(self, cmdLineArgs): for key,val in _domain_dic.items() : if key in self.ExeInputs : - _domain_dic[key]= self.ExeInputs[key] + _domain_dic[key]= self.ExeInputs[key] assert RESTART_str != 2, "Please comment out " + key + " event you set it global" self.domain_def = tempfile.NamedTemporaryFile(mode='w', delete=False) self.domain_def.write('&domain_inputs\n') From fc0e9edd52a20342e6d9fb60d1c3c4a6c4e14c6e Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Mon, 2 Mar 2026 11:14:39 -0500 Subject: [PATCH 5/9] check bcs_path and resolution when RESTART = 1 --- GEOSldas_App/ldas.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index bc318e7..e8ecda4 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -288,6 +288,14 @@ def __init__(self, cmdLineArgs): if RESTART_str == '1' : inpdir_ = inp_ inpgeom_ = inp_ + BCS_txt = glob.glob(inp_ + 'BCS.txt') + if len(BCS_txt)== 0: + print("Warning: There is no BCS.txt in rc_out. The BCS in the restart directory may not be consistent with " + self.ExeInputs['BCS_PATH']) + elif len(BCS_txt)== 1: + BCS_tmp = parseInputFile(BCS_txt[0]) + assert self.ExeInputs['BCS_PATH'] == BCS_tmp['BCS_PATH'], "BCS_PATH does not match " + BCS_tmp['BCS_PATH'] + " in restart directoy" + assert self.ExeInputs['BCS_RESOLUTION'] == BCS_tmp['BCS_RESOLUTION'], "BCS resolution or gridname should be the same for RESTART =1" + txt_tile = glob.glob(inp_ + '*.domain') if len(txt_tile) > 0: domain_ = '.domain' @@ -474,7 +482,7 @@ def __init__(self, cmdLineArgs): self.scratchdir = self.expdir + '/scratch' self.blddirLn = self.expdir + '/build' self.out_path = self.outdir + '/'+self.ExeInputs['EXP_DOMAIN'] - self.bcsdir = self.outdir + '/'+self.ExeInputs['EXP_DOMAIN']+'/rc_out/' + self.rc_out = self.outdir + '/'+self.ExeInputs['EXP_DOMAIN']+'/rc_out/' self.rstdir = self.outdir + '/'+self.ExeInputs['EXP_DOMAIN']+'/rs/' self.exefyl = self.blddirLn + exefyl @@ -691,13 +699,13 @@ def createLnRstBc(self) : # update tile file tile= self.ExeInputs['TILING_FILE'] short_tile= os.path.basename(self.ExeInputs['TILING_FILE']) - newtile = self.bcsdir+'/'+short_tile + newtile = self.rc_out+'/'+short_tile shutil.copy(tile, newtile) tile=newtile # if three extra lines exist, remove them and save it to inputdir print ('\nCorrect the tile file if it is an old EASE tile format... \n') - EASEtile=self.bcsdir+'/MAPL_'+short_tile + EASEtile=self.rc_out+'/MAPL_'+short_tile cmd = self.bindir + '/preprocess_ldas.x correctease '+ tile + ' '+ EASEtile print ("cmd: " + cmd) @@ -764,8 +772,8 @@ def createLnRstBc(self) : bcs += [self.ExeInputs['VEGOPACITY_FILE']] bcstmp=[] for bcf in bcs : - shutil.copy(bcf, self.bcsdir+'/') - bcstmp=bcstmp+[self.bcsdir+'/'+os.path.basename(bcf)] + shutil.copy(bcf, self.rc_out+'/') + bcstmp=bcstmp+[self.rc_out+'/'+os.path.basename(bcf)] bcs=bcstmp if self.isZoomIn: @@ -803,13 +811,6 @@ def createLnRstBc(self) : myRstDir = self.inpdir + '/restart/' - rstpath = self.ExeInputs['RESTART_PATH']+ \ - self.ExeInputs['RESTART_ID'] + \ - '/output/'+self.ExeInputs['RESTART_DOMAIN']+'/rs/' - rcoutpath = self.ExeInputs['RESTART_PATH']+ \ - self.ExeInputs['RESTART_ID'] + \ - '/output/'+self.ExeInputs['RESTART_DOMAIN']+'/rc_out/' - # pass into remap_config_ldas exp_id = self.ExeInputs['EXP_ID'] RESTART_str = str(self.ExeInputs['RESTART']) @@ -818,6 +819,7 @@ def createLnRstBc(self) : rstid = self.ExeInputs['RESTART_ID'] rstdomain = self.ExeInputs['RESTART_DOMAIN'] rstpath0 = self.ExeInputs['RESTART_PATH'] + rstpath = rstpath0 + rstid + '/output/'+ rstdomain + '/rs/' # just copy the landassim pert seed if it exists for iens in range(self.nens) : @@ -1012,13 +1014,13 @@ def createLnRstBc(self) : os.symlink(pertRstFile, myPertRst) # catch_param restar file - catch_param_file = self.bcsdir+'/'+ y4m2+'/'+self.ExeInputs['EXP_ID']+'.ldas_catparam.'+y4m2d2_h2m2+'z.bin' + catch_param_file = self.rc_out+'/'+ y4m2+'/'+self.ExeInputs['EXP_ID']+'.ldas_catparam.'+y4m2d2_h2m2+'z.bin' if self.with_land: assert os.path.isfile(catch_param_file), "need catch_param file %s" % catch_param_file if self.has_mwrtm : mwRTMRstFile = self.mwrtm_file - mwRTMLocal = self.bcsdir+'/'+ y4m2+'/'+self.ExeInputs['EXP_ID']+'.ldas_mwRTMparam.'+y4m2d2_h2m2+'z.nc4' + mwRTMLocal = self.rc_out+'/'+ y4m2+'/'+self.ExeInputs['EXP_ID']+'.ldas_mwRTMparam.'+y4m2d2_h2m2+'z.nc4' if self.isZoomIn : print ("Creating the local mwRTM restart file... \n") cmd= self.bindir +'/preprocess_ldas.x zoomin_mwrtmrst '+ mwRTMRstFile +' ' + mwRTMLocal + ' '+ tmp_f2g_file.name @@ -1032,11 +1034,13 @@ def createLnRstBc(self) : mymwRTMRst = myRstDir+'/mwrtm_param_rst' os.symlink(mwRTMRstFile, mymwRTMRst) + #create BCS.txt + with open(self.rc_out+'/BCS.txt','wt') as fout : + fout.write("BCS_PATH: " + self.ExeInputs['BCS_PATH']) + fout.write("BCS_RESOLUTION: " + self.ExeInputs['BCS_RESOLUTION']) # update 'restart_path' to use relative path from outdir print ("Updating restart path...") self.ExeInputs['RESTART_PATH'] = myRstDir - #if os.path.isfile(tmp_f2g_file.name): - # os.remove(tmp_f2g_file.name) status = True return status From 2e406ec15f457982e2bed4c9c0fb69c83d47ce16 Mon Sep 17 00:00:00 2001 From: Weiyuan Jiang Date: Mon, 2 Mar 2026 12:24:19 -0500 Subject: [PATCH 6/9] remove restart=0, add restart=3 --- GEOSldas_App/ldas.py | 80 ++++++++++--------------------------- GEOSldas_App/setup_utils.py | 13 +++--- 2 files changed, 28 insertions(+), 65 deletions(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index e8ecda4..317718d 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -129,18 +129,13 @@ def __init__(self, cmdLineArgs): if 'RESTART' not in self.ExeInputs : self.ExeInputs['RESTART'] = "1" - if self.ExeInputs['RESTART'].isdigit() : - if int(self.ExeInputs['RESTART']) ==0 : - self.ExeInputs['RESTART_ID'] = 'None' - self.ExeInputs['RESTART_DOMAIN'] = 'None' - self.ExeInputs['RESTART_PATH'] = 'None' - else: - if self.ExeInputs['RESTART'] =='G' : - self.ExeInputs['RESTART_DOMAIN'] = 'None' - else: - self.ExeInputs['RESTART_ID'] = 'None' - self.ExeInputs['RESTART_DOMAIN'] = 'None' - self.ExeInputs['RESTART_PATH'] = 'None' + RESTART_str = str(self.ExeInputs['RESTART']) + assert RESTART_str in ["1", "2", "3", "M"], "Only support restart = 1,2,3, M" + + if RESTART_str == 'M': + self.ExeInputs['RESTART_ID'] = 'None' + self.ExeInputs['RESTART_DOMAIN'] = 'None' + self.ExeInputs['RESTART_PATH'] = 'None' ### check if ldas is coupled to adas; if so, set/overwrite input parameters accordingly if self.ladas_cpl > 0 : @@ -281,7 +276,6 @@ def __init__(self, cmdLineArgs): # find restart files and tile files (if necessary) - RESTART_str = str(self.ExeInputs['RESTART']) inp_ = self.ExeInputs['RESTART_PATH']+'/'.join([self.ExeInputs['RESTART_ID'],'output', self.ExeInputs['RESTART_DOMAIN'], 'rc_out/']) @@ -309,7 +303,6 @@ def __init__(self, cmdLineArgs): if len(in_tilefiles_) == 0 : in_tilefiles_ = glob.glob(inp_+'/*.til') self.in_tilefile =os.path.realpath(in_tilefiles_[0]) - inpdir_ = os.path.realpath(inpdir_)+'/' inpgeom_ = os.path.realpath(inpgeom_)+'/' @@ -384,7 +377,7 @@ def __init__(self, cmdLineArgs): self.domain_def.write('/\n') self.domain_def.close() - if RESTART_str in ['1', '2']: + if RESTART_str in ['1','2','3']: y4m2='Y%4d/M%02d' % (self.begDates[0].year, self.begDates[0].month) y4m2d2_h2m2='%4d%02d%02d_%02d%02d' % (self.begDates[0].year, self.begDates[0].month, self.begDates[0].day,self.begDates[0].hour,self.begDates[0].minute) @@ -405,24 +398,6 @@ def __init__(self, cmdLineArgs): landiceRstFile=self.in_rstdir+'/'+tmpFile assert os.path.isfile(landiceRstFile), 'landice_internal_rst file [%s] does not exist!' %(landiceRstFile) - if RESTART_str == '0': - assert ( self.with_land and not self.with_landice), "RESTART = 0 is only for land" - if (self.catch == 'catch'): - self.in_rstdir = '/discover/nobackup/projects/gmao/ssd/land/l_data/LandRestarts_for_Regridding' \ - '/Catch/M09/20170101/' #catch_internal_rst - self.in_tilefile = '/discover/nobackup/projects/gmao/ssd/land/l_data/geos5/bcs/CLSM_params' \ - '/mkCatchParam_SMAP_L4SM_v002/SMAP_EASEv2_M09/SMAP_EASEv2_M09_3856x1624.til' - elif (self.catch == 'catchcnclm40'): - self.in_rstdir = '/discover/nobackup/projects/gmao/ssd/land/l_data/LandRestarts_for_Regridding' \ - '/CatchCN/M36/20150301_0000/' #catchcnclm40_internal_dummy - self.in_tilefile = '/discover/nobackup/projects/gmao/bcs_shared/legacy_bcs/Heracles-NL/SMAP_EASEv2_M36/SMAP_EASEv2_M36_964x406.til' - elif (self.catch == 'catchcnclm45'): - self.in_rstdir = '/discover/nobackup/projects/gmao/ssd/land/l_data/LandRestarts_for_Regridding' \ - '/CatchCN/M36/19800101_0000/' #catchcnclm45_internal_dummy - self.in_tilefile = '/discover/nobackup/projects/gmao/bcs_shared/legacy_bcs/Icarus-NLv3/Icarus-NLv3_EASE/SMAP_EASEv2_M36/SMAP_EASEv2_M36_964x406.til' - else: - sys.exit('need to provide at least dummy files') - # 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 @@ -503,8 +478,6 @@ def _verifyExeInputs(self): ExeInputs = self.ExeInputs #) verify keys option = '1' - if (ExeInputs['RESTART'] == 'G' or ExeInputs['RESTART'] == '0'): - option = '0' rqdExeInpKeys = getExeKeys(option) for key in rqdExeInpKeys: @@ -553,11 +526,6 @@ def _calculateJobSegments(self): '%Y%m%d %H%M%S' ) ) - if self.ExeInputs['RESTART'].isdigit() : - if int(self.ExeInputs['RESTART']) == 0 : - print ("No restart file (cold restart): Forcing start date to January 1, 0z") - year = self.begDates[0].year - self.begDates[0]=datetime(year =year,month=1,day =1,hour =0, minute= 0,second= 0) assert self.endDates[0]>self.begDates[0], \ 'END_DATE <= BEG_DATE' @@ -833,7 +801,7 @@ def createLnRstBc(self) : self.has_landassim_seed = True mk_outdir = self.exphome+'/'+exp_id+'/mk_restarts/' - if (RESTART_str != '1' and (self.with_land or self.with_landice)): + if (RESTART_str in ['2', 'M'] and (self.with_land or self.with_landice)): bcs_path = self.ExeInputs['BCS_PATH'] while bcs_path[-1] == '/' : bcs_path = bcs_path[0:-1] bc_base = os.path.dirname(bcs_path) @@ -848,7 +816,7 @@ def createLnRstBc(self) : config['input']['surface']['catch_tilefile'] = self.in_tilefile config['input']['shared']['expid'] = self.ExeInputs['RESTART_ID'] config['input']['shared']['yyyymmddhh'] = YYYYMMDDHH - if RESTART_str != 'M': + if RESTART_str == '2': config['input']['shared']['rst_dir'] = self.in_rstdir config['input']['surface']['wemin'] = wemin_in config['input']['surface']['catch_model'] = self.catch @@ -915,24 +883,18 @@ def createLnRstBc(self) : catchRstFile = '' vegdynRstFile = '' pertRstFile = '' - print ("restart: " + self.ExeInputs['RESTART']) + print ("restart: " + RESTART_str) if self.with_land : - if self.ExeInputs['RESTART'].isdigit() : - if int(self.ExeInputs['RESTART']) == 0 or int(self.ExeInputs['RESTART']) == 2 : + if RESTART_str in ['2', 'M']: # remap_restart has generated the file in mk_restarts directory + vegdynRstFile = glob.glob(self.bcs_dir_land + 'vegdyn_*.dat')[0] + catchRstFile = glob.glob(self.exphome+'/'+exp_id+'/mk_restarts/*'+self.catch+'_internal_rst.'+YYYYMMDD+'*')[0] + if RESTART_str in ['1', '3']: + catchRstFile = rstpath+ensdir +'/'+ y4m2+'/'+self.ExeInputs['RESTART_ID']+'.'+self.catch+'_internal_rst.'+y4m2d2_h2m2 + vegdynRstFile= rstpath+ensdir +'/'+self.ExeInputs['RESTART_ID']+ '.vegdyn_internal_rst' + if RESTART_str == '3': vegdynRstFile = glob.glob(self.bcs_dir_land + 'vegdyn_*.dat')[0] - catchRstFile = glob.glob(self.exphome+'/'+exp_id+'/mk_restarts/*'+self.catch+'_internal_rst.'+YYYYMMDD+'*')[0] - else : # RESTART == 1 - catchRstFile = rstpath+ensdir +'/'+ y4m2+'/'+self.ExeInputs['RESTART_ID']+'.'+self.catch+'_internal_rst.'+y4m2d2_h2m2 - vegdynRstFile= rstpath+ensdir +'/'+self.ExeInputs['RESTART_ID']+ '.vegdyn_internal_rst' - if not os.path.isfile(vegdynRstFile): # no vegdyn restart from LDASsa - if not os.path.isfile(vegdynRstFile0): - vegdynRstFile = glob.glob(self.bcs_dir_land + 'vegdyn_*.dat')[0] - else : - vegdynRstFile = glob.glob(self.bcs_dir_land + 'vegdyn_*.dat')[0] - if self.with_land: - catchRstFile = glob.glob(self.exphome+'/'+exp_id+'/mk_restarts/*'+self.catch+'_internal_rst.'+YYYYMMDD+'*')[0] # catchment restart file if os.path.isfile(catchRstFile) : @@ -972,11 +934,9 @@ def createLnRstBc(self) : landiceRstFile = '' if self.with_landice : - if RESTART_str == '0' : - exit("RESTART=0 not supported for landice tiles. Please use RESTART=M, 1, or 2") - if RESTART_str == '1' : + if RESTART_str in ['1', '3'] : landiceRstFile = rstpath+ensdir +'/'+ y4m2+'/'+self.ExeInputs['RESTART_ID']+'.'+'landice_internal_rst.'+y4m2d2_h2m2 - if RESTART_str == '2' or RESTART_str == 'M': + if RESTART_str in ['2', 'M']: landiceRstFile = glob.glob(self.exphome+'/'+exp_id+'/mk_restarts/*'+'landice_internal_rst.'+YYYYMMDD+'*')[0] if os.path.isfile(landiceRstFile) : diff --git a/GEOSldas_App/setup_utils.py b/GEOSldas_App/setup_utils.py index e5c650d..a7d2e29 100644 --- a/GEOSldas_App/setup_utils.py +++ b/GEOSldas_App/setup_utils.py @@ -109,7 +109,7 @@ def printExeInputSampleFile(): print ('# #') print ('# RESTART INFO #') print ('# #') - print ('# (i) Select "RESTART" option: #') + print ('# (i) Select "RESTART" option from [1,2,3,M]: #') print ('# #') print ('# Use one of the following options if you *have* a #') print ('# GEOSldas restart file: #') @@ -128,12 +128,15 @@ def printExeInputSampleFile(): print ('# model parameter (WEMIN). #') print ('# Restart *must* be for the GLOBAL domain. #') print ('# #') + print ('# RESTART: 3 #') + print ('# YES, have restart file from GEOSgcm. It needs the #') + print ('# same BCS as that of gcm run #') + print ('# Restart *must* be for the GLOBAL domain. #') + print ('# #') print ('# Use one of the following options if you DO NOT have a #') print ('# GEOSldas restart file #') print ('# (works for global domain ONLY!): #') print ('# #') - print ('# RESTART: 0 #') - print ('# Cold start from some old restart for Jan 1, 0z. #') print ('# #') print ('# RESTART: M #') print ('# Re-tile from archived MERRA-2 restart file. #') @@ -147,12 +150,12 @@ def printExeInputSampleFile(): print ('# #') print ('# (ii) Specify experiment ID/location of restart file: #') print ('# #') - print ('# For RESTART=1 or RESTART=2: #') + print ('# For RESTART=1 or RESTART=2 or RESTART=3: #') print ('# Specify RESTART_ID, RESTART_PATH, RESTART_DOMAIN with #') print ('# restarts stored as follows: #') print ('# RESTART_PATH/RESTART_ID/output/RESTART_DOMAIN/rs/ #') print ('# #') - print ('# For RESTART=0 or RESTART=M: #') + print ('# For RESTART=M: #') print ('# There is no need to specify RESTART_ID, RESTART_PATH, #') print ('# and RESTART_DOMAIN. #') print ('# #') From 9ba7cacc448f98e1d7dcf3bb8e827f762ed41abd Mon Sep 17 00:00:00 2001 From: Rolf Reichle Date: Wed, 4 Mar 2026 12:49:15 -0500 Subject: [PATCH 7/9] rename new output file to "BCS_info.txt" --- GEOSldas_App/ldas.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index 317718d..8050213 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -282,9 +282,9 @@ def __init__(self, cmdLineArgs): if RESTART_str == '1' : inpdir_ = inp_ inpgeom_ = inp_ - BCS_txt = glob.glob(inp_ + 'BCS.txt') + BCS_txt = glob.glob(inp_ + 'BCS_info.txt') if len(BCS_txt)== 0: - print("Warning: There is no BCS.txt in rc_out. The BCS in the restart directory may not be consistent with " + self.ExeInputs['BCS_PATH']) + print("Warning: There is no BCS_info.txt in rc_out. The BCS in the restart directory may not be consistent with " + self.ExeInputs['BCS_PATH']) elif len(BCS_txt)== 1: BCS_tmp = parseInputFile(BCS_txt[0]) assert self.ExeInputs['BCS_PATH'] == BCS_tmp['BCS_PATH'], "BCS_PATH does not match " + BCS_tmp['BCS_PATH'] + " in restart directoy" @@ -994,8 +994,8 @@ def createLnRstBc(self) : mymwRTMRst = myRstDir+'/mwrtm_param_rst' os.symlink(mwRTMRstFile, mymwRTMRst) - #create BCS.txt - with open(self.rc_out+'/BCS.txt','wt') as fout : + #create BCS_info.txt + with open(self.rc_out+'/BCS_info.txt','wt') as fout : fout.write("BCS_PATH: " + self.ExeInputs['BCS_PATH']) fout.write("BCS_RESOLUTION: " + self.ExeInputs['BCS_RESOLUTION']) # update 'restart_path' to use relative path from outdir From a65b6443615c93bfa257daffdaaa761a90a9fd12 Mon Sep 17 00:00:00 2001 From: Rolf Reichle Date: Wed, 4 Mar 2026 14:22:50 -0500 Subject: [PATCH 8/9] edited comments about RESTART options (ldas.py, setup_utils.py) --- GEOSldas_App/ldas.py | 14 +++---- GEOSldas_App/setup_utils.py | 78 ++++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index 8050213..58730e1 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -130,7 +130,7 @@ def __init__(self, cmdLineArgs): self.ExeInputs['RESTART'] = "1" RESTART_str = str(self.ExeInputs['RESTART']) - assert RESTART_str in ["1", "2", "3", "M"], "Only support restart = 1,2,3, M" + assert RESTART_str in ["1", "2", "3", "M"], "RESTART must be 1, 2, 3, or M" if RESTART_str == 'M': self.ExeInputs['RESTART_ID'] = 'None' @@ -261,7 +261,7 @@ def __init__(self, cmdLineArgs): if self.ExeInputs['RESTART_PATH'][-1] != '/': self.ExeInputs['RESTART_PATH'] = self.ExeInputs['RESTART_PATH']+'/' - # make sure catchment and vegdyn restart files ( at least one for each) exist + # make sure catchment and vegdyn restart files exist (at least one of each) if 'CATCH_DEF_FILE' not in self.ExeInputs : self.ExeInputs['CATCH_DEF_FILE']= self.bcs_dir_land + 'clsm/catchment.def' if self.with_land : @@ -284,18 +284,18 @@ def __init__(self, cmdLineArgs): inpgeom_ = inp_ BCS_txt = glob.glob(inp_ + 'BCS_info.txt') if len(BCS_txt)== 0: - print("Warning: There is no BCS_info.txt in rc_out. The BCS in the restart directory may not be consistent with " + self.ExeInputs['BCS_PATH']) + print("Warning: BCS_info.txt not found for restart experiment. User is responsible for ensuring consistency of restart and experiment BCS.") elif len(BCS_txt)== 1: BCS_tmp = parseInputFile(BCS_txt[0]) - assert self.ExeInputs['BCS_PATH'] == BCS_tmp['BCS_PATH'], "BCS_PATH does not match " + BCS_tmp['BCS_PATH'] + " in restart directoy" - assert self.ExeInputs['BCS_RESOLUTION'] == BCS_tmp['BCS_RESOLUTION'], "BCS resolution or gridname should be the same for RESTART =1" + assert self.ExeInputs['BCS_PATH'] == BCS_tmp['BCS_PATH'], "BCS_PATH does not match path from restart dir (" + BCS_tmp['BCS_PATH'] + ")" + assert self.ExeInputs['BCS_RESOLUTION'] == BCS_tmp['BCS_RESOLUTION'], "BCS_RESOLUTION does not match resolution from restart dir (" + BCS_tmp['BCS_RESOLUTION'] + ")" txt_tile = glob.glob(inp_ + '*.domain') if len(txt_tile) > 0: domain_ = '.domain' elif RESTART_str == '2': txt_tile = glob.glob(inp_ + '*.domain') - assert len(txt_tile) == 0, "RESTART = 2 should restart from global domain" + assert len(txt_tile) == 0, "For RESTART=2, must restart from (and run on) global domain" in_tilefiles_ = glob.glob(inp_+'MAPL_*.til') if len(in_tilefiles_) == 0 : nc4_tmp = glob.glob(inp_+'/*.nc4') @@ -417,7 +417,7 @@ def __init__(self, cmdLineArgs): # ------------------ - # Read rm input file + # Read resource manager (rm) input file # ------------------ if self.ladas_cpl == 0 : diff --git a/GEOSldas_App/setup_utils.py b/GEOSldas_App/setup_utils.py index a7d2e29..411a619 100644 --- a/GEOSldas_App/setup_utils.py +++ b/GEOSldas_App/setup_utils.py @@ -111,52 +111,68 @@ def printExeInputSampleFile(): print ('# #') print ('# (i) Select "RESTART" option from [1,2,3,M]: #') print ('# #') - print ('# Use one of the following options if you *have* a #') - print ('# GEOSldas restart file: #') + print ('# Use one of the following options to restart from a #') + print ('# GEOSldas experiment: #') print ('# #') - print ('# RESTART: 1 #') - print ('# YES, have restart file from GEOSldas #') - print ('# in SAME tile space (grid) with SAME boundary #') - print ('# conditions and SAME snow model parameter (WEMIN). #') - print ('# The restart domain can be for the same or #') - print ('# a larger one. #') + print ('# RESTART: 1 = No remapping; zoom optional. #') + print ('# --------------------------------------- #') + print ('# New experiment has SAME tile space (grid), boundary #') + print ('# conditions, and snow model parameter (WEMIN) as #') + print ('# experiment that provides restart files. #') + print ('# Domain of new experiment can be same as or smaller #') + print ('# than domain of restart experiment. #') print ('# #') - print ('# RESTART: 2 #') - print ('# YES, have restart file from GEOSldas but #') - print ('# in a DIFFERENT tile space (grid) or with #') - print ('# DIFFERENT boundary conditions or DIFFERENT snow #') - print ('# model parameter (WEMIN). #') - print ('# Restart *must* be for the GLOBAL domain. #') + print ('# RESTART: 2 = Remapping of bcs version and/or resolution. #') + print ('# ------------------------------------------------------ #') + print ('# New experiment has DIFFERENT tile space (grid) or #') + print ('# DIFFERENT boundary conditions or DIFFERENT snow model #') + print ('# parameter (WEMIN). #') + print ('# New and restart experiments *must* be GLOBAL. #') print ('# #') - print ('# RESTART: 3 #') - print ('# YES, have restart file from GEOSgcm. It needs the #') - print ('# same BCS as that of gcm run #') - print ('# Restart *must* be for the GLOBAL domain. #') - print ('# #') - print ('# Use one of the following options if you DO NOT have a #') - print ('# GEOSldas restart file #') - print ('# (works for global domain ONLY!): #') + print ('# -------------------------------------------------------- #') print ('# #') + print ('# Use the following option if your restart files are from #') + print ('# a GEOSgcm experiment: #') print ('# #') - print ('# RESTART: M #') - print ('# Re-tile from archived MERRA-2 restart file. #') + print ('# RESTART: 3 = No remapping; global only. #') + print ('# ------------------------------------- #') + print ('# New experiment has SAME tile space (grid), boundary #') + print ('# conditions, and snow model parameter (WEMIN) as the #') + print ('# GCM experiment that provides restart files. #') + print ('# New experiment *must* GLOBAL. #') print ('# #') print ('# -------------------------------------------------------- #') + print ('# #') + print ('# Use the following option if you do not have restart #') + print ('# files. #') + print ('# #') + print ('# RESTART: M = Remap from archived MERRA-2 restart files. #') + print ('# ---------------------------------------------------- #') + print ('# New experiment *must* GLOBAL. #') + print ('# Restart date/time must match an archived MERRA-2 #') + print ('# date/time. #') + print ('# #') + print ('# ======================================================== #') print ('# IMPORTANT: #') print ('# Except for RESTART=1, SPIN-UP is REQUIRED in almost #') print ('# all cases. #') - print ('# -------------------------------------------------------- #') + print ('# ======================================================== #') + print ('# #') print ('# #') + print ('# (ii) Specify experiment ID/location of restart files #') print ('# #') - print ('# (ii) Specify experiment ID/location of restart file: #') + print ('# For RESTART = 1, 2, or 3: #') + print ('# ----------------------- #') + print ('# Specify RESTART_ID, RESTART_PATH, RESTART_DOMAIN. #') print ('# #') - print ('# For RESTART=1 or RESTART=2 or RESTART=3: #') - print ('# Specify RESTART_ID, RESTART_PATH, RESTART_DOMAIN with #') - print ('# restarts stored as follows: #') + print ('# For RESTART = 3: #') + print ('# -------------- #') + print ('# Place restarts into the following directory tree: #') print ('# RESTART_PATH/RESTART_ID/output/RESTART_DOMAIN/rs/ #') print ('# #') - print ('# For RESTART=M: #') - print ('# There is no need to specify RESTART_ID, RESTART_PATH, #') + print ('# For RESTART = M: #') + print ('# -------------- #') + print ('# No need to specify RESTART_ID, RESTART_PATH, #') print ('# and RESTART_DOMAIN. #') print ('# #') print ('############################################################') From 2407a13a8814f0abbfbdb5897db04468c13be98d Mon Sep 17 00:00:00 2001 From: Rolf Reichle Date: Wed, 4 Mar 2026 14:38:49 -0500 Subject: [PATCH 9/9] minimal edit of comment about RESTART (ldas.py) --- GEOSldas_App/ldas.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/GEOSldas_App/ldas.py b/GEOSldas_App/ldas.py index 58730e1..99c597c 100644 --- a/GEOSldas_App/ldas.py +++ b/GEOSldas_App/ldas.py @@ -275,8 +275,7 @@ def __init__(self, cmdLineArgs): inpgeom_ = self.bcs_dir_geom - # find restart files and tile files (if necessary) - + # find restart files and tile file in restart dir (if necessary) inp_ = self.ExeInputs['RESTART_PATH']+'/'.join([self.ExeInputs['RESTART_ID'],'output', self.ExeInputs['RESTART_DOMAIN'], 'rc_out/']) if RESTART_str == '1' :