#!/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 set_aero_modes_info chem_has_species);
#-----------------------------------------------------------------------------------------------

sub usage {
    die <<EOF;
SYNOPSIS
     build-namelist [options]
OPTIONS
     -case "name"          Case identifier up to 32 characters
     -config "filepath"    Read the given configuration cache file to determine the configuration
                           of the CAM executable.  Default: "config_cache.xml".
     -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'},
    "config=s"                  => \$opts{'config'},
    "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 CESM scripts or for standalone CAM  scripts.  If
# CESM then only produce namelists for the CAM component.  If CAM standalone then produce
# output for the required non-cam components as well.

my $ccsm_build = $cfg->get('ccsm_seq');
my $cam_build  = $ccsm_build ? 0 : 1;
if ($print>=2) { 
    if ($ccsm_build) {
        print "Writing namelist files for cesm 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: cime_driver_inst #
####################################

add_default($nl, 'ninst_driver', 'val'=>'1');

######################################
# 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 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'};
    }

    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 #
#######################################
# Case name
add_default($nl, 'case_name');

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

# CIME model version
add_default($nl, 'cime_model', 'val'=>'cesm');
add_default($nl, 'gust_fac', 'val'=>'0');

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

# Physics package checks done here since aqua_planet setting is in
# the seq_infodata_inparm group
my $phys_mode_flags = 0;
my $adia_mode = 0;
my $aqua_mode = 0;

my $phys = $cfg->get('phys');

# Aqua planet

my $aqua_mode = $cfg->get('aquaplanet');
my $nl_aqua_flag = $nl->get_value('aqua_planet');

# 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 aqua_planet set 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 aqua_planet set to TRUE in the namelist. \n";
}

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

# Consistency check for namelist variables used to implement physics modes.
if ($phys eq 'adiabatic') {
    $adia_mode = 1;
    ++$phys_mode_flags;
}
my $ideal_mode = 0;
if ($phys eq 'kessler' or $phys eq 'held_suarez') {
    $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 or adiabatic
# modes is being used.
my $simple_phys = 0;
if ($adia_mode or $ideal_mode) { $simple_phys = 1; }

# 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, 'cpl_seq_option');

# 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'));

#-----------------------------------------------------------------------------------------------
# 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 $chem =~ "_sc" or $prog_species =~ "GHG");
my $prog_ghg2    = ($chem =~ "ghg" or $chem =~ "_sc" or $prog_species =~ "GHG");
my $ghg_chem     = ($chem =~ "ghg" or $chem =~ "_sc");
my $aero_chem    = ($chem =~ "aero" or $chem eq 'trop_mozart' 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 =~ "waccm_ma" 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
# or if using MAM and the rrtmg package
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.')
}

my $prescribe_aerosols = $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_sol_facti, $aer_sol_factb, $aer_scav_coef, 
         $aer_drydep_list, $gas_drydep_list ) =
           set_dep_lists( $cfgdir, $chem_proc_src, $chem_src_dir, $nl, $print );

    if (length($gas_wetdep_list)>2){ 
      add_default($nl, 'gas_wetdep_method' );
      add_default($nl, 'gas_wetdep_list', 'val'=>$gas_wetdep_list ); 
    }
    if (length($aer_wetdep_list)>2){ 
        # determine if prescribed aerosols are not needed ...
        if ($aer_wetdep_list =~ /so4/i && 
            $aer_wetdep_list =~ /dst/i && 
           ($aer_wetdep_list =~ /bc/i || $aer_wetdep_list =~ /cb/i) &&
           ($aer_wetdep_list =~ /ncl/i || $aer_wetdep_list =~ /sslt/i)) {
            $prescribe_aerosols = $FALSE;
        }

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

        if (!($chem =~ /_mam/)) {
            if (!defined $nl->get_value('aer_sol_facti')) {
                add_default($nl, 'aer_sol_facti', val=>$aer_sol_facti );
            }
            if (!defined $nl->get_value('aer_sol_factb')) {
                add_default($nl, 'aer_sol_factb', val=>$aer_sol_factb );
            }
            if (!defined $nl->get_value('aer_scav_coef')) {
                add_default($nl, 'aer_scav_coef', val=>$aer_scav_coef );
            }
        }
    }
    if (length($gas_drydep_list)>2){ 
        add_default($nl, 'drydep_list', 'val'=>$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' );
    }
    if (length($aer_drydep_list)>2){ 
        add_default($nl, 'aer_drydep_list', 'val'=>$aer_drydep_list );
    }
}
if ($chem) {
    # 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.
    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');
    }
}

# 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.
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);

# analytic ICs
my $analytic_ic = $cfg->get('analytic_ic');
if ($analytic_ic) {
    add_default($nl, 'analytic_ic_type');
}

#
# 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, 'use_topo_file', 'nofail'=>1);
my $use_topo_file = $nl->get_value('use_topo_file');
if (!defined $use_topo_file or ($use_topo_file =~ m/$TRUE/io)) {
    # Add the topo file unless the "do not use" override has been set.
    add_default($nl, 'bnd_topo', 'nofail'=>1);
}

# Radiation
my $rad_pkg = $cfg->get('rad');
if ($rad_pkg eq 'camrt') {
    add_default($nl, 'absems_data');
}

# Solar irradiance

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

    die "$ProgName - ERROR: It is not allowed to set both solar_const \n".
        "            and solar_irrad_data_file.  solar_const will be ignored. \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_ma
   add_default($nl, 'solar_irrad_data_file');
   add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.true.');

}
elsif (!$simple_phys) {

   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_irrad_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_irrad_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);


# Set number of test tracers requested via -nadv_tt option to configure
my $test_tracer_num = $cfg->get('nadv_tt');
if ($test_tracer_num > 0) {
    add_default($nl, 'test_tracer_num', 'val'=>$test_tracer_num);
}

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_ma/ 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'";
    if (!defined $nl->get_value('prescribed_ozone_file') and !$simple_phys) {
        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_ma/) or ($chem =~ /waccm_sc_mam/) 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 ($prescribe_aerosols =~ /$TRUE/io) {
        # if the chemistry does not include prognostic aerosols then 
        # prescribed aerosols need to be specified unless using simple physics.
        # The only supported prescribed aerosols are 'bulk'.  Set that as the
        # default which can be overridden by the user.
        $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';}
  if ($chem =~ /_mam4/) {$aero_modes = '4mode';}

  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;
  my %modal_groups;
  my %modal_species = ( 'so4'=>'sulfate', 
                        'nh4'=>'ammonium', 
                        'pom'=>'p-organic', 
                        'soa'=>'s-organic', 
                        'bc' =>'black-c', 
                        'dst'=>'dust',
                        'ncl'=>'seasalt' );

  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);

    %modal_groups = ( 'accum'  => [qw(so4 pom soa bc dst ncl)],
                      'aitken' => [qw(so4 soa ncl)],
                      'coarse' => [qw(dst ncl so4)] );


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

  } elsif($aero_modes eq '4mode') {
      # For 4 modes

    # MAM rad_climate settings.  The externally mixed quantities in the modal aerosol
    # model are the modes.
    push @aero_names, qw(mam4_mode1 mam4_mode2 mam4_mode3 mam4_mode4);
    push @aerosources, qw(M: M: M: M:);
  
    # Each of the mode names put into the @aero_names array needs to be defined.
    @mode_names    = qw(mam4_mode1 mam4_mode2 mam4_mode3 mam4_mode4);
    @mode_types    = qw(accum aitken coarse primary_carbon);
    @mode_num      = qw(num_a1 num_a2 num_a3 num_a4);
    @mode_num_cw   = qw(num_c1 num_c2 num_c3 num_c4);

    %modal_groups = ( 'accum'  => [qw(so4 pom soa bc dst ncl)],
                      'aitken' => [qw(so4 soa ncl dst)],
                      'coarse' => [qw(dst ncl so4)],
                      'primary_carbon' => [qw(pom bc)] );

    @mode_num_src  = qw(A A A A);

  } elsif($aero_modes eq '7mode') { 

    # 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);

    %modal_groups = ( 'accum'          => [qw(so4 nh4 pom soa bc ncl)],
                      'aitken'         => [qw(so4 nh4 soa ncl)],
                      'primary_carbon' => [qw(pom bc)],
                      'fine_seasalt'   => [qw(ncl so4 nh4)],
                      'fine_dust'      => [qw(dst so4 nh4)],
                      'coarse_seasalt' => [qw(ncl so4 nh4)],
                      'coarse_dust'    => [qw(dst so4 nh4)] );

    @mode_num_src = qw(A A A A A A A);

  }

  set_aero_modes_info( $cfg, @mode_num_src[0], $print, \@mode_types, \%modal_species, \%modal_groups, 
                       \@mode_spec_type, \@mode_spec, \@mode_spec_cw, \@mode_spec_src);

  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:

