Skip to content

Commit

Permalink
Merge pull request ESCOMP#2031 from ekluzek/merge_simple_PRs
Browse files Browse the repository at this point in the history
NEON fixes and a few simple bit-for-bit -- ctsm5.1.dev129
  • Loading branch information
ekluzek authored Jun 22, 2023
2 parents 5df6c98 + 04f2080 commit bb2a8d2
Show file tree
Hide file tree
Showing 59 changed files with 1,191 additions and 636 deletions.
117 changes: 75 additions & 42 deletions bld/CLMBuildNamelist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ OPTIONS
(default is 0) (standard option with land-ice model is 10)
-glc_use_antarctica Set defaults appropriate for runs that include Antarctica
-help [or -h] Print usage to STDOUT.
-light_res <value> Resolution of lightning dataset to use for CN fire (360x720 or 94x192)
-light_res <value> Resolution of lightning dataset to use for CN or FATES fire (360x720, 106x174, or 94x192)
106x174 can only be used for NEON sites
-lilac If CTSM is being run through LILAC (normally not used)
(LILAC is the Lightweight Infrastructure for Land-Atmosphere Coupling)
-ignore_ic_date Ignore the date on the initial condition files
Expand Down Expand Up @@ -688,6 +689,13 @@ sub setup_cmdl_resolution {
}
}
}
# For NEON sites
if ($nl_flags->{'res'} =~ /NEON/) {
$nl_flags->{'neon'} = ".true."
} else {
$nl_flags->{'neon'} = ".false."
}

}

