#!/usr/bin/env perl #----------------------------------------------------------------------------------------------- # # build-namelist # # This script builds the namelists for the DRV configuration of CESM1. # # build-namelist uses a config_cache.xml file that current contains the ocean grid information. # build-namelist reads this file to obtain information it needs to provide # default values that are consistent with the driver/coupler library. # # 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. # # # Date Contributor Modification # ------------------------------------------------------------------------------------------- # 2012-01-30 Vertenstein Original version #-------------------------------------------------------------------------------------------- use strict; use Cwd; use English; use Getopt::Long; use IO::File; #----------------------------------------------------------------------------------------------- sub usage { die < 0, silent => 0, caseroot => 0, scriptsroot => 0, grid => 0, rof_grid => 0, atm_grid => 0, lnd_grid => 0, ocn_grid => 0); GetOptions( "h|help" => \$opts{'help'}, "infile=s" => \$opts{'infile'}, "namelist=s" => \$opts{'namelist'}, "s|silent" => \$opts{'silent'}, "v|verbose" => \$opts{'verbose'}, "caseroot=s" => \$opts{'caseroot'}, "scriptsroot=s" => \$opts{'scriptsroot'}, "grid=s" => \$opts{'grid'}, "rof_grid=s" => \$opts{'rof_grid'}, "atm_grid=s" => \$opts{'atm_grid'}, "lnd_grid=s" => \$opts{'lnd_grid'}, "ocn_grid=s" => \$opts{'ocn_grid'}, ) or usage(); # Give usage message. usage() if $opts{'help'}; # 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"; my $CASEROOT = $opts{'caseroot'}; my $SCRIPTSROOT = $opts{'scriptsroot'}; my $GRID = $opts{'grid'}; my $ROF_GRID = $opts{'rof_grid'}; my $ATM_GRID = $opts{'atm_grid'}; my $LND_GRID = $opts{'lnd_grid'}; my $OCN_GRID = $opts{'ocn_grid'}; if ($print>=2) { print "Setting DRV configuration script directory to $cfgdir$eol"; } # Validate some of the commandline option values. validate_options("commandline", \%opts); #----------------------------------------------------------------------------------------------- # Create config_cache.xml file (needed below) my $config_cache = "${CASEROOT}/Buildconf/cplconf/config_cache.xml"; my $fh = new IO::File; $fh->open(">$config_cache") or die "** can't open file: $config_cache\n"; print $fh <<"EOF"; EOF $fh->close; if ($print>=2) { print "Wrote file $config_cache $eol"; } (-f "config_cache.xml") or die <<"EOF"; ** $ProgName - Cannot find configuration cache file: config_cache.xml\" ** 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 root directory for the perl5 required utilities my $perl5lib_dir = "${SCRIPTSROOT}/ccsm_utils/Tools/perl5lib"; # The XML::Lite module is required to parse the XML files. (-f "$perl5lib_dir/XML/Lite.pm") or die <<"EOF"; ** $ProgName - Cannot find perl module \"XML/Lite.pm\" in directory \"$perl5lib_dir\" ** EOF # The Build::Config module provides utilities to access the configuration information # in the config_cache.xml file (see below) (-f "$perl5lib_dir/Build/Config.pm") or die <<"EOF"; ** $ProgName - Cannot find perl module \"Build/Config.pm\" in directory \"$perl5lib_dir\" ** EOF # The Build::NamelistDefinition module provides utilities to validate that the output # namelists are consistent with the namelist definition file (-f "$perl5lib_dir/Build/NamelistDefinition.pm") or die <<"EOF"; ** $ProgName - Cannot find perl module \"Build/NamelistDefinition.pm\" in directory \"$perl5lib_dir\" ** 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 "$perl5lib_dir/Build/NamelistDefaults.pm") or die <<"EOF"; ** $ProgName - Cannot find perl module \"Build/NamelistDefaults.pm\" in directory \"$perl5lib_dir\" ** EOF # The Build::Namelist module provides utilities to parse input namelists, to query and modify # namelists, and to write output namelists. (-f "$perl5lib_dir/Build/Namelist.pm") or die <<"EOF"; ** $ProgName - Cannot find perl module \"Build/Namelist.pm\" in directory \"$perl5lib_dir\" ** EOF my $nl_definition_file; if (-f "${CASEROOT}/SourceMods/src.drv/namelist_definition_drv.xml") { $nl_definition_file = "${CASEROOT}/SourceMods/src.drv/namelist_definition_drv.xml"; } if (! defined $nl_definition_file) { # default location of namelist definition file $nl_definition_file = "$cfgdir/namelist_files/namelist_definition_drv.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"; } # The namelist defaults file contains default values for all required namelist variables. my $nl_defaults_file = "$cfgdir/namelist_files/namelist_defaults_drv.xml"; (-f "$nl_defaults_file") or die <<"EOF"; ** $ProgName - Cannot find namelist defaults file \"$nl_defaults_file\" ** EOF if ($print>=2) { print "Using namelist defaults file $nl_defaults_file$eol"; } my $nl_modio_definition_file = "$cfgdir/namelist_files/namelist_definition_modio.xml"; (-f "$nl_modio_definition_file") or die <<"EOF"; ** $ProgName - Cannot find namelist modio definition file \"$nl_modio_definition_file\" ** EOF if ($print>=2) { print "Using namelist modio definition file $nl_modio_definition_file$eol"; } #----------------------------------------------------------------------------------------------- # Add $perl5lib_dir to the list of paths that Perl searches for modules unshift @INC, "$perl5lib_dir"; require XML::Lite; require Build::Config; require Build::NamelistDefinition; require Build::NamelistDefaults; require Build::Namelist; #----------------------------------------------------------------------------------------------- # Create a configuration object from the DRV config_cache.xml file- created by # pop2.cpl7.template in $CASEROOT/Buildconf/cplconf my $cfg = Build::Config->new('config_cache.xml'); # 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. 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 cpl library for which the namelist is being produced. my $defaults = Build::NamelistDefaults->new($nl_defaults_file, $cfg); # Create an empty namelist object. Add values to it in order of precedence. my $nl = Build::Namelist->new(); #----------------------------------------------------------------------------------------------- # 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. # 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); } #----------------------------------------------------------------------------------------------- # Determine xml variables #----------------------------------------------------------------------------------------------- my %xmlvars = (); my @files = <${CASEROOT}/*xml>; foreach my $file (@files) { my $xml = XML::Lite->new( "$file" ); my @e = $xml->elements_by_name('entry'); while ( my $e = shift @e ) { my %a = $e->get_attributes(); $xmlvars{$a{'id'}} = $a{'value'}; } } my $DIN_LOC_ROOT = $xmlvars{'DIN_LOC_ROOT'}; (-d $DIN_LOC_ROOT) or die <<"EOF"; ** $ProgName - CCSM inputdata root is not a directory: \"$DIN_LOC_ROOT\" ** EOF if ($print>=2) { print "CESM inputdata root directory: $DIN_LOC_ROOT$eol"; } # Note - $USER is not in the config_defintion.xml file - it is only in the environment $xmlvars{'USER'} = $ENV{'USER'}; foreach my $attr (keys %xmlvars) { if ( $xmlvars{$attr} =~ m/\$/ ) {$xmlvars{$attr} = expand_env_xml($xmlvars{$attr});} if ( $xmlvars{$attr} =~ m/\$/ ) {$xmlvars{$attr} = expand_env_xml($xmlvars{$attr});} if ( $xmlvars{$attr} =~ m/\$/ ) {$xmlvars{$attr} = expand_env_xml($xmlvars{$attr});} } #----------------------------------------------------------------------------------------------- # Determine drv namelist #----------------------------------------------------------------------------------------------- ############################################# # namelist group: seq_cplflds_inparm # ############################################# my $CCSM_BGC = "$xmlvars{'CCSM_BGC'}"; my $flds_co2a = ".false."; my $flds_co2b = ".false."; my $flds_co2c = ".false."; my $flds_co2_dmsa = ".false."; if ($CCSM_BGC eq 'CO2A') { $flds_co2a = ".true."; } elsif ($CCSM_BGC eq 'CO2B') { $flds_co2b = ".true."; } elsif ($CCSM_BGC eq 'CO2C') { $flds_co2c = ".true."; } elsif ($CCSM_BGC eq 'CO2_DMSA') { $flds_co2_dmsa = ".true."; } my $glc_nec = "$xmlvars{'GLC_NEC'}"; if ( ! defined $glc_nec ) {$glc_nec = 0;} add_default($nl, 'flds_co2a', 'val'=>"$flds_co2a"); add_default($nl, 'flds_co2b', 'val'=>"$flds_co2b"); add_default($nl, 'flds_co2c', 'val'=>"$flds_co2c"); add_default($nl, 'flds_co2_dmsa','val'=>"$flds_co2_dmsa"); add_default($nl, 'glc_nec', 'val'=>"$glc_nec"); ############################################# # namelist group: seq_cplflds_userspec # ############################################# add_default($nl, 'cplflds_custom', 'val'=>''); ############################################# # namelist group: seq_infodata_inparm # ############################################# my $PTS_MODE = "$xmlvars{'PTS_MODE'}"; my $samegrid_ao = '.false.'; if ($ATM_GRID eq $OCN_GRID) {$samegrid_ao = '.true.';} if ($PTS_MODE eq 'TRUE') {$samegrid_ao = '.true.';} my $samegrid_ro = '.false.'; if ($LND_GRID eq $OCN_GRID) {$samegrid_ro = '.true.';} if ($PTS_MODE eq 'TRUE') {$samegrid_ro = '.true.';} my $samegrid_al = '.false.'; if ($ATM_GRID eq $LND_GRID) {$samegrid_al = '.true.';} if ($PTS_MODE eq 'TRUE') {$samegrid_al = '.true.';} my $start_type; my $RUN_TYPE = "$xmlvars{'RUN_TYPE'}"; my $CONTINUE_RUN = "$xmlvars{'CONTINUE_RUN'}"; if ($RUN_TYPE eq 'startup' ) {$start_type = "startup";} if ($RUN_TYPE eq 'hybrid' ) {$start_type = "startup";} if ($RUN_TYPE eq 'branch' ) {$start_type = "branch";} if ($CONTINUE_RUN eq 'TRUE') {$start_type = "continue";} my $BRNCH_RETAIN_CASENAME = "$xmlvars{'BRNCH_RETAIN_CASENAME'}"; my $brnch_retain_casename = '.false.'; if ($BRNCH_RETAIN_CASENAME eq 'TRUE') {$brnch_retain_casename = '.true.';} my $BFBFLAG = "$xmlvars{'BFBFLAG'}"; my $bfbflag = '.false.'; if ($BFBFLAG eq 'TRUE') {$bfbflag = '.true.';} my $BUDGETS = "$xmlvars{'BUDGETS'}"; my $do_budgets = '.false.'; if ($BUDGETS eq 'TRUE') {$do_budgets = '.true.';} my $OCN_TIGHT_COUPLING = "$xmlvars{'OCN_TIGHT_COUPLING'}"; my $ocean_tight_coupling = '.false.'; if ($OCN_TIGHT_COUPLING eq 'TRUE') {$ocean_tight_coupling = '.true.';} my $CPL_ALBAV = "$xmlvars{'CPL_ALBAV'}"; my $flux_albav = '.false.'; if ($CPL_ALBAV eq "true") {$flux_albav = '.true.';} my $DRV_THREADING = "$xmlvars{'DRV_THREADING'}"; my $drv_threading = '.false.'; if ($DRV_THREADING eq 'TRUE') {$drv_threading = '.true.';} my $COMP_RUN_BARRIERS = "$xmlvars{'COMP_RUN_BARRIERS'}"; my $run_barriers = '.false.'; if ($COMP_RUN_BARRIERS eq 'TRUE') {$run_barriers = '.true.';} add_default($nl, 'case_name', 'valxml'=>"$xmlvars{'CASE'}", 'xml'=>'CASE'); add_default($nl, 'case_desc', 'valxml'=>"$xmlvars{'CASESTR'}", 'xml'=>'CASESTR'); add_default($nl, 'username' , 'valxml'=>"$xmlvars{'CCSMUSER'}", 'xml'=>'CCSMUSER'); add_default($nl, 'hostname' , 'valxml'=>"$xmlvars{'MACH'}", 'xml'=>'MACH'); add_default($nl, 'model_version', 'valxml'=>"$xmlvars{'CCSM_REPOTAG'}", 'xml'=>'CCSM_REPOTAG'); add_default($nl, 'start_type', 'valxml'=>"$start_type", 'xml'=>'RUN_TYPE'); add_default($nl, 'brnch_retain_casename','valxml'=>"$brnch_retain_casename", 'xml'=>'BRNCH_RETAIN_CASENAME' ); add_default($nl, 'bfbflag', 'valxml'=>"$bfbflag", 'xml'=>'BFBFLAG'); add_default($nl, 'do_budgets', 'valxml'=>"$do_budgets", 'xml'=>'BUDGETS'); add_default($nl, 'flux_albav', 'valxml'=>"$flux_albav", 'xml'=>'CPL_ALBAV'); add_default($nl, 'ocean_tight_coupling', 'valxml'=>"$ocean_tight_coupling", 'xml'=>'OCN_TIGHT_COUPLING'); add_default($nl, 'drv_threading', 'valxml'=>"$drv_threading", 'xml'=>'DRV_THREADING'); add_default($nl, 'run_barriers', 'valxml'=>"$run_barriers", 'xml'=>'COMP_RUN_BARRIERS'); add_default($nl, 'info_debug', 'valxml'=>"$xmlvars{'INFO_DBUG'}", 'xml'=>'INFO_DBUG'); add_default($nl, 'flux_epbal', 'valxml'=>"$xmlvars{'CPL_EPBAL'}", 'xml'=>'CPL_EPBAL'); add_default($nl, 'samegrid_al', 'valxml'=>"$samegrid_al", 'der'=>'DERIVED'); add_default($nl, 'samegrid_ro', 'valxml'=>"$samegrid_ro", 'der'=>'DERIVED'); add_default($nl, 'samegrid_ao', 'valxml'=>"$samegrid_ao", 'der'=>'DERIVED'); add_default($nl, 'do_histinit'); add_default($nl, 'shr_map_dopole'); add_default($nl, 'cpl_cdf64'); add_default($nl, 'vect_map'); add_default($nl, 'aoflux_grid'); add_default($nl, 'cpl_decomp'); add_default($nl, 'orb_mode'); add_default($nl, 'orb_iyear'); add_default($nl, 'orb_iyear_align'); add_default($nl, 'budget_inst'); add_default($nl, 'budget_daily'); add_default($nl, 'budget_month'); add_default($nl, 'budget_ann'); add_default($nl, 'budget_ltann'); add_default($nl, 'budget_ltend'); add_default($nl, 'histaux_a2x'); add_default($nl, 'histaux_a2x3hr'); add_default($nl, 'histaux_a2x3hrp'); add_default($nl, 'histaux_a2x24hr'); add_default($nl, 'histaux_l2x'); add_default($nl, 'histaux_r2x'); add_default($nl, 'histaux_s2x1yr'); add_default($nl, 'eps_frac'); add_default($nl, 'eps_amask'); add_default($nl, 'eps_agrid'); add_default($nl, 'eps_aarea'); add_default($nl, 'eps_omask'); add_default($nl, 'eps_ogrid'); add_default($nl, 'eps_oarea'); add_default($nl, 'timing_dir'); add_default($nl, 'tchkpt_dir'); if ($PTS_MODE eq "TRUE") { add_default($nl, 'single_column', 'val'=>".true."); add_default($nl, 'scmlat', 'val'=>"$xmlvars{'PTS_LAT'}", 'xml'=>'PTS_LAt'); add_default($nl, 'scmlon', 'val'=>"$xmlvars{'PTS_LON'}", 'xml'=>'PTS_LON'); } # Error checks my $runtype = $nl->get_value('start_type'); my $brnch_retain_casename = $nl->get_value('brnch_retain_casename'); my $case = $xmlvars{'CASE'}; my $run_refcase = $xmlvars{'RUN_REFCASE'}; if (($runtype ne 'startup') && ($case eq $run_refcase) && ($brnch_retain_casename ne '.true.')) { print "$ProgName ERROR: CASE and RUN_REFCASE are identical \n"; die " Set BRNCH_RETAIN_CASENAME to TRUE in env_run.xml \n"; } ############################################# # namelist group: seq_timemgr_inparm # ############################################# my $CALENDAR = "$xmlvars{'CALENDAR'}"; add_default($nl, 'calendar', 'val'=>"$xmlvars{'CALENDAR'}"); my $NCPL_BASE_PERIOD = "$xmlvars{'NCPL_BASE_PERIOD'}"; my $basedt; if ($NCPL_BASE_PERIOD eq 'hour') { $basedt = 3600; } elsif ($NCPL_BASE_PERIOD eq 'day') { $basedt = 3600 * 24; } elsif ($NCPL_BASE_PERIOD eq 'year') { if ($CALENDAR eq 'NO_LEAP') { $basedt = 3600 * 24 * 365; } else { die "$ProgName: ERROR invalid CALENDAR for NCPL_BASE_PERIOD $NCPL_BASE_PERIOD \n"; } } elsif ($NCPL_BASE_PERIOD eq 'decade') { if ($CALENDAR eq 'NO_LEAP') { $basedt = 3600 * 24 * 365 * 10; } else { die "$ProgName: ERROR invalid CALENDAR for NCPL_BASE_PERIOD $NCPL_BASE_PERIOD \n"; } } else { die "$ProgName: ERROR invalid NCPL_BASE_PERIOD $NCPL_BASE_PERIOD \n"; } if ($basedt < 0) { die "$ProgName: ERROR basedt invalid overflow for NCPL_BASE_PERIOD $NCPL_BASE_PERIOD \n"; } my $ATM_NCPL = "$xmlvars{'ATM_NCPL'}"; my $LND_NCPL = "$xmlvars{'LND_NCPL'}"; my $OCN_NCPL = "$xmlvars{'OCN_NCPL'}"; my $ICE_NCPL = "$xmlvars{'ICE_NCPL'}"; my $GLC_NCPL = "$xmlvars{'GLC_NCPL'}"; my $ROF_NCPL = "$xmlvars{'ROF_NCPL'}"; my $atm_cpl_dt = $basedt / $ATM_NCPL; my $lnd_cpl_dt = $basedt / $LND_NCPL; my $ocn_cpl_dt = $basedt / $OCN_NCPL; my $ice_cpl_dt = $basedt / $ICE_NCPL; my $glc_cpl_dt = $basedt / $GLC_NCPL; my $rof_cpl_dt = $basedt / $ROF_NCPL; my $totaldt = $atm_cpl_dt * $ATM_NCPL; if ($totaldt != $basedt) { die "ERROR atm NCPL doesn't divide base dt evenly";} my $totaldt = $lnd_cpl_dt * $LND_NCPL; if ($totaldt != $basedt) { die "ERROR lnd NCPL doesn't divide base dt evenly";} my $totaldt = $ocn_cpl_dt * $OCN_NCPL; if ($totaldt != $basedt) { die "ERROR ocn NCPL doesn't divide base dt evenly";} my $totaldt = $ice_cpl_dt * $ICE_NCPL; if ($totaldt != $basedt) { die "ERROR ice NCPL doesn't divide base dt evenly";} my $totaldt = $glc_cpl_dt * $GLC_NCPL; if ($totaldt != $basedt) { die "ERROR glc NCPL doesn't divide base dt evenly";} my $totaldt = $rof_cpl_dt * $ROF_NCPL; if ($totaldt != $basedt) { die "ERROR rof NCPL doesn't divide base dt evenly";} my $RUN_STARTDATE = "$xmlvars{'RUN_STARTDATE'}"; $RUN_STARTDATE =~ s/[-]//g; my $RUN_REFDATE = "$xmlvars{'RUN_REFDATE'}"; $RUN_REFDATE =~ s/[-]//g; #TODOif ($runtype eq "branch") {$RUN_STARTDATE = $RUN_REFDATE;} add_default($nl, 'atm_cpl_dt', 'val'=>"$atm_cpl_dt", 'xml'=>'ATM_NCPL'); add_default($nl, 'lnd_cpl_dt', 'val'=>"$lnd_cpl_dt", 'xml'=>'LND_NCPL'); add_default($nl, 'ocn_cpl_dt', 'val'=>"$ocn_cpl_dt", 'xml'=>'OCN_NCPL'); add_default($nl, 'ice_cpl_dt', 'val'=>"$ice_cpl_dt", 'xml'=>'ICE_NCPL'); add_default($nl, 'glc_cpl_dt', 'val'=>"$glc_cpl_dt", 'xml'=>'GLC_NCPL'); add_default($nl, 'rof_cpl_dt', 'val'=>"$rof_cpl_dt", 'xml'=>'ROF_NCPL'); add_default($nl, 'start_ymd', 'valxml'=>"$RUN_STARTDATE", 'xml'=>'RUN_STARTDATE'); add_default($nl, 'start_tod', 'valxml'=>"$xmlvars{'START_TOD'}", 'xml'=>'START_TOD'); add_default($nl, 'stop_option', 'valxml'=>"$xmlvars{'STOP_OPTION'}", 'xml'=>'STOP_OPTION'); add_default($nl, 'stop_n', 'valxml'=>"$xmlvars{'STOP_N'}", 'xml'=>'STOP_N'); add_default($nl, 'stop_ymd', 'valxml'=>"$xmlvars{'STOP_DATE'}", 'xml'=>'STOP_DATE'); add_default($nl, 'restart_option', 'valxml'=>"$xmlvars{'REST_OPTION'}", 'xml'=>'REST_OPTION'); add_default($nl, 'restart_n', 'valxml'=>"$xmlvars{'REST_N'}", 'xml'=>'REST_N'); add_default($nl, 'restart_ymd', 'valxml'=>"$xmlvars{'REST_DATE'}", 'xml'=>'REST_DATE'); add_default($nl, 'end_restart'); add_default($nl, 'history_option', 'valxml'=>"$xmlvars{'HIST_OPTION'}", 'xml'=>'HIST_OPTION'); add_default($nl, 'history_n', 'valxml'=>"$xmlvars{'HIST_N'}", 'xml'=>'HIST_N'); add_default($nl, 'history_ymd', 'valxml'=>"$xmlvars{'HIST_DATE'}", 'xml'=>'HIST_DATE'); add_default($nl, 'histavg_option'); add_default($nl, 'histavg_n'); add_default($nl, 'histavg_ymd'); add_default($nl, 'tprof_option'); add_default($nl, 'tprof_n'); add_default($nl, 'tprof_ymd'); ############################################# # namelist group: ccsm_pes # ############################################# add_default($nl, 'atm_ntasks', 'valxml'=>"$xmlvars{'NTASKS_ATM'}", 'xml'=>'NTASKS_ATM'); add_default($nl, 'atm_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_ATM'}", 'xml'=>'NTHRDS_ATM'); add_default($nl, 'atm_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_ATM'}", 'xml'=>'ROOTPE_ATM'); add_default($nl, 'atm_pestride', 'valxml'=>"$xmlvars{'PSTRID_ATM'}", 'xml'=>'PSTRID_ATM'); add_default($nl, 'atm_layout', 'valxml'=>"$xmlvars{'NINST_ATM_LAYOUT'}", 'xml'=>'NINST_ATM_LAYOUT'); add_default($nl, 'lnd_ntasks', 'valxml'=>"$xmlvars{'NTASKS_LND'}", 'xml'=>'NTASKS_LND'); add_default($nl, 'lnd_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_LND'}", 'xml'=>'NTHRDS_LND'); add_default($nl, 'lnd_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_LND'}", 'xml'=>'ROOTPE_LND'); add_default($nl, 'lnd_pestride', 'valxml'=>"$xmlvars{'PSTRID_LND'}", 'xml'=>'PSTRID_LND'); add_default($nl, 'lnd_layout', 'valxml'=>"$xmlvars{'NINST_LND_LAYOUT'}", 'xml'=>'NINST_LND_LAYOUT'); add_default($nl, 'ice_ntasks', 'valxml'=>"$xmlvars{'NTASKS_ICE'}", 'xml'=>'NTASKS_ICE'); add_default($nl, 'ice_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_ICE'}", 'xml'=>'NTHRDS_ICE'); add_default($nl, 'ice_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_ICE'}", 'xml'=>'ROOTPE_ICE'); add_default($nl, 'ice_pestride', 'valxml'=>"$xmlvars{'PSTRID_ICE'}", 'xml'=>'PSTRID_ICE'); add_default($nl, 'ice_layout', 'valxml'=>"$xmlvars{'NINST_ICE_LAYOUT'}", 'xml'=>'NINST_ICE_LAYOUT'); add_default($nl, 'ocn_ntasks', 'valxml'=>"$xmlvars{'NTASKS_OCN'}", 'xml'=>'NTASKS_OCN'); add_default($nl, 'ocn_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_OCN'}", 'xml'=>'NTHRDS_OCN'); add_default($nl, 'ocn_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_OCN'}", 'xml'=>'ROOTPE_OCN'); add_default($nl, 'ocn_pestride', 'valxml'=>"$xmlvars{'PSTRID_OCN'}", 'xml'=>'PSTRID_OCN'); add_default($nl, 'ocn_layout', 'valxml'=>"$xmlvars{'NINST_OCN_LAYOUT'}", 'xml'=>'NINST_OCN_LAYOUT'); add_default($nl, 'glc_ntasks', 'valxml'=>"$xmlvars{'NTASKS_GLC'}", 'xml'=>'NTASKS_GLC'); add_default($nl, 'glc_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_GLC'}", 'xml'=>'NTHRDS_GLC'); add_default($nl, 'glc_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_GLC'}", 'xml'=>'ROOTPE_GLC'); add_default($nl, 'glc_pestride', 'valxml'=>"$xmlvars{'PSTRID_GLC'}", 'xml'=>'PSTRID_GLC'); add_default($nl, 'glc_layout', 'valxml'=>"$xmlvars{'NINST_GLC_LAYOUT'}", 'xml'=>'NINST_GLC_LAYOUT'); add_default($nl, 'rof_ntasks', 'valxml'=>"$xmlvars{'NTASKS_ROF'}", 'xml'=>'NTASKS_ROF'); add_default($nl, 'rof_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_ROF'}", 'xml'=>'NTHRDS_ROF'); add_default($nl, 'rof_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_ROF'}", 'xml'=>'ROOTPE_ROF'); add_default($nl, 'rof_pestride', 'valxml'=>"$xmlvars{'PSTRID_ROF'}", 'xml'=>'PSTRID_ROF'); add_default($nl, 'rof_layout', 'valxml'=>"$xmlvars{'NINST_ROF_LAYOUT'}", 'xml'=>'NINST_ROF_LAYOUT'); add_default($nl, 'cpl_ntasks', 'valxml'=>"$xmlvars{'NTASKS_CPL'}", 'xml'=>'NTASKS_CPL'); add_default($nl, 'cpl_nthreads', 'valxml'=>"$xmlvars{'NTHRDS_CPL'}", 'xml'=>'NTHRDS_CPL'); add_default($nl, 'cpl_rootpe', 'valxml'=>"$xmlvars{'ROOTPE_CPL'}", 'xml'=>'ROOTPE_CPL'); add_default($nl, 'cpl_pestride', 'valxml'=>"$xmlvars{'PSTRID_CPL'}", 'xml'=>'PSTRID_CPL'); ############################################# # namelist group: prof_inparm # # in utils/timing/perf_mod.F90 ############################################# my $profdepth; my $profdisable; my $TIMER_LEVEL = "$xmlvars{'TIMER_LEVEL'}"; if ($TIMER_LEVEL <= 0) { $profdepth = 20; $profdisable = ".true."; } elsif ($TIMER_LEVEL >= 1 ) { $profdepth = $TIMER_LEVEL; $profdisable = '.false.'; } my $MPILIB = "$xmlvars{'MPILIB'}"; my $OS = "$xmlvars{'OS'}"; my $prof_timer = 4; # mpiwtime if ($MPILIB eq "mpi-serial") { if ($OS eq "AIX") { $prof_timer = 3; # read_real_time } else { $prof_timer = 1; # gettimeofday } } add_default($nl, 'profile_global_stats', 'val'=>".true."); add_default($nl, 'profile_disable', 'val'=>"$profdisable"); add_default($nl, 'profile_depth_limit', 'val'=>"$profdepth"); add_default($nl, 'profile_single_file', 'val'=>".false."); add_default($nl, 'profile_detail_limit', 'val'=>"0"); add_default($nl, 'profile_timer', 'val'=>"$prof_timer"); add_default($nl, 'profile_barrier'); ############################################# # namelist group: pio_default_inparm # ############################################# my $COMP_OCN = "$xmlvars{'COMP_OCN'}"; my $PIO_ASYNC_INTERFACE = "$xmlvars{'PIO_ASYNC_INTERFACE'}"; my $pioasync = '.false.'; if ($PIO_ASYNC_INTERFACE eq 'TRUE') {$pioasync = '.true.';} add_default($nl, 'pio_async_interface', 'val'=>"$pioasync"); add_default($nl, 'pio_stride', 'val'=>"$xmlvars{'PIO_STRIDE'}", 'xml'=>'PIO_STRIDE'); add_default($nl, 'pio_root', 'val'=>"$xmlvars{'PIO_ROOT'}", 'xml'=>'PIO_ROOT'); add_default($nl, 'pio_numiotasks', 'val'=>"$xmlvars{'PIO_NUMTASKS'}", 'xml'=>'PIO_NUMTASKS'); add_default($nl, 'pio_typename', 'val'=>"$xmlvars{'PIO_TYPENAME'}", 'xml'=>'PIO_TYPENAME'); add_default($nl, 'pio_debug_level', 'val'=>"$xmlvars{'PIO_DEBUG_LEVEL'}", 'xml'=>'PIO_DEBUG_LEVEL'); add_default($nl, 'pio_blocksize', 'val'=>"$xmlvars{'PIO_BLOCKSIZE'}", 'xml'=>'PIO_BLOCKSIZE'); add_default($nl, 'pio_buffer_size_limit', 'val'=>"$xmlvars{'PIO_BUFFER_SIZE_LIMIT'}", 'xml'=>'PIO_BUFFER_SIZE_LIMIT'); # NOTE: pio_async_interface=.true. is not yet supported # If pio_async_interface is .true. or {component}_PIO_* variable is not set or set to -99 # the component variable will be set using the pio_* value. #----------------------------------------------------------------------------------------------- # (1) Write output namelist file (drv_in) and input dataset list (drv.input_data_list) #----------------------------------------------------------------------------------------------- # Write out drv_in namelist groups my @groups = qw(seq_cplflds_inparm seq_cplflds_userspec seq_infodata_inparm seq_timemgr_inparm ccsm_pes prof_inparm pio_default_inparm); my $outfile = "./drv_in"; $nl->write($outfile, 'groups'=>\@groups); if ($print>=2) { print "Writing driver namelist to $outfile $eol"; } #----------------------------------------------------------------------------------------------- # (2) Write out seq_map.rc file #----------------------------------------------------------------------------------------------- my $COMP_ROF = "$xmlvars{'COMP_ROF'}"; my $DROF_MODE = "$xmlvars{'DROF_MODE'}"; if ($COMP_ROF == 'drof') { if ($DROF_MODE =~ /DIATREN_ANN_RX1/) {$cfg->set('rof_grid', 'rx1');} if ($DROF_MODE =~ /DIATREN_IAF_RX1/) {$cfg->set('rof_grid', 'rx1');} } my $fh = new IO::File; $fh->open(">seq_maps.rc") or die "** can't open file: seq_maps.rc\n"; print $fh <<"EOF"; ################################################################## # # seq_maps.rc # # This is a resource file which lists the names of mapping # weight files to use in a sequential CCSM run (mapname). # You can also set when data is rearranged in the mapping (maptype). # # This file is read during the map_model2model_init calls. # # For maptype: X = Rearrange the input so that the output # is on the correct processor. # Y = Rearrange the output and sum partial outputs # if necessary # # NOTE: For bfb on different processor counts, set all maptypes to "X". ################################################################## EOF $fh->close(); my @mapgroup = qw(seq_maps); add_default($nl, 'atm2ocnFmapname'); add_default($nl, 'atm2ocnSmapname'); add_default($nl, 'atm2ocnVmapname'); add_default($nl, 'ocn2atmFmapname'); add_default($nl, 'ocn2atmSmapname'); my $atm2iceFmapname = $nl->get_value('atm2ocnFmapname'); my $atm2iceSmapname = $nl->get_value('atm2ocnSmapname'); my $atm2iceVmapname = $nl->get_value('atm2ocnVmapname'); my $ice2atmFmapname = $nl->get_value('ocn2atmFmapname'); my $ice2atmSmapname = $nl->get_value('ocn2atmSmapname'); add_default($nl, 'atm2iceFmapname', 'val'=>"$atm2iceFmapname"); add_default($nl, 'atm2iceSmapname', 'val'=>"$atm2iceSmapname"); add_default($nl, 'atm2iceVmapname', 'val'=>"$atm2iceVmapname"); add_default($nl, 'ice2atmFmapname', 'val'=>"$ice2atmFmapname"); add_default($nl, 'ice2atmSmapname', 'val'=>"$ice2atmSmapname"); add_default($nl, 'atm2lndFmapname'); add_default($nl, 'atm2lndSmapname'); add_default($nl, 'lnd2atmFmapname'); add_default($nl, 'lnd2atmSmapname'); add_default($nl, 'lnd2rofFmapname'); add_default($nl, 'rof2lndFmapname'); add_default($nl, 'rof2ocnFmapname'); add_default($nl, 'atm2ocnFmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'atm2ocnSmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'atm2ocnVmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'ocn2atmFmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'ocn2atmSmaptype', 'BFBFLAG'=>"$BFBFLAG"); my $atm2iceFmaptype = $nl->get_value('atm2ocnFmaptype'); my $atm2iceSmaptype = $nl->get_value('atm2ocnSmaptype'); my $atm2iceVmaptype = $nl->get_value('atm2ocnVmaptype'); my $ice2atmFmaptype = $nl->get_value('ocn2atmFmaptype'); my $ice2atmSmaptype = $nl->get_value('ocn2atmSmaptype'); add_default($nl, 'atm2iceFmaptype', 'val'=>"$atm2iceFmaptype"); add_default($nl, 'atm2iceSmaptype', 'val'=>"$atm2iceSmaptype"); add_default($nl, 'atm2iceVmaptype', 'val'=>"$atm2iceVmaptype"); add_default($nl, 'ice2atmFmaptype', 'val'=>"$ice2atmFmaptype"); add_default($nl, 'ice2atmSmaptype', 'val'=>"$ice2atmSmaptype"); add_default($nl, 'atm2lndFmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'atm2lndSmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'lnd2atmFmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'lnd2atmSmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'lnd2rofFmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'rof2lndFmaptype', 'BFBFLAG'=>"$BFBFLAG"); add_default($nl, 'rof2ocnFmaptype', 'BFBFLAG'=>"$BFBFLAG"); $nl->write_rc('./seq_maps.rc', 'groups'=>\@mapgroup, 'append'=>"1"); if ($print>=2) { print "Writing map namelist to seq_maps.rc $eol"; } #----------------------------------------------------------------------------------------------- # (3) Write input dataset list. #----------------------------------------------------------------------------------------------- check_input_files($nl, $DIN_LOC_ROOT, "../cpl.input_data_list"); #----------------------------------------------------------------------------------------------- # (4) Write out model_modelio.nml files #----------------------------------------------------------------------------------------------- $definition = Build::NamelistDefinition->new($nl_modio_definition_file); foreach my $model qw(cpl atm lnd ice ocn glc rof) { my $LID = "$ENV{'LID'}"; my $moddiri = "$xmlvars{'EXEROOT'}/${model}"; my $moddiro = "$xmlvars{'RUNDIR'}"; my $logfile; my $inst_count; if ($model eq 'cpl') {$inst_count = 1;} if ($model eq 'atm') {$inst_count = "$xmlvars{'NINST_ATM'}";} if ($model eq 'lnd') {$inst_count = "$xmlvars{'NINST_LND'}";} if ($model eq 'rof') {$inst_count = "$xmlvars{'NINST_LND'}";} if ($model eq 'ice') {$inst_count = "$xmlvars{'NINST_ICE'}";} if ($model eq 'ocn') {$inst_count = "$xmlvars{'NINST_OCN'}";} if ($model eq 'glc') {$inst_count = "$xmlvars{'NINST_GLC'}";} my $inst_index = 1; my $inst_string; my $modeliofile; my @iogroup = qw(modelio pio_inparm); while ($inst_index <= $inst_count) { $inst_string = "$inst_index"; if ($inst_index <= 999) {$inst_string = "0${inst_string}"}; if ($inst_index <= 99) {$inst_string = "0${inst_string}"}; if ($inst_index <= 9) {$inst_string = "0${inst_string}"}; if ($inst_count > 1) { $modeliofile = "${model}_modelio.nml_${inst_string}"; } else { $modeliofile = "./${model}_modelio.nml"; } my $nlio = Build::Namelist->new(); if ($inst_count > 1) { $logfile = "${model}_${inst_string}.log.$LID"; } else { $logfile = "${model}.log.$LID"; } add_default($nlio, 'diri', 'val'=>"$moddiri"); add_default($nlio, 'diro', 'val'=>"$moddiro"); add_default($nlio, 'logfile','val'=>"$logfile"); if ($model eq 'cpl') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'CPL_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'CPL_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks','val'=>"$xmlvars{'CPL_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'CPL_PIO_TYPENAME'}"); } if ($model eq 'atm') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'ATM_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'ATM_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks', 'val'=>"$xmlvars{'ATM_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'ATM_PIO_TYPENAME'}"); } if ($model eq 'lnd') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'LND_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'LND_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks', 'val'=>"$xmlvars{'LND_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'LND_PIO_TYPENAME'}"); } if ($model eq 'rof') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'LND_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'LND_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks', 'val'=>"$xmlvars{'LND_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'LND_PIO_TYPENAME'}"); } if ($model eq 'ice') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'ICE_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'ICE_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks', 'val'=>"$xmlvars{'ICE_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'ICE_PIO_TYPENAME'}"); } if ($model eq 'ocn') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'OCN_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'OCN_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks', 'val'=>"$xmlvars{'OCN_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'OCN_PIO_TYPENAME'}"); } if ($model eq 'glc') { add_default($nlio, 'pio_stride', 'val'=>"$xmlvars{'GLC_PIO_STRIDE'}"); add_default($nlio, 'pio_root', 'val'=>"$xmlvars{'GLC_PIO_ROOT'}"); add_default($nlio, 'pio_numiotasks', 'val'=>"$xmlvars{'GLC_PIO_NUMTASKS'}"); add_default($nlio, 'pio_typename', 'val'=>"$xmlvars{'GLC_PIO_TYPENAME'}"); } $nlio->write($modeliofile, 'groups'=>\@iogroup); if ($print>=2) { print "Writing io namelist to $modeliofile $eol"; } $inst_index = $inst_index + 1; } } #----------------------------------------------------------------------------------------------- # END OF MAIN SCRIPT #=============================================================================================== #=============================================================================================== 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 IF # there is also not a corresponding value in the valxml input $val = $nl->get_variable_value($group, $var); if (defined $val) { if (defined $opts{'valxml'}) { if (defined $opts{'xml'}) { die "$ProgName - ERROR: $var can only by reset by changing the xml variable $opts{'xml'}, not in user_nl_cpl \n"; } elsif (defined $opts{'der'}) { die "$ProgName - ERROR: $var is derived - cannot be changed in user_nl_cpl \n"; } else { die "$ProgName - ERROR: $var cannot be modified in user_nl_cpl \n"; } } return; } # Look for a specified value in the options hash if (defined $opts{'val'}) { $val = $opts{'val'}; } elsif (defined $opts{'valxml'}) { $val = $opts{'valxml'}; } # 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); $val = expand_env_xml($val); } # 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 =~ s/ //g; if ($val eq 'idmap') { # do nothing } else { $val = set_abs_filepath($val, $DIN_LOC_ROOT); } } # 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 in the namelist defaults return $defaults->get_value($var_name, $usr_att_ref); } #----------------------------------------------------------------------------------------------- sub check_input_files { # For each variable in the namelist which is an input dataset, check to see if it # exists locally. # # ***** 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; open(OUTFILE, ">$outfile") if defined $inputdata_rootdir; # 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 ($pathname =~ /idmap/) { # do nothing } elsif ($input_pathname_type eq 'abs') { if ($inputdata_rootdir) { print OUTFILE "$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 OUTFILE "$var = $pathname\n"; } else { if (-f "$rootdir/$pathname") { print "OK -- found $var = $rootdir/$pathname\n"; } else { print "NOT FOUND: $var = $rootdir/$pathname\n"; } } } } } } close OUTFILE if defined $inputdata_rootdir; return 0 if defined $inputdata_rootdir; } #----------------------------------------------------------------------------------------------- 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_options { 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); } #------------------------------------------------------------------------------- sub quote_string { my $str = shift; $str =~ s/^\s+//; $str =~ s/\s+$//; unless ($str =~ /^['"]/) { #"' $str = "\'$str\'"; } return $str; } #------------------------------------------------------------------------------- sub expand_env_xml { my $value = shift; if ($value =~ /\$([\w_]+)(.*)$/) { my $subst = $xmlvars{$1}; $value =~ s/\$${1}/$subst/g; } return $value; }