# For modal aerosols the mode definitions and emission tuning parameters are
# influenced by the value of modal_accum_coarse_exch.  This value is set by certain
# waccm use_case files, but it is now also used by the cam6 physics package.  So
# need to make sure a default is set.
if ($aer_model eq 'mam' ) {
    add_default($nl, 'modal_accum_coarse_exch');
}

foreach my $name (@aero_names) {
    my $source = shift(@aerosources);
    my $file;
    if ($source =~ 'M') {
        $file = "${name}_file";
    }
    else {
        $file = "${aer_model}_$name";
    }
    my $defversion = ''; # mode definition version
    if ($nl->get_value('modal_accum_coarse_exch') =~ /$TRUE/io) {
        $defversion = 'strat';
    }
    my $rel_filepath = get_default_value($file, {'ver'=>$defversion} );
    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");
    }
  }
}
# CARMA microphysics
#
# Each CARMA model may require a different set of default
# namelist values to enable the processes that correspond
# to the desired microphysics.
if ($carma ne 'none') {
  add_default($nl, 'carma_model',       'val'=>$carma);
  add_default($nl, 'carma_flag',        'val'=>'.true.');
  add_default($nl, 'history_carma',     '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_partialinit','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_partialinit','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_fixedinit','val'=>'.true.');
  add_default($nl, 'carma_do_grow',     'val'=>'.true.');
  add_default($nl, 'carma_hetchem_feedback','val'=>'.true.');
  add_default($nl, 'carma_rad_feedback','val'=>'.true.');
  add_default($nl, 'carma_do_partialinit','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');
}

# Stratospheric sulfur aerosols 

# turn on stratospheric aerosol forcings in CAM6 configurations
my $chem_has_ocs = chem_has_species($cfg, 'OCS');
if ($phys =~ /cam6/) { 
  # turn on volc forcings in cam6 -- prognostic or prescribed
  if ( $chem_has_ocs ) {
      # turn on prognostic stratospheric aerosols
      add_default($nl, 'modal_strat_sulfate','val'=>'.true.');
  } else {
      # turn on prescribed stratospheric aerosols
      add_default($nl, 'prescribed_strataero_feedback','val'=>'.true.');
  }
}
if ( $nl->get_value('modal_strat_sulfate')=~ /$TRUE/io and 
     $nl->get_value('prescribed_strataero_feedback') =~ /$TRUE/io ) {
    die "Cannot set both modal_strat_sulfate and prescribed_strataero_feedback to TRUE \n";
}

# stratospheric aerosols are needed for heterogeneous chemistry as well as radiation feedback
my $het_chem = chem_has_species($cfg, 'N2O5');

# determine if prescribed stratospheric aerosol data is needed
if ( ($het_chem) || ($nl->get_value('prescribed_strataero_feedback') =~ /$TRUE/io ) ){
    if ( ($carma ne 'sulfate') && !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols
        unless (defined $nl->get_value('prescribed_strataero_type')) {
            add_default($nl, 'prescribed_strataero_type','val'=>'CYCLICAL');
            my %valhash = ('val'=>'2000');
            if ($nl->get_value('prescribed_strataero_3modes') =~ /$TRUE/io) {%valhash = ('val'=>'1990')}
            add_default($nl, 'prescribed_strataero_cycle_yr', %valhash );
        }
        unless (defined $nl->get_value('prescribed_strataero_file')) {
            my %verhash ;
            if ($nl->get_value('prescribed_strataero_3modes') =~ /$TRUE/io) {%verhash = ('ver'=>'3modes')}
            add_default($nl, 'prescribed_strataero_file', %verhash );
            add_default($nl, 'prescribed_strataero_datapath', %verhash );
        }
    }
}
# add to rad_climate the contributions from stratospheric aerosols if feedback is switched on
if (($nl->get_value('prescribed_strataero_feedback') =~ /$TRUE/io) 
 || ($nl->get_value('carma_rad_feedback') =~ /$TRUE/io)) {
    if ($nl->get_value('prescribed_strataero_3modes') =~ /$TRUE/io) {
        my $rel_filepath = get_default_value("VOLC_MMR1");
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $radval .= "," . quote_string("N:VOLC_MMR1:" . $abs_filepath);

        $rel_filepath = get_default_value("VOLC_MMR2");
        $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $radval .= "," . quote_string("N:VOLC_MMR2:" . $abs_filepath);

        $rel_filepath = get_default_value("VOLC_MMR3");
        $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $radval .= "," . quote_string("N:VOLC_MMR3:" . $abs_filepath);
    } else {
        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);
    }
}
# check for inadvertent setting of both old and new prescribed volcanoes
if ( (defined $nl->get_value('prescribed_volcaero_file')) and 
     (defined $nl->get_value('prescribed_strataero_file')) ) {
    die "Cannot set both prescribed_volcaero_file and prescribed_strataero_file \n";
}
if (defined $nl->get_value('prescribed_strataero_file')) {
    add_default($nl, 'prescribed_strataero_use_chemtrop');
}