#-------------------------------------------------------------------------------
Expand Down Expand Up @@ -952,59 +960,84 @@ sub setup_cmdl_fire_light_res {

my $var = "light_res";
my $val = $opts->{$var};
if ( &value_is_true($nl->get_value('use_cn')) ) {
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fire_method');
}
my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') );
if ( $val eq "default" ) {
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var,
'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'},
'neon'=>$nl_flags->{'neon'},
'fates_spitfire_mode'=>$nl->get_value('fates_spitfire_mode'),
'use_fates'=>$nl_flags->{'use_fates'}, fire_method=>$nl->get_value('fire_method') );
'use_fates'=>$nl_flags->{'use_fates'}, fire_method=>$fire_method );
$val = remove_leading_and_trailing_quotes( $nl->get_value($var) );
$nl_flags->{$var} = $val;
} else {
my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') );
if ( defined($fire_method) && $val ne "none" ) {
if ( $fire_method eq "nofire" ) {
$log->fatal_error("-$var option used with fire_method='nofire'. -$var can ONLY be used without the nofire option");
}
}
my $stream_fldfilename_lightng = remove_leading_and_trailing_quotes( $nl->get_value('stream_fldfilename_lightng') );
if ( defined($stream_fldfilename_lightng) && $val ne "none" ) {
$log->fatal_error("-$var option used while also explicitly setting stream_fldfilename_lightng filename which is a contradiction. Use one or the other not both.");
}
if ( ! &value_is_true($nl->get_value('use_cn')) ) {
if ( &value_is_true($nl_flags->{'use_fates'}) ) {
if ( $nl->get_value('fates_spitfire_mode') < 2) {
if ( $val ne "none" ) {
$log->fatal_error("-$var option used when FATES is on, but fates_spitfire_mode does NOT use lightning data");
}
} else {
if ( $val eq "none" ) {
$log->fatal_error("-$var option is set to none, but FATES is on and fates_spitfire_mode requires lightning data");
}
}
} else {
$log->fatal_error("-$var option used when FATES off and CN is NOT on. -$var can only be used when BGC is set to bgc or fates");
}
} else {
if ( $val eq "none" and $fire_method ne "nofire" ) {
$log->fatal_error("-$var option is set to none, but CN is on (with bgc: cn or bgc) which is a contradiction");
}
}
$nl_flags->{$var} = $val;
}
# Check that NEON data is only used for NEON sites
if ( $val eq "106x174" ) {
if ( ! &value_is_true($nl_flags->{'neon'}) ) {
if ( defined($opts->{'clm_usr_name'}) ) {
$log->warning("The NEON lightning dataset does NOT cover the entire globe, make sure it covers the region for your grid");
} else {
$log->fatal_error("The NEON lightning dataset can NOT be used for global grids or regions or points outside of its area as it does NOT cover the entire globe.");
}
}
my $stream_fldfilename_lightng = remove_leading_and_trailing_quotes( $nl->get_value('stream_fldfilename_lightng') );
if ( defined($stream_fldfilename_lightng) && $val ne "none" ) {
$log->fatal_error("-$var option used while also explicitly setting stream_fldfilename_lightng filename which is a contradiction. Use one or the other not both.");
}
if ( ! &value_is_true($nl->get_value('use_cn')) ) {
$log->fatal_error("-$var option used CN is NOT on. -$var can only be used when CN is on (with bgc: cn or bgc)");
}
if ( &value_is_true($nl->get_value('use_cn')) && $val eq "none" ) {
$log->fatal_error("-$var option is set to none, but CN is on (with bgc: cn or bgc) which is a contradiction");
}
$nl_flags->{$var} = $val;
}
my $group = $definition->get_group_name($var);
$nl->set_variable_value($group, $var, quote_string($nl_flags->{$var}) );
if ( ! $definition->is_valid_value( $var, $nl_flags->{$var}, 'noquotes'=>1 ) ) {
my @valid_values = $definition->get_valid_values( $var );
$log->fatal_error("$var has a value (".$nl_flags->{$var}.") that is NOT valid. Valid values are: @valid_values");
}
$log->verbose_message("Using $nl_flags->{$var} for $var.");
#
# Set flag if cn-fires are on or not
#
$var = "cnfireson";
if ( &value_is_true($nl->get_value('use_cn')) ) {
add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fire_method');
}
my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') );
if ( defined($fire_method) && ! &value_is_true($nl_flags->{'use_cn'}) && ! &value_is_true($nl_flags->{'use_fates'}) ) {
$log->fatal_error("fire_method is being set while use_cn and use_fates are both false.");
}
if ( defined($fire_method) && $fire_method eq "nofire" ) {
$nl_flags->{$var} = ".false.";
# } elsif ( &value_is_true($nl->get_value('use_cn')) || $nl_flags->{'fates_spitfire_mode'} > 1 ) {
} elsif ( &value_is_true($nl->get_value('use_cn')) || &value_is_true($nl->get_value('use_fates')) ) {
$nl_flags->{$var} = ".true.";
} else {
$nl_flags->{$var} = ".false.";
}
}
}
# check for valid values...
my $group = $definition->get_group_name($var);
$nl->set_variable_value($group, $var, quote_string($nl_flags->{$var}) );
if ( ! $definition->is_valid_value( $var, $nl_flags->{$var}, 'noquotes'=>1 ) ) {
my @valid_values = $definition->get_valid_values( $var );
$log->fatal_error("$var has a value (".$nl_flags->{$var}.") that is NOT valid. Valid values are: @valid_values");
}
$log->verbose_message("Using $nl_flags->{$var} for $var.");
#
# Set flag if cn-fires are on or not, only for BGC (not FATES)
#
$var = "cnfireson";
my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') );
if ( defined($fire_method) && ! &value_is_true($nl_flags->{'use_cn'}) && ! &value_is_true($nl_flags->{'use_fates'}) ) {
$log->fatal_error("fire_method is being set while use_cn and use_fates are both false.");
}
if ( defined($fire_method) && $fire_method eq "nofire" ) {
$nl_flags->{$var} = ".false.";
# } elsif ( &value_is_true($nl->get_value('use_cn')) || $nl_flags->{'fates_spitfire_mode'} > 1 ) {
} elsif ( &value_is_true($nl->get_value('use_cn')) || &value_is_true($nl->get_value('use_fates')) ) {
$nl_flags->{$var} = ".true.";
} else {
$nl_flags->{$var} = ".false.";
}
}

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

