#!/usr/bin/env perl
#-----------------------------------------------------------------------------------------------
#
# build-namelist
#
# This script builds the namelists for the standalone CAM configuration of CCSM4.
# Eventually the system's build will be reworked so that individual components are responsible
# for building their own namelists.
#
# build-namelist is designed to be used in conjuction with configure.  By default configure
# produces a config_cache.xml file that contains all information needed at build time to procduce
# a CAM executable.  build-namelist reads this file to obtain information it needs to provide
# default values that are consistent with the CAM executable.  For example, the grid resolution
# is obtained from the cache file and used to determine appropriate defaults for boundary datasets
# that are resolution dependent.
#
# The simplest use of build-namelist is to execute it from the build directory where configure
# was run.  By default it will use the config_cache.xml file that was written by configure to
# determine the build time properties of the executable, and will write the files that contain 
# the output namelists in that same directory.  But if multiple runs are to made using the
# same executable, successive invocations of build-namelist will overwrite previously generated
# namelist files.  So generally the best strategy is to invoke build-namelist from the run
# directory and use the -config option to provide the filepath of the config_cache.xml file.
#
#
# Date        Contributor      Modification
# -------------------------------------------------------------------------------------------
# 2007-12-31  Brian Eaton      Original version
# 2008-02-02  B. Eaton         Restore -test functionality.
# 2008-07-01  Sean Santos      Added -inputdata functionality.
# 2008-07-09  B. Eaton         Provide default values for rad_climate variable which
#                              specifies the radiatively active constituents.
# 2008-08-26  B. Eaton         Add the driver namelist group ccsm_pes to specify the
#                              task/thread layout for all components.
# 2008-11-14  B. Eaton         Extend use_case functionality.
# 2009-09-02  B. Eaton         Allow namelist definition, defaults, and use case files
#                              to come from the user source mod directories.
#--------------------------------------------------------------------------------------------

use strict;
#use warnings;
#use diagnostics;

use Cwd;
use English;
use File::Basename;
use Getopt::Long;
use IO::File;
use FindBin qw($Bin);
use lib "$Bin/perl5lib";
use Build::ChemNamelist qw(set_dep_lists);
#-----------------------------------------------------------------------------------------------

sub usage {
    die <<EOF;
SYNOPSIS
     build-namelist [options]
OPTIONS
     -case "name"          Case identifier up to 32 characters
     -cice_nl "namelist"   Specify namelist settings for CICE directly on the commandline by supplying 
                           a string containing FORTRAN namelist syntax, e.g.,
                              -cice_nl "&ice histfreq=1 /"
                           This namelist will be passed to the invocation of the CICE build-namelist
                           via its -namelist argument.
     -config "filepath"    Read the given configuration cache file to determine the configuration
                           of the CAM executable.  Default: "config_cache.xml".
     -config_cice "filepath"
                           Filepath of the CICE config_cache file.  This filepath is passed to the
                           invocation of the CICE build-namelist.  Only specify this to override the
                           default filepath which was set when the CICE configure was invoked by
                           the CAM configure.
     -csmdata "dir"        Root directory of CCSM input data.
                           Can also be set by using the CSMDATA environment variable.
     -dir "directory"      Directory where output namelist files for each component will be
                           written, i.e., atm_in, drv_in, ice_in, lnd_in, rof_in, and ocn_in.
                           Default: current working directory.
     -help [or -h]         Print usage to STDOUT.
     -ignore_ic_date       Ignore the date of the initial condition files
                           when determining the default.
     -ignore_ic_year       Ignore just the year part of the date of the initial condition files
                           when determining the default.
     -infile "filepath"    Specify a file containing namelists to read values from.
     -inputdata "filepath" Writes out a list containing pathnames for required input datasets in
                           file specified.
     -namelist "namelist"  Specify namelist settings directly on the commandline by supplying 
                           a string containing FORTRAN namelist syntax, e.g.,
                              -namelist "&camexp stop_option='ndays' stop_n=10 /"
     -ntasks <n>           Specify the number of MPI tasks being used by the run.  This is used
                           to set a default decomposition for the FV dycore only (npr_yz).
     -runtype "type"       Type of simulation (startup, continue, or branch)
     -silent [-s]          Turns on silent mode - only fatal messages issued.
     -test                 Enable checking that input datasets exist on local filesystem.
     -use_case             Specify a use case.  Default: present day climatology
     -verbose [or -v]      Turn on verbose echoing of informational messages.
     -version              Echo the CVS tag name used to check out this CAM distribution.

Note: The precedence for setting the values of namelist variables is (highest to lowest):
      1. namelist values set by specific command-line options, i.e., -case, 
         -runtype
      2. values set on the command-line using the -namelist option,
      3. values read from the file specified by -infile,
      4. values specified by the -use_case option,
      5. values from the namelist defaults file.
EOF
}

#-----------------------------------------------------------------------------------------------
# Set the directory that contains the CAM configuration scripts.  If the command was
# issued using a relative or absolute path, that path is in $ProgDir.  Otherwise assume the
# command was issued from the current working directory.

(my $ProgName = $0) =~ s!(.*)/!!;      # name of this script
$ProgName = "CAM $ProgName";           # Since multiple components are now using a build-namelist
                                       # utility add "CAM" qualifier to the name.  This helps when
                                       # looking at error output from the whole CCSM system.
my $ProgDir = $1;                      # name of directory containing this script -- may be a
                                       # relative or absolute path, or null if the script is in
                                       # the user's PATH
my $cwd = getcwd();                    # current working directory
my $cfgdir;                            # absolute pathname of directory that contains this script
if ($ProgDir) { 
    $cfgdir = absolute_path($ProgDir);
} else {
    $cfgdir = $cwd;
}

# CAM root directory.  
my $cam_root = absolute_path("$cfgdir/../../../..");

my $cfg_cache = "config_cache.xml";           # Default name of configuration cache file
my $outdirname = ".";                         # Default name of output directory name

#-----------------------------------------------------------------------------------------------
# Save commandline
my $commandline = "$cfgdir/build-namelist @ARGV";

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

# Process command-line options.

my %opts = ( config         => $cfg_cache,
	     csmdata        => undef,
	     help           => 0,
	     dir            => $outdirname,
	     silent         => 0,
	     test           => 0,
	    );

GetOptions(
    "case=s"                    => \$opts{'case'},
    "cice_nl=s"                 => \$opts{'cice_nl'},
    "config=s"                  => \$opts{'config'},
    "config_cice=s"             => \$opts{'config_cice'},
    "csmdata=s"                 => \$opts{'csmdata'},
    "d|dir=s"                   => \$opts{'dir'},
    "h|help"                    => \$opts{'help'},
    "ignore_ic_date"            => \$opts{'ignore_ic_date'},
    "ignore_ic_year"            => \$opts{'ignore_ic_year'},
    "infile=s"                  => \$opts{'infile'},
    "inputdata=s"               => \$opts{'inputdata'},
    "namelist=s"                => \$opts{'namelist'},
    "ntasks=s"                  => \$opts{'ntasks'},
    "runtype=s"                 => \$opts{'runtype'},
    "s|silent"                  => \$opts{'silent'},
    "test"                      => \$opts{'test'},
    "uc|use_case=s"             => \$opts{'use_case'},
    "v|verbose"                 => \$opts{'verbose'},
    "version"                   => \$opts{'version'},
)  or usage();

# Give usage message.
usage() if $opts{'help'};

# Echo version info.
if ($opts{'version'}) {
    version($cfgdir);
    exit;
}

# Check for unparsed arguments
if (@ARGV) {
    print "ERROR: unrecognized arguments: @ARGV\n";
    usage();
}

# Define print levels:
# 0 - only issue fatal error messages
# 1 - only informs what files are created (default)
# 2 - verbose
my $print = 1;
if ($opts{'silent'})  { $print = 0; }
if ($opts{'verbose'}) { $print = 2; }
my $eol = "\n";

if ($print>=2) { print "Setting CAM configuration script directory to $cfgdir$eol"; }
if ($print>=2) { print "build-namelist was invoked with the commandline:\n $commandline$eol"; }

# Check that configuration cache file exists.
(-f $opts{'config'})  or  die <<"EOF";
** $ProgName - ERROR: Cannot find configuration cache file: \"$opts{'config'}\" **
EOF

if ($print>=2) { print "Using CAM configuration cache file $opts{'config'}$eol"; }

# Check that the CCSM inputdata root directory has been specified.
my $inputdata_rootdir = undef;
if (defined($opts{'csmdata'})) {
    $inputdata_rootdir = $opts{'csmdata'};
}
elsif (defined $ENV{'CSMDATA'}) {
    $inputdata_rootdir = $ENV{'CSMDATA'};
}
else {
    die "$ProgName - ERROR: CCSM inputdata root directory must be specified by either -csmdata argument\n" .
	" or by the CSMDATA environment variable. :";
}

if ($print>=2) { print "CCSM inputdata root directory: $inputdata_rootdir$eol"; }

# If the -test option is specified, then the inputdata root directory must be local or nfs mounted.
if ($opts{'test'}) {
(-d $inputdata_rootdir)  or  die <<"EOF";
** $ProgName - ERROR: CCSM inputdata root is not a directory: \"$inputdata_rootdir\" **
EOF
}

#-----------------------------------------------------------------------------------------------
# Make sure we can find required perl modules, definition, and defaults files.
# Look for them under the directory that contains the configure script.

# The XML::Lite module is required to parse the XML files.
(-f "$cfgdir/perl5lib/XML/Lite.pm")  or  die <<"EOF";
** $ProgName - ERROR: Cannot find perl module \"XML/Lite.pm\" in directory \"$cfgdir/perl5lib\" **
EOF

# The Build::Config module provides utilities to access the configuration information
# in the config_cache.xml file
(-f "$cfgdir/perl5lib/Build/Config.pm")  or  die <<"EOF";
** $ProgName - ERROR: Cannot find perl module \"Build/Config.pm\" in directory \"$cfgdir/perl5lib\" **
EOF

# The Build::NamelistDefinition module provides utilities to validate that the output
# namelists are consistent with the namelist definition file
(-f "$cfgdir/perl5lib/Build/NamelistDefinition.pm")  or  die <<"EOF";
** $ProgName - ERROR: Cannot find perl module \"Build/NamelistDefinition.pm\" in directory \"$cfgdir/perl5lib\" **
EOF

# The Build::NamelistDefaults module provides a utility to obtain default values of namelist
# variables based on finding a best fit with the attributes specified in the defaults file.
(-f "$cfgdir/perl5lib/Build/NamelistDefaults.pm")  or  die <<"EOF";
** $ProgName - ERROR: Cannot find perl module \"Build/NamelistDefaults.pm\" in directory \"$cfgdir/perl5lib\" **
EOF

# The Build::Namelist module provides utilities to parse input namelists, to query and modify
# namelists, and to write output namelists.
(-f "$cfgdir/perl5lib/Build/Namelist.pm")  or  die <<"EOF";
** $ProgName - ERROR: Cannot find perl module \"Build/Namelist.pm\" in directory \"$cfgdir/perl5lib\" **
EOF

#-----------------------------------------------------------------------------------------------
# Add $cfgdir/perl5lib to the list of paths that Perl searches for modules
unshift @INC, "$cfgdir/perl5lib";
require XML::Lite;
require Build::Config;
require Build::NamelistDefinition;
require Build::NamelistDefaults;
require Build::Namelist;

#-----------------------------------------------------------------------------------------------
# Create a configuration object from CAM's config_cache.xml file.  This object contains
# all the build-time specifications of the CAM executable.
my $cfg = Build::Config->new($opts{'config'});

#-----------------------------------------------------------------------------------------------
# Create a namelist definition object.  This object provides a method for verifying that the
# output namelist variables are in the definition file, and are output in the correct
# namelist groups.  Requires a namelist definition file...
#
# The namelist definition file contains entries for all namelist variables that
# can be output by build-namelist.  The version of the file that is associate with a
# fixed CAM tag is $cfgdir/namelist_files/namelist_definition.xml.  To aid developers
# who make use of the source mods directory (via -usr_src arg to configure) we allow
# the definition file to come from one of those directories.

my $nl_definition_file;
my @usr_src_dirs = split ',', $cfg->get('usr_src');
if (@usr_src_dirs) {
    foreach my $dir (@usr_src_dirs) {
	if (-f "$dir/namelist_definition.xml") {
	    $nl_definition_file = "$dir/namelist_definition.xml";
	    last;
	}
    }
}
if (! defined $nl_definition_file) {
    # default location of namelist definition file
    $nl_definition_file = "$cfgdir/namelist_files/namelist_definition.xml";
    (-f "$nl_definition_file")  or  die <<"EOF";
    ** $ProgName - ERROR: Cannot find namelist definition file \"$nl_definition_file\" **
EOF
}

if ($print>=2) { print "Using namelist definition file $nl_definition_file$eol"; }

my $definition = Build::NamelistDefinition->new($nl_definition_file);

#-----------------------------------------------------------------------------------------------
# Create a namelist defaults object.  This object provides default values for variables
# contained in the input defaults file.  The configuration object provides attribute
# values that are relevent for the CAM executable for which the namelist is being produced.
# These attributes are used along with optional user specified attributes to find the
# best match when looking for default values.
#
# The namelist defaults file contains default values for all required namelist variables.
# Analogously to the definition file, we allow a user modified version of this file to
# be present in one of the usr_src directories.

my $nl_defaults_file;
if (@usr_src_dirs) {
    foreach my $dir (@usr_src_dirs) {
	if (-f "$dir/namelist_defaults_cam.xml") {
	    $nl_defaults_file = "$dir/namelist_defaults_cam.xml";
	    last;
	}
    }
}
if (! defined $nl_defaults_file) {
    # default location of namelist defaults file
    $nl_defaults_file = "$cfgdir/namelist_files/namelist_defaults_cam.xml";
    (-f "$nl_defaults_file")  or  die <<"EOF";
    ** $ProgName - ERROR: Cannot find namelist defaults file \"$nl_defaults_file\" **
EOF
}

if ($print>=2) { print "Using namelist defaults file $nl_defaults_file$eol"; }

my $defaults = Build::NamelistDefaults->new($nl_defaults_file, $cfg);

#-----------------------------------------------------------------------------------------------
# Similarly to the namelist definition and defaults files, the use case file
# may also come from the usr_src directories.  Determine the location of the 
# use case file.

my $use_case_file;
if (defined $opts{'use_case'}) {

    if (@usr_src_dirs) {
	foreach my $dir (@usr_src_dirs) {
	    if (-f "$dir/$opts{'use_case'}.xml") {
		$use_case_file = "$dir/$opts{'use_case'}.xml";
		last;
	    }
	}
    }

    if (! defined $use_case_file) {
	# default location of namelist use case files
	$opts{'use_case_dir'} = "$cfgdir/namelist_files/use_cases";
	validate_use_case("commandline", \%opts);
	$use_case_file = "$opts{'use_case_dir'}/$opts{'use_case'}.xml";
    }

    if ($print>=2) { print "Using namelist use case file $use_case_file$eol"; }
}

#-----------------------------------------------------------------------------------------------
# Create an empty namelist object.  Add values to it in order of precedence.
my $nl = Build::Namelist->new();

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

# Some regular expressions...
# **N.B.** the use of qr// for precompiling regexps isn't supported until perl 5.005.
my $TRUE  = "\.true\.";
my $FALSE = "\.false\.";

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

# Process the user input in order of precedence.  At each point we'll only add new
# values to the namelist and not overwrite previously specified specified values which
# have higher precedence.

# Process the commandline args that provide specific namelist values.

# Case name
if (defined $opts{'case'}) { add_default($nl, 'case_name', 'val'=>$opts{'case'}); }

# Run type
if (defined $opts{'runtype'}) { add_default($nl, 'start_type', 'val'=>$opts{'runtype'}); }

# Process the -namelist arg.

if (defined $opts{'namelist'}) {
    # Parse commandline namelist
    my $nl_arg = Build::Namelist->new($opts{'namelist'});

    # Validate input namelist -- trap exceptions
    my $nl_arg_valid;
    eval { $nl_arg_valid = $definition->validate($nl_arg); };
    if ($@) {
	die "$ProgName - ERROR: Invalid namelist variable in commandline arg '-namelist'.\n $@";
    }

    # Merge input values into namelist.  Previously specified values have higher precedence
    # and are not overwritten.
    $nl->merge_nl($nl_arg_valid);
}

# Process the -infile arg.

if (defined $opts{'infile'}) {
    # Parse namelist input from a file
    my $nl_infile = Build::Namelist->new($opts{'infile'});

    # Validate input namelist -- trap exceptions
    my $nl_infile_valid;
    eval { $nl_infile_valid = $definition->validate($nl_infile); };
    if ($@) {
	die "$ProgName - ERROR: Invalid namelist variable in '-infile' $opts{'infile'}.\n $@";
    }

    # Merge input values into namelist.  Previously specified values have higher precedence
    # and are not overwritten.
    $nl->merge_nl($nl_infile_valid);
}

# Process the -use_case arg.
# Declare global symbol $uc_defaults even if it's not defined, because we check whether it's
# defined before using it in the get_default_value method below.

my $uc_defaults;
if (defined $use_case_file) {

    # The use case definition is contained in an xml file with the same format as the defaults file.
    # Create a new NamelistDefaults object.
    $uc_defaults = Build::NamelistDefaults->new($use_case_file, $cfg);

    # Loop over the variables specified in the use case.
    # A defaults file may contain information for variables that are not namelist variables.
    # Check each name in the defaults file, and add each namelist variable to the namelist.
    my @vars = $uc_defaults->get_variable_names();
    VAR: foreach my $var (@vars) {

	# Query the definition to find which group the variable belongs to.  Skip if not found.
	my $group = $definition->get_group_name($var);
	if ($group) {
	    # Get the value of $var from the use case defaults
	    my $val = $uc_defaults->get_value($var);
	    if (defined $val) {
		add_default($nl, $var, 'val'=>$val);
	    }
	    # If the use case doesn't provide a default value, then just ignore.  This allows the
	    # use case mechanism to provide defaults for some attributes (e.g. a specific grid), and
	    # not for others.
	}
    }
}

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

# Add default values for required namelist variables that have not been previously set.
# This is done either by using the namelist default object, or directly with inline logic.

# Are we building namelists for the cpl6 scripts, the cpl7 scripts, or for standalone CAM 
# scripts.
my $cpl7_build = $cfg->get('ccsm_seq');
my $ccsm_build = $cpl7_build;
my $cam_build  = $ccsm_build ? 0 : 1;
if ($print>=2) { 
    if ($cpl7_build) {
	print "Writing namelist files for cpl7 scripts$eol";
    }
    elsif ($cam_build) {
	print "Writing namelist files for cam standalone scripts$eol";
    }
}


# Start with the driver component.  These settings are communicated by the driver to
# all subcomponents.

######################################
# namelist group: seq_cplflds_inparm #
######################################
add_default($nl, 'flds_co2_dmsa',  'val'=>'.false.');
add_default($nl, 'flds_co2a',      'val'=>'.true.');
add_default($nl, 'flds_co2b',      'val'=>'.false.');
add_default($nl, 'flds_co2c',      'val'=>'.false.');
add_default($nl, 'cplflds_custom', 'val'=>'');

############################
# namelist group: ccsm_pes #
############################

# By default the driver sets all components to use all tasks.  This is the
# appropriate default for the standalone CAM configuration.

# By default the driver sets all components to use 1 thread.  This should be
# reset either to user specified values, or by default use the OMP_NUM_THREADS
# environment variable or the nthreads configuration parameter to set the thread
# count for each component.