if ($rad_pkg ne 'none') {
    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-SC options (specified chemical heating)
if ($chem =~ /waccm_sc/) {
    # *** Note *** this dataset only needed for waccm_sc.
    # 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_data_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/ or $chem =~ /waccm_tsmlt/) {
 
    # 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',
                   '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',
                   'ISOP     -> ' => 'isop_emis_file',
                   'TOLUENE  -> ' => 'toluene_emis_file',
                   );
    if (!($chem =~ /_vbs/) and !($chem =~ /_tsmlt/)) {
        %species = (%species,
                    'NH3      -> ' => 'nh3_emis_file');
    }
    if (!($chem =~ /_vbs/) and !($chem =~ /_tsmlt/)) {
        %species = (%species,
                    'C10H16   -> ' => 'c10h16_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 =~ /_tsmlt_mam4/ or $chem =~ /mam4_vbs/) {
        %species = (%species,
                   'BENZENE  -> ' => 'soa_benzene_emis_file',
                   'XYLENES  -> ' => 'soa_xylene_emis_file',
                   'TOLUENE  -> ' => 'soa_toluene_emis_file',
                   'IVOC     -> ' => 'ivocbb_emis_file',
                   'bc_a4    -> ' => 'bc_a4_emis_file',
                   'pom_a4   -> ' => 'pom_a4_emis_file',
                   'so4_a1   -> ' => 'so4_a1_emis_file',
                   'so4_a2   -> ' => 'so4_a2_emis_file',
                   'num_a1   -> ' => 'mam4_num_a1_emis_file',
                   'num_a2   -> ' => 'num_a2_emis_file',
                   'num_a4   -> ' => 'mam4_num_a4_emis_file',
                   );
    } elsif ($chem =~ /mam4/) {
        %species = (%species,
                   'SOAG     -> ' => 'soag_emis_file',
                   'bc_a4    -> ' => 'bc_a4_emis_file',
                   'pom_a4   -> ' => 'pom_a4_emis_file',
                   'so4_a1   -> ' => 'so4_a1_emis_file',
                   'so4_a2   -> ' => 'so4_a2_emis_file',
                   'num_a1   -> ' => 'mam4_num_a1_emis_file',
                   'num_a2   -> ' => 'num_a2_emis_file',
                   'num_a4   -> ' => 'mam4_num_a4_emis_file',
                   );
    } 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',
                   );
    }

    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 =~ /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 =~ /_tsmlt_mam4/ or $chem =~ /mam4_vbs/) {
      %species = ( 'NO2    -> ' => 'no2_aircraft_emis_file',
                   'SO2    -> ' => 'so2_ext_file',
                   'so4_a1 -> ' => 'so4_a1_ext_file',
                   'so4_a2 -> ' => 'so4_a2_ext_file',
                   'pom_a4 -> ' => 'pom_a4_ext_file',
                   'bc_a4  -> ' => 'bc_a4_ext_file',
                   'num_a1 -> ' => 'mam4_num_a1_ext_file',
                   'num_a2 -> ' => 'num_a2_ext_file',
                   'num_a4 -> ' => 'mam4_num_a4_ext_file',
                   'SVOC -> ' => 'svocbb_ext_file' );
      $cyc_yr = '2000';
    } elsif ($chem =~ /mam4/) {
      %species = ( 'NO2    -> ' => 'no2_aircraft_emis_file',
                   'SO2    -> ' => 'so2_ext_file',
                   'so4_a1 -> ' => 'so4_a1_ext_file',
                   'so4_a2 -> ' => 'so4_a2_ext_file',
                   'pom_a4 -> ' => 'pom_a4_ext_file',
                   'bc_a4  -> ' => 'bc_a4_ext_file',
                   'num_a1 -> ' => 'mam4_num_a1_ext_file',
                   'num_a2 -> ' => 'num_a2_ext_file',
                   'num_a4 -> ' => 'mam4_num_a4_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 =~ /_tsmlt_mam/ or $chem =~ /trop_strat/) {
      $val = "'CCL4','CF2CLBR','CF3BR','CFC11','CFC113','CFC12','CH3BR','CH3CCL3','CH3CL','CH4','CO2'"
            .",'H2','HCFC22','N2O','CFC114','CFC115','HCFC141B','HCFC142B','CH2BR2','CHBR3','H2402'";
    } else {
      $val = "'CH4','H2','N2O','CO2','CFC11','CFC12'";
    }
    if ($chem_has_ocs) {
        $val .= ",'OCS'";
    }
    if (chem_has_species($cfg, 'SF6')) {
        $val .= ",'SF6'";
    }
    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');
    }

    my @files;
    # Datasets
    if ($chem =~ /trop_strat/ or $chem =~ /waccm_tsmlt/) {
       @files = ( 'soil_erod_file', 'flbc_file', 
                  'xs_coef_file','xs_short_file','xs_long_file', 'rsf_file' );
    } else {
       @files = ( 'soil_erod_file', 'flbc_file', 
                  'xs_coef_file','xs_short_file','xs_long_file', 'rsf_file', 'exo_coldens_file', 'sulf_file' );
    }
    foreach my $file (@files) {
        add_default($nl, $file);
    }
}