Expand Down
7 changes: 7 additions & 0 deletions bld/namelist_files/namelist_defaults_ctsm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,7 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1

<light_res use_cn=".false." >none</light_res>
<light_res use_cn=".true." fire_method="nofire" >none</light_res>
<light_res use_cn=".true." neon=".true." >106x174</light_res>
<light_res use_cn=".true." phys="clm4_5" >94x192</light_res>
<light_res use_cn=".true." phys="clm5_0" >94x192</light_res>
<light_res use_cn=".true." phys="clm5_1" >360x720</light_res>
Expand All @@ -1679,12 +1680,18 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1
<light_res use_fates=".true." fates_spitfire_mode="3" >360x720</light_res>
<light_res use_fates=".true." fates_spitfire_mode="4" >360x720</light_res>
<light_res use_fates=".true." fates_spitfire_mode="5" >360x720</light_res>
<light_res use_fates=".true." fates_spitfire_mode="2" neon=".true.">106x174</light_res>
<light_res use_fates=".true." fates_spitfire_mode="3" neon=".true.">106x174</light_res>
<light_res use_fates=".true." fates_spitfire_mode="4" neon=".true.">106x174</light_res>
<light_res use_fates=".true." fates_spitfire_mode="5" neon=".true.">106x174</light_res>

<stream_year_first_lightng >0001</stream_year_first_lightng>
<stream_year_last_lightng >0001</stream_year_last_lightng>

<stream_fldfilename_lightng hgrid="94x192" >atm/datm7/NASA_LIS/clmforc.Li_2012_climo1995-2011.T62.lnfm_Total_c140423.nc</stream_fldfilename_lightng>
<stream_meshfile_lightng hgrid="94x192" >atm/datm7/NASA_LIS/clmforc.Li_2012_climo1995-2011.T62_ESMFmesh_cdf5_110621.nc</stream_meshfile_lightng>
<stream_fldfilename_lightng hgrid="106x174" >atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720.lnfm_Total_NEONarea_c210625.nc</stream_fldfilename_lightng>
<stream_meshfile_lightng hgrid="106x174" >atm/datm7/NASA_LIS/ESMF_MESH.Li_2016.360x720.NEONarea_cdf5_c221104.nc</stream_meshfile_lightng>
<stream_fldfilename_lightng hgrid="360x720" >atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720.lnfm_Total_c160825.nc</stream_fldfilename_lightng>
<stream_meshfile_lightng hgrid="360x720" >atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720_ESMFmesh_cdf5_150621.nc</stream_meshfile_lightng>

Expand Down
6 changes: 3 additions & 3 deletions bld/namelist_files/namelist_definition_ctsm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1992,9 +1992,9 @@ to use for methane model
</entry>

<entry id="light_res" type="char*10" category="default_settings"
group="default_settings" valid_values="none,360x720,94x192">
Resolution of Lightning dataset to use for CN fire model
(only applies when CN and the CN fire model are turned on)
group="default_settings" valid_values="none,360x720,106x174,94x192">
Resolution of Lightning dataset to use for CN or FATES fire model
(only applies when CN or FATES and the fire model is turned on)
</entry>