# Is this an smp build?
my $smp = $cfg->get('smp');
if ($smp) {

    # If user has set the specific variables for component threads on the commandline
    # those values will be used.  If not, the highest precedence will be given the the
    # value of the environment variable OMP_NUM_THREADS.  That is because the number of
    # threads specified on the configure commandline is used to determine an appropriate
    # decomposition for the CICE model, but that decomposition may be valid for a range
    # of ntask/nthread settings.

    # Check for OMP_NUM_THREADS
    my $nthreads;
    if (defined $ENV{'OMP_NUM_THREADS'}) {
	$nthreads = $ENV{'OMP_NUM_THREADS'};
    }
    # Has the number of threads been set by configure
    elsif (defined $cfg->get('nthreads')) {
	$nthreads = $cfg->get('nthreads');
    }

    if ($nthreads) {
	add_default($nl, 'atm_nthreads', 'val'=>$nthreads);
	add_default($nl, 'cpl_nthreads', 'val'=>$nthreads);
	add_default($nl, 'ice_nthreads', 'val'=>$nthreads);
	add_default($nl, 'lnd_nthreads', 'val'=>$nthreads);
	add_default($nl, 'ocn_nthreads', 'val'=>$nthreads);
	add_default($nl, 'rof_nthreads', 'val'=>$nthreads);
    }
}

#######################################
# namelist group: seq_infodata_inparm #
#######################################
my $phys_mode_flags = 0;
my $adia_mode = 0;
my $aqua_mode = 0;

# Case name
add_default($nl, 'case_name');

# Run type
add_default($nl, 'start_type');

# Spectral Element dycore
my $dyn = $cfg->get('dyn');
if ($dyn =~ /se/) {add_default($nl, 'vect_map', 'val'=>'cart3d');}

# Adiabatic or Ideal physics
my $phys = $cfg->get('phys');
if ($phys eq 'adiabatic') { add_default($nl, 'atm_adiabatic',  'val'=>'.true.'); }
if ($phys eq 'ideal')     { add_default($nl, 'atm_ideal_phys', 'val'=>'.true.'); }

# Aqua planet 

my $aqua_flag = $cfg->get('ocn');
my $nl_aqua_flag = $nl->get_value('aqua_planet');

if ($aqua_flag  eq 'aquaplanet') {
    $aqua_mode = 1;
}

# Consistency check between configuration and namelist variables used for aquaplanet.
if ($aqua_mode and defined $nl_aqua_flag  and ($nl_aqua_flag  =~ m/$FALSE/io)) {
   die "$ProgName - ERROR: Configured CAM for aquaplanet but user set aqua_planet to FALSE in the namelist. \n";
}
if (!($aqua_mode) and defined $nl_aqua_flag  and ($nl_aqua_flag  =~ m/$TRUE/io)) {
   die "$ProgName - ERROR: CAM not configured for aquaplanet but user has set aqua_planet to TRUE in the namelist. \n";
}

if ($aqua_mode) {
    add_default($nl, 'aqua_planet', 'val'=>'.true.');
    add_default($nl, 'aqua_planet_sst', 'val'=>'1');
    ++$phys_mode_flags;
}

# Consistency check for namelist variables used to implement physics modes.
my $phys_flag = $nl->get_value('atm_adiabatic');
if (defined $phys_flag  and ($phys_flag  =~ m/$TRUE/io)) {
    $adia_mode = 1;
    ++$phys_mode_flags;
}
my $ideal_mode = 0;
$phys_flag = $nl->get_value('atm_ideal_phys');
if (defined $phys_flag  and ($phys_flag  =~ m/$TRUE/io)) {
    $ideal_mode = 1;
    ++$phys_mode_flags;
}
if ($phys_mode_flags > 1) {
    die "$ProgName - ERROR: Only one of the variables atm_adiabatic, atm_ideal_phys, and aqua_planet can be set .true. \n";
}

# Set convenience flag to indicate that one of the ideal, adiabatic, or 
# aqua-planet modes is being used.
my $ideal_or_adia_or_aqua = 0;
if ($phys_mode_flags == 1) { $ideal_or_adia_or_aqua = 1; }

# Set some flags that determine whether or not build-namelist will produce output
# for non-atm components.

# Start by checking how the executable was configured.


# If the physics mode is one of adiabatic, ideal, or aqua_planet, then the
# land, rof, and sea ice components are inactive (whether the executable was configured
# with them or not).
my $lnd_active = 1;
my $rof_active = 1;
my $ice_active = 1;
if ($ideal_or_adia_or_aqua) {
    $lnd_active = 0;
    $rof_active = 0;
    $ice_active = 0;
}

# Note that the prescribed SSTs
# used by aqua-planet mode are implemented in the cam_aqua component.)

# Single column mode
my $scam = $cfg->get('scam');
if ($scam) {
    add_default($nl, 'single_column', 'val'=>'.true.');
    my $scmlat = $nl->get_value('scmlat');
    my $scmlon = $nl->get_value('scmlon');
    unless (defined $scmlat and defined $scmlon) {
	die "$ProgName - ERROR: In SCAM mode both scmlat and scmlon namelist variables must be set. \n";
    }
}

######################################
# namelist group: seq_timemgr_inparm #
######################################

# Length of simulation
add_default($nl, 'stop_option');
unless (defined $nl->get_value('stop_ymd')) { add_default($nl, 'stop_n'); }

# Restart interval
add_default($nl, 'restart_option');

# Start date
# The following check should be done for CAM standalone builds only.
if ($cam_build) {
    # When the user specifies ncdata there is no default for start_ymd since there is
    # no way to determine the corresponding date of the ncdata file.  So only add
    # a default for start_ymd if the user has not specified ncdata.
    if (defined $nl->get_value('ncdata')) {
	unless (defined $nl->get_value('start_ymd')) {
	    die "$ProgName - ERROR: It is not allowed to set ncdata without also setting start_ymd. \n";
	}
    }
    else {
	add_default($nl, 'start_ymd');
    }
}

# Orbit (if not coupled)
# If orbital parameters have not been specified then check for orbit year.
# If orbit year has not been specified, then set a default value.
if ($cam_build) {
    if (not defined $nl->get_value('orb_obliq') or
	not defined $nl->get_value('orb_eccen') or
	not defined $nl->get_value('orb_mvelp')     ) {
	if (not defined $nl->get_value('orb_iyear')) {
	    add_default($nl, 'orb_iyear');
	}
    }
}

add_default($nl, 'ocean_tight_coupling');

# Coupling interval
# The default is for CAM to couple to the surface components every CAM timestep.
# So start by making sure CAM's dtime is set.
add_default($nl, 'dtime');
add_default($nl, 'atm_cpl_dt', 'val'=>$nl->get_value('dtime'));

###############################
# namelist group: prof_inparm #
###############################

# The default for timing output is to use separate files for each MPI task.
# Change default to using a single file.
add_default($nl, 'profile_single_file', 'val'=>'.true.');

#-----------------------------------------------------------------------------------------------
# Add defaults for the CAM component 

my $chem = $cfg->get('chem');
my $waccm_chem = ($chem =~ "waccm_");
my $waccm_phys = $cfg->get('waccm_phys');
my $carma = $cfg->get('carma');

my $prog_species = $cfg->get('prog_species');
my $prog_ghg1    = ($chem =~ "trop_mozart" or $chem =~ "trop_strat" or $chem =~ "ghg" or $prog_species =~ "GHG");
my $prog_ghg2    = ($chem =~ "ghg" or $prog_species =~ "GHG");
my $ghg_chem     = ($chem =~ "ghg");
my $aero_chem    = ($chem =~ "aero" or $chem eq 'trop_mozart' or $chem eq 'trop_mozart_soa' or $chem =~ 'trop_strat' or $chem =~ 'tsmlt' or $chem eq 'trop_bam');

my $chem_rad_passive = ($nl->get_value('chem_rad_passive') =~ /$TRUE/io);
my $ipcc_aircraft_emis = ($nl->get_value('ipcc_aircraft_emis') =~ /$TRUE/io);

my $rad_prog_ocarb = (($prog_species =~ "OC"   or $aero_chem) and !($chem_rad_passive));
my $rad_prog_bcarb = (($prog_species =~ "BC"   or $aero_chem) and !($chem_rad_passive));
my $rad_prog_sulf  = (($prog_species =~ "SO4"  or $aero_chem or $chem =~ "super_fast_llnl") and !($chem_rad_passive));
my $rad_prog_dust  = (($prog_species =~ "DST"  or $aero_chem) and !($chem_rad_passive));
my $rad_prog_sslt  = (($prog_species =~ "SSLT" or $aero_chem) and !($chem_rad_passive));
my $rad_prog_ozone = (($chem =~ "mozart" or $chem =~ "tsmlt" or $chem =~ "trop_strat" or $chem =~ "super_fast_llnl") and !($chem_rad_passive));

# Check for eruptive volcano emissions.  These will be radiatively active by default, but
# only if using BAM and the camrt radiation package (cam4 physics)
# or if using MAM and the rrtmg package  (cam5 physics)
my $rad_volcaero = $nl->get_value('prescribed_volcaero_file') ? 1 : 0;

#################
# CAM namelists #
#################

# Print conservation errors
# Turn this off for PERGRO runs or for WACCM runs
if ($cfg->get('pergro') or ($chem ne 'none')) {
    add_default($nl, 'print_energy_errors', 'val'=>'.false.');
}

# Turn on debugging checks
if ($cfg->get('debug')) {
    add_default($nl, 'state_debug_checks', 'val'=> '.true.')
}

# Chemistry deposition lists
if ( ($chem ne 'none') or ( $prog_species ) ){
    my $chem_proc_src = $cfg->get('chem_proc_src');
    my $chem_src_dir = $cfg->get('chem_src_dir');

    my ($gas_wetdep_list, $aer_wetdep_list, $aer_drydep_list, $gas_drydep_list) =
	set_dep_lists( $cfgdir, $chem_proc_src, $chem_src_dir, $print );

    if ($gas_wetdep_list){
      add_default($nl, 'gas_wetdep_method' );
      add_default($nl, 'gas_wetdep_list', 'val'=>$gas_wetdep_list ); 
    }
    if ($aer_wetdep_list){ add_default($nl, 'aer_wetdep_list', 'val'=>$aer_wetdep_list ); }
    if ($gas_drydep_list){ add_default($nl,     'drydep_list', 'val'=>$gas_drydep_list ); }
    if ($aer_drydep_list){ add_default($nl, 'aer_drydep_list', 'val'=>$aer_drydep_list ); }

    if ( $gas_drydep_list ) {
      add_default($nl, 'depvel_file' );
      add_default($nl, 'depvel_lnd_file' );
      add_default($nl, 'clim_soilw_file' );
      add_default($nl, 'season_wes_file' );
    }
}

# Initial conditions
#
# Most of the attributes that are matched to determine the default initial file are 
# build time options that come from the configuration object.  But there are also a couple
# of run time options that need to be considered.  Set those in the optional hash argument
# to add_default.
#
# Check for aqua-planet run:
my %atts = ();

# The initial date is an attribute in the defaults file which should be matched unless
# the user explicitly requests to ignore the initial date via the -ignore_ic_date option, 
# or just ignore the year of the initial date via the -ignore_ic_year option.
my $ic_date = $nl->get_value('start_ymd');
if ($opts{'ignore_ic_date'}) {
    # Don't set any attribute for date matching.  By putting this option first it
    # will take precedence in the case that the user has set both -ignore_ic_date
    # and -ignore_ic_year
}
elsif ($opts{'ignore_ic_year'}) {
    $atts{'ic_md'} = $ic_date;
}
else {
    # if neither option specified then match full date
    $atts{'ic_ymd'} = $ic_date;
}
add_default($nl, 'ncdata', %atts);