# 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', 
                 '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', 
                 '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'=>'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 = ();
    if (defined $nl->get_value('fire_emis_specifier')){ # without prescribed forest fire and grass fire sources 
      %species = ('SO2         -> ' => 'so2_ext_wofire_file',
                  'so4_a1      -> ' => 'so4_a1_ext_wofire_file', 
                  'so4_a2      -> ' => 'so4_a2_ext_file',        # background volc emissions
                  'num_a1      -> ' => 'num_a1_ext_wofire_file', 
                  'num_a2      -> ' => 'num_a2_ext_file', );     # background volc emissions
    } else {  # default prescribed sources
      %species = ('SO2         -> ' => 'so2_ext_file',
                  'so4_a1      -> ' => 'so4_a1_ext_file', 
                  'so4_a2      -> ' => 'so4_a2_ext_file', # background volc emissions
                  'pom_a1      -> ' => 'pom_a1_ext_file', # only forest fire and grass fire emissions
                  'bc_a1       -> ' => 'bc_a1_ext_file',  # only forest fire and grass fire emissions
                  'num_a1      -> ' => 'num_a1_ext_file', 
                  'num_a2      -> ' => 'num_a2_ext_file', ); # background volc emissions
    }
    # for mechanisms without OCS use prescribed OCS oxidation rates for 
    # precursers of prognostic stratosphere aerosols 
    if ($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) {
	%species = (%species, 'SO2 -> ' => 'so2_ocs_ox_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_tsmlt_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',
                'so4_a1    -> ' => 'so4_a1_emis_file', 
                'so4_a2    -> ' => 'so4_a2_emis_file',
        );
    if ($chem =~ /_mam3/) {
      %species = (%species,
                'bc_a1     -> ' => 'bc_a1_emis_file',
                'pom_a1    -> ' => 'pom_a1_emis_file',
                'num_a1    -> ' => 'num_a1_emis_file', 
                'num_a2    -> ' => 'num_a2_emis_file',
	  );

    } elsif ($chem =~ /_mam4/) {
      %species = (%species,
                'bc_a4     -> ' => 'bc_a4_emis_file',
                'pom_a4    -> ' => 'pom_a4_emis_file',
                'num_a1    -> ' => 'mam4_num_a1_emis_file',
                'num_a2    -> ' => 'num_a2_emis_file',
                'num_a4    -> ' => 'mam4_num_a4_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',
        );
    if ($chem =~ /_mam3/) {
      %species = (%species,
                'pom_a1      -> ' => 'pom_a1_ext_file', 
                'bc_a1       -> ' => 'bc_a1_ext_file', 
                'num_a1      -> ' => 'num_a1_ext_file', 
                'num_a2      -> ' => 'num_a2_ext_file', 
          );

    } elsif ($chem =~ /_mam4/) {
      %species = (%species,
                'pom_a4      -> ' => 'pom_a4_ext_file', 
                'bc_a4       -> ' => 'bc_a4_ext_file', 
                'num_a1      -> ' => 'mam4_num_a1_ext_file',
                'num_a2      -> ' => 'num_a2_ext_file',
                'num_a4      -> ' => 'mam4_num_a4_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_mam4' or $chem eq 'waccm_sc_mam4') {

    my %species;

    # Surface emission datasets:
    %species = ('dms_ot_srf_file'    => 'DMS',
                'dms_bb_srf_file'    => 'DMS',
                'so2_ag_sh_file'     => 'SO2',
                'so2_an_srf_file'    => 'SO2',
                'so2_bb_srf_file'    => 'SO2',
                'so4_a1_an_srf_file' => 'so4_a1',
                'so4_a2_an_srf_file' => 'so4_a2',
                'num_a1_sh_srf_file' => 'num_a1',
                'num_a2_an_srf_file' => 'num_a2',
                'bc_a4_an_srf_file'  => 'bc_a4',
                'num_a4_bc_srf_file' => 'num_a4',
                'num_a4_oc_srf_file' => 'num_a4',
                'pom_a4_an_srf_file' => 'pom_a4',
                'soag_an_srf_file'   => 'SOAG',
                'soag_bg_srf_file'   => 'SOAG',
                'soag_bb_srf_file'   => 'SOAG',
               );
    my %verhash = ('ver'=>'cam6');
    my $first = 1;
    my $pre = "";
    my $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($id, \%verhash);
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string("$species{$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 = ('so2_cv_ext_file'    => 'SO2',
                'bc_a4_bb_ext_file'  => 'bc_a4',
                'pom_a4_bb_ext_file' => 'pom_a4',
                'so4_a1_an_ext_file' => 'so4_a1',
                'so4_a1_bb_ext_file' => 'so4_a1',
                'so4_a1_cv_ext_file' => 'so4_a1',
                'so4_a2_cv_ext_file' => 'so4_a2',
                'num_a1_an_ext_file' => 'num_a1',
                'num_a1_bb_ext_file' => 'num_a1',
                'num_a1_cv_ext_file' => 'num_a1',
                'num_a2_cv_ext_file' => 'num_a2',
                'num_bc_a4_bb_ext_file'  => 'num_a4',
                'num_pom_a4_bb_ext_file' => 'num_a4',                
               );


    # for cam6 add h2o source from methane oxidation
    if ($phys =~ /cam6/ && $chem !~ /waccm_sc/) {
	%species = (%species, 'h2o_ch4ox_ext_file' => 'H2O');
    }
    # for mechanisms without OCS use prescribed OCS oxidation rates for 
    # precursers of prognostic stratosphere aerosols 
    if ($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) {
	%species = (%species, 'so2_ocs_ox_file' => 'SO2');
    }

    $first = 1;
    $pre = "";
    $val = "";
    foreach my $id (sort keys %species) {
        my $rel_filepath = get_default_value($id, \%verhash);
        my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir);
        $val .= $pre . quote_string("$species{$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
    if ($chem eq 'waccm_sc_mam4') {
        add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2','HALONS'");
        add_default($nl, 'tracer_cnst_file',    'ver'=>'fixed_ox_halons');
        add_default($nl, 'tracer_cnst_datapath','ver'=>'fixed_ox_halons');
        unless (defined $nl->get_value('tracer_cnst_type')) {
            add_default($nl, 'tracer_cnst_type',    'ver'=>'fixed_ox_halons');
            add_default($nl, 'tracer_cnst_cycle_yr','ver'=>'fixed_ox_halons');
        }
    }
    else {
        add_default($nl, 'tracer_cnst_specifier', 'val'=>"'O3','OH','NO3','HO2'");
        add_default($nl, 'tracer_cnst_file',    'ver'=>'fixed_ox');
        add_default($nl, 'tracer_cnst_datapath','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'=>"' '");
    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);
    }
}

my $waccmx = $cfg->get('waccmx');

# WACCM options.
if ($chem =~ /waccm_ma/ 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','CFC114','CFC115','HCFC141B','HCFC142B','CH2BR2','CHBR3','H2402'";
    if ($chem =~ /waccm_ma/) {
      $val .= ",'H1202'";
    }
    if ($chem_has_ocs) {
        $val .= ",'OCS'";
    }
    if (chem_has_species($cfg, 'SF6')) {
        $val .= ",'SF6'";
    }

    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');
    }

    # Datasets
    my @files = ('flbc_file', 'efield_lflux_file', 'efield_hflux_file', 'efield_wei96_file',
                 'photon_file', 'electron_file', 'igrf_geomag_coefs_file',
                 'euvac_file', 'solar_parms_data_file',  
                 'depvel_lnd_file', 'clim_soilw_file', 'season_wes_file',
                 'xs_coef_file', 'xs_short_file','xs_long_file', 'rsf_file', 
                 'soil_erod_file' );

    if (!$waccmx) { @files = (@files, 'tgcm_ubc_file', 'snoe_ubc_file' ); }

    if ($chem =~ /_mozart/) {
        @files = (@files, 'sulf_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_ma_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 ($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.
        if (!$simple_phys) {
            add_default($nl, 'co2vmr');
            add_default($nl, 'ch4vmr');
            add_default($nl, 'n2ovmr');
            add_default($nl, 'f11vmr');
            add_default($nl, 'f12vmr');
        }
    }
}

# 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);

my $use_simple_phys = $nl->get_value('use_simple_phys');
if (defined $use_simple_phys) {
    die "CAM Namelist ERROR: User may not specify the value of use_simple_phys.\n".
        "This variable is set by build-namelist based on information\n".
        "from the configure cache file.\n";
}
$use_simple_phys = '.false.';
if ($simple_phys) {$use_simple_phys = '.true.';}
$nl->set_variable_value('phys_ctl_nl', 'use_simple_phys', $use_simple_phys);

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

if ($waccmx) {
  my $wmx_opt = $nl->get_value('waccmx_opt');
  my $ionos = $cfg->get('ionosphere');

  if (($ionos eq 'none') and ($wmx_opt =~ /ionosphere/) ) {
    die "CAM Namelist ERROR: WACCMX must be configured with an active ionosphere wmx_opt is set to ionosphere\n";
  }
  if (($ionos ne 'none') and ($wmx_opt =~ /neutral/) ) {
    die "CAM Namelist ERROR: WACCMX cannot be configured with an active ionosphere wmx_opt is set to neutral\n";
  }

  if (($ionos eq 'wxie') and ($wmx_opt =~ /ionosphere/) and ($dyn eq 'fv')) {
    # turn on electro-dynamo generated ion drift velocities 
    add_default($nl, 'ionos_xport_active', 'val'=>'.true.');
    add_default($nl, 'ionos_edyn_active', 'val'=>'.true.');
    add_default($nl, 'empirical_ion_velocities', 'val'=>'.false.');
  } elsif (($ionos eq 'wxi') and ($wmx_opt =~ /ionosphere/) and ($dyn eq 'fv')) {
    # turn off electro-dynamo generated ion drift velocities 
    add_default($nl, 'ionos_xport_active', 'val'=>'.true.');
    add_default($nl, 'ionos_edyn_active', 'val'=>'.false.');
    add_default($nl, 'empirical_ion_velocities', 'val'=>'.true.');
  } elsif (($ionos eq 'none') and ($wmx_opt =~ /neutral/)) {
    add_default($nl, 'ionos_xport_active', 'val'=>'.false.');
    add_default($nl, 'ionos_edyn_active', 'val'=>'.false.');
    add_default($nl, 'empirical_ion_velocities', 'val'=>'.true.');
  } else {
    die "CAM Namelist ERROR: Incompatible WACCMX settings \n" ;
  }
  if  ($dyn eq 'fv') {
    add_default($nl, 'fv_high_altitude', 'val'=>'.true.');
  }
  add_default($nl,'dadadj_niter');
  add_default($nl,'ionos_epotential_model');
  if ($nl->get_value('ionos_epotential_model') =~ 'weimer') {
    add_default($nl,'wei05_coefs_file');
    add_default($nl,'solar_wind_data_file');
  }
}

# Chemistry options

# EPP namelist sanity checks

(my $epp_all_file = $nl->get_value('epp_all_filepath')) =~ s/\s//g;
(my $epp_spe_file = $nl->get_value('epp_spe_filepath')) =~ s/\s//g;
(my $epp_gcr_file = $nl->get_value('epp_gcr_filepath')) =~ s/\s//g;
(my $epp_mee_file = $nl->get_value('epp_mee_filepath')) =~ s/\s//g;
(my $gcr_ion_file = $nl->get_value('gcr_ionization_filename')) =~ s/\s//g;

if (length($gcr_ion_file)>2) {
    if (length($epp_all_file)>2 or length($epp_gcr_file)>2) {
	die "CAM Namelist ERROR: Conflicting GCR inputs specified.  Variable gcr_ionization_filename".
            " is set while epp_all_filepath or epp_gcr_filepath is set.\n";
    }
}
if (length($epp_all_file)>2) {
    if (length($epp_gcr_file)>2 or length($epp_spe_file)>2 or length($epp_mee_file)>2 ) {
        die "CAM Namelist ERROR: Conflicting EPP inputs specified.  Variable epp_all_filepath".
            " is set while epp_gcr_filepath or epp_spe_filepath or epp_mee_filepath is set.\n";
    }
}

# 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";
}
$cam_chempkg = "'" . "$chem" . "'";  # add quotes to this string value

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

# Tropopause climatology
if (!$simple_phys) {
    add_default($nl, 'tropopause_climo_file');
}

# tropopause level used in gas-phase / aerosol processes
if (($chem ne 'none') and ($chem ne 'terminator')) {
    add_default($nl, 'chem_use_chemtrop');
}

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

# Radiation scheme
add_default($nl, 'radiation_scheme', 'val'=>$rad_pkg);

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

# Default for shallow convection scheme depends
# on the value of the eddy scheme.
my $eddy_scheme = $nl->get_value('eddy_scheme');
$eddy_scheme =~ s/['"]//g;  # strip quotes "'
add_default($nl, 'shallow_scheme', 'eddy_scheme'=>$eddy_scheme);

add_default($nl, 'srf_flux_avg', 'val'=>0);

# Microphysics scheme
add_default($nl, 'use_subcol_microp');
add_default($nl, 'microp_scheme');

if ($cfg->get('microphys') =~ /^mg/) {
    add_default($nl, 'micro_mg_version');
    add_default($nl, 'micro_mg_sub_version');
    add_default($nl, 'micro_mg_num_steps');
    add_default($nl, 'micro_mg_adjust_cpt');
    add_default($nl, 'nucleate_ice_subgrid');
    add_default($nl, 'nucleate_ice_subgrid_strat');
    add_default($nl, 'nucleate_ice_use_troplev');
    add_default($nl, 'cld_macmic_num_steps');
    add_default($nl, 'micro_mg_dcs');
    add_default($nl, 'micro_mg_precip_frac_method');
    add_default($nl, 'micro_mg_berg_eff_factor');
    add_default($nl, 'nucleate_ice_incloud');
    add_default($nl, 'nucleate_ice_strat');
}

    my $mg_ver = $nl->get_value('micro_mg_version');
    my $do_sb = $mg_ver >= 2 ? '.true.' : '.false.';
    add_default($nl, 'micro_do_sb_physics', 'val'=>$do_sb);

# Ice nucleation options
if (!$simple_phys) {
    add_default($nl, 'use_hetfrz_classnuc');
    add_default($nl, 'use_preexisting_ice');
    if ($chem =~ /_mam7/) {
        if ($nl->get_value('use_preexisting_ice') =~ m/$TRUE/io) {
            die "$ProgName - Error: use_preexisting_ice is not supported by MAM7 \n";
        }
    }
}

# Macrophysics scheme
add_default($nl, 'macrop_scheme');

# Sub-column switches for physics packages
# Check that a subcol_scheme is specified if use_subcol_microp is turned on (true)
my $use_subcol_microp = $nl->get_value('use_subcol_microp');
my $subcol_scheme;
if (defined $use_subcol_microp and $use_subcol_microp =~ m/$TRUE/io) {
    add_default($nl, 'subcol_scheme');
    $subcol_scheme = $nl->get_value('subcol_scheme');    
    $subcol_scheme =~ s/['"]//g; # strip quotes "' 
    if ($subcol_scheme =~ /off/) {
        die "$ProgName - Error: use_subcol_microp set to .true. but no subcol_scheme is set\n";
    }
    elsif ($subcol_scheme !~ /tstcp|SILHS|vamp|CloudObj/) {
        die "$ProgName - Error: subcol_scheme not recognized: $subcol_scheme\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');
   add_default($nl, 'subcol_tstcp_restart');
}
    
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 use_subcol_microp
if ($use_subcol_microp =~ /$TRUE/io) {
    add_default($nl, 'microp_uniform', 'val'=>'.true.');
}

# CLUBB_SGS
add_default($nl, 'do_clubb_sgs');
my $clubb_sgs = $nl->get_value('do_clubb_sgs');
if ($clubb_sgs  =~ /$TRUE/io) {
   my $clubb_do_adv = $cfg->get('clubb_do_adv');
   if($clubb_do_adv == '1') {
       add_default($nl, 'clubb_do_adv', 'val'=>'.true.');
   }
   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";
   }

   add_default($nl, 'clubb_expldiff');
   add_default($nl, 'clubb_rainevap_turb');
   add_default($nl, 'clubb_cloudtop_cooling');
   add_default($nl, 'clubb_timestep');
   add_default($nl, 'clubb_rnevap_effic');
   add_default($nl, 'clubb_stabcorrect');

   add_default($nl, 'clubb_c11');
   add_default($nl, 'clubb_c11b');
   add_default($nl, 'clubb_c14');
   add_default($nl, 'clubb_mult_coef');
   add_default($nl, 'clubb_gamma_coef');
   add_default($nl, 'clubb_c_K10');
   add_default($nl, 'clubb_c_K10h');
   add_default($nl, 'clubb_beta');
   add_default($nl, 'clubb_C2rt');
   add_default($nl, 'clubb_C2thl');
   add_default($nl, 'clubb_C2rtthl');
   add_default($nl, 'clubb_C8');
   add_default($nl, 'clubb_C7');
   add_default($nl, 'clubb_C7b');
   add_default($nl, 'clubb_lambda0_stability_coef');
   add_default($nl, 'clubb_Skw_denom_coef');
   add_default($nl, 'clubb_l_lscale_plume_centered');
   add_default($nl, 'clubb_l_use_ice_latent');
   add_default($nl, 'clubb_do_liqsupersat');
}

# 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
my $do_tms;
if (!$simple_phys) {
    add_default($nl, 'do_tms');
    $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 "$ProgName - 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');
    }
}

# Beljaars 
if (!$simple_phys) {
    add_default($nl, 'do_beljaars');
    my $do_beljaars = $nl->get_value('do_beljaars');
    if ($do_tms =~ /$TRUE/io and $do_beljaars =~ /$TRUE/io) {
        die "$ProgName - ERROR: by default, do_beljaars and do_tms cannot be set to  \n".
            "true at the same time. If you really want to set do_beljaars and do_tms \n".
            "to true at the same time, remove this check from the build-namelist.    \n";
    }
}

# Implicit Turbulent Surface Stress
if (!$simple_phys) {
    add_default($nl, 'do_iss');
}

# Convective water in radiation
if (!$simple_phys) {
    add_default($nl, 'conv_water_in_rad');
    add_default($nl, 'conv_water_frac_limit');
}

# Cloud fraction
if (!$simple_phys) {
    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');
    add_default($nl, 'cldfrc2m_rhmini');
    add_default($nl, 'cldfrc2m_rhmaxi');
    add_default($nl, 'cldfrc2m_rhminis');
    add_default($nl, 'cldfrc2m_rhmaxis');
    add_default($nl, 'cldfrc2m_do_subgrid_growth');
}

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

# condensate to rain autoconversion coefficients
if (!$simple_phys) {
    add_default($nl, 'zmconv_momcu');
    add_default($nl, 'zmconv_momcd');
    add_default($nl, 'zmconv_c0_lnd');
    add_default($nl, 'zmconv_c0_ocn');
    add_default($nl, 'zmconv_ke');
    add_default($nl, 'zmconv_ke_lnd');
    add_default($nl, 'zmconv_org');
    add_default($nl, 'zmconv_microp');
    add_default($nl, 'zmconv_num_cin');
}

# moist convection rainwater coefficients
my $shallow_scheme = $nl->get_value('shallow_scheme');
$shallow_scheme =~ s/['"]//g;            # strip quotes "' 
if ($shallow_scheme eq 'Hack') {
    add_default($nl, 'hkconv_cmftau');
    add_default($nl, 'hkconv_c0');
}

if ($shallow_scheme eq 'UW') {
  add_default($nl, 'uwshcu_rpen');
}

# cldwat ice coefficients
if ($cfg->get('microphys') eq 'rk') {
    add_default($nl, 'rk_strat_icritc');
    add_default($nl, 'rk_strat_icritw');
    add_default($nl, 'rk_strat_conke');
    add_default($nl, 'rk_strat_r3lcrit');
}

# Eddy Diffusivity Adjustments
if ($cfg->get('pbl') eq "uw" or $cfg->get('pbl') eq "spcam_m2005") {
    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');
}

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

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

    add_default($nl, 'diff_cnsrv_mass_check');
}

if ($cfg->get('microphys') eq 'rk') {
  # Cloud sedimentation
  add_default($nl, 'cldsed_ice_stokes_fac');
}

# Dust emissions tuning factor
# If dust is prognostic ==> supply the tuning factor
if ( length($nl->get_value('soil_erod_file'))>0 ) {
    # 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');
    }
}

# Seasalt emissions tuning factor
if ($chem =~ /_mam(\d)/) {
    my $ver = undef;
    if ($nl->get_value('modal_accum_coarse_exch') =~ /$TRUE/io) {
        # Check for accumulation/coarse mode exchange.
        $ver = 'strat';
    }
    elsif ($1 eq '7') {
        # Check for mam7
        $ver = 'mam7';
    }
    if (defined $ver) {
        add_default($nl, 'seasalt_emis_scale', 'ver'=>$ver);
    }
    else {
        add_default($nl, 'seasalt_emis_scale');
    }
}

# Gravity wave drag settings

# By default, orographic waves are always on
if (!$simple_phys) {
    add_default($nl, 'use_gw_oro'       , 'val'=>'.true.');
    add_default($nl, 'use_gw_rdg_beta'  , 'val'=>'.false.');
    add_default($nl, 'use_gw_rdg_gamma' , 'val'=>'.false.');
    add_default($nl, 'use_gw_front_igw' , 'val'=>'.false.');
    add_default($nl, 'use_gw_convect_sh', 'val'=>'.false.');
    add_default($nl, 'gw_lndscl_sgh');
    add_default($nl, 'gw_oro_south_fac');
    add_default($nl, 'gw_limit_tau_without_eff');
    add_default($nl, 'gw_apply_tndmax');

    # Gravity wave ridge settings
    # By default, gw_rdg_do_divstream is set to true
    add_default($nl, 'gw_rdg_do_divstream'       , 'val'=>'.true.');
}

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_front'     , 'val'=>'.true.');
    add_default($nl, 'use_gw_convect_dp', 'val'=>'.true.');
    my $hdepth_scaling = '0.25D0' ;
    if ($nl->get_value('qbo_use_forcing') =~ /$TRUE/io or $nl->get_value('met_data_file')) {
       $hdepth_scaling = '1.D0' ;
       add_default($nl, 'qbo_cyclic','val'=>'.true.');
       add_default($nl, 'qbo_forcing_file');
    }
    add_default($nl, 'gw_qbo_hdepth_scaling', 'val'=>$hdepth_scaling);
} else {
    add_default($nl, 'use_gw_front'     , 'val'=>'.false.');
    add_default($nl, 'use_gw_convect_dp', 'val'=>'.false.');
}

# We need a lot of logic to use these below, so make flags for them.
my $do_gw_oro        = ($nl->get_value('use_gw_oro')        =~ /$TRUE/io);
my $do_gw_front      = ($nl->get_value('use_gw_front')      =~ /$TRUE/io);
my $do_gw_front_igw  = ($nl->get_value('use_gw_front_igw')  =~ /$TRUE/io);
my $do_gw_convect_dp = ($nl->get_value('use_gw_convect_dp') =~ /$TRUE/io);
my $do_gw_convect_sh = ($nl->get_value('use_gw_convect_sh') =~ /$TRUE/io);
my $do_gw_rdg_beta   = ($nl->get_value('use_gw_rdg_beta')   =~ /$TRUE/io);
my $do_gw_rdg_gamma  = ($nl->get_value('use_gw_rdg_gamma')  =~ /$TRUE/io);

my $do_divstream        = ($nl->get_value('gw_rdg_do_divstream')  =~ /$TRUE/io);

if (!$simple_phys) {
    # GW option used only for backwards compatibility with CAM3.
    add_default($nl, 'fcrit2', 'val'=>'1.0');
}
# Mid-scale wavelength settings.
if ($do_gw_front or $do_gw_convect_dp or $do_gw_convect_sh) {
    add_default($nl, 'pgwv', 'val'=>'32');
    add_default($nl, 'gw_dc','val'=>'2.5D0');
} elsif (!$simple_phys) {
    add_default($nl, 'pgwv', 'val'=>'0');
    add_default($nl, 'gw_dc','val'=>'0.D0');
}

# Long wavelength settings (for IGWs).
if ($do_gw_front_igw) {
    add_default($nl, 'pgwv_long', 'val'=>'10');
    add_default($nl, 'gw_dc_long', 'val'=>'2.0D0');
} elsif (!$simple_phys) {
    add_default($nl, 'pgwv_long', 'val'=>'0');
    add_default($nl, 'gw_dc_long','val'=>'0.D0');
}

if ($do_gw_oro) {
    add_default($nl, 'effgw_oro');
}

if ($do_gw_front) {
    add_default($nl, 'effgw_cm');
    add_default($nl, 'taubgnd');
    add_default($nl, 'gw_polar_taper');
}

if ($do_gw_front_igw) {
    add_default($nl, 'effgw_cm_igw');
    add_default($nl, 'taubgnd_igw');
}

if ($do_gw_front or $do_gw_front_igw) {
    add_default($nl, 'frontgfc');
}

if ($do_gw_convect_dp) {
    add_default($nl, 'gw_drag_file');
    add_default($nl, 'effgw_beres_dp');
}

if ($do_gw_convect_sh) {
    add_default($nl, 'gw_drag_file_sh');
    add_default($nl, 'effgw_beres_sh');
}

if ($do_gw_rdg_beta) {
    add_default($nl, 'n_rdg_beta',          'val'=>'10');
    add_default($nl, 'effgw_rdg_beta',      'val'=>'1.0D0');
    add_default($nl, 'effgw_rdg_beta_max',  'val'=>'1.0D0');
    add_default($nl, 'trpd_leewv_rdg_beta', 'val'=>'.false.');
    add_default($nl, 'rdg_beta_cd_llb',     'val'=>'1.0D0');
}

if ($do_gw_rdg_beta) {
    add_default($nl, 'gw_prndl',      'val'=>'0.5D0');  
} elsif (!$simple_phys) {
    add_default($nl, 'gw_prndl');
}

if ($do_gw_rdg_gamma) {
    add_default($nl, 'n_rdg_gamma',           'val'=>'-1');
    add_default($nl, 'effgw_rdg_gamma',       'val'=>'1.0D0');
    add_default($nl, 'effgw_rdg_gamma_max',   'val'=>'1.0D0');
    add_default($nl, 'trpd_leewv_rdg_gamma',  'val'=>'.true.');
    add_default($nl, 'rdg_gamma_cd_llb',      'val'=>'1.0D0');
    add_default($nl, 'bnd_rdggm');
}

if (($do_gw_rdg_beta or $do_gw_rdg_gamma) and $do_gw_oro) {
    die "$ProgName - ERROR: both orographic wave and ridge scheme are on. \n" ;
    "Turn off one of them.\n";
}

if (($do_gw_rdg_beta or $do_gw_rdg_gamma)) {
   if ($do_divstream) {
       add_default($nl, 'gw_rdg_FR_c',               'val'=>'1.0D0');
       add_default($nl, 'gw_rdg_do_backward_compat', 'val'=>'.false.');
   } else {
       add_default($nl, 'gw_rdg_FR_c',               'val'=>'0.7D0');
       add_default($nl, 'gw_rdg_do_backward_compat', 'val'=>'.true.');
   }

   add_default($nl, 'gw_rdg_do_smooth_regimes');
   add_default($nl, 'gw_rdg_do_adjust_tauoro');
   add_default($nl, 'gw_rdg_C_BetaMax_DS');
   add_default($nl, 'gw_rdg_C_GammaMax');
   add_default($nl, 'gw_rdg_Frx0');
   add_default($nl, 'gw_rdg_Frx1');
   add_default($nl, 'gw_rdg_C_BetaMax_SM');
   add_default($nl, 'gw_rdg_orohmin');
   add_default($nl, 'gw_rdg_orovmin');
   add_default($nl, 'gw_rdg_orostratmin');
   add_default($nl, 'gw_rdg_orom2min');
}

# 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
    ($do_gw_front or $do_gw_front_igw or
     $do_gw_convect_dp or $do_gw_convect_sh)) {
    add_default($nl, 'tau_0_ubc', 'val'=>'.true.');
} elsif (!$simple_phys) {
    add_default($nl, 'tau_0_ubc', 'val'=>'.false.');
}

