Skip to content

Commit 4a1802e

Browse files
committed
additional changes and cleanup for coupled land-atm DAS (ldas_setup):
- cleaned up logic of processing resource manager inputs - reverted to relative paths for rc files in ./etc - documentation of new functionality - updated language about compute nodes in sample batinp file (removed Skylake, added Milan) - fixed indentation
1 parent df1b1f3 commit 4a1802e

File tree

1 file changed

+83
-61
lines changed

1 file changed

+83
-61
lines changed

GEOSldas_App/ldas_setup

Lines changed: 83 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -54,36 +54,47 @@ class LDASsetup:
5454
'MINLON','MAXLON','MINLAT','MAXLAT','EXCLUDE_FILE','INCLUDE_FILE','MWRTM_PATH','GRIDNAME',
5555
'ADAS_EXPDIR', 'BCS_RESOLUTION', 'TILE_FILE_FORMAT' ]
5656

57-
5857
self.GEOS_SITE = "@GEOS_SITE@"
5958

6059
# ------
6160
# Required resource manager input fields
6261
# ------
63-
rqdRmInpKeys = ['account', 'walltime', 'ntasks_model', 'ntasks-per-node']
62+
rqdRmInpKeys = ['account', 'walltime', 'ntasks_model', 'ntasks-per-node']
6463
# ------
6564
# Optional resource manager input fields
6665
# ------
6766
optSlurmInpKeys = ['job_name', 'qos', 'oserver_nodes', 'writers-per-node']
6867

68+
69+
# ===============================================================================================
70+
#
6971
# ------
70-
# ./ldsetup.py sample ...
72+
# ./ldas_setup sample ...
7173
# ------
72-
if 'exeinp' in cmdLineArgs:
73-
# sample sub-command
74-
# by construction, we can have
75-
# either: {'exeinp': False, 'batinp': True }
76-
# or: {'exeinp': True, 'batinp': False}
74+
#
75+
# "sample" sub-command:
76+
# '--exeinp' and '--batinp' are mutually exclusive command line arguments.
77+
# Specifying one will set it to True and set the other one to False.
78+
# That is, we can have either: {'exeinp': False, 'batinp': True }
79+
# or: {'exeinp': True, 'batinp': False}
80+
81+
if 'exeinp' in cmdLineArgs: # 'exeinp' is always present in "sample" mode.
82+
7783
if cmdLineArgs['exeinp']:
7884
_produceExeInput()
7985
elif cmdLineArgs['batinp']:
8086
_printRmInputKeys( rqdRmInpKeys, optSlurmInpKeys)
8187
else:
8288
raise Exception('unrecognized option')
89+
#
90+
# EXIT after completing "sample" sub-command
8391
sys.exit(0)
92+
8493

94+
# ===============================================================================================
95+
#
8596
# ------
86-
# ./ldsetup.py setup ...
97+
# ./ldas_setup setup ...
8798
# ------
8899
# Instance variables
89100
self.exeinpfile = cmdLineArgs['exeinpfile']
@@ -569,7 +580,6 @@ class LDASsetup:
569580
self.has_vegopacity = True
570581
self.rqdExeInp['VEGOPACITY_FILE'] = vegopacity_file_
571582

572-
# DEAL WITH optional input from exec
573583

574584
# ------
575585
# Read rm input file
@@ -579,46 +589,43 @@ class LDASsetup:
579589
# ------
580590
# re-using inpDictFromFile
581591

582-
inpDictFromFile = self._parseInputFile(cmdLineArgs['batinpfile'])
583-
584-
if self.ladas_cpl > 0 :
585-
self.rqdRmInp['walltime'] = "01:00:00"
586-
self.rqdRmInp['ntasks_model'] = 120
587-
self.rqdRmInp['ntasks-per-node'] = 46 # 46 works on Cascade Lake and Milan
588-
else :
589-
# REQUIRED inputs
590-
for key in rqdRmInpKeys:
592+
if self.ladas_cpl == 0 :
593+
inpDictFromFile = self._parseInputFile(cmdLineArgs['batinpfile'])
594+
# REQUIRED inputs
595+
for key in rqdRmInpKeys:
591596
self.rqdRmInp[key] = inpDictFromFile.pop(key)
592597

