#!/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 < Specify the number of MPI tasks being used by the run. This is used to set a default decomposition for the FV dycore only (npr_yz). -runtype "type" Type of simulation (startup, continue, or branch) -silent [-s] Turns on silent mode - only fatal messages issued. -test Enable checking that input datasets exist on local filesystem. -use_case Specify a use case. Default: present day climatology -verbose [or -v] Turn on verbose echoing of informational messages. -version Echo the CVS tag name used to check out this CAM distribution. Note: The precedence for setting the values of namelist variables is (highest to lowest): 1. namelist values set by specific command-line options, i.e., -case, -runtype 2. values set on the command-line using the -namelist option, 3. values read from the file specified by -infile, 4. values specified by the -use_case option, 5. values from the namelist defaults file. EOF } #----------------------------------------------------------------------------------------------- # Set the directory that contains the CAM configuration scripts. If the command was # issued using a relative or absolute path, that path is in $ProgDir. Otherwise assume the # command was issued from the current working directory. (my $ProgName = $0) =~ s!(.*)/!!; # name of this script $ProgName = "CAM $ProgName"; # Since multiple components are now using a build-namelist # utility add "CAM" qualifier to the name. This helps when # looking at error output from the whole CCSM system. my $ProgDir = $1; # name of directory containing this script -- may be a # relative or absolute path, or null if the script is in # the user's PATH my $cwd = getcwd(); # current working directory my $cfgdir; # absolute pathname of directory that contains this script if ($ProgDir) { $cfgdir = absolute_path($ProgDir); } else { $cfgdir = $cwd; } # CAM root directory. my $cam_root = absolute_path("$cfgdir/../../.."); my $cfg_cache = "config_cache.xml"; # Default name of configuration cache file my $outdirname = "."; # Default name of output directory name #----------------------------------------------------------------------------------------------- # Save commandline my $commandline = "$cfgdir/build-namelist @ARGV"; #----------------------------------------------------------------------------------------------- # Process command-line options. my %opts = ( config => $cfg_cache, csmdata => undef, help => 0, dir => $outdirname, silent => 0, test => 0, ); GetOptions( "case=s" => \$opts{'case'}, "cice_nl=s" => \$opts{'cice_nl'}, "config=s" => \$opts{'config'}, "config_cice=s" => \$opts{'config_cice'}, "csmdata=s" => \$opts{'csmdata'}, "d|dir=s" => \$opts{'dir'}, "h|help" => \$opts{'help'}, "ignore_ic_date" => \$opts{'ignore_ic_date'}, "ignore_ic_year" => \$opts{'ignore_ic_year'}, "infile=s" => \$opts{'infile'}, "inputdata=s" => \$opts{'inputdata'}, "namelist=s" => \$opts{'namelist'}, "ntasks=s" => \$opts{'ntasks'}, "runtype=s" => \$opts{'runtype'}, "s|silent" => \$opts{'silent'}, "test" => \$opts{'test'}, "uc|use_case=s" => \$opts{'use_case'}, "v|verbose" => \$opts{'verbose'}, "version" => \$opts{'version'}, ) or usage(); # Give usage message. usage() if $opts{'help'}; # Echo version info. if ($opts{'version'}) { version($cfgdir); exit; } # Check for unparsed arguments if (@ARGV) { print "ERROR: unrecognized arguments: @ARGV\n"; usage(); } # Define print levels: # 0 - only issue fatal error messages # 1 - only informs what files are created (default) # 2 - verbose my $print = 1; if ($opts{'silent'}) { $print = 0; } if ($opts{'verbose'}) { $print = 2; } my $eol = "\n"; if ($print>=2) { print "Setting CAM configuration script directory to $cfgdir$eol"; } if ($print>=2) { print "build-namelist was invoked with the commandline:\n $commandline$eol"; } # Check that configuration cache file exists. (-f $opts{'config'}) or die <<"EOF"; ** $ProgName - ERROR: Cannot find configuration cache file: \"$opts{'config'}\" ** EOF if ($print>=2) { print "Using CAM configuration cache file $opts{'config'}$eol"; } # Check that the CCSM inputdata root directory has been specified. my $inputdata_rootdir = undef; if (defined($opts{'csmdata'})) { $inputdata_rootdir = $opts{'csmdata'}; } elsif (defined $ENV{'CSMDATA'}) { $inputdata_rootdir = $ENV{'CSMDATA'}; } else { die "$ProgName - ERROR: CCSM inputdata root directory must be specified by either -csmdata argument\n" . " or by the CSMDATA environment variable. :"; } if ($print>=2) { print "CCSM inputdata root directory: $inputdata_rootdir$eol"; } # If the -test option is specified, then the inputdata root directory must be local or nfs mounted. if ($opts{'test'}) { (-d $inputdata_rootdir) or die <<"EOF"; ** $ProgName - ERROR: CCSM inputdata root is not a directory: \"$inputdata_rootdir\" ** EOF } #----------------------------------------------------------------------------------------------- # Make sure we can find required perl modules, definition, and defaults files. # Look for them under the directory that contains the configure script. # The XML::Lite module is required to parse the XML files. (-f "$cfgdir/perl5lib/XML/Lite.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"XML/Lite.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::Config module provides utilities to access the configuration information # in the config_cache.xml file (-f "$cfgdir/perl5lib/Build/Config.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/Config.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::NamelistDefinition module provides utilities to validate that the output # namelists are consistent with the namelist definition file (-f "$cfgdir/perl5lib/Build/NamelistDefinition.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/NamelistDefinition.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::NamelistDefaults module provides a utility to obtain default values of namelist # variables based on finding a best fit with the attributes specified in the defaults file. (-f "$cfgdir/perl5lib/Build/NamelistDefaults.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/NamelistDefaults.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::Namelist module provides utilities to parse input namelists, to query and modify # namelists, and to write output namelists. (-f "$cfgdir/perl5lib/Build/Namelist.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/Namelist.pm\" in directory \"$cfgdir/perl5lib\" ** EOF #----------------------------------------------------------------------------------------------- # Add $cfgdir/perl5lib to the list of paths that Perl searches for modules unshift @INC, "$cfgdir/perl5lib"; require XML::Lite; require Build::Config; require Build::NamelistDefinition; require Build::NamelistDefaults; require Build::Namelist; #----------------------------------------------------------------------------------------------- # Create a configuration object from CAM's config_cache.xml file. This object contains # all the build-time specifications of the CAM executable. my $cfg = Build::Config->new($opts{'config'}); #----------------------------------------------------------------------------------------------- # Create a namelist definition object. This object provides a method for verifying that the # output namelist variables are in the definition file, and are output in the correct # namelist groups. Requires a namelist definition file... # # The namelist definition file contains entries for all namelist variables that # can be output by build-namelist. The version of the file that is associate with a # fixed CAM tag is $cfgdir/namelist_files/namelist_definition.xml. To aid developers # who make use of the source mods directory (via -usr_src arg to configure) we allow # the definition file to come from one of those directories. my $nl_definition_file; my @usr_src_dirs = split ',', $cfg->get('usr_src'); if (@usr_src_dirs) { foreach my $dir (@usr_src_dirs) { if (-f "$dir/namelist_definition.xml") { $nl_definition_file = "$dir/namelist_definition.xml"; last; } } } if (! defined $nl_definition_file) { # default location of namelist definition file $nl_definition_file = "$cfgdir/namelist_files/namelist_definition.xml"; (-f "$nl_definition_file") or die <<"EOF"; ** $ProgName - ERROR: Cannot find namelist definition file \"$nl_definition_file\" ** EOF } if ($print>=2) { print "Using namelist definition file $nl_definition_file$eol"; } my $definition = Build::NamelistDefinition->new($nl_definition_file); #----------------------------------------------------------------------------------------------- # Create a namelist defaults object. This object provides default values for variables # contained in the input defaults file. The configuration object provides attribute # values that are relevent for the CAM executable for which the namelist is being produced. # These attributes are used along with optional user specified attributes to find the # best match when looking for default values. # # The namelist defaults file contains default values for all required namelist variables. # Analogously to the definition file, we allow a user modified version of this file to # be present in one of the usr_src directories. my $nl_defaults_file; if (@usr_src_dirs) { foreach my $dir (@usr_src_dirs) { if (-f "$dir/namelist_defaults_cam.xml") { $nl_defaults_file = "$dir/namelist_defaults_cam.xml"; last; } } } if (! defined $nl_defaults_file) { # default location of namelist defaults file $nl_defaults_file = "$cfgdir/namelist_files/namelist_defaults_cam.xml"; (-f "$nl_defaults_file") or die <<"EOF"; ** $ProgName - ERROR: Cannot find namelist defaults file \"$nl_defaults_file\" ** EOF } if ($print>=2) { print "Using namelist defaults file $nl_defaults_file$eol"; } my $defaults = Build::NamelistDefaults->new($nl_defaults_file, $cfg); #----------------------------------------------------------------------------------------------- # Similarly to the namelist definition and defaults files, the use case file # may also come from the usr_src directories. Determine the location of the # use case file. my $use_case_file; if (defined $opts{'use_case'}) { if (@usr_src_dirs) { foreach my $dir (@usr_src_dirs) { if (-f "$dir/$opts{'use_case'}.xml") { $use_case_file = "$dir/$opts{'use_case'}.xml"; last; } } } if (! defined $use_case_file) { # default location of namelist use case files $opts{'use_case_dir'} = "$cfgdir/namelist_files/use_cases"; validate_use_case("commandline", \%opts); $use_case_file = "$opts{'use_case_dir'}/$opts{'use_case'}.xml"; } if ($print>=2) { print "Using namelist use case file $use_case_file$eol"; } } #----------------------------------------------------------------------------------------------- # Create an empty namelist object. Add values to it in order of precedence. my $nl = Build::Namelist->new(); #----------------------------------------------------------------------------------------------- # Some regular expressions... # **N.B.** the use of qr// for precompiling regexps isn't supported until perl 5.005. my $TRUE = "\.true\."; my $FALSE = "\.false\."; #----------------------------------------------------------------------------------------------- # Process the user input in order of precedence. At each point we'll only add new # values to the namelist and not overwrite previously specified specified values which # have higher precedence. # Process the commandline args that provide specific namelist values. # Case name if (defined $opts{'case'}) { add_default($nl, 'case_name', 'val'=>$opts{'case'}); } # Run type if (defined $opts{'runtype'}) { add_default($nl, 'start_type', 'val'=>$opts{'runtype'}); } # Process the -namelist arg. if (defined $opts{'namelist'}) { # Parse commandline namelist my $nl_arg = Build::Namelist->new($opts{'namelist'}); # Validate input namelist -- trap exceptions my $nl_arg_valid; eval { $nl_arg_valid = $definition->validate($nl_arg); }; if ($@) { die "$ProgName - ERROR: Invalid namelist variable in commandline arg '-namelist'.\n $@"; } # Merge input values into namelist. Previously specified values have higher precedence # and are not overwritten. $nl->merge_nl($nl_arg_valid); } # Process the -infile arg. if (defined $opts{'infile'}) { # Parse namelist input from a file my $nl_infile = Build::Namelist->new($opts{'infile'}); # Validate input namelist -- trap exceptions my $nl_infile_valid; eval { $nl_infile_valid = $definition->validate($nl_infile); }; if ($@) { die "$ProgName - ERROR: Invalid namelist variable in '-infile' $opts{'infile'}.\n $@"; } # Merge input values into namelist. Previously specified values have higher precedence # and are not overwritten. $nl->merge_nl($nl_infile_valid); } # Process the -use_case arg. # Declare global symbol $uc_defaults even if it's not defined, because we check whether it's # defined before using it in the get_default_value method below. my $uc_defaults; if (defined $use_case_file) { # The use case definition is contained in an xml file with the same format as the defaults file. # Create a new NamelistDefaults object. $uc_defaults = Build::NamelistDefaults->new($use_case_file, $cfg); # Loop over the variables specified in the use case. # A defaults file may contain information for variables that are not namelist variables. # Check each name in the defaults file, and add each namelist variable to the namelist. my @vars = $uc_defaults->get_variable_names(); VAR: foreach my $var (@vars) { # Query the definition to find which group the variable belongs to. Skip if not found. my $group = $definition->get_group_name($var); if ($group) { # Get the value of $var from the use case defaults my $val = $uc_defaults->get_value($var); if (defined $val) { add_default($nl, $var, 'val'=>$val); } # If the use case doesn't provide a default value, then just ignore. This allows the # use case mechanism to provide defaults for some attributes (e.g. a specific grid), and # not for others. } } } #----------------------------------------------------------------------------------------------- # Add default values for required namelist variables that have not been previously set. # This is done either by using the namelist default object, or directly with inline logic. # Are we building namelists for the 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: seq_cplflds_inparm # ###################################### add_default($nl, 'flds_co2_dmsa', 'val'=>'.false.'); add_default($nl, 'flds_co2a', 'val'=>'.true.'); add_default($nl, 'flds_co2b', 'val'=>'.false.'); add_default($nl, 'flds_co2c', 'val'=>'.false.'); add_default($nl, 'cplflds_custom', 'val'=>''); ############################ # namelist group: ccsm_pes # ############################ # By default the driver sets all components to use all tasks. This is the # appropriate default for the standalone CAM configuration. # By default the driver sets all components to use 1 thread. This should be # reset either to user specified values, or by default use the OMP_NUM_THREADS # environment variable or the nthreads configuration parameter to set the thread # count for each component. # Is this an smp build? my $smp = $cfg->get('smp'); if ($smp) { # If user has set the specific variables for component threads on the commandline # those values will be used. If not, the highest precedence will be given the the # value of the environment variable OMP_NUM_THREADS. That is because the number of # threads specified on the configure commandline is used to determine an appropriate # decomposition for the CICE model, but that decomposition may be valid for a range # of ntask/nthread settings. # Check for OMP_NUM_THREADS my $nthreads; if (defined $ENV{'OMP_NUM_THREADS'}) { $nthreads = $ENV{'OMP_NUM_THREADS'}; } # Has the number of threads been set by configure elsif (defined $cfg->get('nthreads')) { $nthreads = $cfg->get('nthreads'); } if ($nthreads) { add_default($nl, 'atm_nthreads', 'val'=>$nthreads); add_default($nl, 'cpl_nthreads', 'val'=>$nthreads); add_default($nl, 'ice_nthreads', 'val'=>$nthreads); add_default($nl, 'lnd_nthreads', 'val'=>$nthreads); add_default($nl, 'ocn_nthreads', 'val'=>$nthreads); add_default($nl, 'rof_nthreads', 'val'=>$nthreads); } } ####################################### # namelist group: seq_infodata_inparm # ####################################### my $phys_mode_flags = 0; my $adia_mode = 0; my $aqua_mode = 0; # Case name add_default($nl, 'case_name'); # Run type add_default($nl, 'start_type'); # 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');} # Adiabatic or Ideal physics my $phys = $cfg->get('phys'); if ($phys eq 'ideal') { my $analytic_ic = $cfg->get('analytic_ic'); if ($analytic_ic) { add_default($nl, 'analytic_ic_type', 'val'=>'held_suarez_1994'); } } # 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, adiabatic, or # aqua-planet modes is being used. my $ideal_or_adia_or_aqua = 0; if ($phys_mode_flags == 1) { $ideal_or_adia_or_aqua = 1; } # If the physics mode is one of adiabatic, ideal, or aqua_planet, then the # land, rof, and sea ice components are inactive (whether the executable was configured # with them or not). my $lnd_active = 1; my $rof_active = 1; my $ice_active = 1; if ($ideal_or_adia_or_aqua) { $lnd_active = 0; $rof_active = 0; $ice_active = 0; } # Note that the prescribed SSTs # used by aqua-planet mode are implemented in the cam_aqua component.) # Single column mode my $scam = $cfg->get('scam'); if ($scam) { add_default($nl, 'single_column', 'val'=>'.true.'); my $scmlat = $nl->get_value('scmlat'); my $scmlon = $nl->get_value('scmlon'); unless (defined $scmlat and defined $scmlon) { die "$ProgName - ERROR: In SCAM mode both scmlat and scmlon namelist variables must be set. \n"; } } ###################################### # namelist group: seq_timemgr_inparm # ###################################### # Length of simulation add_default($nl, 'stop_option'); unless (defined $nl->get_value('stop_ymd')) { add_default($nl, 'stop_n'); } # Restart interval add_default($nl, 'restart_option'); # Start date # The following check should be done for CAM standalone builds only. if ($cam_build) { # When the user specifies ncdata there is no default for start_ymd since there is # no way to determine the corresponding date of the ncdata file. So only add # a default for start_ymd if the user has not specified ncdata. if (defined $nl->get_value('ncdata')) { unless (defined $nl->get_value('start_ymd')) { die "$ProgName - ERROR: It is not allowed to set ncdata without also setting start_ymd. \n"; } } else { add_default($nl, 'start_ymd'); } } # Orbit (if not coupled) # If orbital parameters have not been specified then check for orbit year. # If orbit year has not been specified, then set a default value. if ($cam_build) { if (not defined $nl->get_value('orb_obliq') or not defined $nl->get_value('orb_eccen') or not defined $nl->get_value('orb_mvelp') ) { if (not defined $nl->get_value('orb_iyear')) { add_default($nl, 'orb_iyear'); } } } add_default($nl, '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; # assume prescribed aerosols are needed # 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 ); } } # 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); # # 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); } # Tropopause climatology add_default($nl, 'tropopause_climo_file'); # Radiation my $rad_pkg = $cfg->get('rad'); if ($rad_pkg eq 'camrt') { # Only needed for CAM3/4 RT code # Absorptivity and emissivity data add_default($nl, 'absems_data'); } # Solar irradiance # First check that solar_const and solar_data_file are not both defined if (defined $nl->get_value('solar_const') and defined $nl->get_value('solar_data_file')) { print "$ProgName - WARNING: It is not allowed to set both solar_const \n". " and solar_data_file. solar_const will be ignored. \n"; if ($nl->delete_variable('solar_inparm', 'solar_const') != 0) { die "$ProgName - ERROR: not able to delete solar_const from group solar_inparm.\n" } } if ($rad_pkg eq 'rrtmg' or $chem =~ /waccm/) { if (defined $nl->get_value('solar_const')) { die "$ProgName - ERROR: Specifying solar_const with RRTMG or WACCM is not allowed.\n" } # use solar data file as the default for rrtmg and waccm_ma add_default($nl, 'solar_data_file'); add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.true.'); } else { if ($chem eq 'none' and !($prog_species =~ /SO4/) ) { # Spectral solar data is needed for photolysis # this preserves the default cam3 and cam4 configurations which do not have chemistry unless (defined $nl->get_value('solar_data_file')) { add_default($nl, 'solar_const'); } } else { # use solar data file as the default for all chem conifigurations unless (defined $nl->get_value('solar_const')) { add_default($nl, 'solar_data_file'); } } add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.false.'); } # COSP simulator if ($cfg->get('cosp')) { add_default($nl, 'docosp', 'val'=>'.true.'); } # Constituents # ============ # Carbon cycle constituents my $co2_cycle = $cfg->get('co2_cycle'); if ($co2_cycle) { # co2_flag turns on the co2_cycle code in CAM add_default($nl, 'co2_flag', 'val'=>'.true.'); # Supply a fossil fuel dataset if the co2_cycle is active and it's a # transient run ... if ($sim_year =~ /(\d+)-(\d+)/) { add_default($nl, 'co2_readflux_fuel', 'val'=>'.true.'); # Check whether user has explicitly turned off reading the fossil fuel dataset. # (user specification has higher precedence than the true value set above) if ($nl->get_value('co2_readflux_fuel') =~ /$TRUE/io) { add_default($nl, 'co2flux_fuel_file', 'sim_year'=>$sim_year); } } } # By default the prognostic co2_cycle CO2 will be radiative active, unless the # the user sets this override variable. This is used below to construct the # rad_climate variable. my $co2_cycle_rad_passive = ($nl->get_value('co2_cycle_rad_passive') =~ /$TRUE/io); # Set number of test tracers requested via -nadv_tt option to configure add_default($nl, 'test_tracer_num', 'val'=>$cfg->get('nadv_tt')); 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'"; unless (defined $nl->get_value('prescribed_ozone_file')) { add_default($nl, 'prescribed_ozone_datapath'); add_default($nl, 'prescribed_ozone_file'); add_default($nl, 'prescribed_ozone_name'); add_default($nl, 'prescribed_ozone_type'); add_default($nl, 'prescribed_ozone_cycle_yr'); } } elsif ($cam3_ozone_data =~ /$TRUE/io) { $radval .= ",'N:O3:O3'"; } else { die "ERROR: can not set ozone rad_climate specification\n"; } if (($chem =~ /super_fast_llnl/) and !$chem_rad_passive ) { $radval .= ",'N:N2O:N2O','N:prsd_ch4:CH4','N:CFC11:CFC11','N:CFC12:CFC12'"; } elsif ((($chem =~ /waccm_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 physics # package is adiabatic or ideal. if ($phys =~ /cam5/) { $prescribed_aero_model = 'modal'; } elsif ($phys eq 'cam4' or $phys eq 'cam3' or $phys eq 'spcam_sam1mom') { $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 cam5.4 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. add_default($nl, 'carma_model', 'val'=>$carma); if ($carma ne 'none') { add_default($nl, 'carma_flag', 'val'=>'.true.'); } if ($carma eq 'bc_strat') { add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_emission', 'val'=>'.false.'); add_default($nl, 'carma_do_vdiff', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_do_wetdep', 'val'=>'.true.'); } if ($carma eq 'cirrus') { add_default($nl, 'carma_do_cldice', 'val'=>'.true.'); add_default($nl, 'carma_do_aerosol', 'val'=>'.false.'); add_default($nl, 'carma_do_cldliq', 'val'=>'.false.'); add_default($nl, 'carma_do_clearsky', 'val'=>'.false.'); add_default($nl, 'carma_do_coag', 'val'=>'.true.'); add_default($nl, 'carma_do_detrain', 'val'=>'.true.'); add_default($nl, 'carma_do_fixedinit','val'=>'.true.'); add_default($nl, 'carma_do_grow', 'val'=>'.true.'); add_default($nl, 'carma_do_incloud', 'val'=>'.true.'); add_default($nl, 'carma_do_pheat', 'val'=>'.false.'); add_default($nl, 'carma_do_optics', 'val'=>'.false.'); add_default($nl, 'carma_do_substep', 'val'=>'.true.'); add_default($nl, 'carma_do_thermo', 'val'=>'.true.'); add_default($nl, 'carma_do_vdiff', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_conmax', 'val'=>'0.25'); add_default($nl, 'carma_maxretries', 'val'=>'20'); add_default($nl, 'carma_maxsubsteps', 'val'=>'1'); add_default($nl, 'carma_dt_threshold','val'=>'2.'); add_default($nl, 'carma_gsticki', 'val'=>'0.5'); add_default($nl, 'carma_rhcrit', 'val'=>'0.7'); add_default($nl, 'wv_sat_scheme', 'val'=>'MurphyKoop'); add_default($nl, 'macro_park_do_cldice', 'val'=>'.false.'); add_default($nl, 'macro_park_do_cldliq', 'val'=>'.true.'); add_default($nl, 'macro_park_do_detrain', 'val'=>'.false.'); add_default($nl, 'micro_mg_do_cldice','val'=>'.false.'); add_default($nl, 'micro_mg_do_cldliq','val'=>'.true.'); add_default($nl, 'spectralflux', 'val'=>'.false.'); } if ($carma eq 'cirrus_dust') { add_default($nl, 'carma_do_cldice', 'val'=>'.true.'); add_default($nl, 'carma_do_aerosol', 'val'=>'.false.'); add_default($nl, 'carma_do_cldliq', 'val'=>'.false.'); add_default($nl, 'carma_do_clearsky', 'val'=>'.false.'); add_default($nl, 'carma_do_coag', 'val'=>'.true.'); add_default($nl, 'carma_do_detrain', 'val'=>'.true.'); add_default($nl, 'carma_do_drydep', 'val'=>'.false.'); add_default($nl, 'carma_do_emission', 'val'=>'.true.'); add_default($nl, 'carma_do_fixedinit','val'=>'.true.'); add_default($nl, 'carma_do_grow', 'val'=>'.true.'); add_default($nl, 'carma_do_incloud', 'val'=>'.true.'); add_default($nl, 'carma_do_pheat', 'val'=>'.false.'); add_default($nl, 'carma_do_optics', 'val'=>'.false.'); add_default($nl, 'carma_do_substep', 'val'=>'.true.'); add_default($nl, 'carma_do_thermo', 'val'=>'.true.'); add_default($nl, 'carma_do_vdiff', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_do_wetdep', 'val'=>'.true.'); add_default($nl, 'carma_conmax', 'val'=>'0.25'); add_default($nl, 'carma_maxretries', 'val'=>'20'); add_default($nl, 'carma_maxsubsteps', 'val'=>'1'); add_default($nl, 'carma_dt_threshold','val'=>'2.'); add_default($nl, 'carma_gsticki', 'val'=>'0.5'); add_default($nl, 'carma_rhcrit', 'val'=>'0.7'); add_default($nl, 'wv_sat_scheme', 'val'=>'MurphyKoop'); add_default($nl, 'macro_park_do_cldice', 'val'=>'.false.'); add_default($nl, 'macro_park_do_cldliq', 'val'=>'.true.'); add_default($nl, 'macro_park_do_detrain', 'val'=>'.false.'); add_default($nl, 'micro_mg_do_cldice','val'=>'.false.'); add_default($nl, 'micro_mg_do_cldliq','val'=>'.true.'); add_default($nl, 'spectralflux', 'val'=>'.false.'); add_default($nl, 'carma_soilerosion_file'); add_default($nl, 'carma_fields', 'val'=>'Sl_soilw'); } elsif ($carma eq 'dust') { add_default($nl, 'carma_do_emission', 'val'=>'.true.'); add_default($nl, 'carma_do_fixedinit','val'=>'.true.'); add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_optics', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_do_wetdep', 'val'=>'.true.'); add_default($nl, 'carma_soilerosion_file'); add_default($nl, 'carma_fields', 'val'=>'Sl_soilw'); } elsif ($carma eq 'meteor_impact') { add_default($nl, 'carma_do_coag', 'val'=>'.true.'); add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_emission', 'val'=>'.true.'); add_default($nl, 'carma_do_fixedinit', 'val'=>'.true.'); add_default($nl, 'carma_do_optics', 'val'=>'.true.'); add_default($nl, 'carma_do_vdiff', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_do_wetdep', 'val'=>'.true.'); add_default($nl, 'carma_emis_dust', 'val'=>'0.0'); add_default($nl, 'carma_emis_soot', 'val'=>'2.8e10'); add_default($nl, 'carma_emis_startdate', 'val'=>'1'); add_default($nl, 'carma_emis_starttime', 'val'=>'43200'); add_default($nl, 'carma_emis_stopdate', 'val'=>'2'); add_default($nl, 'carma_emis_stoptime', 'val'=>'43200'); add_default($nl, 'carma_emis_minlat', 'val'=>'-5.85'); add_default($nl, 'carma_emis_maxlat', 'val'=>'-0.15'); add_default($nl, 'carma_emis_minlon', 'val'=>'-58.75'); add_default($nl, 'carma_emis_maxlon', 'val'=>'-51.25'); add_default($nl, 'carma_fractal_soot', 'val'=>'.false.'); add_default($nl, 'irad_always', 'val'=>'-48'); } elsif ($carma eq 'meteor_smoke') { add_default($nl, 'carma_do_coag', 'val'=>'.true.'); add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_emission', 'val'=>'.true.'); add_default($nl, 'carma_do_fixedinit','val'=>'.true.'); add_default($nl, 'carma_do_vdiff', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_do_wetdep', 'val'=>'.true.'); add_default($nl, 'carma_emis_total', 'val'=>'16.0'); add_default($nl, 'carma_emis_file'); add_default($nl, 'carma_do_escale', 'val'=>'.false.'); add_default($nl, 'carma_escale_file'); } elsif ($carma eq 'mixed_sulfate') { add_default($nl, 'carma_do_coag', 'val'=>'.true.'); add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_emission', 'val'=>'.true.'); add_default($nl, 'carma_do_fixedinit','val'=>'.true.'); add_default($nl, 'carma_do_grow', 'val'=>'.true.'); add_default($nl, 'carma_do_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 CAM5.5/CAM6 configurations my $chem_has_ocs = chem_has_species($cfg, 'OCS'); if ( $phys =~ /cam5.4/ and $cfg->get('clubb_sgs' ) ) { # 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'); } 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_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 = (); %species = ('DMS -> ' => 'dms_emis_file', 'SO2 -> ' => 'so2_emis_file', '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', ); 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 = (); 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 -> ' => 'mam4_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_a4 -> ' => 'pom_a4_ext_file', # only forest fire and grass fire emissions 'bc_a4 -> ' => 'bc_a4_ext_file', # only forest fire and grass fire emissions 'num_a1 -> ' => 'mam4_num_a1_ext_file', 'num_a2 -> ' => 'num_a2_ext_file', # background volc emissions 'num_a4 -> ' => 'mam4_num_a4_ext_file', ); # only forest fire and grass fire emissions } # for cam6 add h2o source from methane oxidation if ($phys =~ /cam5.4/ && $cfg->get('clubb_sgs') == 1 && $chem !~ /waccm_sc/) { %species = (%species, 'H2O -> ' => 'h2o_ch4_ox_file'); } # 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 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_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. add_default($nl, 'co2vmr'); add_default($nl, 'ch4vmr'); add_default($nl, 'n2ovmr'); add_default($nl, 'f11vmr'); add_default($nl, 'f12vmr'); } } # Dry Deposition -- The responsibility for dry deposition is shared between CAM and CLM. # The namelist is read by a driver module, seq_drydep_mod, and the information is shared # between CAM and CLM by use association of that module. if ( $chem ) { add_default($nl, 'drydep_method'); # drydep_srf_file is only needed for prognostic MAM when the grid is unstructured. # structured grids can do interpolation on the fly. if ($chem =~ /_mam/ and $dyn =~ /se/) { add_default($nl, 'drydep_srf_file'); } } # Physics options # Add the name of the physics package based on the info in configure. If the user tries # to explicitly specify this namelist variable issue error. my $cam_physpkg = $nl->get_value('cam_physpkg'); if (defined $cam_physpkg) { die "CAM Namelist ERROR: User may not specify the value of cam_physpkg.\n". "This variable is set by build-namelist based on information\n". "from the configure cache file.\n"; } $cam_physpkg = "'" . "$phys" . "'"; # add quotes to this string value $nl->set_variable_value('phys_ctl_nl', 'cam_physpkg', $cam_physpkg); # WACCM-X runtime options add_default($nl, 'waccmx_opt'); 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'); } # 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 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'); # Eddy scheme (vertical diffusion) add_default($nl, 'eddy_scheme'); # Defaults for shallow convection scheme and surface flux averaging both depend # on the value of the eddy scheme. my $eddy_scheme = $nl->get_value('eddy_scheme'); # Need to strip the quotes to use as a value for attribute matching. $eddy_scheme =~ s/['"]//g; #"' add_default($nl, 'shallow_scheme', 'eddy_scheme'=>$eddy_scheme); add_default($nl, 'srf_flux_avg', 'eddy_scheme'=>$eddy_scheme); # Microphysics scheme add_default($nl, 'use_subcol_microp'); add_default($nl, 'microp_scheme'); 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'); } # Ice nucleation options 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) add_default($nl, 'subcol_scheme'); my $subcol_scheme = $nl->get_value('subcol_scheme'); my $use_subcol_microp = $nl->get_value('use_subcol_microp'); if ($print>=2) { print "subcol_scheme=$subcol_scheme \n"; } if (($subcol_scheme eq "'off'") && ($use_subcol_microp =~ m/$TRUE/io)) { die "$ProgName - Error: use_subcol_microp set to .true. but no subcol_scheme is set \n"; } if ($subcol_scheme eq 'tstcp') { add_default($nl, 'subcol_tstcp_noavg'); add_default($nl, 'subcol_tstcp_filter'); add_default($nl, 'subcol_tstcp_weight'); add_default($nl, 'subcol_tstcp_perturb'); 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 the subcol_schemes and use_subcol_microp unless overridden by the user my $microp_uniform = $nl->get_value('microp_uniform'); if (defined $microp_uniform) { add_default($nl, 'microp_uniform', 'val'=>$microp_uniform); } # If use_subcol_microp is turned on and has not been turned off via the namelist, turn on microp_uniform elsif ($use_subcol_microp =~ /$TRUE/io) { add_default($nl, 'microp_uniform', 'val'=>'.true.'); } # Turn off by default else { add_default($nl, 'microp_uniform', 'val'=>'.false.'); } # CLUBB_SGS add_default($nl, 'do_clubb_sgs'); 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 add_default($nl, 'do_tms'); my $do_tms = $nl->get_value('do_tms'); # Check to be sure that do_tms has been set to true if the user sets a customized # value of tms_orocnst or tms_z0fac. if (defined $nl->get_value('tms_orocnst') or defined $nl->get_value('tms_z0fac')) { # a tms parameter has been set in the namelist. Make sure do_tms is true. if ( $do_tms =~ /$FALSE/io ) { die "$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 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 add_default($nl, 'do_iss'); # Convective water in radiation add_default($nl, 'conv_water_in_rad'); add_default($nl, 'conv_water_frac_limit'); # Cloud fraction add_default($nl, 'cldfrc_freeze_dry'); add_default($nl, 'cldfrc_ice'); add_default($nl, 'cldfrc_rhminl'); add_default($nl, 'cldfrc_rhminl_adj_land'); add_default($nl, 'cldfrc_rhminh'); add_default($nl, 'cldfrc_sh1'); add_default($nl, 'cldfrc_sh2'); add_default($nl, 'cldfrc_dp1'); add_default($nl, 'cldfrc_dp2'); add_default($nl, 'cldfrc_premit'); add_default($nl, 'cldfrc_premib'); add_default($nl, 'cldfrc_iceopt'); add_default($nl, 'cldfrc_icecrit'); 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 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 add_default($nl, 'hkconv_cmftau'); add_default($nl, 'hkconv_c0'); if ($phys =~ /cam5/ and $cfg->get('pbl') 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'); } # Top level pressure for troposphere cloud physics add_default($nl, 'trop_cloud_top_press'); # 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'); } add_default($nl, 'diff_cnsrv_mass_check'); # Pressure limits for molecular diffusion. add_default($nl, 'do_molec_press'); add_default($nl, 'molec_diff_bot_press'); 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 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); # GW option used only for backwards compatibility with CAM3. add_default($nl, 'fcrit2'); # 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'); } else { 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'); } else { 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'); } else { 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.'); } else { 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_carma'); add_default($nl, 'history_clubb'); # The history output for the AMWG variability diagnostics assumes that auxilliary history # files h1, h2, and h3 contain daily, 6-hrly, and 3-hrly output respectively. If this output # has been requested, then make sure the user has not already set nhtfrq to something # inconsistent with this requirement. my $history_vdiag = $nl->get_value('history_vdiag'); if ($history_vdiag =~ m/$TRUE/io) { # Check for consistent setting of nhtfrq. my $nhtfrq = $nl->get_value('nhtfrq'); if (defined $nhtfrq) { # # If already set, check for consistency my @nhtfrq = split /,/, $nhtfrq; if ($nhtfrq[1] != -24 or $nhtfrq[2] != -6 or $nhtfrq[3] != -3) { die "$ProgName - ERROR: history_vdiag is .true., but nhtfrq is set to $nhtfrq\n". "The first 4 elements of nhtfrq must be 0,-24,-6,-3. Note that the use case may\n". "be the source of the inconsistent nhtfrq values.\n"; } } else { # set the default add_default($nl, 'nhtfrq', 'val'=>'0, -24, -6, -3'); } } # 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 = ''; # The %mask variable is used to set namelist defaults for CLM. my %mask = (); # 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'); # Assume that the focndomain filename contains the name of the ocean grid used to construct # the lnd/ocn mask. Recover the ocean grid name using a regexp match, and use it subsequently # to determine consistent CLM files. if ($focndomain =~ m/_(gx\dv\d)_/) { $mask{'mask'} = $1; } elsif ($focndomain =~ m/_USGS_/) { $mask{'mask'} = 'USGS'; } ############################## # namelist group: dom_inparm # ############################## if ($ocn_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"; $datasource time time xc lon yc lat area area mask mask $fsstdomain_path $fsstdomain_file EOF if ($ocn_comp eq 'docn') { print $fh <<"EOF"; SST_cpl t $sstdata_path $sstdata_file EOF } elsif ($ocn_comp eq 'som') { print $fh <<"EOF"; T t S s U u V v dhdx dhdx dhdy dhdy hblt h qdp qbot $sstdata_path $sstdata_file 0 EOF } $fh->close; if ($print>=1) { print "Writing DOCN stream file to $outfile $eol"; } } #----------------------------------------------------------------------------------------------- # Add defaults for the CLM component # Only produce a namelist for CLM if running with CAM standalone scripts # and if the lnd component is active. my $lnd_pkg = $cfg->get('lnd'); if ($lnd_pkg eq 'clm' and $cam_build and $lnd_active) { ############################## # namelist group: clm_inparm # ############################## # Timestep # *** N.B. *** this code enforces the constraint that the CLM timestep match the CAM timestep. # Note that a Namelist object method is used to add the value of dtime to clm_inparm to avoid # the namelist definition checking done by add_default. That's because dtime is in CAM's definition # file as a variable that belongs in cam_inparm and it can't also be in clm_inparm. This will be # resolved when the CLM component is made responsible for producing the clm_inparm namelist. my $clmval = $nl->get_value('dtime'); $nl->set_variable_value('clm_inparm', 'dtime', $clmval); # Check that "nrevsn" is set if this is a branch simulation if ($nl->get_value('start_type') =~ /branch/ and !defined $nl->get_value('nrevsn')) { die "$ProgName - ERROR: The CLM2 master restart file must be specified for a branch\n". " run. Set the namelist variable NREVSN to the absolute\n". " pathname for this dataset.\n". " This can be done on the command-line using the -namelist\n". " option or in an input namelist file that is specified\n". " using the -infile option.\n"; } add_default($nl, 'fatmlndfrc', %mask); add_default($nl, 'fsnowoptics'); add_default($nl, 'fsnowaging'); add_default($nl, 'fpftcon'); # CO2 # *** N.B. *** This is forced to use the same value that CAM is using. my $co2vmr = $nl->get_value('co2vmr'); if (defined $co2vmr) { my $co2_ppmv = sprintf '%e', $co2vmr * 1.e6; $nl->set_variable_value('clm_inparm', 'co2_ppmv', $co2_ppmv); } # All F compsets currently set co2_type='diagnostic' add_default($nl, 'co2_type', 'val'=>'diagnostic'); add_default($nl, 'urban_hac'); add_default($nl, 'urban_traffic'); add_default($nl, 'fsurdat', 'sim_year'=>$sim_year_start); # Initial conditions # The initial date is an attribute in the defaults file which should be matched unless # the user explicitly requests to ignore the initial date via the -ignore_ic_date option, # or just ignore the year of the initial date via the -ignore_ic_year option. my $ic_date = $nl->get_value('start_ymd'); if ($opts{'ignore_ic_date'}) { add_default($nl, 'finidat', 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask); } elsif ($opts{'ignore_ic_year'}) { add_default($nl, 'finidat', 'ic_md'=>$ic_date, 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask); } else { add_default($nl, 'finidat', 'ic_ymd'=>$ic_date, 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask); } # If sim_year is input as a range of years, then add the dynamic PFT dataset. if ($sim_year =~ /(\d+)-(\d+)/) { add_default($nl, 'flanduse_timeseries', 'sim_year'=>$sim_year) } } #----------------------------------------------------------------------------------------------- # Add defaults for the CICE component # Only produce a namelist for CICE if running with CAM standalone scripts. # Which sea ice model? my $ice_comp = $cfg->get('ice'); if ($ice_comp eq 'cice' and $cam_build and $ice_active) { # The CICE component has its own build-namelist utility. my $cice_bldnl = "$cam_root/components/cice/bld/build-namelist"; # Set up the commandline args # CICE config_cache filepath my $cice_config_dir = $cfg->get('cice_config_cache_dir'); my $cice_config_file = $cfg->get('cice_config_cache_file'); my $cice_config_filepath = "$cice_config_dir/$cice_config_file"; if (defined $opts{'config_cice'}) { $cice_config_filepath = $opts{'config_cice'}; } # Pass namelist settings to CICE. my $cice_nl = "&ice \n"; if ($ocn_comp eq 'dom' or $ocn_comp eq 'docn') { # CICE namelist variables that need to be set consistently with CAM-DOM. $cice_nl .= "grid_file=$focndomain \n" . "kmt_file=$focndomain \n" . "stream_domfilename=$bndtvs \n" . "stream_fldfilename=$bndtvs \n" . "stream_fldvarname='ice_cov' \n"; # Check for variables used to specify the years of a multi-year SST dataset. # If not set by user, default to 0 which is the year used in the climatology files. my $stream_year_first = $nl->get_value('stream_year_first'); unless (defined $stream_year_first) { $stream_year_first = 0; } $cice_nl .= "stream_year_first=$stream_year_first \n"; # Set model_year_align equal to stream_year_first. The flexibility enabled # by model_year_align is not available in CAM-DOM. $cice_nl .= "model_year_align=$stream_year_first \n"; my $stream_year_last = $nl->get_value('stream_year_last'); unless (defined $stream_year_last) { $stream_year_last = 0; } $cice_nl .= "stream_year_last=$stream_year_last \n"; } # If the user has specified variables to send to the CICE build-namelist # via the -cice_nl argument then append them here. if (defined $opts{'cice_nl'}) { my $usr_cice_nl = $opts{'cice_nl'}; # strip off the leading group name and trailing terminator $usr_cice_nl =~ s/^\s*&\w+//; # group name with optional leading whitespace $usr_cice_nl =~ s/\/\s*$//; # slash terminator with optional trailing whitespace $cice_nl .= $usr_cice_nl; # Parse out the ice_ic name and fill the rpointer.ice file, if needed for a branch run my $run_type = $opts{'runtype'}; if ($run_type eq 'branch') { $usr_cice_nl =~ s/^\s*ice_ic='//; $usr_cice_nl =~ s/'\s*//; my $fh = new IO::File; my $outfile = "rpointer.ice"; $fh->open(">$outfile") or die "** can't open file: $outfile\n"; print $fh "$usr_cice_nl\n"; $fh->close; } } # For phys pkg <=cam4 send the variable "cam4=.true." to get correct defaults for several # cice parameters. if ($phys eq 'cam4' or $phys eq 'cam3' or $phys eq 'spcam_sam1mom') { $cice_nl .= "cam4=.true. \n"; } $cice_nl .= "grid_type='latlon' \n"; $cice_nl .= "grid_format='nc' \n"; $cice_nl .= "stream_domtvarname='time' \n" . "stream_domxvarname='lon' \n" . "stream_domyvarname='lat' \n" . "stream_domareaname='area' \n" . "stream_dommaskname='mask' \n"; # Terminate the namelist $cice_nl .= " /"; # Commandline arguments for CICE build-namelist my @nl_args = ('-csmdata', $inputdata_rootdir, '-config', $cice_config_filepath, '-dir', $opts{'dir'}, '-namelist', $cice_nl, '-cimeroot', "$cam_root/cime" ); my @command = ($cice_bldnl, @nl_args); system(@command) == 0 or die "system @command failed: $? \n"; my $outfile = "$opts{'dir'}/ice_in"; if ($print>=1) { print "Writing CICE namelist to $outfile $eol"; } } #----------------------------------------------------------------------------------------------- # Add defaults for the RTM component # Only produce a namelist for RTM if running with CAM standalone scripts # and if the rof component is active. my $rof_pkg = $cfg->get('rof'); if ($rof_pkg eq 'rtm' and $cam_build and $rof_active) { my $fh = new IO::File; # Create rof_in # -------------- my $outfile = "$opts{'dir'}/rof_in"; $fh->open(">$outfile") or die "** can't open file: $outfile\n"; # Currently, just always turn off RTM, but that might change # in order to get flooding feedback into CLM. print $fh <<"EOF"; &rtm_inparm rtm_mode = "NULL" / EOF #/ $fh->close; if ($print>=1) { print "Writing RTM namelist to $outfile $eol"; } } #----------------------------------------------------------------------------------------------- # Rename component logfiles. # # This requires special handling because the logfiles are coordinated using # share code. Each component is using shr_file_mod::shr_file_setIO to attach # a unique Fortran unit to a named file. shr_file_setIO reads the namelist # group /modelio/ and hence each component is using the same variable names. # To work around this component specific names have been added to the special # namelist group /camexp/. Check for those variables and write the component # specific versions of /modelio/ to files whose names are hardwired in the top # level component interface, e.g., atm_comp_mct, lnd_comp_mct, and seq_ccsm_drv. my @comps = qw(atm cpl lnd rof); foreach my $comp (@comps) { my $logfile = "${comp}_logfile"; my $logfiledir = "${comp}_logfile_diro"; my $outfile = "${comp}_modelio.nml"; # check to see if user requests renaming this component logfile my $logfile_val = $nl->get_variable_value('camexp', $logfile); if (defined $logfile_val) { # create namelist object for /modelio/ my $modelio = Build::Namelist->new("&modelio logfile=$logfile_val /"); # check whether a directory has been specified... if so add to namelist my $logfiledir_val = $nl->get_variable_value('camexp', $logfiledir); if (defined $logfiledir_val) { $modelio->set_variable_value('modelio', 'diro', $logfiledir_val); } # write the namelist to the component specific file $modelio->write($outfile); if ($print>=1) { print "Writing modelio namelist to $outfile $eol"; } } } #----------------------------------------------------------------------------------------------- # Write output files # Get array of group names that have been defined in the namelist. my @nl_groups = $nl->get_group_names(); # Create a hash with the group names as keys. This makes it easy to remove # names from the list. my %nl_group = (); foreach my $name (@nl_groups) { $nl_group{$name} = ''; } # Write fixed sets of namelist groups for the components other than CAM. # Remove the group names from %nl_group as they are written. # CLM my @comp_groups = qw(clm_inparm clm_rtm_inparm); my $outfile = "$opts{'dir'}/lnd_in"; if ($cam_build and $lnd_active) { $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { print "Writing CLM namelist to $outfile $eol"; } } delete @nl_group{@comp_groups}; # Driver @comp_groups = qw(seq_cplflds_inparm seq_cplflds_userspec ccsm_pes seq_infodata_inparm seq_timemgr_inparm prof_inparm pio_default_inparm); $outfile = "$opts{'dir'}/drv_in"; if ($cam_build) { $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { print "Writing driver namelist to $outfile $eol"; } } delete @nl_group{@comp_groups}; # Dry deposition and MEGAN VOC emis namelists @comp_groups = qw(drydep_inparm megan_emis_nl 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); 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; } } } #-------------------------------------------------------------------------------