<entry id="chk_res" type="integer" category="default_settings"
Expand Down
22 changes: 20 additions & 2 deletions bld/unit_testers/build-namelist_test.pl
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ sub cat_and_create_namelistinfile {
#
# Figure out number of tests that will run
#
my $ntests = 1958;
my $ntests = 1975;
if ( defined($opts{'compare'}) ) {
$ntests += 1335;
$ntests += 1344;
}
plan( tests=>$ntests );

Expand Down Expand Up @@ -466,6 +466,9 @@ sub cat_and_create_namelistinfile {
"-bgc bgc -use_case 2000_control -namelist \"&a fire_method='nofire'/\" -crop",
"-res 0.9x1.25 -bgc sp -use_case 1850_noanthro_control -drydep -fire_emis",
"-res 0.9x1.25 -bgc bgc -use_case 1850_noanthro_control -drydep -fire_emis -light_res 360x720",
"--bgc bgc --light_res none --namelist \"&a fire_method='nofire'/\"",
"--bgc fates --light_res 360x720 --no-megan --namelist \"&a fates_spitfire_mode=2/\"",
"--bgc fates --light_res none --no-megan --namelist \"&a fates_spitfire_mode=1/\"",
) {
my $file = $startfile;
&make_env_run();
Expand Down Expand Up @@ -686,6 +689,11 @@ sub cat_and_create_namelistinfile {
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_0",
},
"NEONlightresButGlobal" =>{ options=>"--res 4x5 --bgc bgc --envxml_dir . --light_res 106x740",
namelst=>"",
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_1",
},
"spno-fire" =>{ options=>"-bgc sp -envxml_dir . -use_case 2000_control",
namelst=>"fire_method='nofire'",
GLC_TWO_WAY_COUPLING=>"FALSE",
Expand Down Expand Up @@ -971,6 +979,11 @@ sub cat_and_create_namelistinfile {
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_1",
},
"FATESwspitfireOffLigtOn" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res 360x720",
namelst=>"fates_spitfire_mode=0",
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_1",
},
"FireNoneButBGCfireon" =>{ options=>"-bgc bgc -envxml_dir . -light_res none",
namelst=>"fire_method='li2021gswpfrc'",
GLC_TWO_WAY_COUPLING=>"FALSE",
Expand Down Expand Up @@ -1227,6 +1240,11 @@ sub cat_and_create_namelistinfile {
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_1",
},
"NotNEONbutNEONlightres" =>{ options=>"--res CLM_USRDAT --clm_usr_name regional --envxml_dir . --bgc bgc --light_res 106x174",
namelst=>"fsurdat='build-namelist_test.pl'",
GLC_TWO_WAY_COUPLING=>"FALSE",
phys=>"clm5_1",
},
);
foreach my $key ( keys(%warntest) ) {
print( "$key\n" );
Expand Down
Empty file.
67 changes: 36 additions & 31 deletions cime_config/SystemTests/fsurdatmodifyctsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,70 +12,73 @@

logger = logging.getLogger(__name__)

class FSURDATMODIFYCTSM(SystemTestsCommon):

class FSURDATMODIFYCTSM(SystemTestsCommon):
def __init__(self, case):
"""
initialize an object interface to the SMS system test
"""
SystemTestsCommon.__init__(self, case)

if not os.path.exists(os.path.join(self._get_caseroot(),
'done_FSURDATMODIFYCTSM_setup.txt')):
if not os.path.exists(
os.path.join(self._get_caseroot(), "done_FSURDATMODIFYCTSM_setup.txt")
):
# Create out-of-the-box lnd_in to obtain fsurdat_in
case.create_namelists(component='lnd')
case.create_namelists(component="lnd")
# If fsurdat_in does not exist, download it from the server
case.check_all_input_data()

lnd_in_path = os.path.join(self._get_caseroot(), 'CaseDocs/lnd_in')
with open (lnd_in_path,'r') as lnd_in:
lnd_in_path = os.path.join(self._get_caseroot(), "CaseDocs/lnd_in")
with open(lnd_in_path, "r") as lnd_in:
for line in lnd_in:
fsurdat_in = re.match(r" *fsurdat *= *'(.*)'", line)
if fsurdat_in:
self._fsurdat_in = fsurdat_in.group(1)
break

self._fsurdat_out = os.path.join(self._get_caseroot(), 'fsurdat.nc')
self._ctsm_root = self._case.get_value( 'COMP_ROOT_DIR_LND')
self._cfg_file_path = os.path.join(self._get_caseroot(),
'modify_fsurdat.cfg')
self._fsurdat_out = os.path.join(self._get_caseroot(), "fsurdat.nc")
self._ctsm_root = self._case.get_value("COMP_ROOT_DIR_LND")
self._cfg_file_path = os.path.join(self._get_caseroot(), "modify_fsurdat.cfg")

logger.info(" create config file to modify")
self._create_config_file()
logger.info(" run modify_fsurdat")
self._run_modify_fsurdat()
logger.info(" modify user_nl files")
self._modify_user_nl()
with open('done_FSURDATMODIFYCTSM_setup.txt', 'w') as fp:
with open("done_FSURDATMODIFYCTSM_setup.txt", "w") as fp:
pass

def _create_config_file(self):
cfg_template_path = os.path.join(self._ctsm_root,
'tools/modify_input_files/modify_fsurdat_template.cfg')
cfg_template_path = os.path.join(
self._ctsm_root, "tools/modify_input_files/modify_fsurdat_template.cfg"
)

with open (self._cfg_file_path,'w') as cfg_out:
with open (cfg_template_path,'r') as cfg_in:
with open(self._cfg_file_path, "w") as cfg_out:
with open(cfg_template_path, "r") as cfg_in:
for line in cfg_in:
if re.match(r' *fsurdat_in *=', line):
line = 'fsurdat_in = {}'.format(self._fsurdat_in)
elif re.match(r' *fsurdat_out *=', line):
line = 'fsurdat_out = {}'.format(self._fsurdat_out)
elif re.match(r' *idealized *=', line):
line = 'idealized = True'
if re.match(r" *fsurdat_in *=", line):
line = "fsurdat_in = {}".format(self._fsurdat_in)
elif re.match(r" *fsurdat_out *=", line):
line = "fsurdat_out = {}".format(self._fsurdat_out)
elif re.match(r" *idealized *=", line):
line = "idealized = True"
cfg_out.write(line)


def _run_modify_fsurdat(self):
tool_path = os.path.join(self._ctsm_root,
'tools/modify_input_files/fsurdat_modifier')
tool_path = os.path.join(self._ctsm_root, "tools/modify_input_files/fsurdat_modifier")

self._case.load_env(reset=True)
conda_env = ". "+self._get_caseroot()+"/.env_mach_specific.sh; "
conda_env = ". " + self._get_caseroot() + "/.env_mach_specific.sh; "
# Preprend the commands to get the conda environment for python first
conda_env += self._get_conda_env()
# Source the env
try:
subprocess.run( conda_env+"python3 "+tool_path+" "+self._cfg_file_path, shell=True, check=True)
subprocess.run(
conda_env + "python3 " + tool_path + " " + self._cfg_file_path,
shell=True,
check=True,
)
except subprocess.CalledProcessError as error:
print("ERROR while getting the conda environment and/or ")
print("running the fsurdat_modifier tool: ")
Expand All @@ -95,9 +98,11 @@ def _run_modify_fsurdat(self):
raise

def _modify_user_nl(self):
append_to_user_nl_files(caseroot = self._get_caseroot(),
component = "clm",
contents = "fsurdat = '{}'".format(self._fsurdat_out))
append_to_user_nl_files(
caseroot=self._get_caseroot(),
component="clm",
contents="fsurdat = '{}'".format(self._fsurdat_out),
)

def _get_conda_env(self):
#
Expand All @@ -107,7 +112,7 @@ def _get_conda_env(self):
# Execute the module unload/load when "which conda" fails
# eg on cheyenne
try:
subprocess.run( "which conda", shell=True, check=True)
subprocess.run("which conda", shell=True, check=True)
conda_env = " "
except subprocess.CalledProcessError:
# Remove python and add conda to environment for cheyennne
Expand All @@ -118,4 +123,4 @@ def _get_conda_env(self):
# End above to get to actual command
conda_env += " && "

return( conda_env )
return conda_env
2 changes: 1 addition & 1 deletion cime_config/SystemTests/funitctsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

logger = logging.getLogger(__name__)

class FUNITCTSM(FUNIT):

class FUNITCTSM(FUNIT):
def __init__(self, case):
FUNIT.__init__(self, case)

Expand Down
Loading

0 comments on commit bb2a8d2

Please sign in to comment.