593-
# checks on rqd rm inputs
594-
## account and walltime should exist
595-
assert self.rqdRmInp['account']
596-
assert self.rqdRmInp['walltime']
597-
## ntasks_model is a +ve integer
598-
_ntasks = int(self.rqdRmInp['ntasks_model'])
599-
assert _ntasks>0
600-
self.rqdRmInp['ntasks_model'] = _ntasks
601-
_ntasks = None
598+
# checks on rqd rm inputs
599+
## account and walltime should exist
600+
assert self.rqdRmInp['account']
601+
assert self.rqdRmInp['walltime']
602+
## ntasks_model is a +ve integer
603+
_ntasks = int(self.rqdRmInp['ntasks_model'])
604+
assert _ntasks>0
605+
self.rqdRmInp['ntasks_model'] = _ntasks
606+
_ntasks = None
607+
608+
# OPTIONAL inputs
609+
for key in inpDictFromFile:
610+
assert key in optSlurmInpKeys, \
611+
'unknown resource manager key [%s]' % key
612+
self.optRmInp[key] = inpDictFromFile[key]
613+
else :
614+
self.rqdRmInp['account'] = cmdLineArgs['account']
615+
self.rqdRmInp['walltime'] = "01:00:00"
616+
self.rqdRmInp['ntasks_model'] = 120
617+
self.rqdRmInp['ntasks-per-node'] = 46 # 46 works on Cascade Lake and Milan
618+
602619

603-
if cmdLineArgs['account'] is not None:
604-
self.rqdRmInp['account'] = cmdLineArgs['account']
605620

606-
# print rqd rm inputs
621+
# print rm inputs
607622
if self.verbose:
608623
print ('\n\nRequired inputs for resource manager:')
609624
_printdict(self.rqdRmInp)
610-
611-
# OPTIONAL inputs
612-
for key in inpDictFromFile:
613-
assert key in optSlurmInpKeys, \
614-
'unknown resource manager key [%s]' % key
615-
self.optRmInp[key] = inpDictFromFile[key]
616-
617-
# print opt rm inputs
618-
if self.verbose:
619625
print ('\n\nOptional inputs for resource manager:')
620626
_printdict(self.optRmInp)
621-
627+
print ('\n\n')
628+
622629
# ------
623630
# set top level directories
624631
# rundir, inpdir, outdir, blddir
@@ -1201,11 +1208,11 @@ class LDASsetup:
12011208
assert os.path.isdir(mydir), \
12021209
'dir [%s] does not exist!' % mydir
12031210

1204-
# first copy ldsetup input files to rundir
1205-
# if a file w/ the same name already exists at rundir
1206-
# append 1,2,3 etc, to the filename
1207-
## exe inp file
1208-
if self.ladas_cpl == 0 :
1211+
if self.ladas_cpl == 0:
1212+
# copy ldas_setup exeinp and batinp input files to rundir (for the record)
1213+
# if a file w/ the same name already exists at rundir
1214+
# append 1,2,3 etc, to the filename
1215+
## exe inp file
12091216
exefilename = self.exeinpfile.rstrip('/').split('/')[-1]
12101217
newfilename = exefilename
12111218
_nens = self.nens
@@ -1223,6 +1230,8 @@ class LDASsetup:
12231230
newfilename = batfilename + '.%d' % ctr
12241231
shutil.copy(self.batinpfile, self.rundir+'/'+newfilename)
12251232

1233+
# -----------------------------------
1234+
12261235
etcdir = self.blddirLn + '/etc'
12271236

12281237
#defalt nml
@@ -1624,13 +1633,19 @@ def _printdict(d):
16241633

16251634
def _produceExeInput(out_dict=None,ladas_cpl=0):
16261635
"""
1627-
Private method: print sample exe input
1636+
Private method: (1) Print sample exeinp file to stdout for offline GEOSldas setup:
1637+
_produceExeInput().
1638+
*or*
1639+
(2) Create dictionary w/ default parameters from GEOSldas_LDAS.rc and
1640+
GEOS_SurfaceGridComp.rc for coupled land-atm DAS setup:
1641+
_produceExeInput(out_dict, ladas_cpl=[1,2]).
16281642
"""
1643+
16291644
if ladas_cpl > 0:
16301645
assert out_dict is not None , " Need out_dict to hold the default parameters"
16311646

16321647
# stand-alone (offline) LDAS:
1633-
# sample exeinp file includes placeholders for inputs that the user needs to provide
1648+
# sample exeinp file includes placeholders for inputs that the user needs to provide
16341649
if ladas_cpl == 0:
16351650
print ('####################################################################################')
16361651
print ('# #')
@@ -1750,15 +1765,16 @@ def _produceExeInput(out_dict=None,ladas_cpl=0):
17501765
print ()
17511766
print ('############################################################')
17521767