#
# Simulated years: sim_year and sim_year_start
#
# sim_year
# This is used to identify appropriate defaults for climatological or transient
# forcing datasets.  If user hasn't specified then default to 2000 (present day climatology).
my $sim_year = '2000';
if (defined $nl->get_value('sim_year')) {
    $sim_year = $nl->get_value('sim_year');
    # strip quotes to use the value in attribute matching.
    $sim_year =~ s/['"]//g; #"'
}

# sim_year_start
# If sim_year is input as a range of years, then select the first year
# to use with some datasets
my $sim_year_start = $sim_year;
if ($sim_year =~ /(\d+)-(\d+)/) {
    $sim_year_start = $1;
}

# Topography
add_default($nl, 'bnd_topo', 'nofail'=>1);

# Tropopause climatology
add_default($nl, 'tropopause_climo_file');

# Radiation
my $rad_pkg = $cfg->get('rad');
if ($rad_pkg eq 'camrt') {
    # Only needed for CAM3/4 RT code
    # Absorptivity and emissivity data
    add_default($nl, 'absems_data');
}

# Solar irradiance

# First check that solar_const and solar_data_file are not both defined
if (defined $nl->get_value('solar_const') and 
    defined $nl->get_value('solar_data_file')) {

    print "$ProgName - WARNING: It is not allowed to set both solar_const \n".
	  "            and solar_data_file.  solar_const will be ignored. \n";

    if ($nl->delete_variable('solar_inparm', 'solar_const') != 0) {
	die "$ProgName - ERROR: not able to delete solar_const from group solar_inparm.\n"
    }

}

if ($rad_pkg eq 'rrtmg' or $chem =~ /waccm/) {

   if (defined $nl->get_value('solar_const')) {
      die "$ProgName - ERROR: Specifying solar_const with RRTMG or WACCM is not allowed.\n"
   }

   # use solar data file as the default for rrtmg and waccm_mozart
   add_default($nl, 'solar_data_file');
   add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.true.');

} else {

   if ($chem eq 'none' and !($prog_species =~ /SO4/) ) { # Spectral solar data is needed for photolysis
      # this preserves the default cam3 and cam4 configurations which do not have chemistry
      unless (defined $nl->get_value('solar_data_file')) {
        add_default($nl, 'solar_const');
      }
   } else {
      # use solar data file as the default for all chem conifigurations
      unless (defined $nl->get_value('solar_const')) {
         add_default($nl, 'solar_data_file');
      }
   }

   add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.false.');
}


# COSP simulator
if ($cfg->get('cosp')) {
    add_default($nl, 'docosp', 'val'=>'.true.');
}


# Constituents
# ============

# Carbon cycle constituents
my $co2_cycle = $cfg->get('co2_cycle');

if ($co2_cycle) {

    # co2_flag turns on the co2_cycle code in CAM
    add_default($nl, 'co2_flag', 'val'=>'.true.');


    # Supply a fossil fuel dataset if the co2_cycle is active and it's a
    # transient run ...
    if ($sim_year =~ /(\d+)-(\d+)/) {

	add_default($nl, 'co2_readflux_fuel', 'val'=>'.true.');

	# Check whether user has explicitly turned off reading the fossil fuel dataset.
	# (user specification has higher precedence than the true value set above)
	if ($nl->get_value('co2_readflux_fuel') =~ /$TRUE/io) {
	    add_default($nl, 'co2flux_fuel_file', 'sim_year'=>$sim_year);
	}
    }
}

# By default the prognostic co2_cycle CO2 will be radiative active, unless the
# the user sets this override variable.  This is used below to construct the
# rad_climate variable.
my $co2_cycle_rad_passive = ($nl->get_value('co2_cycle_rad_passive') =~ /$TRUE/io);


# If test tracers have been requested, set tracers_flag=.true.
if ($cfg->get('nadv_tt')) { add_default($nl, 'tracers_flag', 'val'=>'.true.'); }
if ($cfg->get('age_of_air_trcs')) { add_default($nl, 'aoa_tracers_flag', 'val'=>'.true.'); }

# If phys option is "cam3" then turn on the CAM3 prescribed ozone and aerosols
if ($phys eq 'cam3' and !$aqua_mode) {
    add_default($nl, 'cam3_ozone_data_on', 'val'=>'.true.');
    add_default($nl, 'cam3_aero_data_on', 'val'=>'.true.');
}

# Defaults for radiatively active constituents

my $cam3_ozone_data = $FALSE;
my $cam3_aero_data = $FALSE;

my $moz_ozone_data = $FALSE;
if (!$rad_prog_ozone) {
    $moz_ozone_data = $TRUE;
}

my $moz_aero_data = $FALSE;
if (!($rad_prog_ocarb) or !($rad_prog_bcarb) or !($rad_prog_sulf) or !($rad_prog_dust) or !($rad_prog_sslt)){
    $moz_aero_data = $TRUE;
}

# CAM3 prescribed ozone only by request
if (defined $nl->get_value('cam3_ozone_data_on') and
    $nl->get_value('cam3_ozone_data_on') =~ /$TRUE/io) {
    add_default($nl, 'bndtvo');
    $cam3_ozone_data = $TRUE;
    $moz_ozone_data = $FALSE;
}

# CAM3 prescribed aerosols only by request
if (defined $nl->get_value('cam3_aero_data_on') and
    $nl->get_value('cam3_aero_data_on') =~ /$TRUE/io) {

    # CAM3 aerosol mass climatology dataset (horizontal resolution dependent)
    add_default($nl, 'bndtvaer');
    $cam3_aero_data = $TRUE;
    $moz_aero_data = $FALSE;
}

if ($chem_rad_passive or $aqua_mode) {
    add_default($nl, 'atm_dep_flux', 'val'=>'.false.');
}

# The aerosol optics depend on which radiative transfer model is used due to differing
# wavelength bands used.
my $rrtmg = $rad_pkg eq 'rrtmg' ? 1 : 0;

# @aero_names contains the names of the entities (bulk aerosols and modes)
# that are externally mixed in aerosol optics calculation.  These entities are all
# associated with a file that contains their physical and optical properties.
my @aero_names = ();

# @aerosources contains a source identifier corresponding to each entity in @aero_names.
# The values are 'A', 'N', or 'M'
my @aerosources = ();

## Start assembling the gas contributions to the rad_climate specifier.

# $radval contains the "list of strings" value (stored as a scalar string with embedded quotes
# and commas) that will be assigned to the namelist variable rad_climate.  
my $radval = "'A:Q:H2O'";

if (($chem =~ /waccm_mozart/ or $chem =~ /waccm_tsmlt/) and !$chem_rad_passive) {
    $radval .= ",'A:O2:O2','A:CO2:CO2'";
}
elsif ($chem =~ /trop_strat/ and !$chem_rad_passive) {
    $radval .= ",'N:O2:O2','A:CO2:CO2'";
}
elsif ($co2_cycle and !$co2_cycle_rad_passive) {
    $radval .= ",'N:O2:O2','A:CO2:CO2'";
}
else {
    $radval .= ",'N:O2:O2','N:CO2:CO2'";
}

if ($rad_prog_ozone) {
    $radval .= ",'A:O3:O3'";
} elsif ($moz_ozone_data =~ /$TRUE/io) {
    $radval .= ",'N:ozone:O3'";
    unless (defined $nl->get_value('prescribed_ozone_file')) {
        add_default($nl, 'prescribed_ozone_datapath');
        add_default($nl, 'prescribed_ozone_file');
        add_default($nl, 'prescribed_ozone_name');
        add_default($nl, 'prescribed_ozone_type');
        add_default($nl, 'prescribed_ozone_cycle_yr');
    }
} elsif ($cam3_ozone_data =~ /$TRUE/io) {
    $radval .= ",'N:O3:O3'";
} else {
    die "ERROR: can not set ozone rad_climate specification\n";
}

if (($chem =~ /super_fast_llnl/) and !$chem_rad_passive ) {
    $radval .= ",'N:N2O:N2O','N:prsd_ch4:CH4','N:CFC11:CFC11','N:CFC12:CFC12'";
} elsif ((($chem =~ /waccm_mozart/) or ($chem =~ /waccm_tsmlt/) or ($chem =~ /trop_strat/)) and !$chem_rad_passive ) {
    $radval .= ",'A:N2O:N2O','A:CH4:CH4','N:CFC11STAR:CFC11','A:CFC12:CFC12'";
} elsif ($prog_ghg1 and $prog_ghg2 and !$chem_rad_passive ) {
    $radval .= ",'A:N2O:N2O','A:CH4:CH4','A:CFC11:CFC11','A:CFC12:CFC12'";
} elsif ($prog_ghg1 and !$prog_ghg2  and !$chem_rad_passive ) {
    $radval .= ",'A:N2O:N2O','A:CH4:CH4','N:CFC11:CFC11','N:CFC12:CFC12'";
} else {
    $radval .= ",'N:N2O:N2O','N:CH4:CH4','N:CFC11:CFC11','N:CFC12:CFC12'";
}

# Aerosol contributions to rad_climate

# The aerosol "model" is either bulk or modal.  If the aerosols are prescribed
# we can't tell (without looking in datasets) what the aerosol model is, so the
# prescribed_aero_model namelist variable is provided to allow the user to 
# override the default which is based on the physics package setting.
my $prescribed_aero_model = $nl->get_value('prescribed_aero_model');
if (defined $prescribed_aero_model) {
    # Strip the quotes from namelist input
    $prescribed_aero_model =~ s/['"]//g;                 #"'
}
else {
    $prescribed_aero_model = 'none';
    if ($chem eq 'none' or $chem eq 'waccm_ghg' or $chem eq 'super_fast_llnl' or $chem eq 'waccm_mozart' or $chem eq 'waccm_mozart_sulfur') {
	# If no chemistry then there must be prescribed aerosols unless physics
	# package is adiabatic or ideal.
	if ($phys eq 'cam5') {
	    $prescribed_aero_model = 'modal';
	}
	elsif ($phys eq 'cam4' or $phys eq 'cam3') {
	    $prescribed_aero_model = 'bulk';
	}
    }
}


# $aer_model is either 'bam' or 'mam'.  This token is used in the element names that
# are constructed to get the default physprops files.
my $aer_model = 'bam';
if ($prescribed_aero_model eq 'modal' or $chem =~ /_mam/) {$aer_model = 'mam';}

if ($aer_model eq 'mam' ) {

  my $aero_modes = '3mode';
  if ($chem =~ /_mam7/) {$aero_modes = '7mode';}

  my @mode_names;
  my @mode_types;
  my @mode_num;
  my @mode_num_cw ;
  my @mode_spec ;
  my @mode_spec_type;
  my @mode_spec_cw;
  my @mode_num_src;
  my @mode_spec_src;

  if ($aero_modes eq '3mode' ) {
    # MAM rad_climate settings.  The externally mixed quantities in the modal aerosol
    # model are the modes.
    push @aero_names, qw(mam3_mode1 mam3_mode2 mam3_mode3);
    push @aerosources, qw(M: M: M:);

    # Each of the mode names put into the @aero_names array needs to be defined.
    @mode_names    = qw(mam3_mode1 mam3_mode2 mam3_mode3);
    @mode_types    = qw(accum aitken coarse);
    @mode_num      = qw(num_a1 num_a2 num_a3);
    @mode_num_cw   = qw(num_c1 num_c2 num_c3);
    @mode_spec     = (
	[qw(so4_a1 pom_a1 soa_a1 bc_a1 dst_a1 ncl_a1)],
	[qw(so4_a2 soa_a2 ncl_a2)],
	[qw(dst_a3 ncl_a3 so4_a3)],
	);
    @mode_spec_type = (
	[qw(sulfate p-organic s-organic black-c dust seasalt)],
	[qw(sulfate s-organic seasalt)],
	[qw(dust seasalt sulfate)],
	);
    @mode_spec_cw  = (
	[qw(so4_c1 pom_c1 soa_c1 bc_c1 dst_c1 ncl_c1)],
	[qw(so4_c2 soa_c2 ncl_c2)],
	[qw(dst_c3 ncl_c3 so4_c3)],
	);

    if ($chem =~ /_mam3/) {
	@mode_num_src  = qw(A A A);
	@mode_spec_src = (
	    [qw(A A A A A A)],
	    [qw(A A A)],
	    [qw(A A A)],
	    );
    }
    else {
	@mode_num_src  = qw(N N N);
	@mode_spec_src = (
	    [qw(N N N N N N)],
	    [qw(N N N)],
	    [qw(N N N)],
	    );
    }
  } else { 

    # For 7 modes

    # MAM rad_climate settings.  The externally mixed quantities in the modal aerosol
    # model are the modes.
    push @aero_names, qw(mam7_mode1 mam7_mode2 mam7_mode3 mam7_mode4 mam7_mode5 mam7_mode6 mam7_mode7);
    push @aerosources, qw(M: M: M: M: M: M: M:);

    # Each of the mode names put into the @aero_names array needs to be defined.
    @mode_names    = qw(mam7_mode1 mam7_mode2 mam7_mode3 mam7_mode4 mam7_mode5 mam7_mode6 mam7_mode7);
    @mode_types    = qw(accum aitken primary_carbon fine_seasalt fine_dust coarse_seasalt coarse_dust);
    @mode_num      = qw(num_a1 num_a2 num_a3 num_a4 num_a5 num_a6 num_a7);
    @mode_num_cw   = qw(num_c1 num_c2 num_c3 num_c4 num_c5 num_c6 num_c7);

    @mode_spec     = (
	[qw(so4_a1 nh4_a1 pom_a1 soa_a1 bc_a1 ncl_a1)],
	[qw(so4_a2 nh4_a2 soa_a2 ncl_a2)],
	[qw(pom_a3 bc_a3)],
	[qw(ncl_a4 so4_a4 nh4_a4)],
	[qw(dst_a5 so4_a5 nh4_a5)],
	[qw(ncl_a6 so4_a6 nh4_a6)],
	[qw(dst_a7 so4_a7 nh4_a7)],
	);
    @mode_spec_type = (
	[qw(sulfate ammonium p-organic s-organic black-c seasalt)],
	[qw(sulfate ammonium s-organic seasalt)],
	[qw(p-organic black-c)],
	[qw(seasalt sulfate ammonium)],
	[qw(dust sulfate ammonium)],
	[qw(seasalt sulfate ammonium)],
	[qw(dust sulfate ammonium)],
	);
    @mode_spec_cw  = (
	[qw(so4_c1 nh4_c1 pom_c1 soa_c1 bc_c1 ncl_c1)],
	[qw(so4_c2 nh4_c2 soa_c2 ncl_c2)],
	[qw(pom_c3 bc_c3)],
	[qw(ncl_c4 so4_c4 nh4_c4)],
	[qw(dst_c5 so4_c5 nh4_c5)],
	[qw(ncl_c6 so4_c6 nh4_c6)],
	[qw(dst_c7 so4_c7 nh4_c7)],
	);


    @mode_num_src = qw(A A A A A A A);
    @mode_spec_src= (
	    [qw(A A A A A A)],
	    [qw(A A A A)],
	    [qw(A A)],
	    [qw(A A A)],
	    [qw(A A A)],
	    [qw(A A A)],
	    [qw(A A A)],
			);

  }
  my $mode_defs = create_mode_defs(\@mode_names, \@mode_types, \@mode_num, \@mode_num_cw, \@mode_num_src,
				     \@mode_spec, \@mode_spec_type, \@mode_spec_cw, \@mode_spec_src);

  add_default($nl, 'mode_defs', 'val'=>$mode_defs);

  # Top level for MAM processes that impact CAM climate.
  add_default($nl, 'clim_modal_aero_top_press');

  # water refractive index properties needed for modal optics calculations
  add_default($nl, 'water_refindex_file');

} else {

  # bulk aerosol contributions

  if ($rad_prog_sulf) {
    push(@aero_names, "SO4" );
    push(@aerosources, "A:" );
  } elsif ($moz_aero_data =~ /$TRUE/io) {
    push(@aero_names, "sulf");
    push(@aerosources, "N:" );
  } elsif ($cam3_aero_data =~ /$TRUE/io) {
    push(@aero_names, "cam3_sul" );
    push(@aerosources, "N:" );
  } else {
    die "ERROR: can not set sulf rad_climate specification\n";
  }

  if ($rad_prog_dust) {
    push(@aero_names, "DST01", "DST02", "DST03", "DST04" );
    push(@aerosources, "A:", "A:", "A:", "A:" );
  } elsif ($moz_aero_data =~ /$TRUE/io) {
    push(@aero_names, "dust1", "dust2", "dust3", "dust4");
    push(@aerosources, "N:", "N:", "N:", "N:" );
  } elsif ($cam3_aero_data =~ /$TRUE/io) {
    push(@aero_names, "cam3_dust1", "cam3_dust2", "cam3_dust3", "cam3_dust4" );
    push(@aerosources, "N:", "N:", "N:", "N:" );
  } else {
    die "ERROR: can not set dust rad_climate specification\n";
  }

  if ($rad_prog_bcarb) {
    push(@aero_names, "CB1", "CB2" );
    push(@aerosources, "A:", "A:" );
  } elsif ($moz_aero_data =~ /$TRUE/io) {
    push(@aero_names, "bcar1", "bcar2");
    push(@aerosources, "N:", "N:" );
  } elsif ($cam3_aero_data =~ /$TRUE/io) {
    push(@aero_names, "cam3_bcpho", "cam3_bcphi");
    push(@aerosources, "N:", "N:" );
  } else {
    die "ERROR: can not set black carbon rad_climate specification\n";
  }

  if ($rad_prog_ocarb) {
    push(@aero_names, "OC1", "OC2" );
    push(@aerosources, "A:", "A:" );
  } elsif ($moz_aero_data =~ /$TRUE/io) {
    push(@aero_names, "ocar1", "ocar2");
    push(@aerosources, "N:", "N:" );
  } elsif ($cam3_aero_data =~ /$TRUE/io) {
    push(@aero_names, "cam3_ocpho", "cam3_ocphi");
    push(@aerosources, "N:", "N:" );
  } else {
    die "ERROR: can not set organic carbon rad_climate specification\n";
  }

  if ($rad_prog_sslt) {
    if ($rrtmg) {
	push(@aero_names, "SSLT01", "SSLT02", "SSLT03", "SSLT04");
	push(@aerosources, "A:", "A:", "A:", "A:" );
    } else {
	push(@aero_names, "SSLTA", "SSLTC");
	push(@aerosources, "N:", "N:");
    }
  } elsif ($moz_aero_data =~ /$TRUE/io ) {
    if ($rrtmg) {
        push(@aero_names, "sslt1", "sslt2", "sslt3", "sslt4");
        push(@aerosources, "N:", "N:", "N:", "N:" );
    } else {
	push(@aero_names, "SSLTA", "SSLTC");
	push(@aerosources, "N:", "N:");
    }
  } elsif ($cam3_aero_data =~ /$TRUE/io ) {
    push(@aero_names, "cam3_ssam", "cam3_sscm");
    push(@aerosources, "N:", "N:" );
  } else {
    die "ERROR: can not set sslt rad_climate specification\n";
  }
}

if ( $prescribed_aero_model ne 'none' ) {
  # Prescribed aerosols -- bulk or modal
  if ($moz_aero_data =~ /$TRUE/io ) {
      # If user has not set prescribed_aero_file, then use defaults
      unless (defined $nl->get_value('prescribed_aero_file')) {
	  my @settings = ('prescribed_aero_datapath', 'prescribed_aero_file', 'prescribed_aero_type',
			'prescribed_aero_cycle_yr');
	  foreach my $setting (@settings) {
	      add_default($nl, $setting, 'aer_model'=>$aer_model);
	  }
      }
  }

  # Prescribed aerosol deposition fluxes.
  # Not needed if in aquaplanet mode.
  if ( (($moz_aero_data =~ /$TRUE/io) or ($cam3_aero_data =~ /$TRUE/io)) and !$aqua_mode ) {
      # If user has not set aerodep_flx_file, then use defaults
      unless (defined $nl->get_value('aerodep_flx_file')) {
	  my @settings = ('aerodep_flx_datapath', 'aerodep_flx_file', 'aerodep_flx_type',
			'aerodep_flx_cycle_yr');
	  foreach my $setting (@settings) {
	      add_default($nl, $setting, 'aer_model'=>$aer_model);
	  }
      }
  }
}

# Construct the aerosol part of the rad_climate string array by looping over
# the aerosol names and getting the default properties file for each:
foreach my $name (@aero_names) {
    my $source = shift(@aerosources);
    my $file;
    if ($source =~ 'M') {
	$file = "${name}_file";
    }
    else {
	$file = "${aer_model}_$name";
    }
    my $rel_filepath = get_default_value($file);
    my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
    $radval .= "," . quote_string($source . $name . ":" . $abs_filepath);
}

# Eruptive volcanic aerosols can be run with either BAM or MAM.
if ($rad_volcaero) {
    my $rel_filepath = get_default_value("VOLC_MMR");
    my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
    $radval .= "," . quote_string("N:VOLC_MMR:" . $abs_filepath);
}

# CARMA RRTMG and CAMRT
#
# Stratospheric black carbon
if ($carma eq 'bc_strat') {
    my $rel_filepath;
    if ($aer_model eq 'bam') {
        $rel_filepath = get_default_value("${aer_model}_bcar1");
    } else {
        $rel_filepath = get_default_value("${aer_model}_bc_a1");
    }
    my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
    my @val = ('SOOT01');
    foreach my $val (@val) {
        $radval .= "," . quote_string("A:" . $val . ":" . $abs_filepath);
    }
}

if ($rrtmg) {

  # CARMA Microphysics - RRTMG Only
  #
  # New CARMA models that have radiatively active tracers need to define the name of
  # each of the radiatively active constituents.
  
  if ($carma eq 'meteor_impact') {
    my @val = ('CRDUST01', 'CRDUST02', 'CRDUST03', 'CRDUST04', 'CRDUST05', 'CRDUST06', 'CRDUST07', 
               'CRDUST08', 'CRDUST09', 'CRDUST10', 'CRDUST11', 'CRDUST12', 'CRDUST13', 'CRDUST14',
               'CRDUST15', 'CRDUST16', 'CRDUST17', 'CRDUST18', 'CRDUST19', 'CRDUST20', 'CRDUST21');
  
    foreach my $val (@val) {
      $radval .= "," . quote_string("A:" . $val . ":" . $carma . "_" . $val . "_rrtmg.nc");
    }

    my @val = ('CRSOOT01', 'CRSOOT02', 'CRSOOT03', 'CRSOOT04', 'CRSOOT05', 'CRSOOT06', 'CRSOOT07', 
               'CRSOOT08', 'CRSOOT09', 'CRSOOT10', 'CRSOOT11', 'CRSOOT12', 'CRSOOT13', 'CRSOOT14',
               'CRSOOT15', 'CRSOOT16', 'CRSOOT17', 'CRSOOT18', 'CRSOOT19', 'CRSOOT20', 'CRSOOT21');
  
    foreach my $val (@val) {
      $radval .= "," . quote_string("A:" . $val . ":" . $carma . "_" . $val . "_rrtmg.nc");
    }
  }

  if ($carma eq 'test_radiative') {
    my @val = ('DUST01', 'DUST02', 'DUST03', 'DUST04', 'DUST05', 'DUST06', 'DUST07', 'DUST08', 
               'DUST09', 'DUST10', 'DUST11', 'DUST12', 'DUST13', 'DUST14', 'DUST15', 'DUST16');
  
    foreach my $val (@val) {
      $radval .= "," . quote_string("A:" . $val . ":" . $carma . "_" . $val . "_rrtmg.nc");
    }
  }
}

# Stratospheric sulfur aerosols 
if ($nl->get_value('strat_aero_feedback') =~ /$TRUE/io) {
    my $rel_filepath = get_default_value("VOLC_MMR");
    my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
    $radval .= "," . quote_string("N:VOLC_MMR:" . $abs_filepath);
}

add_default($nl, 'rad_climate', 'val'=>$radval);

# Cloud optics
if ($rrtmg) {
    add_default($nl, 'liqcldoptics');
    add_default($nl, 'icecldoptics');
    add_default($nl, 'liqopticsfile');
    add_default($nl, 'iceopticsfile');
}

# Volcanic Aerosol Mass climatology dataset
if ($nl->get_value('strat_volcanic')) { add_default($nl, 'bndtvvolc'); }

# Greenhouse gas production/loss rates
if ($ghg_chem) {
    add_default($nl, 'bndtvg');
    add_default($nl, 'ghg_chem', 'val'=>".true.");
}

# WACCM-GHG options
if ($chem eq 'waccm_ghg') {
    # *** Note *** this dataset only needed for waccm_ghg.
    # O2,O1,N2, CO2 Constituents for non-LTE calculations and heating rates below 200 nm
    unless (defined $nl->get_value('waccm_forcing_file')) {
	add_default($nl, 'waccm_forcing_datapath');
	add_default($nl, 'waccm_forcing_file');
    }
    add_default($nl, 'nlte_use_mo', 'val'=>".false.");
    add_default($nl, 'h2orates');
    add_default($nl, 'solar_parms_file');
}

if ( $prog_species ) {
    my $ddval;
    my $emisval;
    my $xfrcval;
    my $emisfirst = 1; my $emispre = "";
    my $xfrcfirst = 1; my $xfrcpre = "";
    if ( $prog_species =~ /SO4/ )  { 
      my %emis = ('DMS -> ' => 'dms_emis_bam',
                  'SO2 -> ' => 'so2_emis_bam',
                  'SO4 -> ' => 'so4_emis_bam', );
      foreach my $id (sort keys %emis) {
        my $rel_filepath = get_default_value($emis{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $emisval .= $emispre . quote_string($id . $abs_filepath);
        if ($emisfirst) { $emispre = ","; $emisfirst = 0; }
      }
      my %xfrc = ('SO2 -> ' => 'so2_vrt_emis_file',
		  'SO4 -> ' => 'so4_vrt_emis_file', );
      foreach my $id (sort keys %xfrc) {
        my $rel_filepath = get_default_value($xfrc{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $xfrcval .= $xfrcpre . quote_string($id . $abs_filepath);
        if ($xfrcfirst) { $xfrcpre = ","; $xfrcfirst = 0; }
      }
      # Prescribed oxidants
      my $val = "'O3','OH','NO3','HO2'";
      add_default($nl, 'tracer_cnst_specifier', 'val'=>$val);
      my @files = ( 'tracer_cnst_datapath','tracer_cnst_file');
      foreach my $file (@files) {
	add_default($nl, $file, 'ver'=>'fixed_ox');
      }
      unless (defined $nl->get_value('tracer_cnst_type')) {
	  add_default($nl, 'tracer_cnst_type', 'ver'=>'fixed_ox');
	  add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ox');
      }
      # Datasets
      my @files = ( 'xs_coef_file','xs_short_file','xs_long_file', 'rsf_file', 'exo_coldens_file' );
      foreach my $file (@files) {
	add_default($nl, $file);
      }
    }

    if ( $prog_species =~ /OC/ )  { 
      my %emis = ('OC1 -> ' => 'oc1_emis_bam', );
      foreach my $id (sort keys %emis) {
        my $rel_filepath = get_default_value($emis{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $emisval .= $emispre . quote_string($id . $abs_filepath);
        if ($emisfirst) { $emispre = ","; $emisfirst = 0; }
      }
    }
    if ( $prog_species =~ /BC/ )  { 
      my %emis = ('CB1 -> ' => 'cb1_emis_bam', );
      foreach my $id (sort keys %emis) {
        my $rel_filepath = get_default_value($emis{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $emisval .= $emispre . quote_string($id . $abs_filepath);
        if ($emisfirst) { $emispre = ","; $emisfirst = 0; }
      }
    }
    if ( $prog_species =~ /GHG/ )  { 
      add_default($nl, 'ghg_chem', 'val'=>".true.");
      add_default($nl, 'bndtvg');
    }
    if ( $prog_species =~ /DST/ )  { 
      add_default($nl, 'soil_erod_file' );
    }

    if ( $emisval ) {
      unless (defined $nl->get_value('srf_emis_type')) {
        add_default($nl, 'srf_emis_specifier', 'val'=>$emisval);
	add_default($nl, 'srf_emis_type',      'val'=>'CYCLICAL');
      }
    }
    if ( $xfrcval ) {
      add_default($nl, 'ext_frc_specifier',  'val'=>$xfrcval);
      add_default($nl, 'ext_frc_type',  'val'=>'CYCLICAL');
    }
} 

# if prescribed aerosol deposition fluxes then set aerodep_flx_specifier 
# depending on prescribed_aero_model -- bulk type is the default
if (defined $nl->get_value('aerodep_flx_file')) {
    unless (defined $nl->get_value('aerodep_flx_specifier')) {
	my $val;
	if ( $prescribed_aero_model eq 'modal' ) {
	    $val = "'bc_a1DDF','bc_c1DDF','pom_a1DDF','pom_c1DDF','soa_a1DDF','soa_c1DDF',"
                 . "'soa_a2DDF','soa_c2DDF','dst_a1DDF','dst_c1DDF','dst_a3DDF','dst_c3DDF',"
                 . "'bc_a1SFWET','bc_c1SFWET','pom_a1SFWET','pom_c1SFWET','soa_a1SFWET','soa_c1SFWET',"
                 . "'dst_a1SFWET','dst_c1SFWET','dst_a3SFWET','dst_c3SFWET'";
	} else {
	    $val = "'BCDEPWET','BCPHODRY','BCPHIDRY','OCDEPWET','OCPHODRY', 'OCPHIDRY',"
                 . "'DSTX01DD','DSTX02DD','DSTX03DD','DSTX04DD',"
		 . "'DSTX01WD','DSTX02WD','DSTX03WD','DSTX04WD'";
	}
	add_default($nl, 'aerodep_flx_specifier', 'val'=>$val);
    }
}
# if prescribed aerosol concentrations then set prescribed_aero_specifier
# depending on prescribed_aero_model -- bulk type is the default
if (defined $nl->get_value('prescribed_aero_file')) {
    unless (defined $nl->get_value('prescribed_aero_specifier')) {
	my $val;
	if ( $prescribed_aero_model eq 'modal' ) {
 	    #*_a1, *_a2 and *_a3 are now computed using *_logm and *logv, therefore they are removed
 	    $val ="'num_c1','bc_c1',  'dst_c1','ncl_c1',"
                  . "'pom_c1','so4_c1','soa_c1','num_c2',"
                  . "'ncl_c2','so4_c2','soa_c2','num_c3',"
                  . "'dst_c3','ncl_c3','so4_c3',"
                  #Adding log mean     quantities (only for interstitial aerosols)
 		  . "'num_a1_logm','bc_a1_logm', 'dst_a1_logm','ncl_a1_logm',"
                  . "'pom_a1_logm','so4_a1_logm','soa_a1_logm','num_a2_logm',"
                  . "'ncl_a2_logm','so4_a2_logm','soa_a2_logm','num_a3_logm',"
                  . "'dst_a3_logm','ncl_a3_logm','so4_a3_logm',"
                  #Adding log variance quantities (only for interstitial aerosols)
 		  . "'num_a1_logv','bc_a1_logv', 'dst_a1_logv','ncl_a1_logv',"
                  . "'pom_a1_logv','so4_a1_logv','soa_a1_logv','num_a2_logv',"
                  . "'ncl_a2_logv','so4_a2_logv','soa_a2_logv','num_a3_logv',"
                  . "'dst_a3_logv','ncl_a3_logv','so4_a3_logv'";
	} else {
	    $val = "'sulf:SO4','bcar1:CB1','bcar2:CB2','ocar1:OC1','ocar2:OC2',"
                 . "'sslt1:SSLT01','sslt2:SSLT02','sslt3:SSLT03','sslt4:SSLT04',"
	         . "'dust1:DST01','dust2:DST02','dust3:DST03','dust4:DST04'";
	}
	add_default($nl, 'prescribed_aero_specifier', 'val'=>$val);
    }
}

my $megan_emis = defined $nl->get_value('megan_specifier');
if ( $megan_emis ) { add_default($nl, 'megan_factors_file'); }

# Tropospheric full chemistry options
if ($chem =~ /trop_mozart/ or $chem =~ /trop_strat/ ) {
 
    # Surface emission datasets:
    my %verhash;
    my $val;
    my %species = ('CH3COCH3 -> ' => 'acetone_emis_file',
		   'BIGALK   -> ' => 'bigalk_emis_file',
		   'BIGENE   -> ' => 'bigene_emis_file',
		   'C2H4     -> ' => 'c2h4_emis_file',
		   'C2H5OH   -> ' => 'c2h5oh_emis_file',
		   'C2H6     -> ' => 'c2h6_emis_file',
		   'C3H6     -> ' => 'c3h6_emis_file',
		   'C3H8     -> ' => 'c3h8_emis_file',
		   'CH2O     -> ' => 'ch2o_emis_file',
		   'CH3CHO   -> ' => 'ch3cho_emis_file',
		   'CH3OH    -> ' => 'ch3oh_emis_file',
		   'CO       -> ' => 'co_emis_file',
		   'DMS      -> ' => 'dms_emis_file',
		   'MEK      -> ' => 'mek_emis_file',
		   'NH3      -> ' => 'nh3_emis_file',
		   'NO       -> ' => 'nox_emis_file',
		   'SO2      -> ' => 'so2_emis_file',
		   'HCN      -> ' => 'hcn_emis_file',
                   'HCOOH    -> ' => 'hcooh_emis_file',
		   'CH3CN    -> ' => 'ch3cn_emis_file',
		   'C2H2     -> ' => 'c2h2_emis_file',
		   'CH3COOH  -> ' => 'ch3cooh_emis_file',
                   'C10H16   -> ' => 'c10h16_emis_file',
		   'ISOP     -> ' => 'isop_emis_file',
		   );
    if ($chem =~ /mam3/) {
        %species = (%species,
                   'SOAG     -> ' => 'soag_emis_file',
                   'bc_a1    -> ' => 'bc_a1_emis_file',
                   'pom_a1   -> ' => 'pom_a1_emis_file',
                   'so4_a1   -> ' => 'so4_a1_emis_file', 
                   'so4_a2   -> ' => 'so4_a2_emis_file',
                   'num_a1   -> ' => 'num_a1_emis_file', 
                   'num_a2   -> ' => 'num_a2_emis_file',
		   );
        %verhash = ('ver'=>'mam');
    } elsif ($chem =~ /mam7/) {
        %species = (%species,
                   'SOAG     -> ' => 'soag_emis_file',
                   'bc_a3    -> ' => 'bc_a3_emis_file',
                   'num_a1   -> ' => 'mam7_num_a1_emis_file', 
                   'num_a2   -> ' => 'num_a2_emis_file',
                   'num_a3   -> ' => 'mam7_num_a3_emis_file',
                   'pom_a3   -> ' => 'pom_a3_emis_file',
                   'so4_a1   -> ' => 'so4_a1_emis_file', 
                   'so4_a2   -> ' => 'so4_a2_emis_file',
		   );
        %verhash = ('ver'=>'mam');
    } else {
        %species = (%species,
		   'CB1      -> ' => 'cb1_emis_file',
		   'CB2      -> ' => 'cb2_emis_file',
		   'OC1      -> ' => 'oc1_emis_file',
		   'OC2      -> ' => 'oc2_emis_file',
		    );
    }
    if ($chem =~ /_soa/) {
        %species = (%species,
                   'BENZENE  -> ' => 'soa_benzene_emis_file',
                   'XYLENE   -> ' => 'soa_xylene_emis_file',
		   'TOLUENE  -> ' => 'soa_toluene_emis_file',
		    );
    } else {
        %species = (%species,
		   'TOLUENE  -> ' => 'toluene_emis_file',
	           );
    }

    my $first = 1; my $pre = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id},\%verhash);
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_type',    'val'=>'CYCLICAL');
	add_default($nl, 'srf_emis_cycle_yr','val'=>'2000');
    }

    # aircraft emission datasets:
    %species = ();
    my $cyc_yr = '1999';
    if ($chem eq 'trop_strat_soa') {
      %species = ( 'NO2    -> ' => 'no2_aircraft_emis_file',
                   'CB1    -> ' => 'bc_aircraft_emis_file' );
    } elsif ($chem =~ /mam3/) {
      %species = ( 'NO2    -> ' => 'no2_aircraft_emis_file',
                   'SO2    -> ' => 'so2_ext_file',
                   'so4_a1 -> ' => 'so4_a1_ext_file', 
                   'so4_a2 -> ' => 'so4_a2_ext_file',
                   'pom_a1 -> ' => 'pom_a1_ext_file', 
                   'bc_a1  -> ' => 'bc_a1_ext_file', 
                   'num_a1 -> ' => 'num_a1_ext_file', 
                   'num_a2 -> ' => 'num_a2_ext_file', );
      $cyc_yr = '2000';
    } elsif ($chem =~ /mam7/) {
      %species = ( 'NO2    -> ' => 'no2_aircraft_emis_file',
                   'so4_a1 -> ' => 'so4_a1_ext_file', 
                   'so4_a2 -> ' => 'so4_a2_ext_file',
                   'pom_a3 -> ' => 'pom_a3_ext_file', 
                   'bc_a3  -> ' => 'bc_a3_ext_file', 
                   'num_a1 -> ' => 'mam7_num_a1_ext_file', 
                   'num_a2 -> ' => 'num_a2_ext_file',
                   'num_a3 -> ' => 'mam7_num_a3_ext_file', );
      $cyc_yr = '2000';
    } else {
      %species = ( 'CO     -> ' => 'co_aircraft_emis',
	  	   'NO     -> ' => 'no_aircraft_emis',
                   'SO2    -> ' => 'so2_aircraft_emis', );
    }

    $first = 1;
    $pre = "";
    $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id},\%verhash);
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    unless (defined $nl->get_value('ext_frc_type')) {
	add_default($nl, 'ext_frc_type',      'val'=>'CYCLICAL');
	add_default($nl, 'ext_frc_cycle_yr',  'val'=>$cyc_yr);
    }
    # 

    # 

    if ($chem =~ /trop_mozart/) {
      # Species with fixed stratosphere values
      $val = "'O3','NO','NO2','HNO3','CO','CH4','N2O','N2O5'";
      add_default($nl, 'fstrat_list', 'val'=>$val);
      add_default($nl, 'fstrat_file');
    }

    # Species with fixed lower boundary
    if ($chem =~ /trop_strat/) {
      $val = "'CCL4','CF2CLBR','CF3BR','CFC11','CFC113','CFC12','CH3BR','CH3CCL3','CH3CL','CH4','CO2','H2','HCFC22','N2O'";
    } else {
      $val = "'CH4','H2','N2O','CO2','CFC11','CFC12'";
    }
    add_default($nl, 'flbc_list', 'val'=>$val);
    unless (defined $nl->get_value('flbc_type')) {
	add_default($nl, 'flbc_type',  'val'=>'CYCLICAL');
	add_default($nl, 'flbc_cycle_yr',  'val'=>'2000');
    }

    # Datasets
    my @files = ( 'soil_erod_file', 'flbc_file', 
	         'xs_coef_file','xs_short_file','xs_long_file', 'rsf_file', 'exo_coldens_file', 'sulf_file', 'prescribed_strataero_file' );
    foreach my $file (@files) {
	add_default($nl, $file);
    }
    add_default($nl, 'prescribed_strataero_datapath');
    unless (defined $nl->get_value('prescribed_strataero_type')) {
	add_default($nl, 'prescribed_strataero_type',  'val'=>'CYCLICAL');
	add_default($nl, 'prescribed_strataero_cycle_yr',  'val'=>'2000');
    }
}

# Prognostic aerosols via CAM-Chem package.
# BAM settings
if ($chem eq 'trop_bam') {

    my %species;

    # Surface emission datasets:
    %species = ();
    %species = ('CB1      -> ' => 'cb1_emis_bam',
		'DMS      -> ' => 'dms_emis_bam',
		'OC1      -> ' => 'oc1_emis_bam',
		'SO2      -> ' => 'so2_emis_bam',
		'SO4      -> ' => 'so4_emis_bam', );
    my $first = 1;
    my $pre = "";
    my $val = "";
    foreach my $id (sort keys %species) {
	my $rel_filepath = get_default_value($species{$id});
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    add_default($nl, 'srf_emis_type',      'val'=>'CYCLICAL');
    
    # Surface emission datasets:
    %species = ();
    %species = ('SO2      -> ' => 'so2_vrt_emis_file',
		'SO4      -> ' => 'so4_vrt_emis_file', );
    $first = 1;
    $pre = "";
    $val = "";
    foreach my $id (sort keys %species) {
	my $rel_filepath = get_default_value($species{$id});
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    add_default($nl, 'ext_frc_type',      'val'=>'CYCLICAL');

    # Prescribed species
    add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2'");

    my @files = ('tracer_cnst_datapath', 'tracer_cnst_file');
    foreach my $file (@files) {
	add_default($nl, $file, 'ver'=>'fixed_ox');
    }
    unless (defined $nl->get_value('tracer_cnst_type')) {
	add_default($nl, 'tracer_cnst_type',    'ver'=>'fixed_ox');
	add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ox');
    }

    add_default($nl, 'fstrat_list', 'val'=>"' '");
    add_default($nl, 'flbc_list', 'val'=>"' '");

    # Datasets
    my @files = ( 'soil_erod_file','xs_coef_file','xs_short_file','xs_long_file', 'rsf_file', 'exo_coldens_file' );
    foreach my $file (@files) {
	add_default($nl, $file);
    }
}

if ($chem eq 'super_fast_llnl') {
    # Surface emission datasets:
    my $val;
    my %species;
    %species = (
		'CH2O     -> ' => 'ch2o_emis_file',
		'CO       -> ' => 'co_emis_file',
		'DMS      -> ' => 'dms_emis_file',
		'NO       -> ' => 'nox_emis_file',
		'SO2      -> ' => 'so2_emis_file',
                );
    if (! $megan_emis ) {
      %species = ( %species,
		'ISOP     -> ' => 'isop_emis_file',  );
    }
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_cycle_yr',  'val'=>'1997');
	add_default($nl, 'srf_emis_type',  'val'=>'CYCLICAL');
    }
    my $first = 1; my $pre = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id});
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);

    # vertical emissions... 
    %species = ();
    %species = ('SO2 -> ' => 'so2_vrt_emis_file',
		'SO4 -> ' => 'so4_vrt_emis_file' );
    add_default($nl, 'ext_frc_type', 'val'=>"'CYCLICAL'");

    if ($ipcc_aircraft_emis) {
      %species = ('SO2 -> ' => 'so2_vrt_emis_file',
	  	  'SO4 -> ' => 'so4_vrt_emis_file',
                  'NO2 -> ' => 'no2_aircraft_emis_file' );
    }

    $first = 1; $pre = ""; $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);

    # Species with fixed stratosphere values
    $val = "'NO','NO2','HNO3','CO'";
    add_default($nl, 'fstrat_list', 'val'=>$val);

    # Datasets
    my @files = ('airpl_emis_file', 'soil_erod_file', 'flbc_file', 'fstrat_file',
                 'sulf_file', 'tuv_xsect_file', 'o2_xsect_file', 'xs_long_file', 'rsf_file', 
                 'solar_parms_file',
                 'exo_coldens_file', 'linoz_data_path', 'linoz_data_file', 'chlorine_loading_file' );
    foreach my $file (@files) {
	add_default($nl, $file);
    }
    unless (defined $nl->get_value('flbc_type')) {
	add_default($nl, 'flbc_type',  'val'=>'CYCLICAL');
	add_default($nl, 'flbc_cycle_yr',  'val'=>'1990');
    }
    unless (defined $nl->get_value('chlorine_loading_type')) {
	add_default($nl, 'chlorine_loading_type', 'val'=>'FIXED');
	add_default($nl, 'chlorine_loading_fixed_ymd','val'=>'19900101');
    }

    add_default($nl, 'xactive_prates', 'val'=>'.false.');

    # Prescribed methane
    my $val = "'CH4'";
    add_default($nl, 'tracer_cnst_specifier', 'val'=>$val);
    my @files = ( 'tracer_cnst_datapath','tracer_cnst_file', 'tracer_cnst_filelist');
    foreach my $file (@files) {
	add_default($nl, $file, 'ver'=>'fixed_ch4');
    }
    unless (defined $nl->get_value('tracer_cnst_type')) {
	add_default($nl, 'tracer_cnst_type',    'ver'=>'fixed_ch4');
	add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ch4');
    }

    my $val = "'prsd_ch4:CH4'";
    add_default($nl, 'prescribed_ghg_specifier', 'val'=>$val);
    my @files = ( 'prescribed_ghg_datapath','prescribed_ghg_file', 'prescribed_ghg_filelist');
    foreach my $file (@files) {
	add_default($nl, $file, 'ver'=>'fixed_ch4');
    }
    unless (defined $nl->get_value('prescribed_ghg_type')) {
	add_default($nl, 'prescribed_ghg_type',    'ver'=>'fixed_ch4');
	add_default($nl, 'prescribed_ghg_cycle_yr','ver'=>'fixed_ch4');
    }
}

# MAM settings

if ($chem eq 'super_fast_llnl_mam3') {

    # Surface emission datasets:
    my $val;
    my %species;
    my %verhash = ('ver'=>'mam');
    %species = (
	        'CH2O   -> ' => 'ch2o_emis_file',
	        'CO     -> ' => 'co_emis_file',
	        'DMS    -> ' => 'dms_emis_file',
		'NO     -> ' => 'nox_emis_file',
		'SO2    -> ' => 'so2_emis_file',
                'SOAG   -> ' => 'soag_emis_file',
                'bc_a1  -> ' => 'bc_a1_emis_file',
                'pom_a1 -> ' => 'pom_a1_emis_file',
                'so4_a1 -> ' => 'so4_a1_emis_file',
                'so4_a2 -> ' => 'so4_a2_emis_file',
                'num_a1 -> ' => 'num_a1_emis_file',
                'num_a2 -> ' => 'num_a2_emis_file',
                );
    if (! $megan_emis ) {
      %species = ( %species,
		'ISOP   -> ' => 'isop_emis_file',  );
    }

    my $first = 1; my $pre = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id}, \%verhash );
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_type',      'val'=>'CYCLICAL');
	add_default($nl, 'srf_emis_cycle_yr',  'val'=>2000);
    }

    # vertical emissions... 
    %species = ();
    %species = ('SO2         -> ' => 'so2_ext_file',
                'so4_a1      -> ' => 'so4_a1_ext_file', 
                'so4_a2      -> ' => 'so4_a2_ext_file',
                'pom_a1      -> ' => 'pom_a1_ext_file', 
                'bc_a1       -> ' => 'bc_a1_ext_file', 
                'num_a1      -> ' => 'num_a1_ext_file', 
                'num_a2      -> ' => 'num_a2_ext_file', );

    $first = 1; $pre = ""; $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id}, \%verhash );
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    unless (defined $nl->get_value('ext_frc_type')) {
	add_default($nl, 'ext_frc_type', 'val'=>"'CYCLICAL'");
	add_default($nl, 'ext_frc_cycle_yr',  'val'=>2000);
    }

    # Species with fixed stratosphere values
    $val = "'NO','NO2','HNO3','CO'";
    add_default($nl, 'fstrat_list', 'val'=>$val);

    # Datasets
    my @files = ('airpl_emis_file', 'soil_erod_file', 'flbc_file', 'fstrat_file',
                 'sulf_file', 'tuv_xsect_file', 'o2_xsect_file', 'xs_long_file', 'rsf_file', 
                 'solar_parms_file', 'exo_coldens_file', 'prescribed_strataero_file',  
                 'linoz_data_path' , 'linoz_data_file', 'chlorine_loading_file' );
    foreach my $file (@files) {
	add_default($nl, $file);
    }
    add_default($nl, 'prescribed_strataero_datapath');
    unless (defined $nl->get_value('prescribed_strataero_type')) {
	add_default($nl, 'prescribed_strataero_type',  'val'=>'CYCLICAL');
	add_default($nl, 'prescribed_strataero_cycle_yr',  'val'=>'1990');
    }
    unless (defined $nl->get_value('flbc_type')) {
	add_default($nl, 'flbc_type',  'val'=>'CYCLICAL');
	add_default($nl, 'flbc_cycle_yr',  'val'=>'2000');
    }
    unless (defined $nl->get_value('linoz_data_type')) {
	add_default($nl, 'linoz_data_type',  'val'=>'CYCLICAL');
	add_default($nl, 'linoz_data_cycle_yr',  'val'=>'0');
    }
    unless (defined $nl->get_value('chlorine_loading_type')) {
	add_default($nl, 'chlorine_loading_type',  'val'=>'FIXED');
	add_default($nl, 'chlorine_loading_fixed_ymd',  'val'=>'20000101');
    }
    add_default($nl, 'xactive_prates', 'val'=>'.false.');

    # Prescribed methane
    my $val = "'CH4'";
    add_default($nl, 'tracer_cnst_specifier', 'val'=>$val);
    my @files = ( 'tracer_cnst_datapath','tracer_cnst_file', 'tracer_cnst_filelist');
    foreach my $file (@files) {
	add_default($nl, $file, 'ver'=>'fixed_ch4');
    }
    unless (defined $nl->get_value('tracer_cnst_type')) {
	add_default($nl, 'tracer_cnst_type',    'ver'=>'fixed_ch4');
	add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ch4');
    }

    my $val = "'prsd_ch4:CH4'";
    add_default($nl, 'prescribed_ghg_specifier', 'val'=>$val);
    my @files = ( 'prescribed_ghg_datapath','prescribed_ghg_file', 'prescribed_ghg_filelist');
    foreach my $file (@files) {
	add_default($nl, $file, 'ver'=>'fixed_ch4');
    }
    unless (defined $nl->get_value('prescribed_ghg_type')) {
	add_default($nl, 'prescribed_ghg_type',    'ver'=>'fixed_ch4');
	add_default($nl, 'prescribed_ghg_cycle_yr','ver'=>'fixed_ch4');
    }
}