# FV dycore
if ($dyn eq 'fv') {
    add_default($nl, 'fv_fft_flt');
    add_default($nl, 'fv_div24del2flag');
    add_default($nl, 'fv_del2coef');
    add_default($nl, 'fv_filtcw');
    add_default($nl, 'fv_nspltvrm');
    if ($waccm_phys) {
        add_default($nl, 'fv_nsplit');
        add_default($nl, 'fv_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 ($dyn eq 'eul') {
    add_default($nl, 'eul_dif2_coef');
    add_default($nl, 'eul_hdif_order');
    add_default($nl, 'eul_hdif_kmnhdn');
    add_default($nl, 'eul_hdif_coef');
    add_default($nl, 'eul_divdampn');
    add_default($nl, 'eul_tfilt_eps');
    add_default($nl, 'eul_kmxhdc');
    add_default($nl, 'eul_nsplit');
}

# SLD dycore
if ($dyn eq 'sld') {
    add_default($nl, 'sld_dif2_coef');
    add_default($nl, 'sld_dif4_coef');
    add_default($nl, 'sld_divdampn');
    add_default($nl, 'sld_tfilt_eps');
    add_default($nl, 'sld_kmxhdc');
}

# 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 ($dyn =~ /se/) {

    ####################################################
    # namelist group: dyn_se_inparm (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_ftype se_hypervis_order se_hypervis_subcycle
                  se_hypervis_subcycle_q se_limiter_option se_ne se_nsplit
                  se_nu se_nu_div se_nu_p se_nu_q se_nu_top se_qsplit se_rsplit
                  se_statefreq  se_tstep_type se_vert_remap_q_alg);
    my %opts = ( $opts{'nofail'} => 1 );

    # Do we need special refined mesh processing?
    add_default($nl, 'se_refined_mesh');
    my $refined_mesh = $nl->get_value('se_refined_mesh');
    if ($refined_mesh =~ m/$TRUE/i) {
        $opts{'refined_mesh'} = "1";
        my $se_mesh_file = $nl->get_value('se_mesh_file');
        if (!defined $se_mesh_file or ($refined_mesh =~ m/none/i) or ((length $refined_mesh) == 0)) {
            # "none" isn't really a valid mesh_file entry but it is in HOMME
            die "$ProgName - ERROR: se_mesh_file is required for a refined mesh run\n";
        }
        # We are in a refined mesh situation, set appropriate defaults
        $nl->set_variable_value('dyn_se_inparm', 'se_ne', 0);
        add_default($nl, 'se_hypervis_power');
        my $hypervis_power = $nl->get_value('se_hypervis_power');
        if ($hypervis_power == 0) {
            # Configure default tensor hyperviscosity
            $opts{'hypervis_type'} = 'tensor';
            push @vars, 'se_hypervis_scaling';
        }
        else {
            # Configure scalar hyperviscosity
            $opts{'hypervis_type'} = 'scalar';
            if ($hypervis_power != 3.322) { 
                # This is unsupported territory, allow chaos to reign
                print "$ProgName - WARNING: Unsupported value for hypervis_power, assuming scalar hyperviscosity\n";
            }
            push @vars, 'se_fine_ne';
            push @vars, 'se_max_hypervis_courant';
        }
    }
    # Add the collected vars
    foreach my $var (@vars) {
        add_default($nl, $var, %opts);
    }
}