1753-
1768+
# end if ladas_cpl==0
1769+
17541770
# add defaults from GEOSldas_LDAS.rc
1755-
current_directory = os.path.dirname(__file__)
1756-
_fn = current_directory[0:-4]+'/etc/GEOSldas_LDAS.rc' # run ldas_setup from /bin directory
1771+
1772+
_fn = '../etc/GEOSldas_LDAS.rc' # run ldas_setup from ./install directory
17571773
lines = []
17581774
with open(_fn) as _f:
17591775
i_ = 1
17601776
for line in _f:
1761-
if ( i_ < 5 or i_ >10): # ignore lines 5-10 - may need to change if GEOSldas_LDAS.rc is edited
1777+
if ( i_ < 5 or i_ >10): # ignore lines 5-10 - may need to change if GEOSldas_LDAS.rc is edited
17621778
if ladas_cpl == 0:
17631779
sys.stdout.write(line)
17641780
sys.stdout.flush()
@@ -1769,7 +1785,8 @@ def _produceExeInput(out_dict=None,ladas_cpl=0):
17691785
print ()
17701786

17711787
# add land model parameter defaults from GEOS_SurfaceGridComp.rc
1772-
_fn = current_directory[0:-4]+'/etc/GEOS_SurfaceGridComp.rc' # run ldas_setup from /bin directory
1788+
1789+
_fn = '../etc/GEOS_SurfaceGridComp.rc' # run ldas_setup from ./install directory
17731790

17741791
if ladas_cpl == 0 :
17751792
use_rc_defaults = 'GEOSldas=>' # use defaults for LDAS
@@ -1826,10 +1843,10 @@ def _printRmInputKeys(rqdRmInpKeys, optRmInpKeys):
18261843
print ('# - account = computational project number')
18271844
print ('# [At NCCS: Use command "getsponsor" to see available account number(s).]' )
18281845
print ('# - walltime = walltime requested; format is HH:MM:SS (hours/minutes/seconds)')
1829-
print ('# - ntasks_model = number of processors requested for the model (typically 112; output server is not included)')
1830-
print ('# - ntasks-per-node = number of tasks per node (typically 46 for cascade* and 40 for skylake nodes)')
1831-
print ('# [If >40, cascade nodes will be allocated, else cascade or skylake.]')
1832-
print ('# [*NCCS recommends <=46 cores per node on SCU16 (cascade) due to OS issues (as of 6 Oct 2021).]')
1846+
print ('# - ntasks_model = number of processors requested for the model (typically 126; output server is not included)')
1847+
print ('# - ntasks-per-node = number of tasks per node (typically 46 for Cascade Lake and 126 for Milan)')
1848+
print ('# [If >46, Milan nodes will be allocated, else Cascade Lake or Milan.]')
1849+
print ('# [NCCS recommends <=46 for Cascade Lake and <=126 for Milan.]')
18331850
print ('#')
18341851
for key in rqdRmInpKeys:
18351852
print (key + ':')
@@ -1854,17 +1871,22 @@ def parseCmdLine():
18541871
"""
18551872
parse command line arguments and return a dict of options
18561873
"""
1874+
18571875
#print 'in: parseCmdLine'
18581876
p = argparse.ArgumentParser(
18591877
description= \
1860-
"Script to setup a GEOSldas experiment. The script requires "\
1861-
"two (2) input files, one for the experiment inputs and the " \
1862-
"other for the resource manager (SLURM). To create sample input " \
1863-
"files use './ldas_setup sample -h'.",
1878+
"Script to setup a GEOSldas experiment. "\
1879+
"To set up an *offline* GEOSldas experiment, the script requires "\
1880+
"two (2) input files, one for the experiment inputs ('exeinp') and the "\
1881+
"other for the (SLURM) resource manager ('batinp'). To create sample input "\
1882+
"files use './ldas_setup sample -h'. "\
1883+
"When used to set up a coupled land-atm DAS experiment, the script "\
1884+
"*ignores* the input files, but dummy strings must still be specified. "
18641885
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
18651886
)
18661887
p_sub = p.add_subparsers(help='sub-command help')
18671888

1889+
18681890
# subparser: "sample" command
18691891
p_sample = p_sub.add_parser(
18701892
'sample',

0 commit comments

Comments
 (0)