if ($chem eq 'trop_mam3') {

    my %species;

    # Surface emission datasets:
    %species = ();
    %species = ('DMS       -> ' => 'dms_emis_file',
                'SO2       -> ' => 'so2_emis_file',
                'SOAG      -> ' => 'soag_emis_file',
                'bc_a1     -> ' => 'bc_a1_emis_file',
                'pom_a1    -> ' => 'pom_a1_emis_file',
                'so4_a1    -> ' => 'so4_a1_emis_file', 
                'so4_a2    -> ' => 'so4_a2_emis_file',
                'num_a1    -> ' => 'num_a1_emis_file', 
                'num_a2    -> ' => 'num_a2_emis_file',
	);
    my %verhash = ('ver'=>'mam');
    my $first = 1;
    my $pre = "";
    my $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id}, \%verhash );
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_type',      'val'=>'CYCLICAL');
	add_default($nl, 'srf_emis_cycle_yr',  'val'=>2000);
    }

    # Vertical emission datasets:
    %species = ();
    %species = ('SO2         -> ' => 'so2_ext_file',
                'so4_a1      -> ' => 'so4_a1_ext_file', 
                'so4_a2      -> ' => 'so4_a2_ext_file',
                'pom_a1      -> ' => 'pom_a1_ext_file', 
                'bc_a1       -> ' => 'bc_a1_ext_file', 
                'num_a1      -> ' => 'num_a1_ext_file', 
                'num_a2      -> ' => 'num_a2_ext_file', );
    $first = 1;
    $pre = "";
    $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id}, \%verhash );
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    unless (defined $nl->get_value('ext_frc_type')) {
	add_default($nl, 'ext_frc_type',      'val'=>"'CYCLICAL'");
	add_default($nl, 'ext_frc_cycle_yr',  'val'=>2000);
    }
    # Prescribed species
    add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2'");
    unless (defined $nl->get_value('tracer_cnst_type')) {
	add_default($nl, 'tracer_cnst_type',    'ver'=>'fixed_ox');
	add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ox');
    }

    my @files = ('tracer_cnst_datapath', 'tracer_cnst_file', 'tracer_cnst_filelist');
    foreach my $file (@files) {
        add_default($nl, $file, 'ver'=>'fixed_ox');
    }

    add_default($nl, 'fstrat_list', 'val'=>"' '");
    add_default($nl, 'flbc_list', 'val'=>"' '");
    add_default($nl, 'xactive_prates', 'val'=>'.false.');

    # Datasets
    my @files = ('soil_erod_file',
                 'xs_long_file', 'rsf_file', 'exo_coldens_file' );
    foreach my $file (@files) {
        add_default($nl, $file);
    }
}