# 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_chemspecies_srf');
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');
    }
}
# Check incompatible history options
my $interpolate_output = $nl->get_value('interpolate_output');
my @interp_output = split /,/, $interpolate_output;
for my $i (0 .. $#interp_output) {
  if ($interp_output[$i] =~ /$TRUE/io) {
    # Currently, interpolated output is only supported for the SE dycore
    if ( ! ($dyn =~ /se/) ) {
      die "$ProgName - ERROR: interpolate_output is not supported for $dyn dycore";
    }
    # Currently, interpolated output is incompatible with regional output
    my $region = $nl->get_value('fincl${i}lonlat');
    if (defined $region) {
      die "$ProgName - ERROR: interpolate_output is currently incompatible with regional output (e.g., fincl${i}lonlat)";
    }
  }
}

my $offline_drv = $cfg->get('offline_drv');
if ($offline_drv ne 'stub') {

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

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

if ($phys eq 'spcam_sam1mom' or $phys eq 'spcam_m2005') {
    add_default($nl, 'iradsw', 'val'=>'1');
    add_default($nl, 'iradlw', 'val'=>'1');
}

#-----------------------------------------------------------------------------------------------
# Add defaults for the ocean component.

# Which ocean model?
my $ocn_comp = $cfg->get('ocn');

# The aquaplanet namelist is written for both standalone and cesm runs.  Even though
# 'aquaplanet' is called an ocean component, it is implemented by CAM.
if ($ocn_comp eq 'aquaplanet') {
    add_default($nl, 'aqua_planet_sst', 'val'=>'1');
}

# 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 the ocean and sea ice components.
my $bndtvs = '';
my $bndtvs_domain = '';
my $focndomain = '';

# Namelist settings for CAMDOM or DOCN
if ($cam_build and  ($ocn_comp =~ /docn|dom|som/)) {

    # 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 or DOCN and CICE.
    add_default($nl, 'focndomain');
    $focndomain = $nl->get_value('focndomain');

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

}

# Create docn namelists and stream txt file

if ($cam_build and  ($ocn_comp =~ /docn|som/)) {

    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=$focndomain_file;
    my $fsstdomain_path=$focndomain_path;
    if ($ocn_comp eq 'som') {
        $fsstdomain_file=$sstdata_file;
        $fsstdomain_path=$sstdata_path;
    }

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

    # add docn variables
    # ------------------

    add_default($nl, 'decomp', 'val'=>'1d');
    if ($ocn_comp eq 'som') {
        add_default($nl, 'force_prognostic_true', 'val'=>'.false.');
    }

    my $datamode = 'SSTDATA';
    if ($ocn_comp eq 'som') { $datamode = 'SOM';}
    add_default($nl, 'dataMode', 'val'=>$datamode);

    add_default($nl, 'domainFile', 'val'=>$focndomain);

    my $ocn_str = "docn.stream.txt $stream_year_first $stream_year_first $stream_year_last" ;
    add_default($nl, 'streams',    'val'=> $ocn_str);

    if ($ocn_comp eq 'docn') {
        add_default($nl, 'vectors',    'val'=>'null');
    }
    elsif ($ocn_comp eq 'som') {
        add_default($nl, 'fillalgo',    'val'=>'nn');
        add_default($nl, 'fillmask',    'val'=>'nomask');
        add_default($nl, 'mapalgo',     'val'=>'bilinear');
        add_default($nl, 'mapmask',     'val'=>'dstmask');
        add_default($nl, 'taxmode',     'val'=>'cycle');
        add_default($nl, 'tintalgo',    'val'=>'linear');
    }

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

    my $datasource = 'DATASET';
    if ($ocn_comp eq 'som') { $datasource = 'GENERIC';}


    print $fh  <<"EOF";
<streamstemplate>
<stream>
      <dataSource>
         $datasource
      </dataSource>
      <domainInfo> 
         <variableNames>
            time    time
            xc      lon
            yc      lat
            area    area
            mask    mask
         </variableNames>
         <filePath>
            $fsstdomain_path
         </filePath>
         <fileNames>
            $fsstdomain_file
         </fileNames>
      </domainInfo>
EOF
    if ($ocn_comp eq 'docn') {
    print $fh  <<"EOF";
      <fieldInfo>
         <variableNames>
            SST_cpl    t
         </variableNames>
         <filePath>
            $sstdata_path
         </filePath>
         <fileNames>
            $sstdata_file
         </fileNames>
      </fieldInfo>
</stream>
</streamstemplate>
EOF
    }
    elsif ($ocn_comp eq 'som') {
    print $fh  <<"EOF";
      <fieldInfo>
         <variableNames>
            T     t
            S     s
            U     u
            V     v
            dhdx  dhdx
            dhdy  dhdy
            hblt  h
            qdp   qbot
         </variableNames>
         <filePath>
            $sstdata_path
         </filePath>
         <fileNames>
            $sstdata_file
         </fileNames>
         <offset>
            0
         </offset>
      </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();

# Temp vars reused for each component.
my @comp_groups;
my $outfile;

# 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.  

# Driver
@comp_groups = qw(cime_driver_inst 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 fire_emis_nl carma_inparm ndep_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 (dom, docn, or aquaplanet)
if ($ocn_comp eq 'dom') {
    @comp_groups = qw(dom_inparm);
    $outfile = "$opts{'dir'}/ocn_in";
}
elsif ($ocn_comp eq 'docn' or $ocn_comp eq 'som') {
    @comp_groups = qw(docn_nml shr_strdata_nml);
    $outfile = "$opts{'dir'}/docn_in";
}
elsif ($ocn_comp eq 'aquaplanet') {
    @comp_groups = qw(aquap_nl);
    add_default($nl, 'aqua_planet_sst', 'val'=>'1');
    $outfile = "$opts{'dir'}/aquap_in";
}
if (@comp_groups) {
    $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);
    my $aero_modes = "${nmodes}mode";

    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 %aero_modes_hash = ('mam'=>$aero_modes); 
           (my $constituent = $spec_name) =~ s/_.*//;
            $constituent = substr( $constituent, 0, 3 );
            my $rel_filepath = get_default_value("mam_${constituent}",\%aero_modes_hash);
            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);

    # die if bad input
    if ($ntasks < 1) {
        die "$ProgName - ERROR: fv_decomp_set: bad input: ntasks=$ntasks.\n" .
            "  -ntask argument to build-namelist is wrong.";
    }

    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;

                    # look for coefficient multiplier proceeding the filepath in the form ' X * filepath '
                    if ($file  =~ m/\s*(\w+)      # coeffecient preceded by optional whitespace
                                    \s*\*\s*      # '*' separator surrounded by optional whitespace
                                    (\S+)         # filepath (all characters up to optional whitespace)
                                    /xo) {
                        my $coef = $1;
                        $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;
        }
    }

}

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