#!/usr/bin/env perl #----------------------------------------------------------------------------------------------- # # build-namelist # # This script builds the namelists for the standalone CAM configuration of CCSM4. # Eventually the system's build will be reworked so that individual components are responsible # for building their own namelists. # # build-namelist is designed to be used in conjuction with configure. By default configure # produces a config_cache.xml file that contains all information needed at build time to procduce # a CAM executable. build-namelist reads this file to obtain information it needs to provide # default values that are consistent with the CAM executable. For example, the grid resolution # is obtained from the cache file and used to determine appropriate defaults for boundary datasets # that are resolution dependent. # # The simplest use of build-namelist is to execute it from the build directory where configure # was run. By default it will use the config_cache.xml file that was written by configure to # determine the build time properties of the executable, and will write the files that contain # the output namelists in that same directory. But if multiple runs are to made using the # same executable, successive invocations of build-namelist will overwrite previously generated # namelist files. So generally the best strategy is to invoke build-namelist from the run # directory and use the -config option to provide the filepath of the config_cache.xml file. # # # Date Contributor Modification # ------------------------------------------------------------------------------------------- # 2007-12-31 Brian Eaton Original version # 2008-02-02 B. Eaton Restore -test functionality. # 2008-07-01 Sean Santos Added -inputdata functionality. # 2008-07-09 B. Eaton Provide default values for rad_climate variable which # specifies the radiatively active constituents. # 2008-08-26 B. Eaton Add the driver namelist group ccsm_pes to specify the # task/thread layout for all components. # 2008-11-14 B. Eaton Extend use_case functionality. # 2009-09-02 B. Eaton Allow namelist definition, defaults, and use case files # to come from the user source mod directories. #-------------------------------------------------------------------------------------------- use strict; #use warnings; #use diagnostics; use Cwd; use English; use File::Basename; use Getopt::Long; use IO::File; use FindBin qw($Bin); use lib "$Bin/perl5lib"; use Build::ChemNamelist qw(set_dep_lists); #----------------------------------------------------------------------------------------------- sub usage { die < Specify the number of MPI tasks being used by the run. This is used to set a default decomposition for the FV dycore only (npr_yz). -runtype "type" Type of simulation (startup, continue, or branch) -silent [-s] Turns on silent mode - only fatal messages issued. -test Enable checking that input datasets exist on local filesystem. -use_case Specify a use case. Default: present day climatology -verbose [or -v] Turn on verbose echoing of informational messages. -version Echo the CVS tag name used to check out this CAM distribution. Note: The precedence for setting the values of namelist variables is (highest to lowest): 1. namelist values set by specific command-line options, i.e., -case, -runtype 2. values set on the command-line using the -namelist option, 3. values read from the file specified by -infile, 4. values specified by the -use_case option, 5. values from the namelist defaults file. EOF } #----------------------------------------------------------------------------------------------- # Set the directory that contains the CAM configuration scripts. If the command was # issued using a relative or absolute path, that path is in $ProgDir. Otherwise assume the # command was issued from the current working directory. (my $ProgName = $0) =~ s!(.*)/!!; # name of this script $ProgName = "CAM $ProgName"; # Since multiple components are now using a build-namelist # utility add "CAM" qualifier to the name. This helps when # looking at error output from the whole CCSM system. my $ProgDir = $1; # name of directory containing this script -- may be a # relative or absolute path, or null if the script is in # the user's PATH my $cwd = getcwd(); # current working directory my $cfgdir; # absolute pathname of directory that contains this script if ($ProgDir) { $cfgdir = absolute_path($ProgDir); } else { $cfgdir = $cwd; } # CAM root directory. my $cam_root = absolute_path("$cfgdir/../../../.."); my $cfg_cache = "config_cache.xml"; # Default name of configuration cache file my $outdirname = "."; # Default name of output directory name #----------------------------------------------------------------------------------------------- # Save commandline my $commandline = "$cfgdir/build-namelist @ARGV"; #----------------------------------------------------------------------------------------------- # Process command-line options. my %opts = ( config => $cfg_cache, csmdata => undef, help => 0, dir => $outdirname, silent => 0, test => 0, ); GetOptions( "case=s" => \$opts{'case'}, "cice_nl=s" => \$opts{'cice_nl'}, "config=s" => \$opts{'config'}, "config_cice=s" => \$opts{'config_cice'}, "csmdata=s" => \$opts{'csmdata'}, "d|dir=s" => \$opts{'dir'}, "h|help" => \$opts{'help'}, "ignore_ic_date" => \$opts{'ignore_ic_date'}, "ignore_ic_year" => \$opts{'ignore_ic_year'}, "infile=s" => \$opts{'infile'}, "inputdata=s" => \$opts{'inputdata'}, "namelist=s" => \$opts{'namelist'}, "ntasks=s" => \$opts{'ntasks'}, "runtype=s" => \$opts{'runtype'}, "s|silent" => \$opts{'silent'}, "test" => \$opts{'test'}, "uc|use_case=s" => \$opts{'use_case'}, "v|verbose" => \$opts{'verbose'}, "version" => \$opts{'version'}, ) or usage(); # Give usage message. usage() if $opts{'help'}; # Echo version info. if ($opts{'version'}) { version($cfgdir); exit; } # Check for unparsed arguments if (@ARGV) { print "ERROR: unrecognized arguments: @ARGV\n"; usage(); } # Define print levels: # 0 - only issue fatal error messages # 1 - only informs what files are created (default) # 2 - verbose my $print = 1; if ($opts{'silent'}) { $print = 0; } if ($opts{'verbose'}) { $print = 2; } my $eol = "\n"; if ($print>=2) { print "Setting CAM configuration script directory to $cfgdir$eol"; } if ($print>=2) { print "build-namelist was invoked with the commandline:\n $commandline$eol"; } # Check that configuration cache file exists. (-f $opts{'config'}) or die <<"EOF"; ** $ProgName - ERROR: Cannot find configuration cache file: \"$opts{'config'}\" ** EOF if ($print>=2) { print "Using CAM configuration cache file $opts{'config'}$eol"; } # Check that the CCSM inputdata root directory has been specified. my $inputdata_rootdir = undef; if (defined($opts{'csmdata'})) { $inputdata_rootdir = $opts{'csmdata'}; } elsif (defined $ENV{'CSMDATA'}) { $inputdata_rootdir = $ENV{'CSMDATA'}; } else { die "$ProgName - ERROR: CCSM inputdata root directory must be specified by either -csmdata argument\n" . " or by the CSMDATA environment variable. :"; } if ($print>=2) { print "CCSM inputdata root directory: $inputdata_rootdir$eol"; } # If the -test option is specified, then the inputdata root directory must be local or nfs mounted. if ($opts{'test'}) { (-d $inputdata_rootdir) or die <<"EOF"; ** $ProgName - ERROR: CCSM inputdata root is not a directory: \"$inputdata_rootdir\" ** EOF } #----------------------------------------------------------------------------------------------- # Make sure we can find required perl modules, definition, and defaults files. # Look for them under the directory that contains the configure script. # The XML::Lite module is required to parse the XML files. (-f "$cfgdir/perl5lib/XML/Lite.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"XML/Lite.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::Config module provides utilities to access the configuration information # in the config_cache.xml file (-f "$cfgdir/perl5lib/Build/Config.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/Config.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::NamelistDefinition module provides utilities to validate that the output # namelists are consistent with the namelist definition file (-f "$cfgdir/perl5lib/Build/NamelistDefinition.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/NamelistDefinition.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::NamelistDefaults module provides a utility to obtain default values of namelist # variables based on finding a best fit with the attributes specified in the defaults file. (-f "$cfgdir/perl5lib/Build/NamelistDefaults.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/NamelistDefaults.pm\" in directory \"$cfgdir/perl5lib\" ** EOF # The Build::Namelist module provides utilities to parse input namelists, to query and modify # namelists, and to write output namelists. (-f "$cfgdir/perl5lib/Build/Namelist.pm") or die <<"EOF"; ** $ProgName - ERROR: Cannot find perl module \"Build/Namelist.pm\" in directory \"$cfgdir/perl5lib\" ** EOF #----------------------------------------------------------------------------------------------- # Add $cfgdir/perl5lib to the list of paths that Perl searches for modules unshift @INC, "$cfgdir/perl5lib"; require XML::Lite; require Build::Config; require Build::NamelistDefinition; require Build::NamelistDefaults; require Build::Namelist; #----------------------------------------------------------------------------------------------- # Create a configuration object from CAM's config_cache.xml file. This object contains # all the build-time specifications of the CAM executable. my $cfg = Build::Config->new($opts{'config'}); #----------------------------------------------------------------------------------------------- # Create a namelist definition object. This object provides a method for verifying that the # output namelist variables are in the definition file, and are output in the correct # namelist groups. Requires a namelist definition file... # # The namelist definition file contains entries for all namelist variables that # can be output by build-namelist. The version of the file that is associate with a # fixed CAM tag is $cfgdir/namelist_files/namelist_definition.xml. To aid developers # who make use of the source mods directory (via -usr_src arg to configure) we allow # the definition file to come from one of those directories. my $nl_definition_file; my @usr_src_dirs = split ',', $cfg->get('usr_src'); if (@usr_src_dirs) { foreach my $dir (@usr_src_dirs) { if (-f "$dir/namelist_definition.xml") { $nl_definition_file = "$dir/namelist_definition.xml"; last; } } } if (! defined $nl_definition_file) { # default location of namelist definition file $nl_definition_file = "$cfgdir/namelist_files/namelist_definition.xml"; (-f "$nl_definition_file") or die <<"EOF"; ** $ProgName - ERROR: Cannot find namelist definition file \"$nl_definition_file\" ** EOF } if ($print>=2) { print "Using namelist definition file $nl_definition_file$eol"; } my $definition = Build::NamelistDefinition->new($nl_definition_file); #----------------------------------------------------------------------------------------------- # Create a namelist defaults object. This object provides default values for variables # contained in the input defaults file. The configuration object provides attribute # values that are relevent for the CAM executable for which the namelist is being produced. # These attributes are used along with optional user specified attributes to find the # best match when looking for default values. # # The namelist defaults file contains default values for all required namelist variables. # Analogously to the definition file, we allow a user modified version of this file to # be present in one of the usr_src directories. my $nl_defaults_file; if (@usr_src_dirs) { foreach my $dir (@usr_src_dirs) { if (-f "$dir/namelist_defaults_cam.xml") { $nl_defaults_file = "$dir/namelist_defaults_cam.xml"; last; } } } if (! defined $nl_defaults_file) { # default location of namelist defaults file $nl_defaults_file = "$cfgdir/namelist_files/namelist_defaults_cam.xml"; (-f "$nl_defaults_file") or die <<"EOF"; ** $ProgName - ERROR: Cannot find namelist defaults file \"$nl_defaults_file\" ** EOF } if ($print>=2) { print "Using namelist defaults file $nl_defaults_file$eol"; } my $defaults = Build::NamelistDefaults->new($nl_defaults_file, $cfg); #----------------------------------------------------------------------------------------------- # Similarly to the namelist definition and defaults files, the use case file # may also come from the usr_src directories. Determine the location of the # use case file. my $use_case_file; if (defined $opts{'use_case'}) { if (@usr_src_dirs) { foreach my $dir (@usr_src_dirs) { if (-f "$dir/$opts{'use_case'}.xml") { $use_case_file = "$dir/$opts{'use_case'}.xml"; last; } } } if (! defined $use_case_file) { # default location of namelist use case files $opts{'use_case_dir'} = "$cfgdir/namelist_files/use_cases"; validate_use_case("commandline", \%opts); $use_case_file = "$opts{'use_case_dir'}/$opts{'use_case'}.xml"; } if ($print>=2) { print "Using namelist use case file $use_case_file$eol"; } } #----------------------------------------------------------------------------------------------- # Create an empty namelist object. Add values to it in order of precedence. my $nl = Build::Namelist->new(); #----------------------------------------------------------------------------------------------- # Some regular expressions... # **N.B.** the use of qr// for precompiling regexps isn't supported until perl 5.005. my $TRUE = "\.true\."; my $FALSE = "\.false\."; #----------------------------------------------------------------------------------------------- # Process the user input in order of precedence. At each point we'll only add new # values to the namelist and not overwrite previously specified specified values which # have higher precedence. # Process the commandline args that provide specific namelist values. # Case name if (defined $opts{'case'}) { add_default($nl, 'case_name', 'val'=>$opts{'case'}); } # Run type if (defined $opts{'runtype'}) { add_default($nl, 'start_type', 'val'=>$opts{'runtype'}); } # Process the -namelist arg. if (defined $opts{'namelist'}) { # Parse commandline namelist my $nl_arg = Build::Namelist->new($opts{'namelist'}); # Validate input namelist -- trap exceptions my $nl_arg_valid; eval { $nl_arg_valid = $definition->validate($nl_arg); }; if ($@) { die "$ProgName - ERROR: Invalid namelist variable in commandline arg '-namelist'.\n $@"; } # Merge input values into namelist. Previously specified values have higher precedence # and are not overwritten. $nl->merge_nl($nl_arg_valid); } # Process the -infile arg. if (defined $opts{'infile'}) { # Parse namelist input from a file my $nl_infile = Build::Namelist->new($opts{'infile'}); # Validate input namelist -- trap exceptions my $nl_infile_valid; eval { $nl_infile_valid = $definition->validate($nl_infile); }; if ($@) { die "$ProgName - ERROR: Invalid namelist variable in '-infile' $opts{'infile'}.\n $@"; } # Merge input values into namelist. Previously specified values have higher precedence # and are not overwritten. $nl->merge_nl($nl_infile_valid); } # Process the -use_case arg. # Declare global symbol $uc_defaults even if it's not defined, because we check whether it's # defined before using it in the get_default_value method below. my $uc_defaults; if (defined $use_case_file) { # The use case definition is contained in an xml file with the same format as the defaults file. # Create a new NamelistDefaults object. $uc_defaults = Build::NamelistDefaults->new($use_case_file, $cfg); # Loop over the variables specified in the use case. # A defaults file may contain information for variables that are not namelist variables. # Check each name in the defaults file, and add each namelist variable to the namelist. my @vars = $uc_defaults->get_variable_names(); VAR: foreach my $var (@vars) { # Query the definition to find which group the variable belongs to. Skip if not found. my $group = $definition->get_group_name($var); if ($group) { # Get the value of $var from the use case defaults my $val = $uc_defaults->get_value($var); if (defined $val) { add_default($nl, $var, 'val'=>$val); } # If the use case doesn't provide a default value, then just ignore. This allows the # use case mechanism to provide defaults for some attributes (e.g. a specific grid), and # not for others. } } } #----------------------------------------------------------------------------------------------- # Add default values for required namelist variables that have not been previously set. # This is done either by using the namelist default object, or directly with inline logic. # Are we building namelists for the cpl6 scripts, the cpl7 scripts, or for standalone CAM # scripts. my $cpl7_build = $cfg->get('ccsm_seq'); my $ccsm_build = $cpl7_build; my $cam_build = $ccsm_build ? 0 : 1; if ($print>=2) { if ($cpl7_build) { print "Writing namelist files for cpl7 scripts$eol"; } elsif ($cam_build) { print "Writing namelist files for cam standalone scripts$eol"; } } # Start with the driver component. These settings are communicated by the driver to # all subcomponents. ###################################### # namelist group: seq_cplflds_inparm # ###################################### add_default($nl, 'flds_co2_dmsa', 'val'=>'.false.'); add_default($nl, 'flds_co2a', 'val'=>'.true.'); add_default($nl, 'flds_co2b', 'val'=>'.false.'); add_default($nl, 'flds_co2c', 'val'=>'.false.'); add_default($nl, 'cplflds_custom', 'val'=>''); ############################ # namelist group: ccsm_pes # ############################ # By default the driver sets all components to use all tasks. This is the # appropriate default for the standalone CAM configuration. # By default the driver sets all components to use 1 thread. This should be # reset either to user specified values, or by default use the OMP_NUM_THREADS # environment variable or the nthreads configuration parameter to set the thread # count for each component. # Is this an smp build? my $smp = $cfg->get('smp'); if ($smp) { # If user has set the specific variables for component threads on the commandline # those values will be used. If not, the highest precedence will be given the the # value of the environment variable OMP_NUM_THREADS. That is because the number of # threads specified on the configure commandline is used to determine an appropriate # decomposition for the CICE model, but that decomposition may be valid for a range # of ntask/nthread settings. # Check for OMP_NUM_THREADS my $nthreads; if (defined $ENV{'OMP_NUM_THREADS'}) { $nthreads = $ENV{'OMP_NUM_THREADS'}; } # Has the number of threads been set by configure elsif (defined $cfg->get('nthreads')) { $nthreads = $cfg->get('nthreads'); } if ($nthreads) { add_default($nl, 'atm_nthreads', 'val'=>$nthreads); add_default($nl, 'cpl_nthreads', 'val'=>$nthreads); add_default($nl, 'ice_nthreads', 'val'=>$nthreads); add_default($nl, 'lnd_nthreads', 'val'=>$nthreads); add_default($nl, 'ocn_nthreads', 'val'=>$nthreads); add_default($nl, 'rof_nthreads', 'val'=>$nthreads); } } ####################################### # namelist group: seq_infodata_inparm # ####################################### my $phys_mode_flags = 0; my $adia_mode = 0; my $aqua_mode = 0; # Case name add_default($nl, 'case_name'); # Run type add_default($nl, 'start_type'); # HOMME dycore my $dyn = $cfg->get('dyn'); if ($dyn =~ /homme/) {add_default($nl, 'vect_map', 'val'=>'cart3d');} # Adiabatic or Ideal physics my $phys = $cfg->get('phys'); if ($phys eq 'adiabatic') { add_default($nl, 'atm_adiabatic', 'val'=>'.true.'); } if ($phys eq 'ideal') { add_default($nl, 'atm_ideal_phys', 'val'=>'.true.'); } # Aqua planet my $aqua_flag = $cfg->get('ocn'); my $nl_aqua_flag = $nl->get_value('aqua_planet'); if ($aqua_flag eq 'aquaplanet') { $aqua_mode = 1; } # Consistency check between configuration and namelist variables used for aquaplanet. if ($aqua_mode and defined $nl_aqua_flag and ($nl_aqua_flag =~ m/$FALSE/io)) { die "$ProgName - ERROR: Configured CAM for aquaplanet but user set aqua_planet to FALSE in the namelist. \n"; } if (!($aqua_mode) and defined $nl_aqua_flag and ($nl_aqua_flag =~ m/$TRUE/io)) { die "$ProgName - ERROR: CAM not configured for aquaplanet but user has set aqua_planet to TRUE in the namelist. \n"; } if ($aqua_mode) { add_default($nl, 'aqua_planet', 'val'=>'.true.'); add_default($nl, 'aqua_planet_sst', 'val'=>'1'); ++$phys_mode_flags; } # Consistency check for namelist variables used to implement physics modes. my $phys_flag = $nl->get_value('atm_adiabatic'); if (defined $phys_flag and ($phys_flag =~ m/$TRUE/io)) { $adia_mode = 1; ++$phys_mode_flags; } my $ideal_mode = 0; $phys_flag = $nl->get_value('atm_ideal_phys'); if (defined $phys_flag and ($phys_flag =~ m/$TRUE/io)) { $ideal_mode = 1; ++$phys_mode_flags; } if ($phys_mode_flags > 1) { die "$ProgName - ERROR: Only one of the variables atm_adiabatic, atm_ideal_phys, and aqua_planet can be set .true. \n"; } # Set convenience flag to indicate that one of the ideal, adiabatic, or # aqua-planet modes is being used. my $ideal_or_adia_or_aqua = 0; if ($phys_mode_flags == 1) { $ideal_or_adia_or_aqua = 1; } # Set some flags that determine whether or not build-namelist will produce output # for non-atm components. # Start by checking how the executable was configured. # If the physics mode is one of adiabatic, ideal, or aqua_planet, then the # land, rof, and sea ice components are inactive (whether the executable was configured # with them or not). my $lnd_active = 1; my $rof_active = 1; my $ice_active = 1; if ($ideal_or_adia_or_aqua) { $lnd_active = 0; $rof_active = 0; $ice_active = 0; } # Note that the prescribed SSTs # used by aqua-planet mode are implemented in the cam_aqua component.) # Single column mode my $scam = $cfg->get('scam'); if ($scam) { add_default($nl, 'single_column', 'val'=>'.true.'); my $scmlat = $nl->get_value('scmlat'); my $scmlon = $nl->get_value('scmlon'); unless (defined $scmlat and defined $scmlon) { die "$ProgName - ERROR: In SCAM mode both scmlat and scmlon namelist variables must be set. \n"; } } ###################################### # namelist group: seq_timemgr_inparm # ###################################### # Length of simulation add_default($nl, 'stop_option'); unless (defined $nl->get_value('stop_ymd')) { add_default($nl, 'stop_n'); } # Restart interval add_default($nl, 'restart_option'); # Start date # The following check should be done for CAM standalone builds only. if ($cam_build) { # When the user specifies ncdata there is no default for start_ymd since there is # no way to determine the corresponding date of the ncdata file. So only add # a default for start_ymd if the user has not specified ncdata. if (defined $nl->get_value('ncdata')) { unless (defined $nl->get_value('start_ymd')) { die "$ProgName - ERROR: It is not allowed to set ncdata without also setting start_ymd. \n"; } } else { add_default($nl, 'start_ymd'); } } # Orbit (if not coupled) # If orbital parameters have not been specified then check for orbit year. # If orbit year has not been specified, then set a default value. if ($cam_build) { if (not defined $nl->get_value('orb_obliq') or not defined $nl->get_value('orb_eccen') or not defined $nl->get_value('orb_mvelp') ) { if (not defined $nl->get_value('orb_iyear')) { add_default($nl, 'orb_iyear'); } } } add_default($nl, 'ocean_tight_coupling'); # Coupling interval # The default is for CAM to couple to the surface components every CAM timestep. # So start by making sure CAM's dtime is set. add_default($nl, 'dtime'); add_default($nl, 'atm_cpl_dt', 'val'=>$nl->get_value('dtime')); ############################### # namelist group: prof_inparm # ############################### # The default for timing output is to use separate files for each MPI task. # Change default to using a single file. add_default($nl, 'profile_single_file', 'val'=>'.true.'); #----------------------------------------------------------------------------------------------- # Add defaults for the CAM component my $chem = $cfg->get('chem'); my $waccm_chem = ($chem =~ "waccm_"); my $waccm_phys = $cfg->get('waccm_phys'); my $carma = $cfg->get('carma'); my $prog_species = $cfg->get('prog_species'); my $prog_ghg1 = ($chem =~ "trop_mozart" or $chem =~ "trop_strat" or $chem =~ "ghg" or $prog_species =~ "GHG"); my $prog_ghg2 = ($chem =~ "ghg" or $prog_species =~ "GHG"); my $ghg_chem = ($chem =~ "ghg"); my $aero_chem = ($chem =~ "aero" or $chem eq 'trop_mozart' or $chem eq 'trop_mozart_soa' or $chem =~ 'trop_strat' or $chem 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 =~ "trop_strat" or $chem =~ "super_fast_llnl") and !($chem_rad_passive)); # Check for eruptive volcano emissions. These will be radiatively active by default, but # only if using BAM and the camrt radiation package (cam4 physics) # or if using MAM and the rrtmg package (cam5 physics) my $rad_volcaero = $nl->get_value('prescribed_volcaero_file') ? 1 : 0; ################# # CAM namelists # ################# # Print conservation errors # Turn this off for PERGRO runs or for WACCM runs if ($cfg->get('pergro') or ($chem ne 'none')) { add_default($nl, 'print_energy_errors', 'val'=>'.false.'); } # 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, $drydep_list, $mam_drydep_list) = set_dep_lists( $cfgdir, $chem, $chem_proc_src, $chem_src_dir, $print ); if ($gas_wetdep_list){ add_default($nl, 'gas_wetdep_list', 'val'=>$gas_wetdep_list ); } if ($aer_wetdep_list){ add_default($nl, 'aer_wetdep_list', 'val'=>$aer_wetdep_list ); } if ($drydep_list){ add_default($nl, 'drydep_list', 'val'=>$drydep_list ); } if ($mam_drydep_list){ add_default($nl, 'aer_drydep_list', 'val'=>$mam_drydep_list ); } if ( $drydep_list ) { add_default($nl, 'depvel_file' ); add_default($nl, 'depvel_lnd_file' ); add_default($nl, 'clim_soilw_file' ); add_default($nl, 'season_wes_file' ); } } # Initial conditions # # Most of the attributes that are matched to determine the default initial file are # build time options that come from the configuration object. But there are also a couple # of run time options that need to be considered. Set those in the optional hash argument # to add_default. # # Check for aqua-planet run: my %atts = (); # The initial date is an attribute in the defaults file which should be matched unless # the user explicitly requests to ignore the initial date via the -ignore_ic_date option, # or just ignore the year of the initial date via the -ignore_ic_year option. my $ic_date = $nl->get_value('start_ymd'); if ($opts{'ignore_ic_date'}) { # Don't set any attribute for date matching. By putting this option first it # will take precedence in the case that the user has set both -ignore_ic_date # and -ignore_ic_year } elsif ($opts{'ignore_ic_year'}) { $atts{'ic_md'} = $ic_date; } else { # if neither option specified then match full date $atts{'ic_ymd'} = $ic_date; } add_default($nl, 'ncdata', %atts); # # Simulated years: sim_year and sim_year_start # # sim_year # This is used to identify appropriate defaults for climatological or transient # forcing datasets. If user hasn't specified then default to 2000 (present day climatology). my $sim_year = '2000'; if (defined $nl->get_value('sim_year')) { $sim_year = $nl->get_value('sim_year'); # strip quotes to use the value in attribute matching. $sim_year =~ s/['"]//g; #"' } # sim_year_start # If sim_year is input as a range of years, then select the first year # to use with some datasets my $sim_year_start = $sim_year; if ($sim_year =~ /(\d+)-(\d+)/) { $sim_year_start = $1; } # Topography add_default($nl, 'bnd_topo', 'nofail'=>1); # Tropopause climatology add_default($nl, 'tropopause_climo_file'); # Solar irradiance if ($chem eq 'none') { # this preserves the 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_const', 'val'=>'-9999.'); } } # 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'); } if (($chem =~ /waccm_mozart/ )or($rad_pkg =~ /rrtmg/)) { add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.true.'); } else { add_default($nl, 'solar_htng_spctrl_scl', 'val'=>'.false.'); } # COSP simulator if ($cfg->get('cosp')) { add_default($nl, 'docosp', 'val'=>'.true.'); } # Constituents # ============ # Carbon cycle constituents my $co2_cycle = $cfg->get('co2_cycle'); if ($co2_cycle) { # co2_flag turns on the co2_cycle code in CAM add_default($nl, 'co2_flag', 'val'=>'.true.'); # Supply a fossil fuel dataset if the co2_cycle is active and it's a # transient run ... if ($sim_year =~ /(\d+)-(\d+)/) { add_default($nl, 'co2_readflux_fuel', 'val'=>'.true.'); # Check whether user has explicitly turned off reading the fossil fuel dataset. # (user specification has higher precedence than the true value set above) if ($nl->get_value('co2_readflux_fuel') =~ /$TRUE/io) { add_default($nl, 'co2flux_fuel_file', 'sim_year'=>$sim_year); } } } # By default the prognostic co2_cycle CO2 will be radiative active, unless the # the user sets this override variable. This is used below to construct the # rad_climate variable. my $co2_cycle_rad_passive = ($nl->get_value('co2_cycle_rad_passive') =~ /$TRUE/io); # If test tracers have been requested, set tracers_flag=.true. if ($cfg->get('nadv_tt')) { add_default($nl, 'tracers_flag', 'val'=>'.true.'); } if ($cfg->get('age_of_air_trcs')) { add_default($nl, 'aoa_tracers_flag', 'val'=>'.true.'); } # If phys option is "cam3" then turn on the CAM3 prescribed ozone and aerosols if ($phys eq 'cam3' and !$aqua_mode) { add_default($nl, 'cam3_ozone_data_on', 'val'=>'.true.'); add_default($nl, 'cam3_aero_data_on', 'val'=>'.true.'); } # Defaults for radiatively active constituents my $cam3_ozone_data = $FALSE; my $cam3_aero_data = $FALSE; my $moz_ozone_data = $FALSE; if (!$rad_prog_ozone) { $moz_ozone_data = $TRUE; } my $moz_aero_data = $FALSE; if (!($rad_prog_ocarb) or !($rad_prog_bcarb) or !($rad_prog_sulf) or !($rad_prog_dust) or !($rad_prog_sslt)){ $moz_aero_data = $TRUE; } # CAM3 prescribed ozone only by request if (defined $nl->get_value('cam3_ozone_data_on') and $nl->get_value('cam3_ozone_data_on') =~ /$TRUE/io) { add_default($nl, 'bndtvo'); $cam3_ozone_data = $TRUE; $moz_ozone_data = $FALSE; } # CAM3 prescribed aerosols only by request if (defined $nl->get_value('cam3_aero_data_on') and $nl->get_value('cam3_aero_data_on') =~ /$TRUE/io) { # CAM3 aerosol mass climatology dataset (horizontal resolution dependent) add_default($nl, 'bndtvaer'); $cam3_aero_data = $TRUE; $moz_aero_data = $FALSE; } if ($chem_rad_passive or $aqua_mode) { add_default($nl, 'atm_dep_flux', 'val'=>'.false.'); } # The aerosol optics depend on which radiative transfer model is used due to differing # wavelength bands used. my $rrtmg = $rad_pkg eq 'rrtmg' ? 1 : 0; # @aero_names contains the names of the entities (bulk aerosols and modes) # that are externally mixed in aerosol optics calculation. These entities are all # associated with a file that contains their physical and optical properties. my @aero_names = (); # @aerosources contains a source identifier corresponding to each entity in @aero_names. # The values are 'A', 'N', or 'M' my @aerosources = (); ## Start assembling the gas contributions to the rad_climate specifier. # $radval contains the "list of strings" value (stored as a scalar string with embedded quotes # and commas) that will be assigned to the namelist variable rad_climate. my $radval = "'A:Q:H2O'"; if ($chem =~ /waccm_mozart/ 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 =~ /trop_strat/) and !$chem_rad_passive ) { $radval .= ",'A:N2O:N2O','A:CH4:CH4','A:CFC11:CFC11','A:CFC12:CFC12'"; } elsif (($chem =~ /waccm_mozart/) 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 { if ($chem eq 'none') { # If no chemistry then there must be prescribed aerosols unless physics # package is adiabatic or ideal. if ($phys eq 'adiabatic' or $phys eq 'ideal') { $prescribed_aero_model = 'none'; } elsif ($phys eq 'cam3' or $phys eq 'cam4') { $prescribed_aero_model = 'bulk'; } else { $prescribed_aero_model = 'modal'; } } } # $aer_model is either 'bam' or 'mam'. This token is used in the element names that # are constructed to get the default physprops files. my $aer_model = 'bam'; if ($prescribed_aero_model eq 'modal' or $chem =~ /_mam/) {$aer_model = 'mam';} if ($aer_model eq 'mam' ) { my $aero_modes = '3mode'; if ($chem =~ /_mam7/) {$aero_modes = '7mode';} my @mode_names; my @mode_types; my @mode_num; my @mode_num_cw ; my @mode_spec ; my @mode_spec_type; my @mode_spec_cw; my @mode_num_src; my @mode_spec_src; if ($aero_modes eq '3mode' ) { # MAM rad_climate settings. The externally mixed quantities in the modal aerosol # model are the modes. push @aero_names, qw(mam3_mode1 mam3_mode2 mam3_mode3); push @aerosources, qw(M: M: M:); # Each of the mode names put into the @aero_names array needs to be defined. @mode_names = qw(mam3_mode1 mam3_mode2 mam3_mode3); @mode_types = qw(accum aitken coarse); @mode_num = qw(num_a1 num_a2 num_a3); @mode_num_cw = qw(num_c1 num_c2 num_c3); @mode_spec = ( [qw(so4_a1 pom_a1 soa_a1 bc_a1 dst_a1 ncl_a1)], [qw(so4_a2 soa_a2 ncl_a2)], [qw(dst_a3 ncl_a3 so4_a3)], ); @mode_spec_type = ( [qw(sulfate p-organic s-organic black-c dust seasalt)], [qw(sulfate s-organic seasalt)], [qw(dust seasalt sulfate)], ); @mode_spec_cw = ( [qw(so4_c1 pom_c1 soa_c1 bc_c1 dst_c1 ncl_c1)], [qw(so4_c2 soa_c2 ncl_c2)], [qw(dst_c3 ncl_c3 so4_c3)], ); if ($chem =~ /_mam3/) { @mode_num_src = qw(A A A); @mode_spec_src = ( [qw(A A A A A A)], [qw(A A A)], [qw(A A A)], ); } else { @mode_num_src = qw(N N N); @mode_spec_src = ( [qw(N N N N N N)], [qw(N N N)], [qw(N N N)], ); } } else { # For 7 modes # MAM rad_climate settings. The externally mixed quantities in the modal aerosol # model are the modes. push @aero_names, qw(mam7_mode1 mam7_mode2 mam7_mode3 mam7_mode4 mam7_mode5 mam7_mode6 mam7_mode7); push @aerosources, qw(M: M: M: M: M: M: M:); # Each of the mode names put into the @aero_names array needs to be defined. @mode_names = qw(mam7_mode1 mam7_mode2 mam7_mode3 mam7_mode4 mam7_mode5 mam7_mode6 mam7_mode7); @mode_types = qw(accum aitken primary_carbon fine_seasalt fine_dust coarse_seasalt coarse_dust); @mode_num = qw(num_a1 num_a2 num_a3 num_a4 num_a5 num_a6 num_a7); @mode_num_cw = qw(num_c1 num_c2 num_c3 num_c4 num_c5 num_c6 num_c7); @mode_spec = ( [qw(so4_a1 nh4_a1 pom_a1 soa_a1 bc_a1 ncl_a1)], [qw(so4_a2 nh4_a2 soa_a2 ncl_a2)], [qw(pom_a3 bc_a3)], [qw(ncl_a4 so4_a4 nh4_a4)], [qw(dst_a5 so4_a5 nh4_a5)], [qw(ncl_a6 so4_a6 nh4_a6)], [qw(dst_a7 so4_a7 nh4_a7)], ); @mode_spec_type = ( [qw(sulfate ammonium p-organic s-organic black-c seasalt)], [qw(sulfate ammonium s-organic seasalt)], [qw(p-organic black-c)], [qw(seasalt sulfate ammonium)], [qw(dust sulfate ammonium)], [qw(seasalt sulfate ammonium)], [qw(dust sulfate ammonium)], ); @mode_spec_cw = ( [qw(so4_c1 nh4_c1 pom_c1 soa_c1 bc_c1 ncl_c1)], [qw(so4_c2 nh4_c2 soa_c2 ncl_c2)], [qw(pom_c3 bc_c3)], [qw(ncl_c4 so4_c4 nh4_c4)], [qw(dst_c5 so4_c5 nh4_c5)], [qw(ncl_c6 so4_c6 nh4_c6)], [qw(dst_c7 so4_c7 nh4_c7)], ); @mode_num_src = qw(A A A A A A A); @mode_spec_src= ( [qw(A A A A A A)], [qw(A A A A)], [qw(A A)], [qw(A A A)], [qw(A A A)], [qw(A A A)], [qw(A A A)], ); } my $mode_defs = create_mode_defs(\@mode_names, \@mode_types, \@mode_num, \@mode_num_cw, \@mode_num_src, \@mode_spec, \@mode_spec_type, \@mode_spec_cw, \@mode_spec_src); add_default($nl, 'mode_defs', 'val'=>$mode_defs); # 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"; } # 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); } } } # 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); } } } } # Construct the aerosol part of the rad_climate string array by looping over # the aerosol names and getting the default properties file for each: foreach my $name (@aero_names) { my $source = shift(@aerosources); my $file; if ($source =~ 'M') { $file = "${name}_file"; } else { $file = "${aer_model}_$name"; } my $rel_filepath = get_default_value($file); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $radval .= "," . quote_string($source . $name . ":" . $abs_filepath); } # Eruptive volcanic aerosols can be run with either BAM or MAM. if ($rad_volcaero) { my $rel_filepath = get_default_value("VOLC_MMR"); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $radval .= "," . quote_string("N:VOLC_MMR:" . $abs_filepath); } # CARMA RRTMG and CAMRT # # Stratospheric black carbon if ($carma eq 'bc_strat') { my $rel_filepath; if ($aer_model eq 'bam') { $rel_filepath = get_default_value("${aer_model}_bcar1"); } else { $rel_filepath = get_default_value("${aer_model}_bc_a1"); } my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); my @val = ('SOOT01'); foreach my $val (@val) { $radval .= "," . quote_string("A:" . $val . ":" . $abs_filepath); } } if ($rrtmg) { # CARMA Microphysics - RRTMG Only # # New CARMA models that have radiatively active tracers need to define the name of # each of the radiatively active constituents. if ($carma eq 'test_radiative') { my @val = ('DUST01', 'DUST02', 'DUST03', 'DUST04', 'DUST05', 'DUST06', 'DUST07', 'DUST08', 'DUST09', 'DUST10', 'DUST11', 'DUST12', 'DUST13', 'DUST14', 'DUST15', 'DUST16'); foreach my $val (@val) { $radval .= "," . quote_string("A:" . $val . ":" . $carma . "_" . $val . "_rrtmg.nc"); } } } # Stratospheric sulfur aerosols if ($nl->get_value('strat_aero_feedback') =~ /$TRUE/io) { my $rel_filepath = get_default_value("VOLC_MMR"); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $radval .= "," . quote_string("N:H2SO4M:" . $abs_filepath); } add_default($nl, 'rad_climate', 'val'=>$radval); # Cloud optics if ($rrtmg) { add_default($nl, 'liqcldoptics'); add_default($nl, 'icecldoptics'); add_default($nl, 'liqopticsfile'); add_default($nl, 'iceopticsfile'); } # Volcanic Aerosol Mass climatology dataset if ($nl->get_value('strat_volcanic')) { add_default($nl, 'bndtvvolc'); } # Greenhouse gas production/loss rates if ($ghg_chem) { add_default($nl, 'bndtvg'); add_default($nl, 'ghg_chem', 'val'=>".true."); } # WACCM-GHG options if ($chem eq 'waccm_ghg') { # *** Note *** this dataset only needed for waccm_ghg. # O2,O1,N2, CO2 Constituents for non-LTE calculations and heating rates below 200 nm unless (defined $nl->get_value('waccm_forcing_file')) { add_default($nl, 'waccm_forcing_datapath'); add_default($nl, 'waccm_forcing_file'); } add_default($nl, 'nlte_use_mo', 'val'=>".false."); add_default($nl, 'h2orates'); add_default($nl, 'solar_parms_file'); add_default($nl, 'do_circulation_diags', 'val'=>'.true.'); } 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_file', 'SO2 -> ' => 'so2_emis_file', 'SO4 -> ' => 'so4_emis_file', ); 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'); } add_default($nl, 'use_cam_sulfchem', 'val'=>".true."); } if ( $prog_species =~ /OC/ ) { my %emis = ('OC1 -> ' => 'oc1_emis_file', ); 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_file', ); 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' ); } if ( $emisval ) { 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'); } } 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' ) { $val = "'num_a1','bc_a1', 'dst_a1','ncl_a1'," . "'pom_a1','so4_a1','soa_a1','num_a2'," . "'ncl_a2','so4_a2','soa_a2','num_a3'," . "'dst_a3','ncl_a3','so4_a3'," . "'num_c1_pbf:num_c1','bc_c1_pbf:bc_c1', 'dst_c1_pbf:dst_c1','ncl_c1_pbf:ncl_c1'," . "'pom_c1_pbf:pom_c1','so4_c1_pbf:so4_c1','soa_c1_pbf:soa_c1','num_c2_pbf:num_c2'," . "'ncl_c2_pbf:ncl_c2','so4_c2_pbf:so4_c2','soa_c2_pbf:soa_c2','num_c3_pbf:num_c3'," . "'dst_c3_pbf:dst_c3','ncl_c3_pbf:ncl_c3','so4_c3_pbf:so4_c3'," . "'NCAI','NCAL'"; } else { $val = "'sulf:SO4','bcar1:CB1','bcar2:CB2','ocar1:OC1','ocar2:OC2'," . "'sslt1:SSLT01','sslt2:SSLT02','sslt3:SSLT03','sslt4:SSLT04'," . "'dust1:DST01','dust2:DST02','dust3:DST03','dust4:DST04'"; } add_default($nl, 'prescribed_aero_specifier', 'val'=>$val); } } my $megan_emis = defined $nl->get_value('megan_specifier'); if ( $megan_emis ) { add_default($nl, 'megan_factors_file'); } # Tropospheric full chemistry options if ($chem =~ /trop_mozart/ or $chem =~ /trop_strat/ ) { # Surface emission datasets: my %verhash; my $val; my %species = ('CH3COCH3 -> ' => 'acetone_emis_file', 'BIGALK -> ' => 'bigalk_emis_file', 'BIGENE -> ' => 'bigene_emis_file', 'C2H4 -> ' => 'c2h4_emis_file', 'C2H5OH -> ' => 'c2h5oh_emis_file', 'C2H6 -> ' => 'c2h6_emis_file', 'C3H6 -> ' => 'c3h6_emis_file', 'C3H8 -> ' => 'c3h8_emis_file', 'CH2O -> ' => 'ch2o_emis_file', 'CH3CHO -> ' => 'ch3cho_emis_file', 'CH3OH -> ' => 'ch3oh_emis_file', 'CO -> ' => 'co_emis_file', 'DMS -> ' => 'dms_emis_file', 'MEK -> ' => 'mek_emis_file', 'NH3 -> ' => 'nh3_emis_file', 'NO -> ' => 'nox_emis_file', 'SO2 -> ' => 'so2_emis_file', 'HCN -> ' => 'hcn_emis_file', 'HCOOH -> ' => 'hcooh_emis_file', 'CH3CN -> ' => 'ch3cn_emis_file', 'C2H2 -> ' => 'c2h2_emis_file', 'CH3COOH -> ' => 'ch3cooh_emis_file', 'C10H16 -> ' => 'c10h16_emis_file', 'ISOP -> ' => 'isop_emis_file', ); if ($chem =~ /mam3/) { %species = (%species, 'SOAG -> ' => 'soag_emis_file', 'bc_a1 -> ' => 'bc_a1_emis_file', 'pom_a1 -> ' => 'pom_a1_emis_file', 'so4_a1 -> ' => 'so4_a1_emis_file', 'so4_a2 -> ' => 'so4_a2_emis_file', 'num_a1 -> ' => 'num_a1_emis_file', 'num_a2 -> ' => 'num_a2_emis_file', ); %verhash = ('ver'=>'mam'); } elsif ($chem =~ /mam7/) { %species = (%species, 'SOAG -> ' => 'soag_emis_file', 'bc_a3 -> ' => 'bc_a3_emis_file', 'num_a1 -> ' => 'mam7_num_a1_emis_file', 'num_a2 -> ' => 'num_a2_emis_file', 'num_a3 -> ' => 'mam7_num_a3_emis_file', 'pom_a3 -> ' => 'pom_a3_emis_file', 'so4_a1 -> ' => 'so4_a1_emis_file', 'so4_a2 -> ' => 'so4_a2_emis_file', ); %verhash = ('ver'=>'mam'); } else { %species = (%species, 'CB1 -> ' => 'cb1_emis_file', 'CB2 -> ' => 'cb2_emis_file', 'OC1 -> ' => 'oc1_emis_file', 'OC2 -> ' => 'oc2_emis_file', ); } if ($chem =~ /_soa/) { %species = (%species, 'BENZENE -> ' => 'soa_benzene_emis_file', 'XYLENE -> ' => 'soa_xylene_emis_file', 'TOLUENE -> ' => 'soa_toluene_emis_file', ); } else { %species = (%species, 'TOLUENE -> ' => 'toluene_emis_file', ); } my $first = 1; my $pre = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id},\%verhash); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $val .= $pre . quote_string($id . $abs_filepath); if ($first) { $pre = ","; $first = 0; } } add_default($nl, 'srf_emis_specifier', 'val'=>$val); unless (defined $nl->get_value('srf_emis_type')) { add_default($nl, 'srf_emis_type', 'val'=>'CYCLICAL'); add_default($nl, 'srf_emis_cycle_yr','val'=>'2000'); } # aircraft emission datasets: %species = (); my $cyc_yr = '1999'; if ($chem eq 'trop_strat_bam_v1') { %species = ( 'NO2 -> ' => 'no2_aircraft_emis_file', 'CB1 -> ' => 'bc_aircraft_emis_file' ); } elsif ($chem =~ /mam3/) { %species = ( 'NO2 -> ' => 'no2_aircraft_emis_file', 'SO2 -> ' => 'so2_ext_file', 'so4_a1 -> ' => 'so4_a1_ext_file', 'so4_a2 -> ' => 'so4_a2_ext_file', 'pom_a1 -> ' => 'pom_a1_ext_file', 'bc_a1 -> ' => 'bc_a1_ext_file', 'num_a1 -> ' => 'num_a1_ext_file', 'num_a2 -> ' => 'num_a2_ext_file', ); $cyc_yr = '2000'; } elsif ($chem =~ /mam7/) { %species = ( 'NO2 -> ' => 'no2_aircraft_emis_file', 'so4_a1 -> ' => 'so4_a1_ext_file', 'so4_a2 -> ' => 'so4_a2_ext_file', 'pom_a3 -> ' => 'pom_a3_ext_file', 'bc_a3 -> ' => 'bc_a3_ext_file', 'num_a1 -> ' => 'mam7_num_a1_ext_file', 'num_a2 -> ' => 'num_a2_ext_file', 'num_a3 -> ' => 'mam7_num_a3_ext_file', ); $cyc_yr = '2000'; } else { %species = ( 'CO -> ' => 'co_aircraft_emis', 'NO -> ' => 'no_aircraft_emis', 'SO2 -> ' => 'so2_aircraft_emis', ); } $first = 1; $pre = ""; $val = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id},\%verhash); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $val .= $pre . quote_string($id . $abs_filepath); if ($first) { $pre = ","; $first = 0; } } add_default($nl, 'ext_frc_specifier', 'val'=>$val); unless (defined $nl->get_value('ext_frc_type')) { add_default($nl, 'ext_frc_type', 'val'=>'CYCLICAL'); add_default($nl, 'ext_frc_cycle_yr', 'val'=>$cyc_yr); } # # if ($chem =~ /trop_mozart/) { # Species with fixed stratosphere values $val = "'O3','NO','NO2','HNO3','CO','CH4','N2O','N2O5'"; add_default($nl, 'fstrat_list', 'val'=>$val); add_default($nl, 'fstrat_file'); } # Species with fixed lower boundary if ($chem =~ /trop_strat/) { $val = "'CCL4','CF2CLBR','CF3BR','CFC11','CFC113','CFC12','CH3BR','CH3CCL3','CH3CL','CH4','CO2','H2','HCFC22','N2O'"; } else { $val = "'CH4','H2','N2O'"; } add_default($nl, 'flbc_list', 'val'=>$val); unless (defined $nl->get_value('flbc_type')) { add_default($nl, 'flbc_type', 'val'=>'CYCLICAL'); add_default($nl, 'flbc_cycle_yr', 'val'=>'2000'); } # Datasets my @files = ( 'soil_erod', 'flbc_file', 'xs_coef_file','xs_short_file','xs_long_file', 'rsf_file', 'exo_coldens_file', 'sulf_file', 'sad_file' ); foreach my $file (@files) { add_default($nl, $file); } unless (defined $nl->get_value('sad_type')) { add_default($nl, 'sad_type', 'val'=>'CYCLICAL'); add_default($nl, 'sad_cycle_yr', 'val'=>'2000'); } } # Prognostic aerosols via CAM-Chem package. # BAM settings if ($chem eq 'trop_bam') { # add_default($nl, 'use_cam_sulfchem', 'val'=>'.true.'); my %species; # Surface emission datasets: %species = (); %species = ('CB1 -> ' => 'cb1_emis_file', 'DMS -> ' => 'dms_emis_file', 'OC1 -> ' => 'oc1_emis_file', 'SO2 -> ' => 'so2_emis_file', 'SO4 -> ' => 'so4_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); 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 add_default($nl, 'soil_erod'); } 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', 'flbc_file', 'fstrat_file', 'sulf_file', 'tuv_xsect_file', 'o2_xsect_file', 'xs_long_file', 'rsf_file', 'solar_parms_file', 'exo_coldens_file', 'sad_file', 'linoz_data_path' , 'linoz_data_file', 'chlorine_loading_file' ); foreach my $file (@files) { add_default($nl, $file); } unless (defined $nl->get_value('sad_type')) { add_default($nl, 'sad_type', 'val'=>'CYCLICAL'); add_default($nl, 'sad_cycle_yr', 'val'=>'1990'); } unless (defined $nl->get_value('flbc_type')) { add_default($nl, 'flbc_type', 'val'=>'CYCLICAL'); add_default($nl, 'flbc_cycle_yr', 'val'=>'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') { # add_default($nl, 'use_cam_sulfchem', 'val'=>'.false.'); # 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', ); } 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}, \%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); 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); 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', 'flbc_file', 'fstrat_file', 'sulf_file', 'tuv_xsect_file', 'o2_xsect_file', 'xs_long_file', 'rsf_file', 'solar_parms_file', 'exo_coldens_file', 'sad_file', 'linoz_data_path' , 'linoz_data_file', 'chlorine_loading_file' ); foreach my $file (@files) { add_default($nl, $file); } unless (defined $nl->get_value('sad_type')) { add_default($nl, 'sad_type', 'val'=>'CYCLICAL'); add_default($nl, 'sad_cycle_yr', 'val'=>'1990'); } unless (defined $nl->get_value('flbc_type')) { add_default($nl, 'flbc_type', 'val'=>'CYCLICAL'); add_default($nl, 'flbc_cycle_yr', 'val'=>'2000'); } unless (defined $nl->get_value('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'); } } if ($chem eq 'trop_mam3') { # add_default($nl, 'use_cam_sulfchem', 'val'=>'.false.'); 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 $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'); # Vertical emission datasets: %species = (); %species = ('SO2 -> ' => 'so2_ext_file', 'so4_a1 -> ' => 'so4_a1_ext_file', 'so4_a2 -> ' => 'so4_a2_ext_file', 'pom_a1 -> ' => 'pom_a1_ext_file', 'bc_a1 -> ' => 'bc_a1_ext_file', 'num_a1 -> ' => 'num_a1_ext_file', 'num_a2 -> ' => 'num_a2_ext_file', ); $first = 1; $pre = ""; $val = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id} ); 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'"); 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', 'xs_long_file', 'rsf_file', 'exo_coldens_file' ); foreach my $file (@files) { add_default($nl, $file); } } if ($chem eq 'waccm_mozart_mam3') { # add_default($nl, 'use_cam_sulfchem', 'val'=>'.false.'); my %species; # Surface emission datasets: %species = (); %species = ('CH2O -> ' => 'ch2o_emis_file', 'CO -> ' => 'co_emis_file', 'NO -> ' => 'no_emis_file', 'DMS -> ' => 'dms_emis_file', 'SO2 -> ' => 'so2_emis_file', 'SOAG -> ' => 'soag_emis_file', 'bc_a1 -> ' => 'bc_a1_emis_file', 'pom_a1 -> ' => 'pom_a1_emis_file', 'so4_a1 -> ' => 'so4_a1_emis_file', 'so4_a2 -> ' => 'so4_a2_emis_file', 'num_a1 -> ' => 'num_a1_emis_file', 'num_a2 -> ' => 'num_a2_emis_file', ); my $first = 1; my $pre = ""; my $val = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id}); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $val .= $pre . quote_string($id . $abs_filepath); if ($first) { $pre = ","; $first = 0; } } add_default($nl, 'srf_emis_specifier', 'val'=>$val); add_default($nl, 'srf_emis_type', 'val'=>'CYCLICAL'); # Vertical emission datasets: %species = (); %species = ('NO2 -> ' => 'no2_ext_file', 'SO2 -> ' => 'so2_ext_file', 'so4_a1 -> ' => 'so4_a1_ext_file', 'so4_a2 -> ' => 'so4_a2_ext_file', 'pom_a1 -> ' => 'pom_a1_ext_file', 'bc_a1 -> ' => 'bc_a1_ext_file', 'num_a1 -> ' => 'num_a1_ext_file', 'num_a2 -> ' => 'num_a2_ext_file', ); $first = 1; $pre = ""; $val = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id}); if (length($rel_filepath) > 0) { my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $val .= $pre . quote_string($id . $abs_filepath); if ($first) { $pre = ","; $first = 0; } } } add_default($nl, 'ext_frc_specifier', 'val'=>$val); unless (defined $nl->get_value('ext_frc_type')) { add_default($nl, 'ext_frc_type', 'val'=>'CYCLICAL'); add_default($nl, 'ext_frc_cycle_yr', 'val'=>'2000'); } # Prescribed species add_default($nl, 'xactive_prates', 'val'=>'.false.'); # Datasets my @files = ('soil_erod', 'xs_long_file', 'rsf_file', 'exo_coldens_file' ); foreach my $file (@files) { add_default($nl, $file); } } if ($chem eq 'trop_mam7') { # add_default($nl, 'use_cam_sulfchem', 'val'=>'.false.'); my %species; # Surface emission datasets: add_default($nl, 'srf_emis_type', 'val'=>'CYCLICAL'); %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); 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); 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', 'xs_long_file', 'rsf_file', 'exo_coldens_file' ); foreach my $file (@files) { add_default($nl, $file); } } # WACCM_MOZART options. if ($chem =~ /waccm_mozart/) { # Species with fixed lower boundary my $val = "'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2', 'HCFC22','N2O'"; if ($chem eq 'waccm_mozart_sulfur') { $val .= ",'OCS'"; } add_default($nl, 'flbc_list', 'val'=>$val); unless (defined $nl->get_value('flbc_type')) { add_default($nl, 'flbc_type', 'val'=>'CYCLICAL'); add_default($nl, 'flbc_cycle_yr', 'val'=>'1990'); } unless (defined $nl->get_value('sad_type')) { add_default($nl, 'sad_type', 'val'=>'CYCLICAL'); add_default($nl, 'sad_cycle_yr', 'val'=>'1990'); } # Datasets my @files = ('flbc_file', 'efield_lflux_file', 'efield_hflux_file', 'efield_wei96_file', 'euvacdat_file', 'photon_file', 'electron_file', 'euvac_file', 'solar_parms_file', 'sad_file', 'sulf_file', 'depvel_lnd_file', 'clim_soilw_file', 'season_wes_file', 'xs_coef_file', 'xs_short_file','xs_long_file', 'rsf_file', 'tgcm_ubc_file', 'snoe_ubc_file', 'soil_erod' ); 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' ); } if ($chem eq 'waccm_mozart_sulfur') { $species{ 'SO2 -> ' } = ( 'so2_aircraft_emis' ); } my $first = 1; my $pre = ""; my $val = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id}); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $val .= $pre . quote_string($id . $abs_filepath); if ($first) { $pre = ","; $first = 0; } } add_default($nl, 'ext_frc_specifier', 'val'=>$val); unless (defined $nl->get_value('ext_frc_type')) { add_default($nl, 'ext_frc_type', 'val'=>'CYCLICAL'); add_default($nl, 'ext_frc_cycle_yr', 'val'=>'1999'); } # Surface emission datasets: my $val; my %species = ('CO -> ' => 'co_emis_file', 'CH2O -> ' => 'ch2o_emis_file', 'NO -> ' => 'nox_emis_file' ); if ($chem eq 'waccm_mozart_sulfur') { $species{ 'SO2 -> ' } = ( 'so2_emis_file' ); } my $first = 1; my $pre = ""; foreach my $id (sort keys %species) { my $rel_filepath = get_default_value($species{$id}); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); $val .= $pre . quote_string($id . $abs_filepath); if ($first) { $pre = ","; $first = 0; } } add_default($nl, 'srf_emis_specifier', 'val'=>$val); unless (defined $nl->get_value('srf_emis_type')) { add_default($nl, 'srf_emis_type', 'val'=>'CYCLICAL'); add_default($nl, 'srf_emis_cycle_yr', 'val'=>'1997'); } add_default($nl, 'xactive_prates', 'val'=>'.false.'); add_default($nl, 'do_circulation_diags', 'val'=>'.true.'); } my $lbc_file = $nl->get_value('flbc_file'); if ( ! defined $lbc_file ) { # It's assumed that the LBC file used in WACCM/CAM-Chem contains the # necessary GHGs # Greenhouse gas surface values (default to 2000 values) my $scenario_ghg = $nl->get_value('scenario_ghg'); if ((defined $scenario_ghg) and $scenario_ghg =~ /RAMPED/) { # read values from dataset add_default($nl, 'bndtvghg'); } else { # Fixed values for all GHGs. The co2vmr value may just be the # starting value if scenario_ghg == RAMP_CO2_ONLY 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 =~ /homme/) { add_default($nl, 'drydep_srf_file'); } } # Physics options # Add the name of the physics package based on the info in configure. If the user tries # to explicitly specify this namelist variable issue error. my $cam_physpkg = $nl->get_value('cam_physpkg'); if (defined $cam_physpkg) { die "CAM Namelist ERROR: User may not specify the value of cam_physpkg.\n". "This variable is set by build-namelist based on information\n". "from the configure cache file.\n"; } $cam_physpkg = "'" . "$phys" . "'"; # add quotes to this string value $nl->set_variable_value('phys_ctl_nl', 'cam_physpkg', $cam_physpkg); # WACCM-X runtime options add_default($nl, 'waccmx_opt'); # Chemistry options # Add the name of the chemistry package based on the info in configure. If the user tries # to explicitly specify this namelist variable issue error. my $cam_chempkg = $nl->get_value('cam_chempkg'); if (defined $cam_chempkg) { die "CAM Namelist ERROR: User may not specify the value of cam_chempkg.\n". "This variable is set by build-namelist based on information\n". "from the configure cache file.\n"; } if (($chem eq 'waccm_mozart_v1') or ($chem eq 'waccm_mozart_sulfur')) { $cam_chempkg = "'" . 'waccm_mozart'. "'"; } else { $cam_chempkg = "'" . "$chem" . "'"; # add quotes to this string value } $nl->set_variable_value('phys_ctl_nl', 'cam_chempkg', $cam_chempkg); # Deep convection scheme add_default($nl, 'deep_scheme'); # Radiation scheme add_default($nl, 'radiation_scheme'); # Eddy scheme (vertical diffusion) add_default($nl, 'eddy_scheme'); # Defaults for shallow convection scheme and surface flux averaging both depend # on the value of the eddy scheme. my $eddy_scheme = $nl->get_value('eddy_scheme'); # Need to strip the quotes to use as a value for attribute matching. $eddy_scheme =~ s/['"]//g; #"' add_default($nl, 'shallow_scheme', 'eddy_scheme'=>$eddy_scheme); add_default($nl, 'srf_flux_avg', 'eddy_scheme'=>$eddy_scheme); # Microphysics scheme add_default($nl, 'microp_scheme'); add_default($nl, 'macrop_scheme'); add_default($nl, 'history_microphysics'); # CLUBB_SGS add_default($nl, 'do_clubb_sgs'); add_default($nl, 'clubb_history'); add_default($nl, 'clubb_rad_history'); # Turbulent Mountain Stress add_default($nl, 'do_tms'); my $do_tms = $nl->get_value('do_tms'); # Check to be sure that do_tms has been set to true if the user sets a customized # value of tms_orocnst or tms_z0fac. if (defined $nl->get_value('tms_orocnst') or defined $nl->get_value('tms_z0fac')) { # a tms parameter has been set in the namelist. Make sure do_tms is true. if ( $do_tms =~ /$FALSE/io ) { die "CAM Namelist ERROR: If tms_oroconst or tms_z0fac is set do_tms must be .true..\n". "Either remove these from the namelist or add do_tms=.true.\n"; } } if ( $do_tms =~ /$TRUE/io ) { add_default($nl, 'tms_orocnst'); add_default($nl, 'tms_z0fac'); } # Implicit Turbulent Surface Stress add_default($nl, 'do_iss'); # Use Convective water in radiation add_default($nl, 'conv_water_in_rad'); # 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'); # condensate to rain autoconversion coefficients add_default($nl, 'zmconv_c0_lnd'); add_default($nl, 'zmconv_c0_ocn'); add_default($nl, 'zmconv_ke'); # moist convection rainwater coefficients add_default($nl, 'hkconv_cmftau'); add_default($nl, 'hkconv_c0'); if ($phys eq 'cam5') { add_default($nl, 'uwshcu_rpen'); } # cldwat ice coefficients add_default($nl, 'cldwat_icritc'); add_default($nl, 'cldwat_icritw'); add_default($nl, 'cldwat_conke'); add_default($nl, 'cldwat_r3lcrit'); # Top level pressure for troposphere cloud physics add_default($nl, 'trop_cloud_top_press'); # Eddy Diffusivity Adjustments add_default($nl, 'kv_top_pressure'); add_default($nl, 'kv_top_scale'); add_default($nl, 'kv_freetrop_scale'); add_default($nl, 'eddy_lbulk_max'); add_default($nl, 'eddy_leng_max'); add_default($nl, 'eddy_max_bot_pressure'); add_default($nl, 'diff_cnsrv_mass_check'); # 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, 'wvsat_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.'); } 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_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 '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 'sea_salt') { add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_emission', 'val'=>'.true.'); add_default($nl, 'carma_do_vdiff', 'val'=>'.true.'); add_default($nl, 'carma_do_vtran', 'val'=>'.true.'); add_default($nl, 'carma_do_wetdep', 'val'=>'.true.'); add_default($nl, 'carma_do_WeibullK', 'val'=>'.false.'); add_default($nl, 'carma_seasalt_emis', 'val'=>'Gong'); } elsif ($carma eq 'sulfate') { add_default($nl, 'carma_do_coag', 'val'=>'.true.'); add_default($nl, 'carma_do_drydep', 'val'=>'.true.'); add_default($nl, 'carma_do_grow', 'val'=>'.true.'); add_default($nl, 'carma_do_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'); } # Cloud sedimentation add_default($nl, 'cldsed_ice_stokes_fac'); # Dust emissions tuning factor # If dust is prognostic ==> supply the tuning factor if ($chem =~ /_mam/ or $chem =~ /_bam/ or $chem =~ /trop_/) { # check whether turbulent mountain stress parameterization is on if ($nl->get_value('do_tms') =~ /$TRUE/io) { add_default($nl, 'dust_emis_fact', 'tms'=>'1'); } else { add_default($nl, 'dust_emis_fact'); } } # Gravity wave drag settings if ($waccm_phys) { add_default($nl, 'gw_drag_file'); } else { add_default($nl, 'fcrit2'); } # FV dycore if ($cfg->get('dyn') eq 'fv') { add_default($nl, 'fft_flt'); add_default($nl, 'div24del2flag'); add_default($nl, 'del2coef'); add_default($nl, 'filtcw'); add_default($nl, 'nspltvrm'); # If the -ntasks argument has been set, then use it to set the default # FV decomposition unless the user has already set it. my $npr_yz = $nl->get_value('npr_yz'); if (defined $opts{'ntasks'} and ! defined $npr_yz ) { $npr_yz = fv_decomp_set(); add_default($nl, 'npr_yz', 'val'=>$npr_yz); } } # EUL dycore if ($cfg->get('dyn') eq 'eul') { add_default($nl, 'eul_nsplit'); } # Single column model if ($cfg->get('scam')) { add_default($nl, 'iopfile'); } # CAM generates IOP file for SCAM if ($cfg->get('camiop')) { add_default($nl, 'inithist', 'val'=>'CAMIOP'); add_default($nl, 'ndens', 'val'=>'1,1'); add_default($nl, 'mfilt', 'val'=>'1,10'); add_default($nl, 'nhtfrq', 'val'=>'0,1'); } # HOMME dycore # ============ if ($cfg->get('dyn') =~ /homme/) { #################################################### # namelist group: ctl_nl (for CAM_SE) # #################################################### my $hgrid = $cfg->get('hgrid'); if ($hgrid =~ /ne(.*)np/) { add_default($nl, 'se_ne', 'val'=>$1); } else { die "$ProgName - ERROR: Horizontal grid name can NOT be correctly parsed: hgrid = $hgrid. \n"; } my @vars = qw(se_nsplit hypervis_order phys_loadbalance hypervis_subcycle hypervis_subcycle_q statefreq se_partmethod se_topology se_ftype integration nu nu_div nu_p nu_q nu_top energy_fixer se_phys_tscale interpolate_analysis interp_nlat interp_nlon vert_remap_q_alg interp_type interp_gridtype se_limiter_option); foreach my $var (@vars) { add_default($nl, $var); } } #----------------------------------------------------------------------------------------------- # Add defaults for the CAM specific ocn model DOM. # Which ocean model? my $ocn_comp = $cfg->get('ocn'); my $ocn_group = ''; if ($ocn_comp eq 'dom') { $ocn_group = 'dom_inparm'; } if ($ocn_comp eq 'docn') { $ocn_group = 'docn_nml'; } # The following variables are set by namelist variables in the special camexp namelist # group. They are used to ensure consistency between the setting of namelist variables # in DOM and CICE. my $bndtvs = ''; my $bndtvs_domain = ''; my $focndomain = ''; # The %mask variable is used to set namelist defaults for CLM. my %mask = (); # Namelist settings for CAMDOM or DOCN # These namelists aren't needed for ideal, adiabatic, or aqua-planet modes. if ($cam_build and ($ocn_comp eq 'dom' or $ocn_comp eq 'docn') and ! $ideal_or_adia_or_aqua) { # Determine default values for variables that must be set consistently between these models. # sstcyc my $sstcyc = '.true.'; if (defined $nl->get_value('sstcyc')) { $sstcyc = $nl->get_value('sstcyc'); } # bndtvs add_default($nl, 'bndtvs', 'sim_year'=>$sim_year); $bndtvs = $nl->get_value('bndtvs'); # bndtvs_domain if ($dyn =~ /homme/){ add_default($nl, 'bndtvs_domain', 'sim_year'=>$sim_year); $bndtvs_domain = $nl->get_value('bndtvs_domain'); } # focndomain # For CAM in standalone mode, CAM determines the focndomain file to use, and then specifies # that file to DOM and CSIM4/CICE. add_default($nl, 'focndomain'); $focndomain = $nl->get_value('focndomain'); # Assume that the focndomain filename contains the name of the ocean grid used to construct # the lnd/ocn mask. Recover the ocean grid name using a regexp match, and use it subsequently # to determine consistent CLM files. if ($focndomain =~ m/_(gx\dv\d)_/) { $mask{'mask'} = $1; } elsif ($focndomain =~ m/_USGS_/) { $mask{'mask'} = 'USGS'; } ############################## # namelist group: dom_inparm # ############################## if ($ocn_group eq 'dom_inparm') { $nl->set_variable_value($ocn_group, 'sstcyc', $sstcyc); $nl->set_variable_value($ocn_group, 'bndtvs', $bndtvs); $nl->set_variable_value($ocn_group, 'focndomain', $focndomain); } } #----------------------------------------------------------------------------------------------- # Add defaults for the CLM component # Only produce a namelist for CLM if running with CAM standalone scripts # and if the lnd component is active. my $lnd_pkg = $cfg->get('lnd'); if ($lnd_pkg eq 'clm' and $cam_build and $lnd_active) { ############################## # namelist group: clm_inparm # ############################## # Timestep # *** N.B. *** this code enforces the constraint that the CLM timestep match the CAM timestep. # Note that a Namelist object method is used to add the value of dtime to clm_inparm to avoid # the namelist definition checking done by add_default. That's because dtime is in CAM's definition # file as a variable that belongs in cam_inparm and it can't also be in clm_inparm. This will be # resolved when the CLM component is made responsible for producing the clm_inparm namelist. my $clmval = $nl->get_value('dtime'); $nl->set_variable_value('clm_inparm', 'dtime', $clmval); # Check that "nrevsn" is set if this is a branch simulation if ($nl->get_value('start_type') =~ /branch/ and !defined $nl->get_value('nrevsn')) { die "$ProgName - ERROR: The CLM2 master restart file must be specified for a branch\n". " run. Set the namelist variable NREVSN to the absolute\n". " pathname for this dataset.\n". " This can be done on the command-line using the -namelist\n". " option or in an input namelist file that is specified\n". " using the -infile option.\n"; } add_default($nl, 'fatmlndfrc', %mask); add_default($nl, 'fsnowoptics'); add_default($nl, 'fsnowaging'); add_default($nl, 'fpftcon'); # CO2 # *** N.B. *** This is forced to use the same value that CAM is using. my $co2vmr = $nl->get_value('co2vmr'); if (defined $co2vmr) { my $co2_ppmv = sprintf '%e', $co2vmr * 1.e6; $nl->set_variable_value('clm_inparm', 'co2_ppmv', $co2_ppmv); } # All F compsets currently set co2_type='diagnostic' add_default($nl, 'co2_type', 'val'=>'diagnostic'); add_default($nl, 'urban_hac'); add_default($nl, 'urban_traffic'); add_default($nl, 'fsurdat', 'sim_year'=>$sim_year_start); # Initial conditions # The initial date is an attribute in the defaults file which should be matched unless # the user explicitly requests to ignore the initial date via the -ignore_ic_date option, # or just ignore the year of the initial date via the -ignore_ic_year option. my $ic_date = $nl->get_value('start_ymd'); if ($opts{'ignore_ic_date'}) { add_default($nl, 'finidat', 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask); } elsif ($opts{'ignore_ic_year'}) { add_default($nl, 'finidat', 'ic_md'=>$ic_date, 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask); } else { add_default($nl, 'finidat', 'ic_ymd'=>$ic_date, 'nofail'=>1, 'sim_year'=>$sim_year_start, %mask); } # If sim_year is input as a range of years, then add the dynamic PFT dataset. if ($sim_year =~ /(\d+)-(\d+)/) { add_default($nl, 'fpftdyn', 'sim_year'=>$sim_year) } } #----------------------------------------------------------------------------------------------- # Add defaults for the CICE component # Only produce a namelist for CICE if running with CAM standalone scripts. # Which sea ice model? my $ice_comp = $cfg->get('ice'); if ($ice_comp eq 'cice' and $cam_build and $ice_active) { # The CICE component has its own build-namelist utility. my $cice_bldnl = "$cam_root/models/ice/cice/bld/build-namelist"; # Set up the commandline args # CICE config_cache filepath my $cice_config_dir = $cfg->get('cice_config_cache_dir'); my $cice_config_file = $cfg->get('cice_config_cache_file'); my $cice_config_filepath = "$cice_config_dir/$cice_config_file"; if (defined $opts{'config_cice'}) { $cice_config_filepath = $opts{'config_cice'}; } # Pass namelist settings to CICE. my $cice_nl = "&ice \n"; if ($ocn_comp eq 'dom' or $ocn_comp eq 'docn') { # CICE namelist variables that need to be set consistently with CAM-DOM. $cice_nl .= "grid_file=$focndomain \n" . "kmt_file=$focndomain \n" . "stream_domfilename=$bndtvs \n" . "stream_fldfilename=$bndtvs \n" . "stream_fldvarname='ice_cov' \n"; # Check for variables used to specify the years of a multi-year SST dataset. # If not set by user, default to 0 which is the year used in the climatology files. my $stream_year_first = $nl->get_value('stream_year_first'); unless (defined $stream_year_first) { $stream_year_first = 0; } $cice_nl .= "stream_year_first=$stream_year_first \n"; # Set model_year_align equal to stream_year_first. The flexibility enabled # by model_year_align is not available in CAM-DOM. $cice_nl .= "model_year_align=$stream_year_first \n"; my $stream_year_last = $nl->get_value('stream_year_last'); unless (defined $stream_year_last) { $stream_year_last = 0; } $cice_nl .= "stream_year_last=$stream_year_last \n"; } # If the user has specified variables to send to the CICE build-namelist # via the -cice_nl argument then append them here. if (defined $opts{'cice_nl'}) { my $usr_cice_nl = $opts{'cice_nl'}; # strip off the leading group name and trailing terminator $usr_cice_nl =~ s/^\s*&\w+//; # group name with optional leading whitespace $usr_cice_nl =~ s/\/\s*$//; # slash terminator with optional trailing whitespace $cice_nl .= $usr_cice_nl; } # For CAM5 need to send the variable "cam5=.true." to get correct defaults for several # cice parameters. if ($phys eq 'cam5') { $cice_nl .= "cam5=.true. \n"; } $cice_nl .= "grid_type='latlon' \n"; $cice_nl .= "grid_format='nc' \n"; $cice_nl .= "stream_domtvarname='time' \n" . "stream_domxvarname='lon' \n" . "stream_domyvarname='lat' \n" . "stream_domareaname='area' \n" . "stream_dommaskname='mask' \n"; # Terminate the namelist $cice_nl .= " /"; # Commandline arguments for CICE build-namelist my @nl_args = ('-csmdata', $inputdata_rootdir, '-config', $cice_config_filepath, '-dir', $opts{'dir'}, '-namelist', $cice_nl, ); my @command = ($cice_bldnl, @nl_args); system(@command) == 0 or die "system @command failed: $? \n"; my $outfile = "$opts{'dir'}/ice_in"; if ($print>=1) { print "Writing CICE namelist to $outfile $eol"; } } #----------------------------------------------------------------------------------------------- # Add defaults for the RTM component # Only produce a namelist for RTM if running with CAM standalone scripts # and if the rof component is active. my $rof_pkg = $cfg->get('rof'); if ($rof_pkg eq 'rtm' and $cam_build and $rof_active) { my $fh = new IO::File; # Create rof_in # -------------- my $outfile = "$opts{'dir'}/rof_in"; $fh->open(">$outfile") or die "** can't open file: $outfile\n"; # Currently, just always turn off RTM, but that might change # in order to get flooding feedback into CLM. print $fh <<"EOF"; &rtm_inparm do_rtm = .false. / EOF #/ $fh->close; if ($print>=1) { print "Writing RTM namelist to $outfile $eol"; } } #----------------------------------------------------------------------------------------------- # Create docn namelists and stream txt file if ($ocn_comp eq 'docn' and $cam_build) { my $fh = new IO::File; my $stream_year_first = $nl->get_value('stream_year_first'); unless (defined $stream_year_first) { $stream_year_first = 0; } my $stream_year_last = $nl->get_value('stream_year_last'); unless (defined $stream_year_last) { $stream_year_last = 0; } my $temp = $focndomain; $temp =~ s/['"]//g; #"' my $focndomain_file = basename($temp); my $focndomain_path = dirname($temp); $temp = $bndtvs; $temp =~ s/['"]//g; #"' my $sstdata_file= basename($temp); my $sstdata_path = dirname($temp); my $fsstdomain_file=''; my $fsstdomain_path=''; if ($dyn =~ /homme/){ $temp = $bndtvs_domain; $temp =~ s/['"]//g; #"' $fsstdomain_file = basename($temp); $fsstdomain_path = dirname($temp); } else { $fsstdomain_file=$focndomain_file; $fsstdomain_path=$focndomain_path; } my $create_stream = 1; if ($aqua_mode) {$create_stream = 0}; # add docn nml params # -------------- add_default($nl, 'ocn_in', 'val'=>'docn_ocn_in'); add_default($nl, 'decomp', 'val'=>'1d'); # Create docn_ocn_in # -------------- my $outfile = "$opts{'dir'}/docn_ocn_in"; $fh->open(">$outfile") or die "** can't open file: $outfile\n"; print $fh <<"EOF"; &shr_strdata_nml dataMode = 'SSTDATA' domainFile = $focndomain streams = 'docn.stream.txt $stream_year_first $stream_year_first $stream_year_last ' vectors = 'null' / EOF $fh->close; if ($print>=1) { print "Writing DOCN namelist to $outfile $eol"; } if ($create_stream) { # Create docn.stream.txt - ONLY for non aqua_planet mode # -------------- my $outfile = "$opts{'dir'}/docn.stream.txt"; $fh->open(">$outfile") or die "** can't open file: $outfile\n"; print $fh <<"EOF"; Stream description file for generic SST/ifrac data on the CAM grid DATASET time time xc lon yc lat area area mask mask $fsstdomain_path $fsstdomain_file SST_cpl t $sstdata_path $sstdata_file EOF $fh->close; if ($print>=1) { print "Writing DOCN stream file to $outfile $eol"; } } } #----------------------------------------------------------------------------------------------- # Rename component logfiles. # # This requires special handling because the logfiles are coordinated using # share code. Each component is using shr_file_mod::shr_file_setIO to attach # a unique Fortran unit to a named file. shr_file_setIO reads the namelist # group /modelio/ and hence each component is using the same variable names. # To work around this component specific names have been added to the special # namelist group /camexp/. Check for those variables and write the component # specific versions of /modelio/ to files whose names are hardwired in the top # level component interface, e.g., atm_comp_mct, lnd_comp_mct, and seq_ccsm_drv. my @comps = qw(atm cpl lnd rof); foreach my $comp (@comps) { my $logfile = "${comp}_logfile"; my $logfiledir = "${comp}_logfile_diro"; my $outfile = "${comp}_modelio.nml"; # check to see if user requests renaming this component logfile my $logfile_val = $nl->get_variable_value('camexp', $logfile); if (defined $logfile_val) { # create namelist object for /modelio/ my $modelio = Build::Namelist->new("&modelio logfile=$logfile_val /"); # check whether a directory has been specified... if so add to namelist my $logfiledir_val = $nl->get_variable_value('camexp', $logfiledir); if (defined $logfiledir_val) { $modelio->set_variable_value('modelio', 'diro', $logfiledir_val); } # write the namelist to the component specific file $modelio->write($outfile); if ($print>=1) { print "Writing modelio namelist to $outfile $eol"; } } } #----------------------------------------------------------------------------------------------- # Write output files # Get array of group names that have been defined in the namelist. my @nl_groups = $nl->get_group_names(); # Create a hash with the group names as keys. This makes it easy to remove # names from the list. my %nl_group = (); foreach my $name (@nl_groups) { $nl_group{$name} = ''; } # Write fixed sets of namelist groups for the components other than CAM. # Remove the group names from %nl_group as they are written. # CLM my @comp_groups = qw(clm_inparm clm_rtm_inparm); my $outfile = "$opts{'dir'}/lnd_in"; if ($cam_build and $lnd_active) { $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { print "Writing CLM namelist to $outfile $eol"; } } delete @nl_group{@comp_groups}; # Driver @comp_groups = qw(seq_cplflds_inparm seq_cplflds_userspec ccsm_pes seq_infodata_inparm seq_timemgr_inparm prof_inparm pio_default_inparm); $outfile = "$opts{'dir'}/drv_in"; if ($cam_build) { $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { print "Writing driver namelist to $outfile $eol"; } } delete @nl_group{@comp_groups}; # Dry deposition and MEGAN VOC emis namelists @comp_groups = qw(drydep_inparm megan_emis_nl carma_inparm); $outfile = "$opts{'dir'}/drv_flds_in"; $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { print "CAM writing dry deposition namelist to drv_flds_in $eol"; } delete @nl_group{@comp_groups}; # Ocean component (CAMDOM) if ($ocn_group eq 'dom_inparm') { $outfile = "$opts{'dir'}/ocn_in"; } else { $outfile = "$opts{'dir'}/docn_in"; } if ($ocn_group) { @comp_groups = ($ocn_group); $nl->write($outfile, 'groups'=>\@comp_groups); delete @nl_group{@comp_groups}; if ($print>=1) { print "Writing ocean component namelist to $outfile $eol"; } } # CAM # # Have removed the group names for components not associated with CAM, so write # the remaining groups to the CAM namelist file. # *** N.B. *** The assumption that all remaining groups belong to CAM allows adding # new groups to CAM's definition file without requiring a code modification # here to have that group written to the namelist file. # First remove the camexp group since it's a special purpose group that's not # read by CAM if (defined $nl_group{'camexp'}) { delete $nl_group{'camexp'}; } @comp_groups = sort keys %nl_group; $outfile = "$opts{'dir'}/atm_in"; $nl->write($outfile, 'groups'=>\@comp_groups); if ($print>=1) { print "CAM writing namelist to atm_in $eol"; } #----------------------------------------------------------------------------------------------- # Test that input files exist locally. if ($opts{'test'}) { print "Checking whether input datasets exist locally...$eol"; check_input_files($nl); } # Write the input dataset filepaths to the file specified by $opts{'inputdata'}. if ($opts{'inputdata'}) { check_input_files($nl, $inputdata_rootdir, $opts{'inputdata'}); } # END OF MAIN SCRIPT #=============================================================================================== sub create_mode_defs { # create the list of strings used to define the MAM modes my $names = shift; # $names->[$m] - name of mode $m my $types = shift; # $types->[$m] - type of mode $m my $num = shift; # $num->[$m] - name of intersitial number m.r. for mode $m my $num_cw = shift; # $num_cw->[$m] - name of cloud borne number m.r. for mode $m my $num_src = shift; # $num_src->[$m] - source of interstitial number m.r. for mode $m my $spec = shift; # $spec->[$m][$i] - name of interstitial species $i in mode $m my $spec_type = shift; # $spec_type->[$m][$i] - type of species $i in mode $m my $spec_cw = shift; # $spec_cw->[$m][$i] - name of cloud borne species $i in mode $m my $spec_src = shift; # $spec_src->[$m][$i] - source of interstitial species $i in mode $m my $mode_def; # number of modes my $nmodes = scalar(@$names); for (my $m=0; $m < $nmodes; ++$m) { # initial mode definition string $mode_def .= "'$names->[$m]:$types->[$m]:=',"; # add the number mixing ratio field names. the source of the number conc # of cloud borne aerosol defaults to N $mode_def .= "'$num_src->[$m]:$num->[$m]:N:$num_cw->[$m]:num_mr:+',"; # number of species in mode my $nspec = scalar(@{$spec->[$m]}); for (my $i=0; $i < $nspec; ++$i) { my $term = ":+',"; # more species to come if ($i == $nspec - 1) { if ($m == $nmodes - 1) { $term = "'"; # last specie and no more modes } else { $term = "',"; # last specie but more modes to come } } # get default properties file my $spec_name = $spec->[$m][$i]; my $rel_filepath = get_default_value("mam_$spec_name"); my $abs_filepath = set_abs_filepath($rel_filepath, $inputdata_rootdir); # add species info. the source of the mixing ratio # for cloud borne species defaults to N $mode_def .= "'" . $spec_src->[$m][$i] . ":" . $spec->[$m][$i] . ":N:" . $spec_cw->[$m][$i] . ":" . $spec_type->[$m][$i] . ":" . $abs_filepath . $term; } } return $mode_def; } #=============================================================================================== sub add_default { # Add a value for the specified variable to the specified namelist object. The variables # already in the object have the higher precedence, so if the specified variable is already # defined in the object then don't overwrite it, just return. # # This method checks the definition file and adds the variable to the correct # namelist group. # # The value can be provided by using the optional argument key 'val' in the # calling list. Otherwise a default value is obtained from the namelist # defaults object. If no default value is found this method throws an exception # unless the 'nofail' option is set true. # # Additional optional keyword=>value pairs may be specified. If the keyword 'val' is # not present, then any other keyword=>value pairs that are specified will be used to # match attributes in the defaults file. # # Example 1: Specify the default value $val for the namelist variable $var in namelist # object $nl: # # add_default($nl, $var, 'val'=>$val) # # Example 2: Add a default for variable $var if an appropriate value is found. Otherwise # don't add the variable # # add_default($nl, $var, 'nofail'=>1) # # # ***** N.B. ***** This routine assumes the following variables are in package main:: # $definition -- the namelist definition object # $inputdata_rootdir -- CCSM inputdata root directory my $nl = shift; # namelist object my $var = shift; # name of namelist variable my %opts = @_; # options my $val = undef; # Query the definition to find which group the variable belongs to. Exit if not found. my $group = $definition->get_group_name($var); unless ($group) { my $fname = $definition->get_file_name(); die "$ProgName - ERROR: variable \"$var\" not found in namelist definition file $fname.\n"; } # check whether the variable has a value in the namelist object -- if so then return $val = $nl->get_variable_value($group, $var); if (defined $val) {return;} # Look for a specified value in the options hash if (defined $opts{'val'}) { $val = $opts{'val'}; } # or else get a value from namelist defaults object. # Note that if the 'val' key isn't in the hash, then just pass anything else # in %opts to the get_value method to be used as attributes that are matched # when looking for default values. else { $val = get_default_value($var, \%opts); } # if no value is found then exit w/ error (unless 'nofail' option set) unless (defined $val) { unless ($opts{'nofail'}) { print "$ProgName - ERROR: No default value found for $var\n". "user defined attributes:\n"; foreach my $key (keys(%opts)) { if ($key ne 'nofail' and $key ne 'val') { print "key=$key val=$opts{$key}\n"; } } die; } else { return; } } # query the definition to find out if the variable is an input pathname my $is_input_pathname = $definition->is_input_pathname($var); # The default values for input pathnames are relative. If the namelist # variable is defined to be an absolute pathname, then prepend # the CCSM inputdata root directory. if ($is_input_pathname eq 'abs') { $val = set_abs_filepath($val, $inputdata_rootdir); } # Some complex namelist variables set in use cases may have "$INPUTDATA_ROOT" # in the data path specifications. Subsitute the resolved path here for these cases. $val =~ s/\$INPUTDATA_ROOT/$inputdata_rootdir/g ; # query the definition to find out if the variable takes a string value. # The returned string length will be >0 if $var is a string, and 0 if not. my $str_len = $definition->get_str_len($var); # If the variable is a string, then add quotes if they're missing if ($str_len > 0) { $val = quote_string($val); } # set the value in the namelist $nl->set_variable_value($group, $var, $val); } #----------------------------------------------------------------------------------------------- sub get_default_value { # Return a default value for the requested variable. # Return undef if no default found. # # ***** N.B. ***** This routine assumes the following variables are in package main:: # $defaults -- the namelist defaults object # $uc_defaults -- the use case defaults object my $var_name = lc(shift); # name of namelist variable (case insensitive interface) my $usr_att_ref = shift; # reference to hash containing user supplied attributes # Check first in the use case defaults if (defined $uc_defaults) { my $val = $uc_defaults->get_value($var_name, $usr_att_ref); if ($val) {return $val;} } # Check in the namelist defaults return $defaults->get_value($var_name, $usr_att_ref); } #----------------------------------------------------------------------------------------------- sub fv_decomp_set{ # Return a decomposition for the FV dycore, expressed as the value for the namelist # variable npr_yz. The value of npr_yz is ny,nz,nx,ny where ny, nz, and nx are # respecitively the number of y, z, and x subdomains in the multi-2D decomposition. # The following constraints must be observed: # 1) ny*nz = ntasks (ny*nz can be less than ntasks in the case that the dynamics runs # on a subset of the total tasks. Assume the user will set the # decomp explicitly if that is what is desired.) # 2) nx=nz (this is an empirically determined constraint for efficiency in the # dycore communications) # 3) ny*3 <= nlat (these constraints are imposed by the dycore) # nz <= nlev # # The strategy for setting the default decomposition is to use the smallest possible # number of z subdomains. Start with 1 (which is the 1D decomposition). If that works # then done. If not, increase nz, check that it divides ntasks, if so does resulting # ny satisfy ny*3 <= nlat, if so then done. Etc. my $ntasks = $opts{'ntasks'}; my $nlat = $cfg->get('nlat'); my $nlev = $cfg->get('nlev'); my ($ny, $nz); NZ: for ($nz = 1; $nz <= $nlev; ++$nz) { # test that $nz divides $ntasks if ($ntasks%$nz == 0) { $ny = $ntasks/$nz; # test that y subdomains contain at least 3 latitudes # if so then done if (3*$ny <= $nlat) {last NZ;} } } # die if algorithm failed if ($nz > $nlev or $ny*$nz != $ntasks) { die "$ProgName - ERROR: fv_decomp_set failed to find a decomposition.\n" . " npr_yz needs to be set by the user."; } return "$ny,$nz,$nz,$ny"; } #----------------------------------------------------------------------------------------------- sub check_input_files { # For each variable in the namelist which is an input dataset, or contains filepaths # for input datasets, either: # 1) check to see if the input dataset exists on local disk, or # 2) write the input dataset filepath to a file. # # In "test" mode (1) the routine is called with just one argument. # In "inputdata" mode (2) the routine is called with three arguments. # # ***** N.B. ***** This routine assumes the following variables are in package main:: # $definition -- the namelist definition object my $nl = shift; # namelist object my $inputdata_rootdir = shift; # if false prints test, else creates inputdata file my $outfile = shift; my $fh; if (defined $inputdata_rootdir) { open $fh, '>', $outfile or die "check_input_files: error opening $outfile: $!"; } # Look through all namelist groups my @groups = $nl->get_group_names(); foreach my $group (@groups) { # Look through all variables in each group my @vars = $nl->get_variable_names($group); foreach my $var (@vars) { # Is the variable an input dataset? my $input_pathname_type = $definition->is_input_pathname($var); # If it is, check whether it exists locally and print status if ($input_pathname_type) { # Get pathname of input dataset my $pathname = $nl->get_variable_value($group, $var); # Need to strip the quotes $pathname =~ s/['"]//g; if ($input_pathname_type eq 'abs') { if ($inputdata_rootdir) { print $fh "$var = $pathname\n"; } else { if (-e $pathname) { # use -e rather than -f since the absolute pathname # might be a directory print "OK -- found $var = $pathname\n"; } else { print "NOT FOUND: $var = $pathname\n"; } } } elsif ($input_pathname_type =~ m/rel:(.+)/o) { # The match provides the namelist variable that contains the # root directory for a relative filename my $rootdir_var = $1; my $rootdir = $nl->get_variable_value($group, $rootdir_var); $rootdir =~ s/['"]//g; #"' if ($inputdata_rootdir) { $pathname = "$rootdir/$pathname"; print $fh "$var = $pathname\n"; } else { if (-f "$rootdir/$pathname") { print "OK -- found $var = $rootdir/$pathname\n"; } else { print "NOT FOUND: $var = $rootdir/$pathname\n"; } } } } } } # Treat special cases... # These namelist variables are arrays of strings. my @vars = qw(ext_frc_specifier srf_emis_specifier mode_defs rad_climate rad_diag_1 rad_diag_2 rad_diag_3 rad_diag_4 rad_diag_5 rad_diag_6 rad_diag_7 rad_diag_8 rad_diag_9 rad_diag_10); foreach my $var (@vars) { # Is the variable in the namelist? my $value = $nl->get_value($var); if (defined $value) { # The current namelist parser stores all values as a single # string, so start by extracting each quoted string. while ($value =~ m/['"] # opening quote ([^'"]+) # capture all non-quote characters up to ['"] # closing quote (.*) # capture rest of string including newlines /sxo) { # the s modifier lets . match newlines my $spec = $1; $value = $2; # Look for values of the form 'name -> filepath' # Extract name and filename if ($spec =~ m/\s*(\w+) # name of species preceded by optional whitespace \s*->\s* # -> separator surrounded by optional whitespace (\S+) # filename (all characters up to optional whitespace) /xo) { my $name = $1; my $file = $2; if ($inputdata_rootdir) { print $fh "$var for $name = $file\n"; } else { if (-f $file) { print "OK -- found $var for $name = $file\n"; } else { print "NOT FOUND: $var for $name = $file\n"; } } } # Look for values that begin with 'X:name:name2' where X is one of [AMN] # Extract name and filename elsif ($spec =~ m/^\s*[AMN]:(\w+) # name of species preceded by optional whitespace and X: : # : separator (\S+) # name2 /xo) { my $name = $1; my $name2 = $2; # If $name2 starts with a slash, then it is an absolute filepath. # If $name2 starts with a $, then it is an unresolved filepath # (generated when run from CCSM scripts). # Otherwise check for more fields if ($name2 =~ m:^[/\$]:) { my $file = $name2; if ($inputdata_rootdir) { print $fh "$var for $name = $file\n"; } else { if (-f $file) { print "OK -- found $var for $name = $file\n"; } else { print "NOT FOUND: $var for $name = $file\n"; } } } else { # If this value is from a mode_defs string that defined # a mode specie, then breaking it up into colon separated # fields will provide a filepath in the 4rd field (index 3). my @flds = split /:/, $name2; if (scalar(@flds) >= 4) { if ($flds[3] =~ m:^[/\$]:) { my $file = $flds[3]; if ($inputdata_rootdir) { print $fh "$var for $name = $file\n"; } else { if (-f $file) { print "OK -- found $var for $name = $file\n"; } else { print "NOT FOUND: $var for $name = $file\n"; } } } } } } # Look for values that end with "=". These are the initial strings in mode # definitions and should just be ignored. elsif ($spec =~ m/^\s*(\S+)=\s*$/) { # string which ends with "=" and has optional # begining and trailing whitespace # ignore it } else { print "Failed to parse \'$spec\'\n"; } } # end of while loop } } close $fh if defined $inputdata_rootdir; return 0; } #----------------------------------------------------------------------------------------------- sub strip_rootdir { # Strip a root directory from the begining of a filepath. # Allow for the possibility that the root directory is specified as a shell variable # to support a CCSM script requirement. my ($filepath, $rootdir) = @_; # Check whether the rootdir is specified as a shell variable. if ($rootdir =~ m/^\$(\w*)/) { my $rootname = $1; # Strip off the root directory with the following regexp that # avoids the problem of $rootdir being interpolated to a scalar variable # name... #$filepath =~ s:^\$$rootname::; # The CCSM scripts are currently set up to expect the shell variable in the # output file that contains the list of inputdata files. So in this case # do nothing. } else { # Strip off the rootdir specified as a resolved pathname $filepath =~ s:^$rootdir::; } return $filepath; } #----------------------------------------------------------------------------------------------- sub set_abs_filepath { # check whether the input filepath is an absolute path, and if it isn't then # prepend a root directory my ($filepath, $rootdir) = @_; # strip any leading/trailing whitespace $filepath =~ s/^\s+//; $filepath =~ s/\s+$//; $rootdir =~ s/^\s+//; $rootdir =~ s/\s+$//; # strip any leading/trailing quotes $filepath =~ s/^['"]+//; $filepath =~ s/["']+$//; $rootdir =~ s/^['"]+//; $rootdir =~ s/["']+$//; my $out = $filepath; unless ( $filepath =~ /^\// ) { # unless $filepath starts with a / $out = "$rootdir/$filepath"; # prepend the root directory } return $out; } #----------------------------------------------------------------------------------------------- sub absolute_path { # # Convert a pathname into an absolute pathname, expanding any . or .. characters. # Assumes pathnames refer to a local filesystem. # Assumes the directory separator is "/". # my $path = shift; my $cwd = getcwd(); # current working directory my $abspath; # resulting absolute pathname # Strip off any leading or trailing whitespace. (This pattern won't match if # there's embedded whitespace. $path =~ s!^\s*(\S*)\s*$!$1!; # Convert relative to absolute path. if ($path =~ m!^\.$!) { # path is "." return $cwd; } elsif ($path =~ m!^\./!) { # path starts with "./" $path =~ s!^\.!$cwd!; } elsif ($path =~ m!^\.\.$!) { # path is ".." $path = "$cwd/.."; } elsif ($path =~ m!^\.\./!) { # path starts with "../" $path = "$cwd/$path"; } elsif ($path =~ m!^[^/]!) { # path starts with non-slash character $path = "$cwd/$path"; } my ($dir, @dirs2); my @dirs = split "/", $path, -1; # The -1 prevents split from stripping trailing nulls # This enables correct processing of the input "/". # Remove any "" that are not leading. for (my $i=0; $i<=$#dirs; ++$i) { if ($i == 0 or $dirs[$i] ne "") { push @dirs2, $dirs[$i]; } } @dirs = (); # Remove any "." foreach $dir (@dirs2) { unless ($dir eq ".") { push @dirs, $dir; } } @dirs2 = (); # Remove the "subdir/.." parts. foreach $dir (@dirs) { if ( $dir !~ /\.\./ ) { push @dirs2, $dir; } else { pop @dirs2; # remove previous dir when current dir is .. } } if ($#dirs2 == 0 and $dirs2[0] eq "") { return "/"; } $abspath = join '/', @dirs2; return( $abspath ); } #------------------------------------------------------------------------------- sub valid_option { my ($val, @expect) = @_; my ($expect); $val =~ s/^\s+//; $val =~ s/\s+$//; foreach $expect (@expect) { if ($val =~ /^$expect$/i) { return $expect; } } return undef; } #------------------------------------------------------------------------------- sub validate_use_case { my $source = shift; # text string declaring the source of the options being validated my $opts = shift; # reference to hash that contains the options my ($opt, $old, @expect); # use_case $opt = 'use_case'; if (defined $opts->{$opt}) { # create the @expect array by listing the files in $use_case_dir # and strip off the ".xml" part of the filename @expect = (); my @files = glob("$opts->{'use_case_dir'}/*.xml"); foreach my $file (@files) { $file =~ m{.*/(.*)\.xml}; push @expect, $1; } $old = $opts->{$opt}; $opts->{$opt} = valid_option($old, @expect) or die "$ProgName - ERROR: invalid value of $opt ($old) specified in $source\n". "expected one of: @expect\n"; } } #------------------------------------------------------------------------------- sub quote_string { my $str = shift; $str =~ s/^\s+//; $str =~ s/\s+$//; unless ($str =~ /^['"]/) { #"' $str = "\'$str\'"; } return $str; } #------------------------------------------------------------------------------- sub version { # The version is found in CAM's ChangeLog file. # $cfgdir is set by the configure script to the name of its directory. my ($cfgdir) = @_; my $logfile = "$cfgdir/../doc/ChangeLog"; my $fh = IO::File->new($logfile, '<') or die "** $ProgName - ERROR: can't open ChangeLog file: $logfile\n"; while (my $line = <$fh>) { if ($line =~ /^Tag name:\s*(\w+)/ ) { print "$1\n"; last; } } } #-------------------------------------------------------------------------------