if ($chem eq 'waccm_mozart_mam3') {

    my %species;

    # Surface emission datasets:
    %species = ();
    %species = ('CH2O      -> ' => 'ch2o_emis_file',
                'CO        -> ' => 'co_emis_file',
                'NO        -> ' => 'no_emis_file',
                'DMS       -> ' => 'dms_emis_file',
                'SO2       -> ' => 'so2_emis_file',
                'SOAG      -> ' => 'soag_emis_file',
                'bc_a1     -> ' => 'bc_a1_emis_file',
                'pom_a1    -> ' => 'pom_a1_emis_file',
                'so4_a1    -> ' => 'so4_a1_emis_file', 
                'so4_a2    -> ' => 'so4_a2_emis_file',
                'num_a1    -> ' => 'num_a1_emis_file', 
                'num_a2    -> ' => 'num_a2_emis_file',
	);
    my $first = 1;
    my $pre = "";
    my $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_type',    'val'=>'CYCLICAL');
	add_default($nl, 'srf_emis_cycle_yr','val'=>'2000');
    }

    # Vertical emission datasets:
    %species = ();
    %species = ('NO2         -> ' => 'no2_ext_file',
                'SO2         -> ' => 'so2_ext_file',
                'so4_a1      -> ' => 'so4_a1_ext_file', 
                'so4_a2      -> ' => 'so4_a2_ext_file',
                'pom_a1      -> ' => 'pom_a1_ext_file', 
                'bc_a1       -> ' => 'bc_a1_ext_file', 
                'num_a1      -> ' => 'num_a1_ext_file', 
                'num_a2      -> ' => 'num_a2_ext_file', );
    $first = 1;
    $pre = "";
    $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id});
        if (length($rel_filepath) > 0) {
          my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
          $val .= $pre . quote_string($id . $abs_filepath);
          if ($first) {
              $pre = ",";
              $first = 0;
          }
        }
    }

    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    unless (defined $nl->get_value('ext_frc_type')) {
	add_default($nl, 'ext_frc_type',      'val'=>'CYCLICAL');
	add_default($nl, 'ext_frc_cycle_yr',  'val'=>'2000');
    }

    # Prescribed species

     add_default($nl, 'xactive_prates', 'val'=>'.false.');

    # Datasets
    my @files = ('soil_erod_file',
                 'xs_long_file', 'rsf_file', 'exo_coldens_file' );
    foreach my $file (@files) {
        add_default($nl, $file);
    }

}

if ($chem eq 'trop_mam7') {

    my %species;

    # Surface emission datasets:
    %species = ();
    %species = ('DMS       -> ' => 'dms_emis_file',
                'NH3       -> ' => 'nh3_emis_file',
                'SO2       -> ' => 'so2_emis_file',
                'SOAG      -> ' => 'soag_emis_file',
                'bc_a3     -> ' => 'bc_a3_emis_file',
                'num_a1    -> ' => 'mam7_num_a1_emis_file', 
                'num_a2    -> ' => 'num_a2_emis_file',
                'num_a3    -> ' => 'mam7_num_a3_emis_file',
                'pom_a3    -> ' => 'pom_a3_emis_file',
                'so4_a1    -> ' => 'so4_a1_emis_file', 
                'so4_a2    -> ' => 'so4_a2_emis_file',
	);
    my %verhash = ('ver'=>'mam');
    my $first = 1;
    my $pre = "";
    my $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id}, \%verhash );
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_type',    'val'=>'CYCLICAL');
	add_default($nl, 'srf_emis_cycle_yr','val'=>'2000');
    }

    # Vertical emission datasets:
    %species = ();
    %species = ('SO2         -> ' => 'so2_ext_file',
                'so4_a1      -> ' => 'so4_a1_ext_file', 
                'so4_a2      -> ' => 'so4_a2_ext_file',
                'pom_a3      -> ' => 'pom_a3_ext_file', 
                'bc_a3       -> ' => 'bc_a3_ext_file', 
                'num_a1      -> ' => 'mam7_num_a1_ext_file', 
                'num_a2      -> ' => 'num_a2_ext_file',
                'num_a3      -> ' => 'mam7_num_a3_ext_file',
               );
    $first = 1;
    $pre = "";
    $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id}, \%verhash );
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    unless (defined $nl->get_value('ext_frc_type')) {
	add_default($nl, 'ext_frc_type',      'val'=>"'CYCLICAL'");
	add_default($nl, 'ext_frc_cycle_yr',  'val'=>2000);
    }

    # Prescribed species
    add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2'");
    unless (defined $nl->get_value('tracer_cnst_type')) {
	add_default($nl, 'tracer_cnst_type',    'ver'=>'fixed_ox');
	add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ox');
    }


    my @files = ('tracer_cnst_datapath', 'tracer_cnst_file', 'tracer_cnst_filelist');
    foreach my $file (@files) {
        add_default($nl, $file, 'ver'=>'fixed_ox');
    }

    add_default($nl, 'fstrat_list', 'val'=>"' '");
    add_default($nl, 'flbc_list', 'val'=>"' '");
    add_default($nl, 'xactive_prates', 'val'=>'.false.');

    # Datasets
    my @files = ('soil_erod_file',
                 'xs_long_file', 'rsf_file', 'exo_coldens_file' );
    foreach my $file (@files) {
        add_default($nl, $file);
    }
}

# WACCM_MOZART options.
if ($chem =~ /waccm_mozart/ or $chem =~ /waccm_tsmlt/) {

    # Species with fixed lower boundary
    my $val = "'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2', 'HCFC22','N2O'";
    if ($chem eq 'waccm_mozart_sulfur') {
	$val .= ",'OCS'";
    }
    add_default($nl, 'flbc_list', 'val'=>$val);
    unless (defined $nl->get_value('flbc_type')) {
	add_default($nl, 'flbc_type',  'val'=>'CYCLICAL');
	add_default($nl, 'flbc_cycle_yr',  'val'=>'1990');
    }
    add_default($nl, 'prescribed_strataero_datapath');
    unless (defined $nl->get_value('prescribed_strataero_type')) {
	add_default($nl, 'prescribed_strataero_type',  'val'=>'CYCLICAL');
	add_default($nl, 'prescribed_strataero_cycle_yr',  'val'=>'1990');
    }

    # Datasets
    my @files = ('flbc_file', 'efield_lflux_file', 'efield_hflux_file', 'efield_wei96_file',
		 'euvacdat_file', 'photon_file', 'electron_file',
                 'euvac_file', 'solar_parms_file', 'prescribed_strataero_file', 'sulf_file',
                 'depvel_lnd_file', 'clim_soilw_file', 'season_wes_file',
                 'xs_coef_file', 'xs_short_file','xs_long_file', 'rsf_file', 
                 'tgcm_ubc_file', 'snoe_ubc_file', 'soil_erod_file' );

    foreach my $file (@files) {
	add_default($nl, $file);
    }

    # aircraft (vertical) emissions... 
    my %species = ();
    if ($ipcc_aircraft_emis) {
        %species = ('NO2 -> ' => 'no2_aircraft_emis_file' );
    } else {
        %species = ('CO      -> ' => 'co_aircraft_emis',
	   	    'NO      -> ' => 'no_aircraft_emis' );
    }
    my $first = 1; my $pre = ""; my $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($species{$id});
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string($id . $abs_filepath);
        if ($first) {
            $pre = ",";
            $first = 0;
        }
    }
    add_default($nl, 'ext_frc_specifier', 'val'=>$val);
    unless (defined $nl->get_value('ext_frc_type')) {
	add_default($nl, 'ext_frc_type',      'val'=>'CYCLICAL');
	add_default($nl, 'ext_frc_cycle_yr',  'val'=>'1999');
    }

    # Surface emission datasets:
    my $val;
    my %species = ('CO   -> ' => 'co_emis_file',
		   'CH2O -> ' => 'ch2o_emis_file',
		   'NO   -> ' => 'nox_emis_file' );
    if ($chem eq 'waccm_mozart_sulfur') {
       $species{ 'SO2  -> ' } = ( 'so2_emis_file' );
    }

    my $first = 1; my $pre = "";
    foreach my $id (sort keys %species) {
	my $rel_filepath = get_default_value($species{$id});
	my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
	$val .= $pre . quote_string($id . $abs_filepath);
	if ($first) {
	    $pre = ",";
	    $first = 0;
	}
    }
    add_default($nl, 'srf_emis_specifier', 'val'=>$val);
    unless (defined $nl->get_value('srf_emis_type')) {
	add_default($nl, 'srf_emis_type',  'val'=>'CYCLICAL');
	add_default($nl, 'srf_emis_cycle_yr',  'val'=>'1997');
    }

    add_default($nl, 'xactive_prates', 'val'=>'.false.');

    if ($cfg->get('dyn') eq 'fv') {
        add_default($nl, 'do_circulation_diags', 'val'=>'.true.');
    }
}

# Determine the source of the prescribed GHG values.

my $lbc_file = $nl->get_value('flbc_file');
my $scenario_ghg = $nl->get_value('scenario_ghg');

if (defined  $lbc_file) {

    # If a WACCM/CAM-Chem LBC file is specified then use it for the prescribed 
    # GHGs.  Set scenario_ghg='CHEM_LBC_FILE'.

    # If scenario_ghg has been set inconsistently then exit
    if (defined $scenario_ghg and $scenario_ghg !~ /CHEM_LBC_FILE/) {
	die "$ProgName - ERROR: When flbc_file is used cannot set scenario_ghg = $scenario_ghg \n";
    }
    # Otherwise make sure its set.
    add_default($nl, 'scenario_ghg',  'val'=>'CHEM_LBC_FILE');

    # If any individual GHG values are set then remove them and issue info message
    # that they will be ignored.
    foreach my $ghg_vmr ('co2vmr','ch4vmr','n2ovmr','f11vmr','f12vmr') {
	my $val = $nl->get_value($ghg_vmr);
	if (defined $val) {
	    print "$ProgName - INFO: Chem flbc_file in use. $ghg_vmr = $val removed from namelist.\n";

	    if ($nl->delete_variable('chem_surfvals_nl', $ghg_vmr) != 0) {
		die "$ProgName - ERROR: not able to delete $ghg_vmr from group chem_surfvals_nl.\n";
	    }
	}
    }

    # Make sure the flbc_list specifies all the GHGs needed for radiation.
    my $flbc_list = $nl->get_value('flbc_list');
    if (defined $flbc_list) {
	# If flbc_list has already been defined, check that it contains all
	# the GHGs needed by the radiation code.
	foreach my $ghg ('CO2','CH4','N2O','CFC11','CFC12') {
	    if ($flbc_list !~ /$ghg/) {
		die "$ProgName - ERROR: $ghg is missing from flbc_list \n";
	    }
	}
    }
    else {
	my $val = "'CO2','CH4','N2O','CFC11','CFC12'";
	add_default($nl, 'flbc_list', 'val'=>$val);
    }

}
else {

    # If no chemistry then set prescribed GHG surface values using
    # one of the remaining scenario_ghg values.

    if ((defined $scenario_ghg) and $scenario_ghg =~ /RAMPED/) {
        # read values from dataset
        add_default($nl, 'bndtvghg');
    }
    else {
        # If scenario_ghg is 'FIXED' or 'RAMP_CO2_ONLY' then the prescribed
	# values are set using the xxxvmr variables.  For 'RAMP_CO2_ONLY'
        # the co2vmr value is just the starting value.
	add_default($nl, 'co2vmr');
	add_default($nl, 'ch4vmr');
	add_default($nl, 'n2ovmr');
	add_default($nl, 'f11vmr');
	add_default($nl, 'f12vmr');
    }
}

# Dry Deposition -- The responsibility for dry deposition is shared between CAM and CLM.
# The namelist is read by a driver module, seq_drydep_mod, and the information is shared
# between CAM and CLM by use association of that module.
if ( $chem ) {
    add_default($nl, 'drydep_method');

    # drydep_srf_file is only needed for prognostic MAM when the grid is unstructured.
    # structured grids can do interpolation on the fly.
    if ($chem =~ /_mam/ and $dyn =~ /se/) {
	add_default($nl, 'drydep_srf_file');
    }
}

# Physics options

# Add the name of the physics package based on the info in configure.  If the user tries
# to explicitly specify this namelist variable issue error.
my $cam_physpkg = $nl->get_value('cam_physpkg');
if (defined $cam_physpkg) {
    die "CAM Namelist ERROR: User may not specify the value of cam_physpkg.\n".
	"This variable is set by build-namelist based on information\n".
	"from the configure cache file.\n";
}
$cam_physpkg = "'" . "$phys" . "'";  # add quotes to this string value
$nl->set_variable_value('phys_ctl_nl', 'cam_physpkg', $cam_physpkg);

# WACCM-X runtime options
add_default($nl, 'waccmx_opt');

# Chemistry options

# Add the name of the chemistry package based on the info in configure.  If the user tries
# to explicitly specify this namelist variable issue error.
my $cam_chempkg = $nl->get_value('cam_chempkg');
if (defined $cam_chempkg) {
    die "CAM Namelist ERROR: User may not specify the value of cam_chempkg.\n".
       "This variable is set by build-namelist based on information\n".
       "from the configure cache file.\n";
}
if (($chem eq 'waccm_mozart_sulfur') or ($chem eq 'waccm_tsmlt')) {
    $cam_chempkg =  "'" . 'waccm_mozart'. "'";
} else {
    $cam_chempkg = "'" . "$chem" . "'";  # add quotes to this string value
}

$nl->set_variable_value('phys_ctl_nl', 'cam_chempkg', $cam_chempkg);

# Deep convection scheme
add_default($nl, 'deep_scheme');

# Radiation scheme
add_default($nl, 'radiation_scheme');

# Eddy scheme (vertical diffusion)
add_default($nl, 'eddy_scheme');

# Defaults for shallow convection scheme and surface flux averaging both depend
# on the value of the eddy scheme.
my $eddy_scheme = $nl->get_value('eddy_scheme');
# Need to strip the quotes to use as a value for attribute matching.
$eddy_scheme =~ s/['"]//g;                                           #"'
add_default($nl, 'shallow_scheme', 'eddy_scheme'=>$eddy_scheme);
add_default($nl, 'srf_flux_avg', 'eddy_scheme'=>$eddy_scheme);

# Microphysics scheme
add_default($nl, 'use_subcol_microp');
add_default($nl, 'microp_scheme');
add_default($nl, 'macrop_scheme');
if ($cfg->get('microphys') =~ /^mg/) {
    add_default($nl, 'micro_mg_version');
    add_default($nl, 'micro_mg_sub_version');
}

# Sub-column switches for physics packages
# Check that a subcol_scheme is specified if use_subcol_microp is turned on (true)
add_default($nl, 'subcol_scheme');
my $subcol_scheme = $nl->get_value('subcol_scheme');
my $use_subcol_microp = $nl->get_value('use_subcol_microp');
if ($print>=2) { print "subcol_scheme=$subcol_scheme \n"; }
if (($subcol_scheme eq "'off'") && ($use_subcol_microp  =~ m/$TRUE/io)) {
  die "$ProgName - Error: use_subcol_microp set to .true. but no subcol_scheme is set \n";
}
if ($subcol_scheme eq 'tstcp') {
   add_default($nl, 'subcol_tstcp_noavg');
   add_default($nl, 'subcol_tstcp_filter');
   add_default($nl, 'subcol_tstcp_weight');
   add_default($nl, 'subcol_tstcp_perturb');
}
    
if ($subcol_scheme eq 'SILHS') {
   add_default($nl, 'subcol_silhs_weight');
}

if ($subcol_scheme eq 'vamp') {
   add_default($nl, 'subcol_vamp_ctyp');
   add_default($nl, 'subcol_vamp_otyp');
   add_default($nl, 'subcol_vamp_nsubc');
}


# Set microp_uniform based on the subcol_schemes and use_subcol_microp unless overridden by the user
my $microp_uniform = $nl->get_value('microp_uniform');
if (defined  $microp_uniform) {
  add_default($nl, 'microp_uniform', 'val'=>$microp_uniform);
}
     # If use_subcol_microp is turned on and has not been turned off via the namelist, turn on microp_uniform
elsif ($use_subcol_microp =~ /$TRUE/io) {
  add_default($nl, 'microp_uniform',   'val'=>'.true.');
}
     # Turn off by default
else {
  add_default($nl, 'microp_uniform',   'val'=>'.false.');
}

# CLUBB_SGS
add_default($nl, 'do_clubb_sgs');
add_default($nl, 'clubb_history');
add_default($nl, 'clubb_rad_history');

if ($nl->get_value('clubb_history') =~ "true" &&  $nl->get_value('atm_nthreads') != 1) {
  die "$ProgName - ERROR: clubb_history = .true. with multiple threads is not supported. \n";
}

# Tuning for wet scavenging of modal aerosols
if ($chem =~ /_mam/) {
    add_default($nl, 'sol_facti_cloud_borne');
    add_default($nl, 'sol_factb_interstitial');
    add_default($nl, 'sol_factic_interstitial');
}

# Turbulent Mountain Stress
add_default($nl, 'do_tms');
my $do_tms = $nl->get_value('do_tms');
# Check to be sure that do_tms has been set to true if the user sets a customized
# value of tms_orocnst or tms_z0fac.
if (defined $nl->get_value('tms_orocnst') or defined $nl->get_value('tms_z0fac')) {
    # a tms parameter has been set in the namelist.  Make sure do_tms is true.
    if ( $do_tms =~ /$FALSE/io ) {
	die "CAM Namelist ERROR: If tms_oroconst or tms_z0fac is set do_tms must be .true..\n".
	    "Either remove these from the namelist or add do_tms=.true.\n";
    }
}
if ( $do_tms =~ /$TRUE/io ) {
    add_default($nl, 'tms_orocnst');
    add_default($nl, 'tms_z0fac');
}

# Implicit Turbulent Surface Stress
add_default($nl, 'do_iss');

# Convective water in radiation
add_default($nl, 'conv_water_in_rad');
add_default($nl, 'conv_water_frac_limit');

# Cloud fraction
add_default($nl, 'cldfrc_freeze_dry');
add_default($nl, 'cldfrc_ice');
add_default($nl, 'cldfrc_rhminl');
add_default($nl, 'cldfrc_rhminl_adj_land');
add_default($nl, 'cldfrc_rhminh');
add_default($nl, 'cldfrc_sh1');
add_default($nl, 'cldfrc_sh2');
add_default($nl, 'cldfrc_dp1');
add_default($nl, 'cldfrc_dp2');
add_default($nl, 'cldfrc_premit');
add_default($nl, 'cldfrc_premib');
add_default($nl, 'cldfrc_iceopt');
add_default($nl, 'cldfrc_icecrit');

my $cldfrc_rhminp = $nl->get_value('cldfrc_rhminp');
if ($cldfrc_rhminp and !($cfg->get('microphys') eq 'rk')) {
    die "$ProgName - ERROR: cldfrc_rhminp is valid only for RK microphysics scheme\n";
}

# condensate to rain autoconversion coefficients
add_default($nl, 'zmconv_c0_lnd');
add_default($nl, 'zmconv_c0_ocn');
add_default($nl, 'zmconv_ke');

# moist convection rainwater coefficients
add_default($nl, 'hkconv_cmftau');
add_default($nl, 'hkconv_c0');
if ($phys eq 'cam5') {
  add_default($nl, 'uwshcu_rpen');
}

# cldwat ice coefficients
add_default($nl, 'cldwat_icritc');
add_default($nl, 'cldwat_icritw');
add_default($nl, 'cldwat_conke');
add_default($nl, 'cldwat_r3lcrit');

# Top level pressure for troposphere cloud physics
add_default($nl, 'trop_cloud_top_press');

# Eddy Diffusivity Adjustments
add_default($nl, 'kv_top_pressure');
add_default($nl, 'kv_top_scale');
add_default($nl, 'kv_freetrop_scale');
add_default($nl, 'eddy_lbulk_max');
add_default($nl, 'eddy_leng_max');
add_default($nl, 'eddy_max_bot_pressure');
add_default($nl, 'eddy_moist_entrain_a2l');
add_default($nl, 'diff_cnsrv_mass_check');

# Pressure limits for molecular diffusion.
add_default($nl, 'do_molec_press');
add_default($nl, 'molec_diff_bot_press');

# CARMA microphysics
#
# Each CARMA model may require a different set of default
# namelist values to enable the processes that correspond
# to the desired microphysics.
add_default($nl, 'carma_model',    'val'=>$carma);

if ($carma ne 'none') {
  add_default($nl, 'carma_flag',        'val'=>'.true.');
}

if ($carma eq 'bc_strat') {
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.false.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
}
if ($carma eq 'cirrus') {
  add_default($nl, 'carma_do_cldice',   'val'=>'.true.');
  add_default($nl, 'carma_do_aerosol',  'val'=>'.false.');
  add_default($nl, 'carma_do_cldliq',   'val'=>'.false.');
  add_default($nl, 'carma_do_clearsky', 'val'=>'.false.');
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_detrain',  'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_incloud',  'val'=>'.true.');
  add_default($nl, 'carma_do_pheat',    'val'=>'.false.');
  add_default($nl, 'carma_do_optics',   'val'=>'.false.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_conmax',      'val'=>'0.25');
  add_default($nl, 'carma_maxretries',  'val'=>'20');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'1');
  add_default($nl, 'carma_dt_threshold','val'=>'2.');
  add_default($nl, 'carma_gsticki',     'val'=>'0.5');
  add_default($nl, 'carma_rhcrit',      'val'=>'0.7');
  add_default($nl, 'wv_sat_scheme',     'val'=>'MurphyKoop');
  add_default($nl, 'macro_park_do_cldice',  'val'=>'.false.');
  add_default($nl, 'macro_park_do_cldliq',  'val'=>'.true.');
  add_default($nl, 'macro_park_do_detrain', 'val'=>'.false.');
  add_default($nl, 'micro_mg_do_cldice','val'=>'.false.');
  add_default($nl, 'micro_mg_do_cldliq','val'=>'.true.');
  add_default($nl, 'spectralflux',      'val'=>'.false.');
}
if ($carma eq 'cirrus_dust') {
  add_default($nl, 'carma_do_cldice',   'val'=>'.true.');
  add_default($nl, 'carma_do_aerosol',  'val'=>'.false.');
  add_default($nl, 'carma_do_cldliq',   'val'=>'.false.');
  add_default($nl, 'carma_do_clearsky', 'val'=>'.false.');
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_detrain',  'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.false.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_incloud',  'val'=>'.true.');
  add_default($nl, 'carma_do_pheat',    'val'=>'.false.');
  add_default($nl, 'carma_do_optics',   'val'=>'.false.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_conmax',      'val'=>'0.25');
  add_default($nl, 'carma_maxretries',  'val'=>'20');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'1');
  add_default($nl, 'carma_dt_threshold','val'=>'2.');
  add_default($nl, 'carma_gsticki',     'val'=>'0.5');
  add_default($nl, 'carma_rhcrit',      'val'=>'0.7');
  add_default($nl, 'wv_sat_scheme',     'val'=>'MurphyKoop');
  add_default($nl, 'macro_park_do_cldice',  'val'=>'.false.');
  add_default($nl, 'macro_park_do_cldliq',  'val'=>'.true.');
  add_default($nl, 'macro_park_do_detrain', 'val'=>'.false.');
  add_default($nl, 'micro_mg_do_cldice','val'=>'.false.');
  add_default($nl, 'micro_mg_do_cldliq','val'=>'.true.');
  add_default($nl, 'spectralflux',      'val'=>'.false.');
  add_default($nl, 'carma_soilerosion_file');
  add_default($nl, 'carma_fields',      'val'=>'Sl_soilw');
}
elsif ($carma eq 'dust') {
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_optics',   'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_soilerosion_file');
  add_default($nl, 'carma_fields',      'val'=>'Sl_soilw');
}
elsif ($carma eq 'meteor_impact') {
  add_default($nl, 'carma_do_coag',        'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',      'val'=>'.true.');
  add_default($nl, 'carma_do_emission',    'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit',   'val'=>'.true.');
  add_default($nl, 'carma_do_optics',      'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',       'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',       'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',      'val'=>'.true.');
  add_default($nl, 'carma_emis_dust',      'val'=>'0.0');
  add_default($nl, 'carma_emis_soot',      'val'=>'2.8e10');
  add_default($nl, 'carma_emis_startdate', 'val'=>'1');
  add_default($nl, 'carma_emis_starttime', 'val'=>'43200');
  add_default($nl, 'carma_emis_stopdate',  'val'=>'2');
  add_default($nl, 'carma_emis_stoptime',  'val'=>'43200');
  add_default($nl, 'carma_emis_minlat',    'val'=>'-5.85');
  add_default($nl, 'carma_emis_maxlat',    'val'=>'-0.15');
  add_default($nl, 'carma_emis_minlon',    'val'=>'-58.75');
  add_default($nl, 'carma_emis_maxlon',    'val'=>'-51.25');
  add_default($nl, 'carma_fractal_soot',   'val'=>'.false.');
  add_default($nl, 'irad_always',          'val'=>'-48');
}
elsif ($carma eq 'meteor_smoke') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_emis_total',  'val'=>'16.0');
  add_default($nl, 'carma_emis_file');
  add_default($nl, 'carma_do_escale',   'val'=>'.false.');
  add_default($nl, 'carma_escale_file');
}
elsif ($carma eq 'mixed_sulfate') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_pheat',    'val'=>'.false.');
  add_default($nl, 'carma_do_pheatatm', 'val'=>'.false.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_maxretries',  'val'=>'20');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'1');
  add_default($nl, 'carma_neutral_h2so4','val'=>'.true.');
  add_default($nl, 'carma_emis_total',  'val'=>'16.0');
  add_default($nl, 'carma_emis_file');
  add_default($nl, 'carma_do_escale',   'val'=>'.false.');
  add_default($nl, 'carma_escale_file');
  add_default($nl, 'spectralflux',      'val'=>'.false.');
  add_default($nl, 'carma_dt_threshold','val'=>'5.');
}
elsif ($carma eq 'pmc') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_pheat',    'val'=>'.false.');
  add_default($nl, 'carma_do_pheatatm', 'val'=>'.false.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_maxretries',  'val'=>'12');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'1');
  add_default($nl, 'carma_emis_total',  'val'=>'16.0');
  add_default($nl, 'carma_emis_file');
  add_default($nl, 'carma_do_escale',   'val'=>'.false.');
  add_default($nl, 'carma_escale_file');
  add_default($nl, 'carma_mice_file');
  add_default($nl, 'spectralflux',      'val'=>'.false.');
  add_default($nl, 'carma_dt_threshold','val'=>'5.');
}
elsif ($carma eq 'pmc_sulfate') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_pheat',    'val'=>'.false.');
  add_default($nl, 'carma_do_pheatatm', 'val'=>'.false.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_maxretries',  'val'=>'20');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'1');
  add_default($nl, 'carma_neutral_h2so4','val'=>'.true.');
  add_default($nl, 'carma_emis_total',  'val'=>'16.0');
  add_default($nl, 'carma_emis_file');
  add_default($nl, 'carma_do_escale',   'val'=>'.false.');
  add_default($nl, 'carma_escale_file');
  add_default($nl, 'carma_mice_file');
  add_default($nl, 'spectralflux',      'val'=>'.false.');
  add_default($nl, 'carma_dt_threshold','val'=>'5.');
}
elsif ($carma eq 'sea_salt') {
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_do_WeibullK', 'val'=>'.false.');
  add_default($nl, 'carma_seasalt_emis', 'val'=>'Gong');
}
elsif ($carma eq 'sulfate') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_hetchem',  'val'=>'.true.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_maxretries',  'val'=>'20');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'2');
  add_default($nl, 'carma_dt_threshold','val'=>'2.');
}
elsif ($carma eq 'test_detrain') {
  add_default($nl, 'carma_do_detrain',  'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
}
elsif ($carma eq 'test_growth') {
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_do_substep',  'val'=>'.true.');
  add_default($nl, 'carma_do_thermo',   'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_maxretries',  'val'=>'12');
  add_default($nl, 'carma_maxsubsteps', 'val'=>'4');
}
elsif ($carma eq 'test_passive') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
}
elsif ($carma eq 'test_radiative') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_optics',   'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
}
elsif ($carma eq 'test_swelling') {
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
}
elsif ($carma eq 'test_tracers') {
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_launch_doy',  'val'=>'1');
  add_default($nl, 'carma_emission_rate','val'=>'-1e-12');
}
elsif ($carma eq 'test_tracers2') {
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_launch_doy',  'val'=>'1');
  add_default($nl, 'carma_emission_rate','val'=>'-1e-12');
}
elsif ($carma eq 'tholin') {
  add_default($nl, 'carma_do_coag',     'val'=>'.true.');
  add_default($nl, 'carma_do_drydep',   'val'=>'.true.');
  add_default($nl, 'carma_do_emission', 'val'=>'.true.');
  add_default($nl, 'carma_do_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_vdiff',    'val'=>'.true.');
  add_default($nl, 'carma_do_vtran',    'val'=>'.true.');
  add_default($nl, 'carma_do_wetdep',   'val'=>'.true.');
  add_default($nl, 'carma_emis_total',  'val'=>'1e5');
  add_default($nl, 'carma_emis_file');
}

# Cloud sedimentation
add_default($nl, 'cldsed_ice_stokes_fac');

# Dust emissions tuning factor
# If dust is prognostic ==> supply the tuning factor
if ($chem =~ /_mam/ or $chem =~ /_bam/ or $chem =~ /trop_/) {
    # check whether turbulent mountain stress parameterization is on
    if ($nl->get_value('do_tms') =~ /$TRUE/io) {
	add_default($nl, 'dust_emis_fact', 'tms'=>'1');
    }
    else {
	add_default($nl, 'dust_emis_fact');
    }
}

# Gravity wave drag settings
if ($waccm_phys or $cfg->get('nlev') >= 60) {
    # Spectral gravity waves are part of WACCM physics, and also drive the
    # QBO in the high vertical resolution configuration.
    add_default($nl, 'use_gw_oro'    , 'val'=>'.true.');
    add_default($nl, 'use_gw_front'  , 'val'=>'.true.');
    add_default($nl, 'use_gw_convect', 'val'=>'.true.');
} else {
    add_default($nl, 'use_gw_oro'    , 'val'=>'.true.');
    add_default($nl, 'use_gw_front'  , 'val'=>'.false.');
    add_default($nl, 'use_gw_convect', 'val'=>'.false.');
}
add_default($nl, 'pgwv', 'val'=>'32');
add_default($nl, 'gw_dc','val'=>'2.5D0');

if ($nl->get_value('use_gw_oro') =~ /$TRUE/io) {
    add_default($nl, 'effgw_oro');
}

if ($nl->get_value('use_gw_front') =~ /$TRUE/io) {
    add_default($nl, 'effgw_cm');
    add_default($nl, 'frontgfc');
    add_default($nl, 'taubgnd');
}

if ($nl->get_value('use_gw_convect') =~ /$TRUE/io) {
    add_default($nl, 'effgw_beres');
    add_default($nl, 'gw_drag_file');
}

# Some complexity to unpack.
# 1. In WACCM, we want tau_0_ubc = .false., because it hasn't been tuned
#    for that option.
# 2. In the low top model with most gravity waves on, we want tau_0_ubc to
#    be .true., to get a QBO.
# 3. If only orographic waves are on, we can't get a QBO regardless, so
#    use tau_0_ubc = .false. to avoid changing answers.
if ((not $waccm_phys) and
    ($nl->get_value('use_gw_front') =~ /$TRUE/io or
    $nl->get_value('use_gw_convect') =~ /$TRUE/io)) {
    add_default($nl, 'tau_0_ubc', 'val'=>'.true.');
} else {
    add_default($nl, 'tau_0_ubc', 'val'=>'.false.');
}

add_default($nl, 'fcrit2');

# FV dycore
if ($cfg->get('dyn') eq 'fv') {
    add_default($nl, 'fft_flt');
    add_default($nl, 'div24del2flag');
    add_default($nl, 'del2coef');
    add_default($nl, 'filtcw');
    add_default($nl, 'nspltvrm');
    if ($waccm_phys) {
	add_default($nl, 'nsplit');
	add_default($nl, 'nspltrac');
    }
    # If the -ntasks argument has been set, then use it to set the default
    # FV decomposition unless the user has already set it.
    my $npr_yz = $nl->get_value('npr_yz');
    if (defined $opts{'ntasks'} and ! defined $npr_yz ) {
	$npr_yz = fv_decomp_set();
	add_default($nl, 'npr_yz', 'val'=>$npr_yz);
    }
}

# EUL dycore
if ($cfg->get('dyn') eq 'eul') {
    add_default($nl, 'eul_nsplit');
}

# Single column model
if ($cfg->get('scam')) {
    add_default($nl, 'iopfile');
}

# CAM generates IOP file for SCAM
if ($cfg->get('camiop')) {
    add_default($nl, 'inithist', 'val'=>'CAMIOP');
    add_default($nl, 'ndens', 'val'=>'1,1');
    add_default($nl, 'mfilt', 'val'=>'1,10');
    add_default($nl, 'nhtfrq', 'val'=>'0,1');
}

# Spectral Element dycore
# ============

if ($cfg->get('dyn') =~ /se/) {

    ####################################################
    # namelist group: ctl_nl (for CAM_SE) #
    ####################################################

    my $hgrid = $cfg->get('hgrid');
    if ($hgrid =~ /ne(.*)np/) {
	add_default($nl, 'se_ne', 'val'=>$1);
    }
    else {
	die "$ProgName - ERROR: Horizontal grid name can NOT be correctly parsed: hgrid = $hgrid. \n";
    }

    my @vars = qw(se_nsplit hypervis_order phys_loadbalance
                  hypervis_subcycle hypervis_subcycle_q
                  statefreq se_partmethod se_topology se_ftype
                  integration nu nu_div nu_p nu_q nu_top  se_phys_tscale
                  interpolate_analysis interp_nlat interp_nlon vert_remap_q_alg
                  interp_type interp_gridtype se_limiter_option qsplit rsplit tstep_type);

    foreach my $var (@vars) {
	add_default($nl, $var);
    }
}

# Defaults for history output
add_default($nl, 'history_amwg');
add_default($nl, 'history_vdiag');
add_default($nl, 'history_aerosol');
add_default($nl, 'history_aero_optics');
add_default($nl, 'history_budget');
add_default($nl, 'history_eddy');
add_default($nl, 'history_waccm');
add_default($nl, 'history_waccmx');
add_default($nl, 'history_chemistry');
add_default($nl, 'history_carma');
add_default($nl, 'history_clubb');

# The history output for the AMWG variability diagnostics assumes that auxilliary history
# files h1, h2, and h3 contain daily, 6-hrly, and 3-hrly output respectively.  If this output
# has been requested, then make sure the user has not already set nhtfrq to something
# inconsistent with this requirement.
my $history_vdiag = $nl->get_value('history_vdiag');
if ($history_vdiag =~ m/$TRUE/io) {

    # Check for consistent setting of nhtfrq.
    my $nhtfrq = $nl->get_value('nhtfrq');
    if (defined $nhtfrq) { #
	# If already set, check for consistency
	my @nhtfrq = split /,/, $nhtfrq;
	if ($nhtfrq[1] != -24 or $nhtfrq[2] != -6 or $nhtfrq[3] != -3) {
	    die "$ProgName - ERROR: history_vdiag is .true., but nhtfrq is set to $nhtfrq\n".
                "The first 4 elements of nhtfrq must be 0,-24,-6,-3.  Note that the use case may\n".
                "be the source of the inconsistent nhtfrq values.\n";
	}
    }
    else {
	# set the default
	add_default($nl, 'nhtfrq', 'val'=>'0, -24, -6, -3');
    }
}

my $offline_drv = $cfg->get('offline_drv');
if ($offline_drv eq 'rad') {
    add_default($nl, 'iradsw', 'val'=>'1');
    add_default($nl, 'iradlw', 'val'=>'1');
}

#-----------------------------------------------------------------------------------------------
# Add defaults for the CAM specific ocn model DOM.

# Which ocean model?
my $ocn_comp = $cfg->get('ocn');
my $ocn_group = '';
if ($ocn_comp eq 'dom') {
    $ocn_group = 'dom_inparm';
}
if ($ocn_comp eq 'docn') {
    $ocn_group = 'docn_nml';
}

# The following variables are set by namelist variables in the special camexp namelist
# group.  They are used to ensure consistency between the setting of namelist variables
# in DOM and CICE.
my $bndtvs = '';
my $bndtvs_domain = '';
my $focndomain = '';

# The %mask variable is used to set namelist defaults for CLM.
my %mask = ();

# Namelist settings for CAMDOM or DOCN
# These namelists aren't needed for ideal, adiabatic, or aqua-planet modes.
if ($cam_build and  ($ocn_comp eq 'dom' or $ocn_comp eq 'docn') and ! $ideal_or_adia_or_aqua) {

    # Determine default values for variables that must be set consistently between these models.

    # sstcyc
    my $sstcyc = '.true.';
    if (defined $nl->get_value('sstcyc')) { $sstcyc = $nl->get_value('sstcyc'); }

    # bndtvs
    add_default($nl, 'bndtvs', 'sim_year'=>$sim_year);
    $bndtvs = $nl->get_value('bndtvs');

    # bndtvs_domain
    if ($dyn =~ /se/){
       add_default($nl, 'bndtvs_domain', 'sim_year'=>$sim_year);
       $bndtvs_domain = $nl->get_value('bndtvs_domain');
    }

    # focndomain
    # For CAM in standalone mode, CAM determines the focndomain file to use, and then specifies
    # that file to DOM and CICE.
    add_default($nl, 'focndomain');
    $focndomain = $nl->get_value('focndomain');

    # Assume that the focndomain filename contains the name of the ocean grid used to construct
    # the lnd/ocn mask.  Recover the ocean grid name using a regexp match, and use it subsequently
    # to determine consistent CLM files.
    if ($focndomain =~ m/_(gx\dv\d)_/) {
        $mask{'mask'} = $1;
    }
    elsif ($focndomain =~ m/_USGS_/) {
        $mask{'mask'} = 'USGS';
    }

    ##############################
    # namelist group: dom_inparm #
    ##############################
    if ($ocn_group eq 'dom_inparm') {
	$nl->set_variable_value($ocn_group, 'sstcyc',     $sstcyc);
	$nl->set_variable_value($ocn_group, 'bndtvs',     $bndtvs);
	$nl->set_variable_value($ocn_group, 'focndomain', $focndomain);
    }

}

#-----------------------------------------------------------------------------------------------
# Add defaults for the CLM component 
# Only produce a namelist for CLM if running with CAM standalone scripts
# and if the lnd component is active.

my $lnd_pkg = $cfg->get('lnd');

if ($lnd_pkg eq 'clm' and $cam_build and $lnd_active) {

    ##############################
    # namelist group: clm_inparm #
    ##############################

    # Timestep
    # *** N.B. *** this code enforces the constraint that the CLM timestep match the CAM timestep.
    # Note that a Namelist object method is used to add the value of dtime to clm_inparm to avoid
    # the namelist definition checking done by add_default.  That's because dtime is in CAM's definition
    # file as a variable that belongs in cam_inparm and it can't also be in clm_inparm.  This will be
    # resolved when the CLM component is made responsible for producing the clm_inparm namelist.
    my $clmval = $nl->get_value('dtime');
    $nl->set_variable_value('clm_inparm', 'dtime', $clmval);

    # Check that "nrevsn" is set if this is a branch simulation
    if ($nl->get_value('start_type') =~ /branch/  and  !defined $nl->get_value('nrevsn')) {
	die "$ProgName - ERROR: The CLM2 master restart file must be specified for a branch\n".
	    "       run.  Set the namelist variable NREVSN to the absolute\n".
	    "       pathname for this dataset.\n".
	    "       This can be done on the command-line using the -namelist\n".
	    "       option or in an input namelist file that is specified\n".
	    "       using the -infile option.\n";
    }

    add_default($nl, 'fatmlndfrc', %mask);
    add_default($nl, 'fsnowoptics');
    add_default($nl, 'fsnowaging');

    add_default($nl, 'fpftcon');

    # CO2
    # *** N.B. *** This is forced to use the same value that CAM is using.
    my $co2vmr = $nl->get_value('co2vmr');
    if (defined $co2vmr) {
	my $co2_ppmv = sprintf '%e', $co2vmr * 1.e6;
	$nl->set_variable_value('clm_inparm', 'co2_ppmv', $co2_ppmv);
    }

    # All F compsets currently set co2_type='diagnostic'
    add_default($nl, 'co2_type', 'val'=>'diagnostic');

    add_default($nl, 'urban_hac');
    add_default($nl, 'urban_traffic');

    add_default($nl, 'fsurdat', 'sim_year'=>$sim_year_start);

    # Initial conditions
    # The initial date is an attribute in the defaults file which should be matched unless
    # the user explicitly requests to ignore the initial date via the -ignore_ic_date option, 
    # or just ignore the year of the initial date via the -ignore_ic_year option.
    my $ic_date = $nl->get_value('start_ymd');
    if ($opts{'ignore_ic_date'}) {
        add_default($nl, 'finidat', 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask);
    }
    elsif ($opts{'ignore_ic_year'}) {
        add_default($nl, 'finidat', 'ic_md'=>$ic_date, 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask);
    }
    else {
        add_default($nl, 'finidat', 'ic_ymd'=>$ic_date, 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask);
    }

    # If sim_year is input as a range of years, then add the dynamic PFT dataset.
    if ($sim_year =~ /(\d+)-(\d+)/) {
	add_default($nl, 'fpftdyn', 'sim_year'=>$sim_year)
    }
}

#-----------------------------------------------------------------------------------------------
# Add defaults for the CICE component 
# Only produce a namelist for CICE if running with CAM standalone scripts.

# Which sea ice model?
my $ice_comp = $cfg->get('ice');

if ($ice_comp eq 'cice' and $cam_build and $ice_active) {

    # The CICE component has its own build-namelist utility.
    my $cice_bldnl = "$cam_root/models/ice/cice/bld/build-namelist";

    # Set up the commandline args

    # CICE config_cache filepath 
    my $cice_config_dir = $cfg->get('cice_config_cache_dir');
    my $cice_config_file = $cfg->get('cice_config_cache_file');
    my $cice_config_filepath = "$cice_config_dir/$cice_config_file";
    if (defined $opts{'config_cice'}) {
	$cice_config_filepath = $opts{'config_cice'};
    }

    # Pass namelist settings to CICE.
    my $cice_nl = "&ice \n";

    if ($ocn_comp eq 'dom' or $ocn_comp eq 'docn') {

	# CICE namelist variables that need to be set consistently with CAM-DOM.
	$cice_nl .= 
	    "grid_file=$focndomain \n" .
	    "kmt_file=$focndomain \n" .
	    "stream_domfilename=$bndtvs \n" .
	    "stream_fldfilename=$bndtvs \n" .
	    "stream_fldvarname='ice_cov' \n";

	# Check for variables used to specify the years of a multi-year SST dataset.
	# If not set by user, default to 0 which is the year used in the climatology files.
	my $stream_year_first = $nl->get_value('stream_year_first');
	unless (defined $stream_year_first) { $stream_year_first = 0; }
	$cice_nl .= "stream_year_first=$stream_year_first \n";

	# Set model_year_align equal to stream_year_first.  The flexibility enabled 
	# by model_year_align is not available in CAM-DOM.
	$cice_nl .= "model_year_align=$stream_year_first \n";

	my $stream_year_last = $nl->get_value('stream_year_last');
	unless (defined $stream_year_last) { $stream_year_last = 0; }
	$cice_nl .= "stream_year_last=$stream_year_last \n";

    }

    # If the user has specified variables to send to the CICE build-namelist
    # via the -cice_nl argument then append them here.
    if (defined $opts{'cice_nl'}) {
	my $usr_cice_nl = $opts{'cice_nl'};

	# strip off the leading group name and trailing terminator
	$usr_cice_nl =~ s/^\s*&\w+//;  # group name with optional leading whitespace
	$usr_cice_nl =~ s/\/\s*$//;    # slash terminator with optional trailing whitespace

	$cice_nl .= $usr_cice_nl;
    }

    # For CAM5 need to send the variable "cam5=.true." to get correct defaults for several
    # cice parameters.
    if ($phys eq 'cam5') {
	$cice_nl .= "cam5=.true. \n";
    }

    $cice_nl .= "grid_type='latlon' \n";
    $cice_nl .= "grid_format='nc' \n";

    $cice_nl .=  "stream_domtvarname='time' \n" .
                 "stream_domxvarname='lon' \n" .
                 "stream_domyvarname='lat' \n" .
                 "stream_domareaname='area' \n" .
                 "stream_dommaskname='mask' \n";

    # Terminate the namelist
    $cice_nl .= " /";

    # Commandline arguments for CICE build-namelist
    my @nl_args = ('-csmdata',       $inputdata_rootdir,
                  '-config',         $cice_config_filepath,
                   '-dir',           $opts{'dir'},
                  '-namelist',       $cice_nl,
	);

    my @command = ($cice_bldnl, @nl_args);
    system(@command) == 0  or die "system @command failed: $? \n";

    my $outfile = "$opts{'dir'}/ice_in";
    if ($print>=1) { print "Writing CICE namelist to $outfile $eol"; }
}

#-----------------------------------------------------------------------------------------------
# Add defaults for the RTM component
# Only produce a namelist for RTM if running with CAM standalone scripts
# and if the rof component is active.

my $rof_pkg = $cfg->get('rof');

if ($rof_pkg eq 'rtm' and $cam_build and $rof_active) {
    my  $fh = new IO::File;

    # Create rof_in
    # --------------
    my $outfile = "$opts{'dir'}/rof_in";
    $fh->open(">$outfile") or die "** can't open file: $outfile\n";

    # Currently, just always turn off RTM, but that might change
    # in order to get flooding feedback into CLM.
    print $fh  <<"EOF";
 &rtm_inparm
     rtm_mode = "NULL"
 /
EOF
#/
    $fh->close;
    if ($print>=1) { print "Writing RTM namelist to $outfile $eol"; }

}

#-----------------------------------------------------------------------------------------------
# Create docn namelists and stream txt file

if ($ocn_comp eq 'docn' and $cam_build) {
    my  $fh = new IO::File;

    my $stream_year_first = $nl->get_value('stream_year_first');
    unless (defined $stream_year_first) { $stream_year_first = 0; }
    my $stream_year_last = $nl->get_value('stream_year_last');
    unless (defined $stream_year_last) { $stream_year_last = 0; }

    my $temp = $focndomain;
    $temp  =~ s/['"]//g;   #"'
    my $focndomain_file = basename($temp);
    my $focndomain_path = dirname($temp);

    $temp = $bndtvs;
    $temp  =~ s/['"]//g;   #"'
    my $sstdata_file=  basename($temp);
    my $sstdata_path = dirname($temp);

    my $fsstdomain_file='';
    my $fsstdomain_path='';
    if ($dyn =~ /se/){
      $temp = $bndtvs_domain;
      $temp  =~ s/['"]//g;   #"'
      $fsstdomain_file = basename($temp);
      $fsstdomain_path = dirname($temp);
    } else {
      $fsstdomain_file=$focndomain_file;
      $fsstdomain_path=$focndomain_path;
    }

    my $create_stream = 1;
    if ($aqua_mode) {$create_stream = 0};


    # add docn nml params
    # --------------

    add_default($nl, 'ocn_in', 'val'=>'docn_ocn_in');
    add_default($nl, 'decomp', 'val'=>'1d');


    # Create docn_ocn_in
    # --------------
    my $outfile = "$opts{'dir'}/docn_ocn_in";
    $fh->open(">$outfile") or die "** can't open file: $outfile\n";

    print $fh  <<"EOF";
 &shr_strdata_nml
   dataMode   = 'SSTDATA'
   domainFile = $focndomain
   streams    = 'docn.stream.txt $stream_year_first $stream_year_first $stream_year_last '
   vectors    = 'null'
 /
EOF

    $fh->close;
    if ($print>=1) { print "Writing DOCN namelist to $outfile $eol"; }

    if ($create_stream) {

        # Create docn.stream.txt - ONLY for non aqua_planet mode
        # --------------
        my $outfile = "$opts{'dir'}/docn.stream.txt";
        $fh->open(">$outfile") or die "** can't open file: $outfile\n";

        print $fh  <<"EOF";
<streamstemplate>
<stream>
      <comment>
         Stream description file for generic SST/ifrac data on the CAM grid
      </comment> 
      <dataSource>
         DATASET
      </dataSource>
      <domainInfo> 
         <variableNames>
            time time
            xc   lon
            yc   lat
            area area
            mask mask
         </variableNames>
         <filePath>
            $fsstdomain_path
         </filePath>
         <fileNames>
            $fsstdomain_file
         </fileNames>
      </domainInfo>
      <fieldInfo>
         <variableNames>
            SST_cpl    t
         </variableNames>
         <filePath>
            $sstdata_path
         </filePath>
         <fileNames>
            $sstdata_file
         </fileNames>
      </fieldInfo>
</stream>
</streamstemplate>

EOF

        $fh->close;
        if ($print>=1) { print "Writing DOCN stream file to $outfile $eol"; }
    }

}

#-----------------------------------------------------------------------------------------------
# Rename component logfiles.
#
# This requires special handling because the logfiles are coordinated using 
# share code.  Each component is using shr_file_mod::shr_file_setIO to attach
# a unique Fortran unit to a named file.  shr_file_setIO reads the namelist
# group /modelio/ and hence each component is using the same variable names.
# To work around this component specific names have been added to the special
# namelist group /camexp/.  Check for those variables and write the component
# specific versions of /modelio/ to files whose names are hardwired in the top
# level component interface, e.g., atm_comp_mct, lnd_comp_mct, and seq_ccsm_drv.

my @comps = qw(atm cpl lnd rof);
foreach my $comp (@comps) {

    my $logfile    = "${comp}_logfile";
    my $logfiledir = "${comp}_logfile_diro";
    my $outfile    = "${comp}_modelio.nml";

    # check to see if user requests renaming this component logfile
    my $logfile_val = $nl->get_variable_value('camexp', $logfile);
    if (defined $logfile_val) {

	# create namelist object for /modelio/
	my $modelio = Build::Namelist->new("&modelio logfile=$logfile_val /");

	# check whether a directory has been specified... if so add to namelist
	my $logfiledir_val = $nl->get_variable_value('camexp', $logfiledir);
	if (defined $logfiledir_val) {
	    $modelio->set_variable_value('modelio', 'diro', $logfiledir_val);
	}	

	# write the namelist to the component specific file
	$modelio->write($outfile);
	if ($print>=1) { print "Writing modelio namelist to $outfile $eol"; }
    }
}

#-----------------------------------------------------------------------------------------------
# Write output files

# Get array of group names that have been defined in the namelist.
my @nl_groups = $nl->get_group_names();

# Create a hash with the group names as keys.  This makes it easy to remove
# names from the list.
my %nl_group = ();
foreach my $name (@nl_groups) { $nl_group{$name} = ''; }

# Write fixed sets of namelist groups for the components other than CAM.
# Remove the group names from %nl_group as they are written.  

# CLM
my @comp_groups = qw(clm_inparm clm_rtm_inparm);
my $outfile = "$opts{'dir'}/lnd_in";
if ($cam_build and $lnd_active) {
    $nl->write($outfile, 'groups'=>\@comp_groups);
    if ($print>=1) { print "Writing CLM namelist to $outfile $eol"; }

}
delete @nl_group{@comp_groups};

# Driver
@comp_groups = qw(seq_cplflds_inparm seq_cplflds_userspec ccsm_pes seq_infodata_inparm seq_timemgr_inparm prof_inparm pio_default_inparm);
$outfile = "$opts{'dir'}/drv_in";
if ($cam_build) {
    $nl->write($outfile, 'groups'=>\@comp_groups);
    if ($print>=1) { print "Writing driver namelist to $outfile $eol"; }
}
delete @nl_group{@comp_groups};

# Dry deposition and MEGAN VOC emis namelists
@comp_groups = qw(drydep_inparm megan_emis_nl carma_inparm);
$outfile = "$opts{'dir'}/drv_flds_in";
$nl->write($outfile, 'groups'=>\@comp_groups);
if ($print>=1) { print "CAM writing dry deposition namelist to drv_flds_in $eol"; }
delete @nl_group{@comp_groups};

# Ocean component (CAMDOM)
if ($ocn_group eq 'dom_inparm') {
    $outfile = "$opts{'dir'}/ocn_in";
}
else {
    $outfile = "$opts{'dir'}/docn_in";
}
if ($ocn_group) {
    @comp_groups = ($ocn_group);
    $nl->write($outfile, 'groups'=>\@comp_groups);
    delete @nl_group{@comp_groups};
    if ($print>=1) { print "Writing ocean component namelist to $outfile $eol"; }
}

# CAM
#
# Have removed the group names for components not associated with CAM, so write
# the remaining groups to the CAM namelist file.
# *** N.B. *** The assumption that all remaining groups belong to CAM allows adding
#              new groups to CAM's definition file without requiring a code modification
#              here to have that group written to the namelist file.

# First remove the camexp group since it's a special purpose group that's not
# read by CAM
if (defined $nl_group{'camexp'}) { delete $nl_group{'camexp'}; }
@comp_groups = sort keys %nl_group;
$outfile = "$opts{'dir'}/atm_in";
$nl->write($outfile, 'groups'=>\@comp_groups);
if ($print>=1) { print "CAM writing namelist to atm_in $eol"; }

#-----------------------------------------------------------------------------------------------
# Test that input files exist locally.
if ($opts{'test'}) {
    print "Checking whether input datasets exist locally...$eol";
    check_input_files($nl);
}

# Write the input dataset filepaths to the file specified by $opts{'inputdata'}.
if ($opts{'inputdata'}) {
    check_input_files($nl, $inputdata_rootdir, $opts{'inputdata'});
}

# END OF MAIN SCRIPT
#===============================================================================================

sub create_mode_defs {

# create the list of strings used to define the MAM modes

    my $names     = shift;  # $names->[$m]   - name of mode $m
    my $types     = shift;  # $types->[$m]   - type of mode $m
    my $num       = shift;  # $num->[$m]     - name of intersitial number m.r. for mode $m
    my $num_cw    = shift;  # $num_cw->[$m]  - name of cloud borne number m.r. for mode $m
    my $num_src   = shift;  # $num_src->[$m] - source of interstitial number m.r. for mode $m
    my $spec      = shift;  # $spec->[$m][$i]      - name of interstitial species $i in mode $m
    my $spec_type = shift;  # $spec_type->[$m][$i] - type of species $i in mode $m
    my $spec_cw   = shift;  # $spec_cw->[$m][$i]   - name of cloud borne species $i in mode $m
    my $spec_src  = shift;  # $spec_src->[$m][$i]  - source of interstitial species $i in mode $m

    my $mode_def;

    # number of modes
    my $nmodes = scalar(@$names);

    for (my $m=0; $m < $nmodes; ++$m) {

	# initial mode definition string
	$mode_def .= "'$names->[$m]:$types->[$m]:=',";

	# add the number mixing ratio field names.  the source of the number conc
	# of cloud borne aerosol defaults to N
	$mode_def .= "'$num_src->[$m]:$num->[$m]:N:$num_cw->[$m]:num_mr:+',";

	# number of species in mode
	my $nspec = scalar(@{$spec->[$m]});
	for (my $i=0; $i < $nspec; ++$i) {

	    my $term = ":+',";        # more species to come
	    if ($i == $nspec - 1) {
		if ($m == $nmodes - 1) {
		    $term = "'";      # last specie and no more modes
		}
		else {
		    $term = "',";     # last specie but more modes to come
		}
	    }

	    # get default properties file
	    my $spec_name = $spec->[$m][$i];
	    my $rel_filepath = get_default_value("mam_$spec_name");
	    my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);

 	    # add species info. the source of the mixing ratio
            # for cloud borne species defaults to N
	    $mode_def .= "'" .
		         $spec_src->[$m][$i]  . ":" . 
		         $spec->[$m][$i]      . ":N:" . 
		         $spec_cw->[$m][$i]   . ":" . 
		         $spec_type->[$m][$i] . ":" . 
		         $abs_filepath        . $term;
	}


    }

    return $mode_def;
}

#===============================================================================================
sub add_default {

# Add a value for the specified variable to the specified namelist object.  The variables
# already in the object have the higher precedence, so if the specified variable is already
# defined in the object then don't overwrite it, just return.
#
# This method checks the definition file and adds the variable to the correct
# namelist group.
#
# The value can be provided by using the optional argument key 'val' in the
# calling list.  Otherwise a default value is obtained from the namelist
# defaults object.  If no default value is found this method throws an exception
# unless the 'nofail' option is set true.
#
# Additional optional keyword=>value pairs may be specified.  If the keyword 'val' is
# not present, then any other keyword=>value pairs that are specified will be used to
# match attributes in the defaults file.
#
# Example 1: Specify the default value $val for the namelist variable $var in namelist
#            object $nl:
#
#  add_default($nl, $var, 'val'=>$val)
#
# Example 2: Add a default for variable $var if an appropriate value is found.  Otherwise
#            don't add the variable
#
#  add_default($nl, $var, 'nofail'=>1)
#
#
# ***** N.B. ***** This routine assumes the following variables are in package main::
#  $definition        -- the namelist definition object
#  $inputdata_rootdir -- CCSM inputdata root directory

    my $nl = shift;     # namelist object
    my $var = shift;    # name of namelist variable
    my %opts = @_;      # options

    my $val = undef;

    # Query the definition to find which group the variable belongs to.  Exit if not found.
    my $group = $definition->get_group_name($var);
    unless ($group) {
	my $fname = $definition->get_file_name();
	die "$ProgName - ERROR: variable \"$var\" not found in namelist definition file $fname.\n";
    }

    # check whether the variable has a value in the namelist object -- if so then return
    $val = $nl->get_variable_value($group, $var);
    if (defined $val) {return;}

    # Look for a specified value in the options hash
    if (defined $opts{'val'}) {
	$val = $opts{'val'};
    }
    # or else get a value from namelist defaults object.
    # Note that if the 'val' key isn't in the hash, then just pass anything else
    # in %opts to the get_value method to be used as attributes that are matched
    # when looking for default values.
    else {
	$val = get_default_value($var, \%opts);
    }

    # if no value is found then exit w/ error (unless 'nofail' option set)
    unless (defined $val) {
	unless ($opts{'nofail'}) {
	    print "$ProgName - ERROR: No default value found for $var\n".
		"user defined attributes:\n";
	    foreach my $key (keys(%opts)) {
		if ($key ne 'nofail' and $key ne 'val') {
		    print "key=$key  val=$opts{$key}\n";
		}
	    }
	    die;
	}
	else {
	    return;
	}
    }

    # query the definition to find out if the variable is an input pathname
    my $is_input_pathname = $definition->is_input_pathname($var);

    # The default values for input pathnames are relative.  If the namelist
    # variable is defined to be an absolute pathname, then prepend
    # the CCSM inputdata root directory.
    if ($is_input_pathname eq 'abs') {
	$val = set_abs_filepath($val, $inputdata_rootdir);
    }

    # Some complex namelist variables set in use cases may have "$INPUTDATA_ROOT"
    # in the data path specifications.  Subsitute the resolved path here for these cases.
    $val =~ s/\$INPUTDATA_ROOT/$inputdata_rootdir/g ;

    # query the definition to find out if the variable takes a string value.
    # The returned string length will be >0 if $var is a string, and 0 if not.
    my $str_len = $definition->get_str_len($var);

    # If the variable is a string, then add quotes if they're missing
    if ($str_len > 0) {
	$val = quote_string($val);
    }

    # set the value in the namelist
    $nl->set_variable_value($group, $var, $val);
}

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

sub get_default_value {

# Return a default value for the requested variable.
# Return undef if no default found.
#
# ***** N.B. ***** This routine assumes the following variables are in package main::
#  $defaults          -- the namelist defaults object
#  $uc_defaults       -- the use case defaults object

    my $var_name    = lc(shift);   # name of namelist variable (case insensitive interface)
    my $usr_att_ref = shift;       # reference to hash containing user supplied attributes

    # Check first in the use case defaults
    if (defined $uc_defaults) {
	my $val = $uc_defaults->get_value($var_name, $usr_att_ref);
	if ($val) {return $val;}
    }

    # Check in the namelist defaults
    return $defaults->get_value($var_name, $usr_att_ref);

}

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

sub fv_decomp_set{

# Return a decomposition for the FV dycore, expressed as the value for the namelist
# variable npr_yz.  The value of npr_yz is ny,nz,nx,ny where ny, nz, and nx are
# respecitively the number of y, z, and x subdomains in the multi-2D decomposition.
# The following constraints must be observed: 
# 1) ny*nz = ntasks  (ny*nz can be less than ntasks in the case that the dynamics runs
#                     on a subset of the total tasks.  Assume the user will set the
#                     decomp explicitly if that is what is desired.)
# 2) nx=nz           (this is an empirically determined constraint for efficiency in the
#                     dycore communications)
# 3) ny*3 <= nlat    (these constraints are imposed by the dycore)
#    nz   <= nlev
#
# The strategy for setting the default decomposition is to use the smallest possible
# number of z subdomains.  Start with 1 (which is the 1D decomposition).  If that works
# then done.  If not, increase nz, check that it divides ntasks, if so does resulting
# ny satisfy ny*3 <= nlat, if so then done.  Etc.

    my $ntasks = $opts{'ntasks'};
    my $nlat = $cfg->get('nlat');
    my $nlev = $cfg->get('nlev');
    my ($ny, $nz);

    NZ: for ($nz = 1; $nz <= $nlev; ++$nz) {

	# test that $nz divides $ntasks
	if ($ntasks%$nz == 0) {

	    $ny = $ntasks/$nz;

	    # test that y subdomains contain at least 3 latitudes
	    # if so then done
	    if (3*$ny <= $nlat) {last NZ;}
	}
    }

    # die if algorithm failed
    if ($nz > $nlev  or  $ny*$nz != $ntasks) {
	die "$ProgName - ERROR: fv_decomp_set failed to find a decomposition.\n" .
	    "  npr_yz needs to be set by the user.";
    }

    return "$ny,$nz,$nz,$ny";
}

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

sub check_input_files {

# For each variable in the namelist which is an input dataset, or contains filepaths
# for input datasets, either:
# 1) check to see if the input dataset exists on local disk, or
# 2) write the input dataset filepath to a file.
#
# In "test" mode (1) the routine is called with just one argument.
# In "inputdata" mode (2) the routine is called with three arguments.
#
# ***** N.B. ***** This routine assumes the following variables are in package main::
#  $definition        -- the namelist definition object

    my $nl                = shift;    # namelist object
    my $inputdata_rootdir = shift;    # if false prints test, else creates inputdata file
    my $outfile           = shift;

    my $fh;
    if (defined $inputdata_rootdir) {
	open $fh, '>', $outfile or die "check_input_files: error opening $outfile: $!";
    }

    # Look through all namelist groups
    my @groups = $nl->get_group_names();
    foreach my $group (@groups) {

	# Look through all variables in each group
	my @vars = $nl->get_variable_names($group);
	foreach my $var (@vars) {

	    # Is the variable an input dataset?
	    my $input_pathname_type = $definition->is_input_pathname($var);

	    # If it is, check whether it exists locally and print status
	    if ($input_pathname_type) {

		# Get pathname of input dataset
		my $pathname = $nl->get_variable_value($group, $var);
		# Need to strip the quotes
		$pathname =~ s/['"]//g;

		if ($input_pathname_type eq 'abs') {
                    if ($inputdata_rootdir) {
                        print $fh "$var = $pathname\n";
                    }
                    else {
		        if (-e $pathname) {  # use -e rather than -f since the absolute pathname
			                     # might be a directory
			    print "OK -- found $var = $pathname\n";
		        }
		        else {
			    print "NOT FOUND:  $var = $pathname\n";
		        }
                    }
		}
		elsif ($input_pathname_type =~ m/rel:(.+)/o) {
		    # The match provides the namelist variable that contains the
		    # root directory for a relative filename
		    my $rootdir_var = $1;
		    my $rootdir = $nl->get_variable_value($group, $rootdir_var);
		    $rootdir =~ s/['"]//g;          #"'
                    if ($inputdata_rootdir) {
                        $pathname = "$rootdir/$pathname";
                        print $fh "$var = $pathname\n";
                    }
                    else {
		        if (-f "$rootdir/$pathname") {
			    print "OK -- found $var = $rootdir/$pathname\n";
		        }
		        else {
			    print "NOT FOUND:  $var = $rootdir/$pathname\n";
		        }
                    }
		}
	    }
	}
    }

    # Treat special cases...

    # These namelist variables are arrays of strings.
    my @vars = qw(ext_frc_specifier srf_emis_specifier mode_defs rad_climate rad_diag_1 rad_diag_2
                  rad_diag_3 rad_diag_4 rad_diag_5 rad_diag_6 rad_diag_7 rad_diag_8
                  rad_diag_9 rad_diag_10);

    foreach my $var (@vars) {

	# Is the variable in the namelist?
	my $value = $nl->get_value($var);
	if (defined $value) {

	    # The current namelist parser stores all values as a single
	    # string, so start by extracting each quoted string.

	    while ($value =~ m/['"]          # opening quote
                               ([^'"]+)      # capture all non-quote characters up to 
                               ['"]          # closing quote
                               (.*)          # capture rest of string including newlines
                              /sxo) {        # the s modifier lets . match newlines
		my $spec = $1;
		$value = $2;

		# Look for values of the form 'name -> filepath'
		# Extract name and filename
		if ($spec =~ m/\s*(\w+)      # name of species preceded by optional whitespace
                               \s*->\s*      # -> separator surrounded by optional whitespace
                               (\S+)         # filename (all characters up to optional whitespace)
                              /xo) {
		    my $name = $1;
		    my $file = $2;
                    if ($inputdata_rootdir) {
                        print $fh "$var for $name = $file\n";
                    }
                    else {
		        if (-f $file) {
			    print "OK -- found $var for $name = $file\n";
		        }
		        else {
			    print "NOT FOUND:  $var for $name = $file\n";
		        }
                    }
		}
		# Look for values that begin with 'X:name:name2' where X is one of [AMN]
		# Extract name and filename
		elsif ($spec =~ m/^\s*[AMN]:(\w+) # name of species preceded by optional whitespace and X:
                                  :               # : separator
                                  (\S+)           # name2
                                 /xo) {
		    my $name  = $1;
		    my $name2 = $2;

		    # If $name2 starts with a slash, then it is an absolute filepath.
		    # If $name2 starts with a $, then it is an unresolved filepath
		    # (generated when run from CCSM scripts).
		    # Otherwise check for more fields
		    if ($name2 =~ m:^[/\$]:) {

			my $file = $name2;
                        if ($inputdata_rootdir) {
			    print $fh "$var for $name = $file\n";
			}
			else {
			    if (-f $file) {
				print "OK -- found $var for $name = $file\n";
			    }
			    else {
				print "NOT FOUND:  $var for $name = $file\n";
			    }
			}
		    }
		    else {
			# If this value is from a mode_defs string that defined
                        # a mode specie, then breaking it up into colon separated
                        # fields will provide a filepath in the 4rd field (index 3).
			my @flds = split /:/, $name2;
			if (scalar(@flds) >= 4) {

			    if ($flds[3] =~ m:^[/\$]:) {

				my $file = $flds[3];
                                if ($inputdata_rootdir) {
				    print $fh "$var for $name = $file\n";
				}
				else {
				    if (-f $file) {
					print "OK -- found $var for $name = $file\n";
				    }
				    else {
					print "NOT FOUND:  $var for $name = $file\n";
				    }
				}
			    }
			} 
		    }

		}
		# Look for values that end with "=".  These are the initial strings in mode
                # definitions and should just be ignored.
		elsif ($spec =~ m/^\s*(\S+)=\s*$/) { # string which ends with "=" and has optional 
		                                     # begining and trailing whitespace
		    # ignore it
		}
		else {
		    print "Failed to parse \'$spec\'\n";
		}

	    } # end of while loop
	}
    }

    close $fh if defined $inputdata_rootdir;

    return 0;
}

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

sub strip_rootdir {

# Strip a root directory from the begining of a filepath.
# Allow for the possibility that the root directory is specified as a shell variable
# to support a CCSM script requirement.

    my ($filepath, $rootdir) = @_;

    # Check whether the rootdir is specified as a shell variable.
    if ($rootdir =~ m/^\$(\w*)/) {

	my $rootname = $1;

	# Strip off the root directory with the following regexp that
	# avoids the problem of $rootdir being interpolated to a scalar variable
	# name...
	#$filepath =~ s:^\$$rootname::;

	# The CCSM scripts are currently set up to expect the shell variable in the
	# output file that contains the list of inputdata files.  So in this case
	# do nothing.

    }
    else {
	# Strip off the rootdir specified as a resolved pathname
	$filepath =~ s:^$rootdir::;
    }
    return $filepath;
}

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

sub set_abs_filepath {

# check whether the input filepath is an absolute path, and if it isn't then
# prepend a root directory

    my ($filepath, $rootdir) = @_;

    # strip any leading/trailing whitespace
    $filepath =~ s/^\s+//;
    $filepath =~ s/\s+$//;
    $rootdir  =~ s/^\s+//;
    $rootdir  =~ s/\s+$//;

    # strip any leading/trailing quotes
    $filepath =~ s/^['"]+//;
    $filepath =~ s/["']+$//;
    $rootdir =~ s/^['"]+//;
    $rootdir =~ s/["']+$//;

    my $out = $filepath;
    unless ( $filepath =~ /^\// ) {  # unless $filepath starts with a /
	$out = "$rootdir/$filepath"; # prepend the root directory
    }
    return $out;
}

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


sub absolute_path {
#
# Convert a pathname into an absolute pathname, expanding any . or .. characters.
# Assumes pathnames refer to a local filesystem.
# Assumes the directory separator is "/".
#
  my $path = shift;
  my $cwd = getcwd();  # current working directory
  my $abspath;         # resulting absolute pathname

# Strip off any leading or trailing whitespace.  (This pattern won't match if
# there's embedded whitespace.
  $path =~ s!^\s*(\S*)\s*$!$1!;

# Convert relative to absolute path.

  if ($path =~ m!^\.$!) {          # path is "."
      return $cwd;
  } elsif ($path =~ m!^\./!) {     # path starts with "./"
      $path =~ s!^\.!$cwd!;
  } elsif ($path =~ m!^\.\.$!) {   # path is ".."
      $path = "$cwd/..";
  } elsif ($path =~ m!^\.\./!) {   # path starts with "../"
      $path = "$cwd/$path";
  } elsif ($path =~ m!^[^/]!) {    # path starts with non-slash character
      $path = "$cwd/$path";
  }

  my ($dir, @dirs2);
  my @dirs = split "/", $path, -1;   # The -1 prevents split from stripping trailing nulls
                                     # This enables correct processing of the input "/".

  # Remove any "" that are not leading.
  for (my $i=0; $i<=$#dirs; ++$i) {
      if ($i == 0 or $dirs[$i] ne "") {
	  push @dirs2, $dirs[$i];
      }
  }
  @dirs = ();

  # Remove any "."
  foreach $dir (@dirs2) {
      unless ($dir eq ".") {
	  push @dirs, $dir;
      }
  }
  @dirs2 = ();

  # Remove the "subdir/.." parts.
  foreach $dir (@dirs) {
    if ( $dir !~ /\.\./ ) {
        push @dirs2, $dir;
    } else {
        pop @dirs2;   # remove previous dir when current dir is ..
    }
  }
  if ($#dirs2 == 0 and $dirs2[0] eq "") { return "/"; }
  $abspath = join '/', @dirs2;
  return( $abspath );
}

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

sub valid_option {

    my ($val, @expect) = @_;
    my ($expect);

    $val =~ s/^\s+//;
    $val =~ s/\s+$//;
    foreach $expect (@expect) {
	if ($val =~ /^$expect$/i) { return $expect; }
    }
    return undef;
}

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

sub validate_use_case {

    my $source = shift;   # text string declaring the source of the options being validated
    my $opts   = shift;   # reference to hash that contains the options

    my ($opt, $old, @expect);
    
    # use_case
    $opt = 'use_case';
    if (defined $opts->{$opt}) {

	# create the @expect array by listing the files in $use_case_dir
	# and strip off the ".xml" part of the filename
	@expect = ();
	my @files = glob("$opts->{'use_case_dir'}/*.xml");
	foreach my $file (@files) {
	    $file =~ m{.*/(.*)\.xml};
	    push @expect, $1;
	}

	$old = $opts->{$opt};
	$opts->{$opt} = valid_option($old, @expect)
	    or die "$ProgName - ERROR: invalid value of $opt ($old) specified in $source\n".
                   "expected one of: @expect\n";
    }

}

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

sub quote_string {
    my $str = shift;
    $str =~ s/^\s+//;
    $str =~ s/\s+$//;
    unless ($str =~ /^['"]/) {        #"'
        $str = "\'$str\'";
    }
    return $str;
}

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

sub version {
# The version is found in CAM's ChangeLog file.
# $cfgdir is set by the configure script to the name of its directory.

    my ($cfgdir) = @_;

    my $logfile = "$cfgdir/../doc/ChangeLog";

    my $fh = IO::File->new($logfile, '<') or die "** $ProgName - ERROR: can't open ChangeLog file: $logfile\n";

    while (my $line = <$fh>) {

	if ($line =~ /^Tag name:\s*(\w+)/ ) {
	    print "$1\n";
	    last;
	}
    }

}

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