From f497d1c9224b2e3a39fd54759d61de58ea7388ee Mon Sep 17 00:00:00 2001 From: James Foucar Date: Thu, 19 Oct 2017 10:49:36 -0600 Subject: [PATCH] Revert "Merge branch 'jgfouca/cime/remove_zombie_files' into master (PR #1855)" This reverts commit 28136d3d9c57fdabbf2c278fd3f03190919b8410, reversing changes made to 658107a83ea51a90902773754c97bd7480362fe2. --- scripts/Testing/Testcases/ICP_script | 108 ++ scripts/Testing/Testcases/LAR_script | 109 ++ scripts/Testing/Testcases/OCP_script | 89 ++ scripts/Testing/Testcases/README | 39 + scripts/Testing/testreporter.pl | 678 +++++++++ .../namelist_files/namelist_defaults_drv.xml | 9 + .../namelist_definition_drv.xml | 17 + .../namelist_definition_drv_flds.xml | 131 ++ .../namelist_definition_modio.xml | 122 ++ .../bld/testdir/Buildconf/camconf/drv_flds_in | 9 + .../bld/testdir/Buildconf/clmconf/drv_flds_in | 9 + src/drivers/mct/bld/testdir/env_build.xml | 71 + src/drivers/mct/bld/testdir/env_case.xml | 20 + src/drivers/mct/bld/testdir/env_mach_pes.xml | 324 +++++ src/drivers/mct/bld/testdir/env_run.xml | 1278 +++++++++++++++++ src/drivers/mct/bld/testdir/runtest | 1 + src/drivers/mct/bld/testdir/user_nl_cpl | 3 + src/externals/pio2/src/clib/ncparser.pl | 362 +++++ src/externals/pio2/src/clib/ncputgetparser.pl | 352 +++++ .../pio2/src/clib/pio_c_get_template.c | 62 + .../pio2/src/clib/pio_c_put_template.c | 77 + src/externals/pio2/src/clib/pio_c_template.c | 54 + .../tests/general/pio_decomp_fillval2.F90 | 227 +++ src/externals/pio2/tests/unit/README | 5 + src/externals/pio2/tests/unit/test_names.c | 416 ++++++ src/externals/pio2/tests/unit/test_nc4.c | 506 +++++++ tests/unit/test_names.c | 416 ++++++ .../runoff_to_ocn/runoff_map.nml | 15 + .../runoff_to_ocn/runoff_map_r05_gx3v7.nml | 15 + .../runoff_to_ocn/runoff_map_rx1_gx1v6.nml | 15 + .../runoff_to_ocn/runoff_map_tx01.nml | 15 + .../runoff_to_ocn/runoff_map_wr50a_ar9v4.nml | 15 + .../runoff_to_ocn/runoff_map_wr50a_gx3v7.nml | 15 + 33 files changed, 5584 insertions(+) create mode 100755 scripts/Testing/Testcases/ICP_script create mode 100755 scripts/Testing/Testcases/LAR_script create mode 100755 scripts/Testing/Testcases/OCP_script create mode 100644 scripts/Testing/Testcases/README create mode 100755 scripts/Testing/testreporter.pl create mode 100644 src/drivers/mct/bld/namelist_files/namelist_defaults_drv.xml create mode 100644 src/drivers/mct/bld/namelist_files/namelist_definition_drv.xml create mode 100644 src/drivers/mct/bld/namelist_files/namelist_definition_drv_flds.xml create mode 100644 src/drivers/mct/bld/namelist_files/namelist_definition_modio.xml create mode 100644 src/drivers/mct/bld/testdir/Buildconf/camconf/drv_flds_in create mode 100644 src/drivers/mct/bld/testdir/Buildconf/clmconf/drv_flds_in create mode 100644 src/drivers/mct/bld/testdir/env_build.xml create mode 100644 src/drivers/mct/bld/testdir/env_case.xml create mode 100644 src/drivers/mct/bld/testdir/env_mach_pes.xml create mode 100644 src/drivers/mct/bld/testdir/env_run.xml create mode 100755 src/drivers/mct/bld/testdir/runtest create mode 100644 src/drivers/mct/bld/testdir/user_nl_cpl create mode 100644 src/externals/pio2/src/clib/ncparser.pl create mode 100644 src/externals/pio2/src/clib/ncputgetparser.pl create mode 100644 src/externals/pio2/src/clib/pio_c_get_template.c create mode 100644 src/externals/pio2/src/clib/pio_c_put_template.c create mode 100644 src/externals/pio2/src/clib/pio_c_template.c create mode 100644 src/externals/pio2/tests/general/pio_decomp_fillval2.F90 create mode 100644 src/externals/pio2/tests/unit/README create mode 100644 src/externals/pio2/tests/unit/test_names.c create mode 100644 src/externals/pio2/tests/unit/test_nc4.c create mode 100644 tests/unit/test_names.c create mode 100644 tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map.nml create mode 100644 tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_r05_gx3v7.nml create mode 100644 tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_rx1_gx1v6.nml create mode 100644 tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_tx01.nml create mode 100644 tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_ar9v4.nml create mode 100644 tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_gx3v7.nml diff --git a/scripts/Testing/Testcases/ICP_script b/scripts/Testing/Testcases/ICP_script new file mode 100755 index 00000000000..7a4cfd925cf --- /dev/null +++ b/scripts/Testing/Testcases/ICP_script @@ -0,0 +1,108 @@ + +#====================================================================== +# Test setup: +#====================================================================== + +cd $CASEROOT + +touch cice_perf.out + +./xmlchange --file env_run.xml --id CONTINUE_RUN --val FALSE +./xmlchange --file env_run.xml --id REST_OPTION --val none +./xmlchange --file env_build.xml --id CICE_AUTO_DECOMP --val false + +cat >! user_nl_cice.mhT <! user_nl_cice.mhF <> cice_perf.out +while ($cnt < $cntmax && $found == 1) + @ cnt = $cnt + 1 + set acnt = $cnt + if ($cnt < 1000) set acnt = "0${cnt}" + if ($cnt < 100 ) set acnt = "00${cnt}" + if ($cnt < 10 ) set acnt = "000${cnt}" + + if (-e env_build.xml.${acnt}) then + cp -f env_build.xml.${acnt} env_build.xml + cp -f env_build.xml LockedFiles/env_build.xml + cp -f $EXEROOT/${CIME_MODEL}.exe.${acnt} $EXEROOT/${CIME_MODEL}.exe + + foreach maskhalo (T F) + cd $CASEROOT + cp -f user_nl_cice.mh${maskhalo} user_nl_cice + + ./case.run + if ($status != 0) then + echo " ERROR: case.run failed" >>& $TESTSTATUS_LOG + exit -1 + endif + + set ICE_GRID = `./xmlquery ICE_GRID --value` + set CICE_BLCKX = `./xmlquery CICE_BLCKX --value` + set CICE_BLCKY = `./xmlquery CICE_BLCKY --value` + set CICE_MXBLCKS = `./xmlquery CICE_MXBLCKS --value` + set CICE_DECOMPTYPE = `./xmlquery CICE_DECOMPTYPE --value ` + set CICE_DECOMPSETTING = `./xmlquery CICE_DECOMPSETTING --value ` + set NTASKS_ICE = `./xmlquery NTASKS_ICE --value` + set NTHRDS_ICE = `./xmlquery NTHRDS_ICE --value` + + set LID = `ls -1t $RUNDIR/cpl.log* | head -1 | sed 's/.*cpl.log.//' | sed 's/.gz//' ` + @ ice_pes = ${NTASKS_ICE} * ${NTHRDS_ICE} + if ($LID != "") then + set ice_time = `grep -i "ice run time" timing/*$LID | cut -c 40-70` + echo "$LID $ICE_GRID ${ice_pes} $NTASKS_ICE $NTHRDS_ICE $CICE_BLCKX $CICE_BLCKY $CICE_MXBLCKS $CICE_DECOMPTYPE $CICE_DECOMPSETTING $maskhalo ${ice_time}" >> cice_perf.out + mv ${RUNDIR} ${RUNDIR}.${LID} + else + echo " error..... $ICE_GRID ${ice_pes} $NTASKS_ICE $NTHRDS_ICE $CICE_BLCKX $CICE_BLCKY $CICE_MXBLCKS $CICE_DECOMPTYPE $CICE_DECOMPSETTING $maskhalo " >> cice_perf.out + mv ${RUNDIR} ${RUNDIR}.error + endif + end # maskhalo + else + set found = 0 + endif +end # while +echo " done..... " >> cice_perf.out + +set CplLogFile = `ls -1t $RUNDIR/cpl.log* | head -1` +if ( $?CplLogFile ) then + if (-e $CplLogFile) then + set pass = `zgrep "SUCCESSFUL TERMINATION" $CplLogFile | wc -l` + if ($pass != 1) then + echo "ERROR: coupler log $CplLogFile indicates model run failed" >>& $TESTSTATUS_LOG + exit -1 + else + echo "Success: test log is $CplLogFile" >>& $TESTSTATUS_LOG + endif + endif +else + echo "ERROR: no coupler log created, model run failed" >>& $TESTSTATUS_LOG + exit -1 +endif + +#====================================================================== +# Test status check: +#====================================================================== + +set CPLLOG = $CplLogFile + +echo "DONE ${CASEBASEID} : ($msg finished, successful coupler log) " >>& $TESTSTATUS_LOG +echo "" >>& $TESTSTATUS_LOG diff --git a/scripts/Testing/Testcases/LAR_script b/scripts/Testing/Testcases/LAR_script new file mode 100755 index 00000000000..c06ff841367 --- /dev/null +++ b/scripts/Testing/Testcases/LAR_script @@ -0,0 +1,109 @@ + +#====================================================================== +# (1) do an initial run test +#====================================================================== + +cd $CASEROOT + +set RUN_STARTDATE = `./xmlquery RUN_STARTDATE --value` +set DOUT_S_ROOT = `./xmlquery DOUT_S_ROOT --value` +set DOUT_L_MSROOT = `./xmlquery DOUT_L_MSROOT --value` + +echo "doing an initial test" >>& $TESTSTATUS_LOG + +set start_date = $RUN_STARTDATE +set start_year = `echo $start_date | cut -f 1 -d "-"` +set start_date = $start_year-11-01 + +./xmlchange --file env_run.xml --id START_DATE --val $start_yearp2-01-01 +./xmlchange --file env_build.xml --id BUILD_COMPLETE --val TRUE +./xmlchange --file env_run.xml --id CONTINUE_RUN --val FALSE +./xmlchange --file env_run.xml --id REST_OPTION --val none + +./case.run +if ($status != 0) then + echo " ERROR: case.run failed" >>& $TESTSTATUS_LOG + exit -1 +endif + +set CplLogFile = `ls -1t $RUNDIR/cpl.log* | head -1` +if ( $?CplLogFile ) then + if (-e $CplLogFile) then + set pass = `zgrep "SUCCESSFUL TERMINATION" $CplLogFile | wc -l` + if ($pass != 1) then + echo "ERROR: coupler log $CplLogFile indicates model run failed" >>& $TESTSTATUS_LOG + exit -1 + else + echo "Success: test log is $CplLogFile" >>& $TESTSTATUS_LOG + endif + endif +else + echo "ERROR: no coupler log created, model run failed" >>& $TESTSTATUS_LOG + exit -1 +endif + +echo "running long-term archiver" >>& $TESTSTATUS_LOG + +./case.lt_archive + +#====================================================================== +# (2) do a restart run test +#====================================================================== + +echo "doing a continue run" >>& $TESTSTATUS_LOG + +./xmlchange --file env_run.xml --id CONTINUE_RUN --val TRUE + +./case.run +if ($status != 0) then + echo " ERROR: case.run failed" >>& $TESTSTATUS_LOG + exit -1 +endif + +set CplLogFile = `ls -1t $RUNDIR/cpl.log* | head -1` +if ( $?CplLogFile ) then + if (-e $CplLogFile) then + set pass = `zgrep "SUCCESSFUL TERMINATION" $CplLogFile | wc -l` + if ($pass != 1) then + echo "ERROR: coupler log $CplLogFile indicates model run failed" >>& $TESTSTATUS_LOG + exit -1 + else + echo "Success: test log is $CplLogFile" >>& $TESTSTATUS_LOG + endif + endif +else + echo "ERROR: no coupler log created, model run failed" >>& $TESTSTATUS_LOG + exit -1 +endif + +echo "running long-term archiver" >>& $TESTSTATUS_LOG +./case.lt_archive + +# TODO ??? What should be done here? + +#====================================================================== +# Check case validation first +#====================================================================== + +# What should be done here - this is the old code - but I am not sure what we should have to replace it? + +set pass = `$SCRIPTSROOT/Tools/ccsm_msls ${DOUT_L_MSROOT}/restart.tars | grep 0002-01-01 | wc -l` +if ($pass == 0) then + echo "ERROR in ${0}: 0002-01-01 restart.tar not long-term archived" >>& $TESTSTATUS_LOG + set basestatus = "FAIL" +endif + +set pass = `ls -1 ${DOUT_S_ROOT}/restart.tars | grep 0002-01-01 | wc -l` +if ($pass == 1) then + echo "ERROR in ${0}: 0002-01-01 restart.tar not removed in short-term archive" >>& $TESTSTATUS_LOG + set basestatus = "FAIL" +endif + +set pass = `$SCRIPTSROOT/Tools/ccsm_msls ${DOUT_L_MSROOT}/restart.tars | grep 0002-03-01 | wc -l` +if ($pass == 0) then + echo "ERROR in ${0}: 0002-03-01 restart.tar not long-term archived" >>& $TESTSTATUS_LOG + set basestatus = "FAIL" +endif + +echo "$basestatus ${CASEBASEID} ARCHIVE" >>&! $TESTSTATUS_OUT + diff --git a/scripts/Testing/Testcases/OCP_script b/scripts/Testing/Testcases/OCP_script new file mode 100755 index 00000000000..6d854f84892 --- /dev/null +++ b/scripts/Testing/Testcases/OCP_script @@ -0,0 +1,89 @@ + +#====================================================================== +# Test setup: +#====================================================================== + +cd $CASEROOT + +touch pop_perf.out + +./xmlchange --file env_run.xml --id CONTINUE_RUN --val FALSE +./xmlchange --file env_run.xml --id REST_OPTION --val none +./xmlchange --file env_build.xml --id POP_AUTO_DECOMP --val false + +#====================================================================== +# do an initial run test +#====================================================================== + + set cntmax = 1000 + set cnt = 0 + set found = 1 + + echo " start..... " >> pop_perf.out + while ($cnt < $cntmax && $found == 1) + @ cnt = $cnt + 1 + set acnt = $cnt + if ($cnt < 1000) set acnt = "0${cnt}" + if ($cnt < 100 ) set acnt = "00${cnt}" + if ($cnt < 10 ) set acnt = "000${cnt}" + + if (-e env_build.xml.${acnt}) then + cp -f env_build.xml.${acnt} env_build.xml + cp -f env_build.xml LockedFiles/env_build.xml + cp -f $EXEROOT/${CIME_MODEL}.exe.${acnt} $EXEROOT/${CIME_MODEL}.exe + + ./case.run + if ($status != 0) then + echo " ERROR: case.run failed" >>& $TESTSTATUS_LOG + exit -1 + endif + + set OCN_GRID = `./xmlquery OCN_GRID --value` + set POP_BLCKX = `./xmlquery POP_BLCKX --value` + set POP_BLCKY = `./xmlquery POP_BLCKY --value` + set POP_MXBLCKS = `./xmlquery POP_MXBLCKS --value` + set POP_DECOMPTYPE = `./xmlquery POP_DECOMPTYPE --value` + set NTASKS_OCN = `./xmlquery NTASKS_OCN --value` + set NTHRDS_OCN = `./xmlquery NTHRDS_OCN --value` + + set LID = `ls -1t $RUNDIR/cpl.log* | head -1 | sed 's/.*cpl.log.//' | sed 's/.gz//' ` + @ ocn_pes = ${NTASKS_OCN} * ${NTHRDS_OCN} + if ($LID != "") then + set ocn_time = `grep -i "ocn run time" timing/*$LID | cut -c 40-70` + echo "$LID $OCN_GRID ${ocn_pes} $NTASKS_OCN $NTHRDS_OCN $POP_BLCKX $POP_BLCKY $POP_MXBLCKS $POP_DECOMPTYPE ${ocn_time}" >> pop_perf.out + mv ${RUNDIR} ${RUNDIR}.${LID} + else + echo " error..... $OCN_GRID ${ocn_pes} $NTASKS_OCN $NTHRDS_OCN $POP_BLCKX $POP_BLCKY $POP_MXBLCKS $POP_DECOMPTYPE " >> pop_perf.out + mv ${RUNDIR} ${RUNDIR}.error + endif + else + set found = 0 + endif + end # while + echo " done..... " >> pop_perf.out + +set CplLogFile = `ls -1t $RUNDIR/cpl.log* | head -1` +if ( $?CplLogFile ) then + if (-e $CplLogFile) then + set pass = `zgrep "SUCCESSFUL TERMINATION" $CplLogFile | wc -l` + if ($pass != 1) then + echo "ERROR: coupler log $CplLogFile indicates model run failed" >>& $TESTSTATUS_LOG + exit -1 + else + echo "Success: test log is $CplLogFile" >>& $TESTSTATUS_LOG + endif + endif +else + echo "ERROR: no coupler log created, model run failed" >>& $TESTSTATUS_LOG + exit -1 +endif + +#====================================================================== +# Test status check: +#====================================================================== + +set CPLLOG = $CplLogFile + +echo "DONE ${CASEBASEID} : ($msg finished, successful coupler log) " >>& $TESTSTATUS_LOG +echo "" >>& $TESTSTATUS_LOG + diff --git a/scripts/Testing/Testcases/README b/scripts/Testing/Testcases/README new file mode 100644 index 00000000000..33abd639d05 --- /dev/null +++ b/scripts/Testing/Testcases/README @@ -0,0 +1,39 @@ + +NOTES: +Most of the tests have been moved to python in cime/utils/python/CIME/SystemTests +See the README there for more info. + +The remaining tests are: + +====================================================================== + Multi-Instance Tests (smoke) +====================================================================== + +NOC multi-instance validation for single instance ocean (default length) + do an initial run test with NINST 2 (other than ocn), with mod to instance 1 (suffix: inst1_base, inst2_mod) + do an initial run test with NINST 2 (other than ocn), with mod to instance 2 (suffix: inst1_base, inst2_mod) + compare inst1_base with inst2_base + compare inst1_mod with inst2_mod + + +====================================================================== + Performance Tests +====================================================================== + +ICP cice performance test +OCP pop performance test + +====================================================================== + Archiving Tests +====================================================================== + +LAR long term archive test + +====================================================================== + Other +====================================================================== + +HOMME + + + diff --git a/scripts/Testing/testreporter.pl b/scripts/Testing/testreporter.pl new file mode 100755 index 00000000000..96b433d97b0 --- /dev/null +++ b/scripts/Testing/testreporter.pl @@ -0,0 +1,678 @@ +#!/usr/bin/env perl +use Getopt::Long; +use Data::Dumper; +use LWP; +use HTTP::Request; +use HTTP::Request::Common qw(POST); +use XML::LibXML; +use Cwd qw(abs_path); +#------------------------------------------------------------------------------- +# testreporter.pl +# Perl script that watches the CIME tests as they progress, and sends the reports to +# the testdb application at csegweb.cgd.ucar.edu + +#------------------------------------------------------------------------------- +# Constants. Filenames we look in for test results, and the time we sleep between +# reporting test results. +#------------------------------------------------------------------------------- +my $teststatusfilename = "TestStatus"; +my $teststatusoutfilename = "TestStatus.out"; +my $iopstatusfilename = "TestStatus.IOP"; +my $casestatusfilename = "CaseStatus"; +my $sleeptime = 120; +my $baselinetag; +my $testspecfile; +# The URL we send test results to. +my $posturl = "https://csegweb.cgd.ucar.edu/testdb/cgi-bin/processXMLtest.cgi"; + +# Options and global variables. +#------------------------------------------------------------------------------- +# root of the test suite currently running. +my $testroot = undef; +# The tag name you are testing. +my $tagname = undef; +# the testid parameter specified for ./create_test_suite. This script uses this parameter to +# find the tests you are running. +my $testid = undef; +# the email address to send test reports to. +my $email = undef; +# the test type: should be one of prealpha, prebeta, or prerelease. +my $testtype = undef; +my $debug = 0; +my $dumpxml = 0; +my $printreport = 0; +my $dryrun = 0; +my $username = undef; +my $password = undef; + +#------------------------------------------------------------------------------- +# Main +# Get the options first. +# Then, get the test directories, get the test suite info, get the test status for all the tests, +# and send the results. +#------------------------------------------------------------------------------- +opts(); +authenticate(); + +my @testdirs; +my %suiteinfo; + +@testdirs = &getTestDirs($testroot, $testid); +%suiteinfo = &getTestSuiteInfo(\@testdirs); +my $teststatus; +my $nlfailreport; +($teststatus, $nlfailreport) = getTestStatus(\@testdirs, $tagname, $testid); +#print %teststatus; +&Debug( eval { Dumper $teststatus} ); +&Debug( eval { Dumper \%suiteinfo } ); +my $testxml = &makeResultsXml($teststatus, \%suiteinfo, $nlfailreport); +if(!$dryrun) +{ + &sendresults(\%teststatus, \%suiteinfo, $testxml); +} +&printreport($teststatus, $nlfailreport) if $printreport; + +#------------------------------------------------------------------------------- +# End Main +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# Get the options. +#------------------------------------------------------------------------------- +sub opts +{ + my $opt_help; + GetOptions( + "testroot=s" => \$testroot, + "tagname=s" => \$tagname, + "testid=s" => \$testid, + "debug|d" => \$debug, + "testtype=s" => \$testtype, + "help" => \$opt_help, + "dumpxml|x" => \$dumpxml, + "printreport|p" => \$printreport, + "dryrun" => \$dryrun, + ); + + # Show usage if the required options aren't specified. + &help if (defined $opt_help); + &usage if ( (! defined $testroot) ||(! defined $tagname) || (! defined $testid) || (!defined $testtype)); +} + +#------------------------------------------------------------------------------- +# Show the usage, and exit. +#------------------------------------------------------------------------------- +sub usage +{ + print <<'END'; + Usage: + ./testreporter.pl --testroot /glade/scratch/$user/tests/cesm1_1_alphaXX --tagname cesm1_1_alpha15c --testid testid --testtype prealpha|prebeta|prerelease [--dumpxml|--printreport] +END + exit(1); +} + +sub help +{ + + print <<'END'; + This is the CIME test reporter script, intended to be used to simplify the reporting of CIME test sets. + Usage is as follows: + ./testreporter --testroot /glade/scratch/$user/tests/cesm1_1_alphaXX + --tagname cesm1_1_alpha15c --testid testid --testtype prealpha + It gathers all the test results found in the --testroot, gets the relevant test + status fields, and sends the results to the test reporting system on csegweb. + + Options: + --testroot This is the testroot you defined when running the test suite + --tagname The name of the tag you are testing. + For example, if you are testing a sandbox that will eventilally + become cesm1_1_alpha16c, then put cesm1_1_alpha16c. If you are + running a suite that will become a beta tag, put the last alpha + tag used. + --testid The testid you specified to create_test_suite. + --testtype The type of test you are running: prealpha, prebeta, or prerelease. + +END +} + +#------------------------------------------------------------------------------- +# Show debugging information if desired. +#------------------------------------------------------------------------------- +sub Debug +{ + if($debug) + { + my ($msg) = @_; + chomp $msg; + print "Debug: $msg\n"; + } +} + + +#------------------------------------------------------------------------------- +# Using the testroot, find the test directories that end with the specified testid. +# If no matching directories are found, then exit. +#------------------------------------------------------------------------------- +sub getTestDirs +{ + my ($testd, $tid) = @_; + + # Abort if the testroot does not exist. + if ( ! -d $testd) + { + print STDERR "The testroot does not exist! Aborting...\n"; + exit(1); + } + # open the testroot, find the test directories. If no test directories ending in + # the testid exist, then abort. + opendir(my $DIR, $testd) or die "can't open $testd, error was $!"; + my @testdirs = grep { $_ =~ /($tid)$/ } grep { !/sharedlibroot/} grep { !/cs.status/} readdir($DIR); + closedir $DIR; + &Debug("in gettestdirs: test directories: \n"); + &Debug( eval { Dumper \@testdirs} ); + if(@testdirs) + { + return @testdirs; + } + else + { + print STDERR "It appears that the test root exists, but there aren't any test directories\n"; + print STDERR "in the testroot. Aborting...\n"; + exit(1); + } + return @testdirs; +} + +#------------------------------------------------------------------------------- +# Get the suite info and send it back. +#------------------------------------------------------------------------------- +sub getTestSuiteInfo +{ + my $testlist = shift; + my %caseinfo; + my $testpath; + foreach my $testdir(@$testlist) + { + $testpath = $testroot . "/" . $testdir; + if( -e "$testpath/env_case.xml" && -e "$testpath/env_run.xml" && "$testpath/env_build.xml") + { + last; + } + } + &Debug("test path: $testpath\n"); + + # We need to find SetupTools in a path-independent manner. + # so parse out the cimeroot from testspec.*.xml, + # get rid of the tags, and then we have + #my $testspecfile = "$testroot/testspec.$testid.$caseinfo{'mach'}.xml"; + my $testspecfile = "$testroot/testspec.$testid.xml"; + Debug( "testspecfile: $testspecfile\n"); + + # SetupTools needs a case to work, so why not just cd to the + # first test directory, and run SetupTools there?? :) + my $firsttestdir = $testroot . "/" . $$testlist[0]; + Debug("first test dir: $firsttestdir"); + chdir $firsttestdir; + my $cimeroot = `./xmlquery CIMEROOT --value`; + my @dirs = ( $testpath, "$cimeroot/utils/perl5lib"); + unshift @INC, @dirs; + require Config::SetupTools; + + my %config = SetupTools::getAllResolved(); + $caseinfo{'mach'} = $config{'MACH'}; + $caseinfo{'compiler'} = $config{'COMPILER'}; + $caseinfo{'mpilib'} = $config{'MPILIB'}; + $caseinfo{'baselinetag'} = $config{'BASELINE_NAME_CMP'}; + + chdir $testroot; + + &Debug("caseinfo: " . eval { Dumper \%caseinfo} ); + return %caseinfo; +} + +#------------------------------------------------------------------------------- +# Get the test status. open the $testroot , look for all the test directories, +# then get the test status. +#------------------------------------------------------------------------------- +sub getTestStatus +{ + my ($testdirs, $tag, $testid) = @_; + my %teststatushash; + my %nlreporthash; + my $time = localtime; + print "$time\n"; + + # Iterate through each of the test directories, and get the requisite test information. + foreach my $testcase(@$testdirs) + { + # Get the test status + &Debug("testcase $testcase"); + my $testbaseid = $testcase; + $testbaseid =~ s/$testid//g; + $testbaseid =~ s/\.G\.//g; + $testbaseid =~ s/\.C\.//g; + $testbaseid =~ s/\.GC\.//g; + &Debug("testbaseid $testbaseid"); + if( ! -e $testroot . "/" . $testcase . "/" . "TestStatus") + { + next; + } + + my $statusfile = $testroot . "/" . $testcase . "/" . $teststatusfilename; + if( ! -e $statusfile) + { + warn("$statusfile does not exist, skipping to next test."); + $teststatushash{$testcase}{'status'} = "TFAIL"; + $teststatushash{$testcase}{'comment'} = "TestStatus file could not be found!"; + next; + } + &Debug( "Status file: $statusfile\n"); + open (my $teststatusfile, "<", $statusfile) or die "cannot open TestStatus file for $testcase, $!"; + + &Debug("Testcase: $testcase\n"); + &Debug("Teststatus: $teststatus\n"); + + my $testsummary = $teststatus; + + # Now go through the TestStats getting the memleak, compare, baseline tag, throughput, and comments if any. + my @statuslines = <$teststatusfile>; + chomp @statuslines; + + + # If the 'test functionality summary' is not PASS, then report the + # test functionality summary as the teststatus field. + + # Namelist compare + my @testsummarylines = grep { /NLCOMP/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + $teststatushash{$testcase}{'nlcomp'} = (length($testsummary) > 0) ? $testsummary : "----"; + + # Memory leak + my @testsummarylines = grep { /MEMLEAK/ } grep { !/insuffiencient/} @statuslines; + my @testsummary_arr = (split(/\s+/, $testsummarylines[0])); + $teststatushash{$testcase}{'memleak'} = ($#testsummarylines > -1) ? @testsummary_arr[0] : "----"; + $teststatushash{$testcase}{'comment'} .= " @testsummary_arr[3..$#testsummary_arr]"; + + + # Compare memory usage to baseline + my @testsummarylines = grep { /MEMCOMP/} @statuslines; + my @testsummary_arr = (split(/\s+/, $testsummarylines[0])); + $teststatushash{$testcase}{'memcomp'} = ($#testsummarylines > -1) ? @testsummary_arr[0] : "----"; + $teststatushash{$testcase}{'comment'} .= " @testsummary_arr[3..$#testsummary_arr]"; + + #Compare to baseline + my @testsummarylines = grep { /BASELINE/} @statuslines; + my @testsummary_arr = (split(/\s+/, $testsummarylines[0])); + $teststatushash{$testcase}{'compare'} = ($#testsummarylines > -1) ? @testsummary_arr[0] : "----"; + $teststatushash{$testcase}{'comment'} .= " @testsummary_arr[3..$#testsummary_arr]"; + + # Compare through put to baseline + my @testsummarylines = grep { /TPUTCOMP/} @statuslines; + my @testsummary_arr = (split(/\s+/, $testsummarylines[0])); + $teststatushash{$testcase}{'tputcomp'} = ($#testsummarylines > -1) ? @testsummary_arr[0] : "----"; + $teststatushash{$testcase}{'comment'} .= " @testsummary_arr[3..$#testsummary_arr]"; + if ($testcase =~ "PFS" && @testsummary_arr[0] =~ "FAIL") + { + $teststatushash{$testcase}{'status'} = "FAIL"; + next; + } + + # Check for INIT failure + my @testsummarylines = grep { /INIT/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "SFAIL"; + $teststatushash{$testcase}{'comment'} .= "Failed during INIT!"; + next; + } + + # Check for CREATE_NEWCASE failure + my @testsummarylines = grep { /CREATE_NEWCASE/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "SFAIL"; + $teststatushash{$testcase}{'comment'} .= "Failed in CREATE_NEWCASE!"; + next; + } + + # Check for XML failure + my @testsummarylines = grep { /XML/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "SFAIL"; + $teststatushash{$testcase}{'comment'} .= "Failed in XML!"; + next; + } + + # Check for SETUP failure + my @testsummarylines = grep { /SETUP/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "SFAIL"; + $teststatushash{$testcase}{'comment'} .= "Failed during SETUP!"; + next; + } + + # Check for SHARELIB_BUILD failure + my @testsummarylines = grep { /SHAREDLIB_BUILD/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "CFAIL"; + $teststatushash{$testcase}{'comment'} .= "Failed during SHAREDLIB_BUILD!"; + next; + } + + # Check for MODEL_BUILD failure + my @testsummarylines = grep { /MODEL_BUILD/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "CFAIL"; + $teststatushash{$testcase}{'comment'} .= "Failed during MODEL_BUILD!"; + next; + } + + # Check for RUN failure + my @testsummarylines = grep { /RUN/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = $testsummary; + next; + } + + #Compare for functionality + my @testsummarylines = grep { /COMPARE_base_rest/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "FAIL"; + $teststatushash{$testcase}{'comment'} .= "Functionality failed with restart!"; + next; + } + + my @testsummarylines = grep { /COMPARE_base_hybrid/ } @statuslines; + $testsummary = (split(/\s+/, $testsummarylines[0]))[0]; + if(defined $testsummary && $testsummary !~ /PASS/) + { + $teststatushash{$testcase}{'status'} = "FAIL"; + $teststatushash{$testcase}{'comment'} .= "Functionality failed with hybrid!"; + next; + } + + $teststatushash{$testcase}{'status'} = 'PASS'; + + + close $teststatusfile; + + # Check the CaseStatus, and print out the last line... + my $casestatusfile = $testroot . "/" . $testcase . "/" . $casestatusfilename; + if( -e $casestatusfile) + { + open (my $casestatusfile, "<", $casestatusfile) or die "cannot open CaseStatusfile for $testcase, $!"; + + my $lastline; + while(<$casestatusfile>) + { + $lastline = $_ if eof; + } + close $casestatusfile; + chomp $lastline; + &Debug ("last line of CaseStatus: $lastline\n"); + $teststatushash{$testcase}{'casestatus'} = $lastline; + } + else + { + &Debug("Case status file $casestatus doesn't exist"); + $teststatushash{$testcase}{'casestatus'} = "CaseStatus file not found"; + } + + # If the test is an IOP test, set a flag in the test status hash indicating it as such. + if($testcase =~ /IOP\./) + { + $teststatushash{$testcase}{'isioptest'} = "true"; + } + + # Get the IOP test status if the file exists. + # If so, create separate iop* entries in the teststatus hash for this test. + my $iopstatusfile = $testroot . "/" . $testcase . "/" . $iopstatusfilename; + if( -e $iopstatusfile) + { + open (my $iopfh, "<", $iopstatusfile) or die " cannot open IOP status file for $testcase, $!"; + my $iopstatus = <$iopfh>; + chomp $iopstatus; + $iopstatus = (split(/\s+/, $iopstatus))[0]; + $teststatushash{$testcase}{'iopstatus'} = $iopstatus; + @statuslines = <$iopstatusfile>; + + @memleaklines = grep { /memleak/ } @statuslines; + $memleakstatus = (split(/\s+/, $memleaklines[0]))[0]; + $teststatushash{$testcase}{'iopmemleak'} = (length($memleakstatus) > 0) ? $memleakstatus : "---"; + + @comparelines = grep { /compare_hist/} @statuslines; + ($comparestatus,$comparetest) = split(/\s+/, $comparelines[0]); + $teststatushash{$testcase}{'compare'} = $comparestatus; + $comparetag = (split(/\./, $comparetest))[-1]; + $teststatushash{$testcase}{'iopbaselinetag'} = $comparetag; + + @memcomplines = grep { /memcomp/} @statuslines; + $memcompstatus = (split(/\s+/, $memcomplines[0]))[0]; + $teststatushash{$testcase}{'iopmemcomp'} = $memcompstatus; + + @tputcomplines = grep { /tputcomp/ } @statuslines; + $tputcompstatus = (split(/\s+/, $tputcomplines[0]))[0]; + $teststatushash{$testcase}{'ioptputcomp'} = $tputcompstatus; + + @nlcomplines = grep { /nlcomp/i } @statuslines; + $nlcompstatus = (split(/\s+/, $nlcomplines[0]))[0]; + $teststatushash{$testcase}{'iopnlcomp'} = $nlcompstatus; + + @commentlines = grep { /COMMENT/ } @statuslines; + $comment = (split(/\s+/, $commentlines[0], 2) )[1]; + chomp $comment; + $teststatushash{$testcase}{'iopcomment'} = $comment; + + $teststatushash{$testcase}{'iopcasestatus'} = $teststatushash{$testcase}{'casestatus'}; + + close $iopfh; + } + + if($testtype eq 'namelist') + { + my $statusoutfile = $testroot . "/" . $testcase . "/" . $teststatusoutfilename; + if( -e $statusoutfile && $teststatushash{$testcase}{'nlcomp'} eq 'FAIL') + { + open my $STATUSOUT, "<", $statusoutfile or warn "can't open $statusoutfile, $!"; + my @statusoutlines = <$STATUSOUT>; + my $commentflag = 0; + foreach my $soline(@statusoutlines) + { + chomp $soline; + next if ($soline =~ /^$/); + $commentflag = 1 if ($soline =~ /^FAIL/); + $commentflag = 0 if ($soline =~ /^PASS/); + if($commentflag) + { + $teststatushash{$testcase}{'comment'} .= "$soline\n"; + Debug( eval { Dumper \$teststatushash{$testcase}{'comment'} } ); + } + } + $nlreporthash{$teststatushash{$testcase}{'comment'}}{$testcase} = 1; + } + } + + foreach my $blank(keys %nlreporthash) + { + delete $nlreporthash{$blank} if(length $nlreporthash{$blank} == 0); + } + } + + foreach my $blank(keys %nlreporthash) + { + delete $nlreporthash{$blank} if(length $nlreporthash{$blank} == 0); + } + +# print Dumper (\%teststatushash); + return \%teststatushash, \%nlreporthash; +} + + +# Send the results as an XML file, using the following DTD: +# +# +# +# +# +# +# +# +# +# +# +sub makeResultsXml +{ + my ($testresults, $suiteinfo, $nlfailreport) = @_; + my $testxml = XML::LibXML::Document->new('1.0', 'UTF-8'); + my $root = $testxml->createElement('testrecord'); + $root->appendTextChild('tag_name', $tagname); + $root->appendTextChild('mach', $suiteinfo{'mach'}); + my $compilerelem = XML::LibXML::Element->new('compiler'); + $compilerelem->setAttribute('version', ''); + $compilerelem->appendText($suiteinfo{'compiler'}); + $root->appendChild($compilerelem); + my $mpielem = XML::LibXML::Element->new('mpilib'); + $mpielem->setAttribute('version', ''); + $mpielem->appendText($suiteinfo{'mpilib'}); + $root->appendChild($mpielem); + $root->appendTextChild('testroot', $testroot); + $root->appendTextChild('testtype', $testtype); + $root->appendTextChild('baselinetag', $suiteinfo{'baselinetag'}); + + foreach my $test(reverse sort keys %$testresults) + { + my $testelem = $testxml->createElement('tests'); + $testelem->setAttribute('testname', $test); + foreach my $detail(sort keys %{$$testresults{$test}}) + { + my $catelem = $testxml->createElement('category'); + $catelem->setAttribute('name', $detail); + if($detail eq 'comment') + { + $cdata = XML::LibXML::CDATASection->new($$testresults{$test}{$detail}); + $catelem->appendChild($cdata); + } + else + { + $catelem->appendText($$testresults{$test}{$detail}); + } + $testelem->appendChild($catelem); + } + $root->appendChild($testelem); + } + + if($testtype eq 'namelist') + { + my $nlfailreportelem = XML::LibXML::Element->new('namelistfailuresreport'); + foreach my $nlfailkey(sort keys %$nlfailreport) + { + my $nlfailelem = $testxml->createElement('namelistfailure'); + my $nlfailtxt = $testxml->createElement('namelistfailuretext'); + my $nlfailcdata = XML::LibXML::CDATASection->new($nlfailkey); + $nlfailtxt->appendChild($nlfailcdata); + $nlfailelem->appendChild($nlfailtxt); + + foreach my $testname(sort keys %{$$nlfailreport{$nlfailkey}}) + { + $nlfailelem->appendTextChild('test', $testname); + } + $nlfailreportelem->appendChild($nlfailelem); + } + $root->appendChild($nlfailreportelem); + } + + $testxml->setDocumentElement($root); + $xmlstring = $testxml->toString(1); + Debug("testxml file: "); + Debug( $xmlstring); + if($debug || $dumpxml) + { + open my $xmldumpfile, ">", "./testreporter.dump.xml" or die $!; + print $xmldumpfile $testxml->toString(1); + close $xmldumpfile; + print "wrote xml test report to testreporter.dump.xml\n"; + } + return $testxml; +} + +sub sendresults +{ + my ($testresults, $suiteinfo, $testxml) = @_; + my $resultsstr = $testxml->toString(1); + + my $useragent = LWP::UserAgent->new(ssl_opts => {verify_hostname => 0}); + + # Do not do the HTTP post this way, any string data in the variable $resultsstr + # will break the POST on the CGI side + #my $req = HTTP::Request->new(POST => $posturl); + #$req->content_type('application/x-www-form-urlencoded'); + #$req->content("username=$username&password=$password&testXML=$resultsstr"); + + # This method of doing the POST makes sure that everything is escaped properly + my $req = POST "$posturl", + [ username => $username, password => $password, testXML => $resultsstr ]; + my $response = $useragent->request($req); + + if($response->is_success) + { + print "Test results successfully posted to csegweb\n"; + } + elsif($response->code eq '401') + { + my $errmsg = "The server responded with '401 - Unauthorized'\n"; + $errmsg .= "Your svn username & password is most likely incorrect!\n"; + $errmsg .= "Please re-run the script, and provide the correct svn username & password\n"; + die $errmsg; + + } + else + { + print "Posting the results to $posturl failed! \n"; + my $status = $response->status_line; + print "$status\n"; + print "aborting!\n"; + exit(1); + } +} + +sub printreport +{ + my ($teststatus, $nlfailreport) = @_; + foreach my $basefail(keys %$nlfailreport) + { + my @tests = sort keys %{$$nlfailreport{$basefail}}; + print "====================================================================\n"; + print "namelist difference: \n"; + print "$basefail\n"; + print "--------------------------------------------------------------------\n"; + print "Tests which had the above namelist diffs:\n"; + map { print "$_\n"} sort @tests; + print "--------------------------------------------------------------------\n"; + } +} + +sub authenticate +{ + print "Enter your username: \n"; + $username = ; + print "Enter your password: \n"; + system('stty','-echo'); + chop($password = ); + system('stty','echo'); + chomp $username; + chomp $password; +} diff --git a/src/drivers/mct/bld/namelist_files/namelist_defaults_drv.xml b/src/drivers/mct/bld/namelist_files/namelist_defaults_drv.xml new file mode 100644 index 00000000000..2ad5c260133 --- /dev/null +++ b/src/drivers/mct/bld/namelist_files/namelist_defaults_drv.xml @@ -0,0 +1,9 @@ + + + + + + +Buildconf/camconf/drv_flds_in,Buildconf/clmconf/drv_flds_in + + diff --git a/src/drivers/mct/bld/namelist_files/namelist_definition_drv.xml b/src/drivers/mct/bld/namelist_files/namelist_definition_drv.xml new file mode 100644 index 00000000000..493f2f2a01b --- /dev/null +++ b/src/drivers/mct/bld/namelist_files/namelist_definition_drv.xml @@ -0,0 +1,17 @@ + + + + + 1.0 + + + + + + + + + diff --git a/src/drivers/mct/bld/namelist_files/namelist_definition_drv_flds.xml b/src/drivers/mct/bld/namelist_files/namelist_definition_drv_flds.xml new file mode 100644 index 00000000000..b54082981ac --- /dev/null +++ b/src/drivers/mct/bld/namelist_files/namelist_definition_drv_flds.xml @@ -0,0 +1,131 @@ + + + + + + + + List of files to merge together that contains drv_flds_in namelists + The paths are relative to the case directory. drv_flds_in include the namelists that + the driver reads and gives information on additional fields to be passed to different + components that need to look at the same data. + + + + + + + + File containing MEGAN emissions factors. Includes the list of MEGAN compounds that can be + used in the Comp_Name variable on the file. + + + + MEGAN specifier. This is in the form of: Chem-compound = megan_compound(s) + where megan_compound(s) can be the sum of megan compounds with a "+" between them. + In each equation, the item to the left of the equal sign is a CAM chemistry compound, the + items to the right are compounds known to the MEGAN model (single or combinations). + For example: megan_specifier = 'ISOP = isoprene', 'C10H16 = pinene_a + carene_3 + thujene_a' + + + + MEGAN mapped isoprene emissions factors switch + If TRUE then use mapped MEGAN emissions factors for isoprene. + + + + List of possible MEGAN compounds to use + (the list used by the simulation is on the megan_factors_file as the Comp_Name) + + + + + + + + Where dry deposition is calculated (from land, atmosphere, or from a table) + This specifies the method used to calculate dry + deposition velocities of gas-phase chemical species. The available methods + are: + 'table' - prescribed method in CAM + 'xactive_atm' - interactive method in CAM + 'xactive_lnd' - interactive method in CLM + + + + List of species that undergo dry deposition. + + + + + + + + + File containing fire emissions factors. + Default: none + + + + Fire emissions specifier. + Default: none + + + + If ture fire emissions are input into atmosphere as elevated forcings. + Otherwise they are treated as surface emissions. + Default: TRUE + + + + + + + + List of fluxes needed by the CARMA model, from CLM to CAM. + + + diff --git a/src/drivers/mct/bld/namelist_files/namelist_definition_modio.xml b/src/drivers/mct/bld/namelist_files/namelist_definition_modio.xml new file mode 100644 index 00000000000..394692c9037 --- /dev/null +++ b/src/drivers/mct/bld/namelist_files/namelist_definition_modio.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/drivers/mct/bld/testdir/Buildconf/camconf/drv_flds_in b/src/drivers/mct/bld/testdir/Buildconf/camconf/drv_flds_in new file mode 100644 index 00000000000..3946cbdf73e --- /dev/null +++ b/src/drivers/mct/bld/testdir/Buildconf/camconf/drv_flds_in @@ -0,0 +1,9 @@ +&drydep_inparm +/ +&megan_emis_nl +/ +&fire_emis_nl +/ +&carma_inparm + carma_fields = 'rstar' +/ diff --git a/src/drivers/mct/bld/testdir/Buildconf/clmconf/drv_flds_in b/src/drivers/mct/bld/testdir/Buildconf/clmconf/drv_flds_in new file mode 100644 index 00000000000..4f221f9d1dc --- /dev/null +++ b/src/drivers/mct/bld/testdir/Buildconf/clmconf/drv_flds_in @@ -0,0 +1,9 @@ +&drydep_inparm +/ +&megan_emis_nl +/ +&fire_emis_nl + fire_emis_specifier = 'bc_a1 = BC','pom_a1 = 1.4*OC','SO2 = SO2' +/ +&carma_inparm +/ diff --git a/src/drivers/mct/bld/testdir/env_build.xml b/src/drivers/mct/bld/testdir/env_build.xml new file mode 100644 index 00000000000..5536a0de3f7 --- /dev/null +++ b/src/drivers/mct/bld/testdir/env_build.xml @@ -0,0 +1,71 @@ + + +
+ These variables SHOULD NOT be changed once the model has been built. + urrently, these variables are not cached. + Note1: users SHOULD NOT modify BUILD_COMPETE below + this is done automatically by the scripts. +
+ + + char + Model grid - DO NOT EDIT (for experts only) + + + char + atmosphere grid - DO NOT EDIT (for experts only) + + + char + land grid - DO NOT EDIT (for experts only) + + + char + ocn grid - DO NOT EDIT (for experts only) + + + char + ice grid (must equal ocn grid) - DO NOT EDIT (for experts only) + + + char + river runoff (rof) grid + + + char + gland20,gland10,gland5,gland5UM,gland4,null + glacier (glc) grid - DO NOT EDIT (for experts only) + + + char + wave model (wav) grid + + + char + grid mask - DO NOT EDIT (for experts only) + + + + + char + NO_LEAP,GREGORIAN + calendar type + + + + + char + + mpi library (must match one of the supported libraries) - + ignored once Macros has been created + Set in $CIMEROOT/machines/config_machines.xml for each supported machine. + Must be explicitly set in env_build.xml for userdefined machine. + + + integer + 1,2 + PIO library version + + + +
diff --git a/src/drivers/mct/bld/testdir/env_case.xml b/src/drivers/mct/bld/testdir/env_case.xml new file mode 100644 index 00000000000..8527ed622f7 --- /dev/null +++ b/src/drivers/mct/bld/testdir/env_case.xml @@ -0,0 +1,20 @@ + + +
+ These variables CANNOT BE CHANGED once a case has been created. + Invoke create_newcase again if a different grid or component + combination is required. +
+ + + char + case name + + + + + char + case user name + + +
diff --git a/src/drivers/mct/bld/testdir/env_mach_pes.xml b/src/drivers/mct/bld/testdir/env_mach_pes.xml new file mode 100644 index 00000000000..a4fb763b4ae --- /dev/null +++ b/src/drivers/mct/bld/testdir/env_mach_pes.xml @@ -0,0 +1,324 @@ + + +
+ These variables CANNOT be modified once case_setup has been + invoked without first invoking case_setup -clean. + + component task/thread settings + if the user wants to change the values below after ./case_setup, run + ./case_setup -clean + ./case_setup + to reset the pes for the run + + NTASKS are the total number of MPI tasks, a negative value in this field + indicates nodes rather than tasks. + NTHRDS are the number of OpenMP threads per MPI task + ROOTPE is the global mpi task associated with the root task + of that component, a negative value in this field indicates nodes rather than tasks. PSTRID is the stride of MPI tasks across the global + set of pes (for now this is set to 1) + NINST is the number of instances of the component (will be spread + evenly across NTASKS) + + for example, for a setting with + NTASKS = 8 + NTHRDS = 2 + ROOTPE = 32 + NINST = 2 + the MPI tasks would be placed starting on global pe 32 + and each pe would be threaded 2-ways for this component. + These tasks will be divided amongst both instances (4 tasks each). + + Note: PEs that support threading never have an MPI task associated + with them for performance reasons. As a result, NTASKS and ROOTPE + are relatively independent of NTHRDS and they determine + the layout of mpi processors between components. NTHRDS is used + to determine how those mpi tasks should be placed across the machine. + + The following values should not be set by the user since they'll be + overwritten by scripts. + TOTALPES + CCSM_PCOST + CCSM_ESTCOST + PES_LEVEL + MAX_TASKS_PER_NODE + PES_PER_NODE + CCSM_TCOST + CCSM_ESTCOST + + The user can copy env_mach_pes.xml from another run, but they'll need to + do the following + ./case_setup -clean + ./case_setup + ./CASE.build +
+ + + integer + cost relative to 64 pes (DO NOT EDIT) + + + integer + relative cost of test where ERS is 1 (DO NOT EDIT) + + + integer + relative total cost of case (DO NOT EDIT) + + + integer + pes or cores used relative to PES_PER_NODE for accounting (0 means TOTALPES is valid) + + + integer + total number of tasks and threads (setup automatically - DO NOT EDIT) + + + integer + maximum number of tasks/ threads allowed per node + + + integer + pes or cores per node for accounting purposes + + + + + integer + number of atmosphere tasks + + + integer + number of atmosphere threads + + + integer + root atm mpi task + + + integer + Number of atmosphere instances + + + char + sequential,concurrent + Layout of atmosphere instances + + + + + integer + number of land mpi tasks + + + integer + number of land mpi threads + + + integer + root lnd mpi task + + + integer + Number of land instances + + + char + sequential,concurrent + Layout of land instances + + + + + integer + number of ice mpi tasks + + + integer + number of ice mpi threads + + + integer + root ice mpi task + + + integer + Number of sea ice instances + + + char + equential,concurrent + Layout of sea ice instances + + + + + integer + number of ocean mpi tasks + + + integer + number of ocean mpi threads + + + integer + root ocn mpi task + + + integer + Number of ocean instances + + + char + sequential,concurrent + Layout of ocean instances + + + + + integer + number of coupler mpi tasks + + + integer + number of coupler mpi threads + + + integer + root cpl mpi task + + + + + integer + number of glc mpi tasks + + + integer + number of glc mpi threads + + + integer + root glc mpi task + + + integer + Number of glacier instances + + + char + sequential,concurrent + Layout of glacier instances + + + + + integer + number of river runoff tasks + + + integer + number of river runoff threads + + + integer + root rof mpi task + + + integer + Number of river runoff instances + + + char + Layout of river runoff instances + + + + + integer + number of wav mpi tasks + + + integer + number of wav mpi threads + + + integer + root wav mpi task + + + integer + Number of wave instances + + + char + sequential,concurrent + Layout of wave instances + + + + + integer + number of external processing tool mpi tasks + + + integer + number of external processing tool mpi threads + + + integer + root ocn mpi task + + + integer + Number of external processing tool instances + + + char + sequential,concurrent + Layout of external processing tool instances + + + + + integer + stride of mpi tasks for atm comp - currently should always be set to 1 + + + integer + 1 + stride of mpi tasks for lnd comp - currently should always be set to 1 + + + integer + stride of mpi tasks for ice comp - currently should always be set to 1 + + + integer + 1 + stride of mpi tasks for ocn comp - currently should always be set to 1 + + + integer + stride of mpi tasks for cpl comp - currently should always be set to 1 + + + integer + 1 + stride of mpi tasks for glc comp - currently should always be set to 1 + + + integer + stride of mpi tasks for rof comp - currently should always be set to 1 + + + integer + 1 + stride of mpi tasks for wav comp - currently should always be set to 1 + + + integer + 1 + stride of mpi tasks for esp comp - currently should always be set to 1 + + +
diff --git a/src/drivers/mct/bld/testdir/env_run.xml b/src/drivers/mct/bld/testdir/env_run.xml new file mode 100644 index 00000000000..d3044405cf8 --- /dev/null +++ b/src/drivers/mct/bld/testdir/env_run.xml @@ -0,0 +1,1278 @@ + + +
+ These variables MAY BE CHANGED ANYTIME during a run. + Additional machine speific variables that can be changed + during a run are contained in the env_mach_specific file + Note1: users SHOULD NOT modify BUILD_COMPETE in env_build.xml + this is done automatically by the scripts. +
+ + + char + Extra copies of the component log files will be saved here. + + + char + case description + + + char + + The directory where the executable will be run. + By default this is set to EXEROOT/../run. + RUNDIR allows you to keep the run directory separate from the build directory + + + + + + char + startup,hybrid,branch + + Determines the model run initialization type. + This setting is only important for the initial run of a production run when the + CONTINUE_RUN variable is set to FALSE. After the initial run, the CONTINUE_RUN + variable is set to TRUE, and the model restarts exactly using input + files in a case, date, and bit-for-bit continuous fashion. + Default: startup. + -- In a startup run (the default), all components are initialized + using baseline states. These baseline states are set independently by + each component and can include the use of restart files, initial + files, external observed data files, or internal initialization (i.e., + a cold start). In a startup run, the coupler sends the start date to + the components at initialization. In addition, the coupler does not + need an input data file. In a startup initialization, the ocean model + does not start until the second ocean coupling (normally the second + day). + -- In a branch run, all components are initialized using a consistent + set of restart files from a previous run (determined by the + RUN_REFCASE and RUN_REFDATE variables in env_run.xml). The case name + is generally changed for a branch run, although it does not have to + be. In a branch run, setting RUN_STARTDATE is ignored because the + model components obtain the start date from their restart datasets. + Therefore, the start date cannot be changed for a branch run. This is + the same mechanism that is used for performing a restart run (where + CONTINUE_RUN is set to TRUE in the env_run.xml) Branch runs are + typically used when sensitivity or parameter studies are required, or + when settings for history file output streams need to be modified + while still maintaining bit-for-bit reproducibility. Under this + scenario, the new case is able to produce an exact bit-for-bit restart + in the same manner as a continuation run IF no source code or + component namelist inputs are modified. All models use restart files + to perform this type of run. RUN_REFCASE and RUN_REFDATE are required + for branch runs. + To set up a branch run, locate the restart tar file or restart + directory for RUN_REFCASE and RUN_REFDATE from a previous run, then + place those files in the RUNDIR directory. + --- In a hybrid run the model is initialized as a startup, BUT uses + initialization datasets FROM A PREVIOUS case. This + is somewhat analogous to a branch run with relaxed restart + constraints. A hybrid run allows users to bring together combinations + of initial/restart files from a previous case (specified by + RUN_REFCASE) at a given model output date (specified by + RUN_REFDATE). Unlike a branch run, the starting date of a hybrid run + (specified by RUN_STARTDATE) can be modified relative to the reference + case. In a hybrid run, the model does not continue in a bit-for-bit + fashion with respect to the reference case. The resulting climate, + however, should be continuous provided that no model source code or + namelists are changed in the hybrid run. In a hybrid initialization, + the ocean model does not start until the second ocean coupling + (normally the second day), and the coupler does a cold start without + a restart file. + + + + char + + Reference directory containing RUN_REFCASE data - used for hybrid or branch runs + + + + char + + Reference case for hybrid or branch runs + + + + char + + Reference date for hybrid or branch runs (yyyy-mm-dd) + + + + char + + Reference time of day (seconds) for hybrid or branch runs (sssss) + + + + logical + TRUE,FALSE + + Allow same branch casename as reference casename. Only used for branch runs. + + + + logical + TRUE,FALSE + + Flag for automatically prestaging the refcase restart dataset. + If TRUE, then the refcase data is prestaged into the executable directory + + + + char + + Run start date (yyyy-mm-dd). Only used for startup or hybrid runs. + + + + integer + + Run start time-of-day + + + + char + none,never,nsteps,nstep,nseconds,nsecond,nminutes,nminute,nhours,nhour,ndays,nday,nmonths,nmonth,nyears,nyear,date,ifdays0,end + + Sets the run length along with STOP_N and STOP_DATE (must be nyear(s) for _GLC compsets for restarts to work properly). + + + + integer + + Provides a numerical count for $STOP_OPTION. + + + + integer + + Alternative date yyyymmdd date option, sets the run length with STOP_OPTION and STOP_N + negative value implies off + + + + char + none,never,nsteps,nstep,nseconds,nsecond,nminutes,nminute,nhours,nhour,ndays,nday,nmonths,nmonth,nyears,nyear,date,ifdays0,end + + sets frequency of model restart writes (same options as STOP_OPTION) (must be nyear(s) for _GLC compsets) + (must be nyear(s) for _GLC compsets) + + + + integer + + sets model restart writes with REST_OPTION and REST_DATE + + + + char + + Alternative date in yyyymmdd format + sets model restart write date with REST_OPTION and REST_N + + + + char + none,never,nsteps,nstep,nseconds,nsecond,nminutes,nminute,nhours,nhour,ndays,nday,nmonths,nmonth,nyears,nyear,date,ifdays0,end + + sets frequency of full model barrier (same options as STOP_OPTION) for synchronization with BARRIER_N and BARRIER_DATE + + + + char + + sets periodic model barriers with BARRIER_OPTION and BARRIER_DATE for synchronization + + + + char + + Alternative date in yyyymmdd format + sets periodic model barriers with BARRIER_OPTION and BARRIER_N for synchronization + + + + logical + TRUE,FALSE + + A setting of TRUE implies a continuation run + When you first begin a branch, hybrid or startup run, CONTINUE_RUN + must be set to FALSE. When you successfully run and get a restart + file, you will need to change CONTINUE_RUN to TRUE for the remainder + of your run. This variable determines if the run is a restart run. + Set to FALSE when initializing a startup, branch or hybrid case. + Set to TRUE when continuing a run. + + + + integer + If RESUBMIT is greater than 0, then case will automatically resubmit + Enables the model to automatically resubmit a new run. To get + multiple runs, set RESUBMIT greater than 0, then RESUBMIT will be + decremented and the case will be resubmitted. The case will stop automatically + resubmitting when the RESUBMIT value reaches 0. + Long runs can easily outstrip supercomputer queue time limits. For + this reason, a case is usually run as a series of jobs, each + restarting where the previous finished. + + + + logical + This flag controls whether the RESUBMIT flag causes + CONTINUE_RUN to toggle from FALSE to TRUE. The default is + TRUE. This flag might be used in conjunction with COMP_RUN_BARRIERS for + timing tests. + + + + logical + TRUE,FALSE + Logical to determine whether CESM run has been submitted with the submit script or not + + + + + logical + TRUE,FALSE + Logical to turn on short term archiving. + If TRUE, short term archiving will be turned on. + + + logical + TRUE,FALSE + Logical to archive all interim restart files, not just those at eor + If TRUE, perform short term archiving on all interim restart files, + not just those at the end of the run. By default, this value is FALSE. + The restart files are saved under the specific component directory + ($DOUT_S_ROOT/$CASE/$COMPONENT/rest rather than the top-level $DOUT_S_ROOT/$CASE/rest directory). + Interim restart files are created using the REST_N and REST_OPTION variables. + This is for expert users ONLY and requires expert knowledge. + We will not document this further in this guide. + + + logical + TRUE,FALSE + If TRUE, perform long-term archiving on the output data. + logical to turn on long term archiving (if DOUT_S is also TRUE) + + + char + + + + + + logical + TRUE,FALSE + logical to diagnose model timing at the end of the run + + + logical + TRUE,FALSE + logical to save timing files in rundir + + + char + + Where to auto archive timing data + + + integer + timer output depth + + + logical + TRUE,FALSE + Turns on component barriers for component timing. + This variable is for testing and debugging only and should never + be set for a production run. + + + + logical + TRUE,FALSE + Turn on the passing of water isotope fields through the coupler + + + logical + TRUE,FALSE + Turns on component varying thread control in the driver. + Used to set the driver namelist variable "drv_threading". + + + integer + 0,1,2,3,4,5,6 + Coupler decomposition option. + + + logical + TRUE,FALSE + turns on coupler bit-for-bit reproducibility with varying pe counts + + + integer + 0,1,2,3 + level of debug output, 0=minimum, 1=normal, 2=more, 3=too much + + + + + logical + TRUE,FALSE + Enables the papi hardware counters in gptl + The papi library must be included in the build step for + this to work. + + + + + logical + TRUE,FALSE + Operate on only a single point of the global grid - DO NOT EDIT (for experts only) + + + real + Latitude to find nearest points for points mode (only used if PTS_MODE is TRUE) + + + real + Longitude to find nearest points for points mode (only used if PTS_MODE is TRUE) + + + char + atm domain file + + + char + path of atm domain file + + + char + lnd domain file + + + char + path of lnd domain file + + + char + rof domain file + + + char + path of rof domain file + + + char + wav domain file + + + char + path of wav domain file + + + char + ice domain file + + + char + path of ice domain file + + + char + ocn domain file + + + char + path of ocn domain file + + + char + glc domain file + + + char + path of glc domain file + + + char + atm2ocn flux mapping file + + + char + X,Y + atm2ocn flux mapping file decomp type + + + char + atm2ocn state mapping file + + + char + X,Y + atm2ocn state mapping file decomp type + + + char + atm2ocn vector mapping file + + + char + X,Y + atm2ocn vector mapping file decomp type + + + char + atm2lnd flux mapping file + + + char + X,Y + atm2lnd flux mapping file decomp type + + + char + atm2lnd state mapping file + + + char + X,Y + atm2lnd state mapping file decomp type + + + char + atm2wav state mapping file + + + char + X,Y + atm2wav state mapping file decomp type + + + char + ocn2atm flux mapping file + + + char + X,Y + ocn2atm flux mapping file decomp type + + + char + ocn2atm state mapping file + + + char + X,Y + ocn2atm state mapping file decomp type + + + char + lnd2atm flux mapping file + + + char + X,Y + lnd2atm flux mapping file decomp type + + + char + lnd2atm state mapping file + + + char + X,Y + lnd2atm state mapping file decomp type + + + char + lnd2glc flux mapping file + + + char + X,Y + lnd2glc flux mapping file decomp type + + + char + lnd2glc state mapping file + + + char + X,Y + lnd2glc state mapping file decomp type + + + char + lnd2rof flux mapping file + + + char + X,Y + lnd2rof flux mapping file decomp type + + + char + rof2lnd flux mapping file + + + char + X,Y + rof2lnd flux mapping file decomp type + + + char + rof2ocn flux mapping file + + + char + X,Y + rof2ocn flux mapping file decomp type + + + char + rof2ocn runoff liquid mapping file + + + char + rof2ocn runoff ice mapping file + + + char + X,Y + rof2ocn runoff liq mapping file decomp type + + + char + X,Y + rof2ocn runoff ice mapping file decomp type + + + char + glc2lnd flux mapping file + + + char + X,Y + glc2lnd flux mapping file decomp type + + + char + glc2lnd state mapping file + + + char + X,Y + glc2lnd state mapping file decomp type + + + char + glc2ice runoff mapping file + + + char + X,Y + glc2ice runoff mapping file decomp type + + + char + glc2ocn runoff mapping file + + + char + X,Y + glc2ocn runoff mapping file decomp type + + + char + ocn2wav state mapping file + + + char + X,Y + ocn2wav state mapping file decomp type + + + char + ice2wav state mapping file + + + char + X,Y + ice2wav state mapping file decomp type + + + char + wav2ocn state mapping file + + + char + X,Y + wav2ocn state mapping file decomp type + + + char + none,npfix,cart3d,cart3d_diag,cart3d_uvw,cart3d_uvw_diag + vector mapping option + + + char + Error tolerance for differences in fractions in domain checking + + + real + Error tolerance for differences in atm/land areas in domain checking + + + real + Error tolerance for differences in atm/land masks in domain checking + + + real + Error tolerance for differences in atm/land lat/lon in domain checking + + + real + Error tolerance for differences in ocean/ice lon/lat in domain checking + + + real + Error tolerance for differences in ocean/ice lon/lat in domain checking + + + real + Error tolerance for differences in ocean/ice lon/lat in domain checking + + + + + char + + A regular expression to match machine node names to ACME machine. + + + + char + + Proxy (if any) setting for http_proxy to allow web access on this machine. + + + + logical + + Indicates to case.submit that this is a test case. + + + + char + + The root directory of all CIME and component input data for the selected machine. + This is usually a shared disk area. + Default values for the target machine are in the + $CIMEROOT/machines/config_machines.xml + + + + char + CLM-specific root directory for CLM type input forcing data + This directory will only be used for I (CLM/DATM) compsets and only + for datm forcing data that is NOT checked into the svn repository + (datasets other than the Qian or single-point forcing). + This is usually a shared disk area. + Default values for the target machine are in the + $CIMEROOT/machines/config_machines.xml + + + + + char + Root directory for short term archiving. This directory must be visible to compute nodes. + + + char + Root directory on long term archiving store system for long-term data archives. + + + + + char + mpi run command + + + + + logical + TRUE,FALSE + TRUE implies perform asynchronous i/o + + + integer + mpi task stride between io tasks + + + integer + pio root processor + + + integer + pio number of io tasks + + + integer + pio rearranger choice box=1, subset=2 + + + char + p2p,coll,default + pio rearranger communication type + + + char + 2denable,io2comp,comp2io,disable,default + pio rearranger communication flow control direction + + + integer + + pio rearranger communication max pending requests + + + logical + TRUE,FALSE + pio rearranger communiation options: TRUE implies enable handshake + + + logical + TRUE,FALSE + pio rearranger communiation options: TRUE implies enable isend + + + char + netcdf,pnetcdf,netcdf4p,netcdf4c,default + pio io type + + + integer + pio debug level + + + integer + pio blocksize for box decompositions + + + integer + pio buffer size limit for pnetcdf output + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks, -99 value means inherit whatever the driver uses + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + integer + pio stride + + + integer + pio rearranger choice box=1, subset=2 + + + integer + pio root processor + + + integer + pio number of io tasks + + + char + nothing,netcdf,pnetcdf,netcdf4p,netcdf4c + pio io type + + + + + char + CESM1_ORIG,CESM1_ORIG_TIGHT,CESM1_MOD,CESM1_MOD_TIGHT,RASM_OPTION1,RASM_OPTION2 + + Coupler sequencing option. This is used to set the driver namelist variable cpl_seq_option. + CESM1_ORIG is the cesm1.1 implementation. + CESM1_MOD includes a cesm1.3 mod that swaps ocean merging and atm/ocn flux + computation. + RASM_OPTION1 runs prep ocean before the ocean coupling reducing + most of the lags and field inconsistency but still allowing the ocean to run + concurrently with the ice and atmosphere. + RASM_OPTION2 is similar to RASM_OPTION1 + but sequences the ice model, prep ocean and ocean model in that order. The + ocean model loses some of the concurrency with the ice model. + CESM1_ORIG_TIGHT and CESM1_MOD_TIGHT are consistent with the old variables + ocean_tight_coupling = true in the driver. That namelist is gone and the + cpl_seq_option flags take it's place. + TIGHT coupling makes no sense with the OPTION5 and OPTION6 flags. + + + + logical + TRUE,FALSE + determine if per ice thickness category fields are passed from ice to ocean - DO NOT EDIT (set by POP build-namelist) + + + char + none,CO2A,CO2B,CO2C,CO2_DMSA + Flag to turn on new fields in coupling. + If the value is not none, the coupler is compiled so that optional + BGC related fields are exchanged between component models. + + + + char + hour,day,year,decade + Base period associated with NCPL coupling frequency. + This xml variable is only used to set the driver namelist variables, + atm_cpl_dt, lnd_cpl_dt, ocn_cpl_dt, ice_cpl_dt, glc_cpl_dt, rof_cpl_dt, wav_cpl_dt, and esp_dt. + + + integer + Number of atm coupling intervals per NCPL_BASE_PERIOD. + This is used to set the driver namelist atm_cpl_dt, equal to basedt/ATM_NCPL, + where basedt is equal to NCPL_BASE_PERIOD in seconds. + + + integer + Number of land coupling intervals per NCPL_BASE_PERIOD. + This is used to set the driver namelist atm_cpl_dt, equal to basedt/LND_NCPL, + where basedt is equal to NCPL_BASE_PERIOD in seconds. + + + integer + Number of ice coupling intervals per NCPL_BASE_PERIOD. + This is used to set the driver namelist ice_cpl_dt, equal to basedt/ICE_NCPL + where basedt is equal to NCPL_BASE_PERIOD in seconds. + + + integer + Number of ocn coupling intervals per NCPL_BASE_PERIOD. + Thisn is used to set the driver namelist ocn_cpl_dt, equal to basedt/OCN_NCPL + where basedt is equal to NCPL_BASE_PERIOD in seconds. + + + integer + Number of glc coupling intervals per NCPL_BASE_PERIOD. + + + integer + Number of rof coupling intervals per NCPL_BASE_PERIOD. + This is used to set the driver namelist rof_cpl_dt, equal to basedt/ROF_NCPL + where basedt is equal to NCPL_BASE_PERIOD in seconds. + + + integer + Number of wav coupling intervals per NCPL_BASE_PERIOD. + This is used to set the driver namelist wav_cpl_dt, equal to basedt/WAV_NCPL + where basedt is equal to NCPL_BASE_PERIOD in seconds. + + + + + logical + TRUE,FALSE + + Only used for compsets with DATM and POP (currently C, G and J): + If true, compute albedos to work with daily avg SW down + If false (default), albedos are computed with the assumption that downward + solar radiation from the atm component has a diurnal cycle and zenith-angle + dependence. This is normally the case when using an active atm component + If true, albedos are computed with the assumption that downward + solar radiation from the atm component is a daily average quantity and + does not have a zenith-angle dependence. This is often the case when + using a data atm component. Only used for compsets with DATM and POP (currently C, G and J). + NOTE: This should really depend on the datm forcing and not the compset per se. + So, for example, whether it is set in a J compset should depend on + what datm forcing is used. + + + + char + off,ocn + + Only used for compsets with DATM and POP (currently C, G and J): + If ocn, ocn provides EP balance factor for precipitation. + Provides EP balance factor for precip for POP. A factor computed by + POP is applied to precipitation so that precipitation balances + evaporation and ocn global salinity does not drift. This is intended + for use when coupling POP to a DATM. Only used for C, G and J compsets. + Default is off + + + + + + char + + Sets driver snapshot history file frequency (like REST_OPTION) + + + integer + + Sets driver snapshot history file frequency (like REST_N) + + + + integer + + yyyymmdd format, sets coupler snapshot history date (like REST_DATE) + + + char + + Sets driver average history file frequency (like REST_OPTION) + + + char + + Sets driver average history file frequency (like REST_N) + + + integer + + yyyymmdd format, sets driver average history date (like REST_DATE) + + + + + logical + TRUE,FALSE + logical that turns on diagnostic budgets for driver + + + + + real + + This set the namelist values of CO2 ppmv for CAM and CLM. This variables is + introduced to coordinate this value among multiple components. + + + + + integer + 0,1,3,5,10,36 + Glacier model number of elevation classes, 0 implies no glacier land unit in clm + Used by both CLM and CISM (even if CISM is not running, and only SGLC is used). + + + logical + TRUE,FALSE + Whether the glacier component feeds back to the rest of the system + This affects: + (1) Whether CLM updates its areas based on glacier areas sent from GLC + (2) Whether GLC sends fluxes (e.g., calving fluxes) to the coupler + Note that this is set to TRUE by default for TG compsets - even though there are + no feedbacks for TG compsets, this enables extra coupler diagnostics for these + compsets. + + + + + logical + TRUE,FALSE + Run the external tool pointed to by DATA_ASSIMILATION_SCRIPT after the model run completes + + + integer + + Number of model run - data assimilation steps to complete + + + char + + External script to be run after model completion + + + + + char + CORE2_NYF,CORE2_IAF,TN460,CLM_QIAN,CLM1PT,CLMCRUNCEP,CLMCRUNCEP_V5,CLMGSWP3,CPLHIST3HrWx,COPYALL_NPS_v1,COPYALL_NPS_CORE2_v1,WRF,WW3 + Mode for data atmosphere component. + The default is CORE2_NYF (CORE2 normal year forcing) is the + DATM mode used in C and G compsets. CLM_QIAN, CLMCRUNCEP, CLMGSWP3 and CLM1PT are + modes using observational data for forcing CLM in I compsets. + + + char + none,clim_1850,clim_2000,trans_1850-2000,rcp2.6,rcp4.5,rcp6.0,rcp8.5,pt1_pt1 + DATM prescribed aerosol forcing + + + char + none,observed + DATM surface topography forcing + + + char + none,20tr,rcp2.6,rcp4.5,rcp6.0,rcp8.5 + DATM CO2 time series + + + char + + case name for coupler history data mode (only used for CPLHIST3HrWx mode) + + + integer + + Simulation year corresponding to starting year (only used for CPLHIST3HrWx mode) + + + integer + + starting year to loop data over (only used for CPLHIST3HrWx mode) + + + integer + + ending year to loop data over (only used for CPLHIST3HrWx mode) + + + integer + + year align + + + integer + + starting year to loop data over + + + integer + + ending year to loop data over + + + + + char + Tuning parameters should be optimized for what CLM model version and what meteorlogical forcing combination? + + clm4_0_default,clm5_0_cam5.5,clm5_0_GSW3P,clm4_5_CRUNCEP + + + char + CLM namelist use_case. + Determines the use-case that will be sent to the CLM build-namelist utility. + This is normally set by the component set. This is an advanced flag and should only be + used by expert users. + + + char + CLM build-namelist options + + + char + constant,diagnostic,prognostic + + Determines how CLM will determine where CO2 is set. + If value is constant, it will be set to CCSM_CO2_PPMV, + if value is either diagnostic or prognostic, the atmosphere model + MUST send it to CLM. CLM_CO2_TYPE is normally set by the specific + compset, since it HAS to be coordinated with settings for the + atmospheric model. Do not modify this variable. If you want to modify for + your experiment, use your own user-defined component set + This is an advanced flag and should only be used by expert users. + + + char + CLM-specific namelist settings for -namelist option in the CLM + build-namelist. CLM_NAMELIST_OPTS is normally set as a compset variable + and in general should not be modified for supported compsets. + It is recommended that if you want to modify this value for your experiment, + you should use your own user-defined component sets via using create_newcase + with a compset_file argument. + This is an advanced flag and should only be used by expert users. + + + char + on,off + Turn on any settings for accellerating the model spinup. + + + + char + Dataset name for user-created datasets. This is used as the argument + in Buildconf/clm.buildnml to build-namelist -clm_usr_name. An example of + such a dataset would be 1x1pt_boulderCO_c090722. The default value is UNSET. + This is an advanced flag and should only be used by expert users. + + + char + on,off + Flag to the CLM build-namelist command to force CLM to do a + cold start (finidat will be set to blanks). + A value of on forces the model to spin up from a cold-start + (arbitrary initial conditions). Setting this value in the xml file will take + precedence over any settings for finidat in the $CASEROOT/user_clm_clm file. + + + + + char + + RTM build-namelist options + + + char + + RTM-specific namelist settings in the RTM build-namelist. + RTM_NAMELIST_OPTS is normally set as a compset variable + and in general should not be modified for supported compsets. + It is recommended that if you want to modify this value for your experiment, + you should use your own user-defined component sets via using create_newcase + with a compset_file argument. + + +
diff --git a/src/drivers/mct/bld/testdir/runtest b/src/drivers/mct/bld/testdir/runtest new file mode 100755 index 00000000000..a3e88ecfd60 --- /dev/null +++ b/src/drivers/mct/bld/testdir/runtest @@ -0,0 +1 @@ +../build-namelist -caseroot . -cimeroot ../../.. -v -infile user_nl_cpl diff --git a/src/drivers/mct/bld/testdir/user_nl_cpl b/src/drivers/mct/bld/testdir/user_nl_cpl new file mode 100644 index 00000000000..306ee2c9a3c --- /dev/null +++ b/src/drivers/mct/bld/testdir/user_nl_cpl @@ -0,0 +1,3 @@ +&a + drydep_method = 'xactive_lnd' +/ diff --git a/src/externals/pio2/src/clib/ncparser.pl b/src/externals/pio2/src/clib/ncparser.pl new file mode 100644 index 00000000000..960e3db688a --- /dev/null +++ b/src/externals/pio2/src/clib/ncparser.pl @@ -0,0 +1,362 @@ +#!/usr/bin/perl +use strict; + +my $netcdf_incdir = $ARGV[0]; +my $pnetcdf_incdir = $ARGV[1]; + +my $netcdf_inc = "$netcdf_incdir/netcdf.h"; +my $pnetcdf_inc = "$pnetcdf_incdir/pnetcdf.h"; + +my $functions; + +open(PF,$pnetcdf_inc) or die "Could not open $pnetcdf_inc"; +my @file = ; +my $func=""; +foreach my $line (@file){ + chomp($line); + next if($line =~ /^\s*\/\*/); + next if($line =~ /^\s*[#\*]/); + $line =~ s/\s+/ /g; + if($line =~ / ncmpi_(.*)(\(.*)$/) { + $func = $1; + + $functions->{$func}{pnetcdf} = $2; + }elsif($func ne ""){ + $functions->{$func}{pnetcdf} .= $line; + } + $func="" if($line =~ /\;\s*$/); +} +close(PF); + +open(NF,$netcdf_inc) or die "Could not open $netcdf_inc"; +my @file = ; + +my $func=""; +foreach my $line (@file){ + chomp($line); + next if($line =~ /^\s*\/\*/); + next if($line =~ /^\s*[#\*]/); + $line =~ s/\s+/ /g; + if($line =~ /^\s*nc_([^_].*)(\(.*)$/) { + $func = $1; + $functions->{$func}{netcdf} = $2; + }elsif($func ne ""){ + $functions->{$func}{netcdf} .= $line; + } + $func="" if($line =~ /\;\s*$/); +} +close(NF); + +my $func=""; + +open(F,">pio_nc.c"); +print F +"/** +* \@file +* \@author Jim Edwards (jedwards\@ucar.edu) +* \@date Feburary 2014 +* \@brief PIO interfaces to [NetCDF](http://www.unidata.ucar.edu/software/netcdf/docs/modules.html) support functions +* \@details +* This file provides an interface to the [NetCDF](http://www.unidata.ucar.edu/software/netcdf/docs/modules.html) support functions. +* Each subroutine calls the underlying netcdf or pnetcdf or netcdf4 functions from +* the appropriate subset of mpi tasks (io_comm). Each routine must be called +* collectively from union_comm. +* +*/ +#include +#include \n\n"; + +open(T,"pio_c_template.c") or die "Could not open file pio_c_template.c"; +my @template = ; +close(T); + +my $typemap = {text=>"MPI_CHAR", short=>"MPI_SHORT", uchar=>"MPI_UNSIGNED_CHAR", + schar =>"MPI_CHAR", float=>"MPI_FLOAT", ushort=>"MPI_UNSIGNED_SHORT", + ulonglong=>"MPI_UNSIGNED_LONG_LONG",longlong=>"MPI_LONG_LONG",ubyte=>"MPI_BYTE", + double=>"MPI_DOUBLE",uint=>"MPI_UNSIGNED",int=>"MPI_INT",long=>"MPI_LONG"}; + +my $urls = {files=>"http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html", + dims=>"http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html", + vars=>"http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html", + atts=>"http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html", + groups=>"http://www.unidata.ucar.edu/software/netcdf/docs/group__groups.html", + utypes=>"http://www.unidata.ucar.edu/software/netcdf/docs/group__user__types.html", + other=>"http://www.unidata.ucar.edu/software/netcdf/docs/modules.html"}; +my $currurl = $urls->{other}; + + +foreach my $func (keys %{$functions}){ + next if($func=~/get_v/ or $func=~/put_v/); + next if($func=~/strerror/); + next if($func=~/delete/); + next if($func=~/sync/); + next if($func=~/open/); + next if($func=~/close/); + next if($func=~/create/); + next if($func=~/default_format/); + next if($func=~/copy_att/); + next if($func=~/abort/); + next if($func=~/def_var_fill/); + next if($func=~/string/); + next if($func=~/t_att$/); # skip void versions of get and put att + next if($functions->{$func}{pnetcdf} =~ /\(void\)/); + + my @tmptmp = @template; + + if($functions->{$func}{pnetcdf} =~ /ngattsp/){ + $functions->{$func}{netcdf} =~ s/nattsp/ngattsp/g; + } + + if($functions->{$func}{pnetcdf} =~ /fill_value/){ + $functions->{$func}{netcdf} =~ s/fill_valuep/fill_value/g; + } + + if(defined ($functions->{$func}{pnetcdf}) && defined($functions->{$func}{netcdf})){ +# && defined($functions->{$func}{pio})){ + + foreach my $line (@tmptmp){ + if($line =~ /msg = 0/){ + my $msg = "PIO_MSG_".$func; + $msg =~ tr/a-z/A-Z/; + $line =~ s/msg = 0/msg = $msg/; +# print " $msg,\n"; + } + if($line =~/function/){ + if($line =~ s/PIO_function/PIOc_$func/){ + $line =~ s/\(\)/ $functions->{$func}{pnetcdf} / ; +# $line =~ s/int ncid/file_desc_t *file/; + $line =~ s/MPI_Offset/PIO_Offset/g; + $line =~ s/\;//; + + if($func=~/.*var/){ + $currurl = $urls->{vars}; + } elsif ($func=~/.*att/) { + $currurl = $urls->{atts}; + } elsif ($func=~/.*dim/){ + $currurl = $urls->{dims}; + } elsif ($func=~/.*grp/){ + $currurl = $urls->{groups}; + } elsif ($func=~/.*def/ || $func=~/.*fill/ || $func=~/.*inq/) { + $currurl = $urls->{files}; + } else { + $currurl = $urls->{other}; } + + print F +"/** + * \@ingroup PIOc_$func + * The PIO-C interface for the NetCDF function nc_$func. + * + * This routine is called collectively by all tasks in the communicator + * ios.union_comm. For more information on the underlying NetCDF commmand + * please read about this function in the NetCDF documentation at: + * ".$currurl." + * + * \@param ncid the ncid of the open file, obtained from + * PIOc_openfile() or PIOc_createfile().\n"; + if($functions->{$func}{pnetcdf} =~ /varid/){ + print F " * \@param varid the variable ID.\n"; + } + + if($functions->{$func}{pnetcdf} =~ /int attnum/){ + print F " * \@param attnum the attribute ID.\n"; + } + + if($functions->{$func}{pnetcdf} =~ /const char *name/){ + print F " * \@param name the attribute name.\n"; + } + + if($functions->{$func}{pnetcdf} =~ /\*xtypep/){ + print F " * \@param xtypep a pointer that will get the type of the attribute.\n"; + } + if($functions->{$func}{pnetcdf} =~ /\*idp/){ + print F " * \@param idp a pointer that will get the id of the variable or attribute.\n"; + } + if($functions->{$func}{pnetcdf} =~ /\*lenp/){ + print F " * \@param lenp a pointer that will get the number of values \n"; + } + if($functions->{$func}{pnetcdf} =~ /\*varidp/){ + print F " * \@param varidp a pointer that will get the variable id \n"; + } + if($functions->{$func}{pnetcdf} =~ /\*formatp/){ + print F " * \@param formatp a pointer that will get the file format \n"; + } + if($functions->{$func}{pnetcdf} =~ /\*nattsp/){ + print F " * \@param nattsp a pointer that will get the number of attributes \n"; + } + +print F +" * \@return PIO_NOERR for success, error code otherwise. See PIOc_Set_File_Error_Handling + */\n"; + + + }else{ + my $args; + if($line =~ s/ncmpi_function/ncmpi_$func/){ + $args = $functions->{$func}{pnetcdf} ; + } + if($line =~ s/nc_function/nc_$func/){ + $args = $functions->{$func}{netcdf} ; + } + $args =~ s/int ncid/file->fh/; +# $args =~ s/int varid/vdesc->varid/; + $args =~ s/const //g; + $args =~ s/unsigned //g; + $args =~ s/signed //g; + $args =~ s/char //g; + $args =~ s/nc_type //g; + $args =~ s/MPI_Offset //g; + $args =~ s/int //g; + $args =~ s/short //g; + $args =~ s/long //g; + $args =~ s/float //g; + $args =~ s/double //g; + $args =~ s/void//g; + $args =~ s/MPI_Info //g; + $args =~ s/,\s+\*/, /g; + if($args =~ s/size_t \*/\(size_t \*\)/g){ + }else{ + $args =~ s/size_t /\(size_t\)/g; + } + + $line =~ s/\(\)/$args/; + } + } + if($line =~ /check_netcdf/){ + print F " if(ierr != PIO_NOERR){\n"; + if($func =~ /get_att/){ + print F " errstr = (char *) malloc((strlen(name)+strlen(__FILE__) + 40)* sizeof(char));\n"; + print F " sprintf(errstr,\"name %s in file %s\",name,__FILE__);\n"; + }else{ + print F " errstr = (char *) malloc((strlen(__FILE__) + 20)* sizeof(char));\n"; + print F " sprintf(errstr,\"in file %s\",__FILE__);\n"; + } + print F " }\n"; + } + + + print F $line; + if($func =~ /sync/ && $line =~ /case PIO_IOTYPE_PNETCDF/){ + printf F " flush_output_buffer(file);\n"; + } + if($func =~ /def_var/ && $line =~ /NETCDF4C/){ + printf F " if(ios->io_rank==0){\n"; + printf F " ierr = nc_def_var(file->fh, name, xtype, ndims, dimidsp, varidp);\n"; + printf F " if(ierr == PIO_NOERR){\n"; + printf F " ierr = nc_def_var_deflate(file->fh, *varidp, 0,1,1);\n"; + printf F " }\n"; + printf F " }\n"; + printf F " break;\n"; + } + if($line =~ /msg =/){ + if($func =~ /inq_varndims/){ + print F " if(file->varlist[varid].ndims > 0){\n"; + print F " (*ndimsp) = file->varlist[varid].ndims;\n"; + print F " return PIO_NOERR;\n }\n"; +# }elsif($func =~ /inq_dimlen/){ +# print F " printf(\"dimid %d\\n\",dimid);\n"; + + } + } + + if($line =~ /check_netcdf/){ + if($func =~ /inq_varid/){ + print F " mpierr = MPI_Bcast(varidp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_unlimdim/){ + print F " mpierr = MPI_Bcast(unlimdimidp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_ndims/){ + print F " mpierr = MPI_Bcast(ndimsp , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /var_fill/){ + print F " mpierr = MPI_Bcast(fill_value, 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /def_var/){ + print F " mpierr = MPI_Bcast(varidp , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /def_dim/){ + print F " mpierr = MPI_Bcast(idp , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_format/){ + print F " mpierr = MPI_Bcast(formatp , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_natts/){ + print F " mpierr = MPI_Bcast(ngattsp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_varnatts/){ + print F " mpierr = MPI_Bcast(nattsp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_nvars/){ + print F " mpierr = MPI_Bcast(nvarsp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_varndims/){ + print F " mpierr = MPI_Bcast(ndimsp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " file->varlist[varid].ndims = (*ndimsp);\n"; + }elsif($func =~ /inq_dimlen/ || $func =~ /inq_attlen/){ + print F " mpierr = MPI_Bcast(lenp , 1, MPI_OFFSET, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_varid/){ + print F " mpierr = MPI_Bcast(varidp , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_vartype/ || $func =~ /inq_atttype/){ + print F " mpierr = MPI_Bcast(xtypep , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_attid/ || $func =~ /inq_dimid/){ + print F " mpierr = MPI_Bcast(idp , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_att$/){ + print F " if(xtypep != NULL) mpierr = MPI_Bcast(xtypep , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " if(lenp != NULL) mpierr = MPI_Bcast(lenp , 1, MPI_OFFSET, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_var$/){ + print F " if(xtypep != NULL) mpierr = MPI_Bcast(xtypep , 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " if(ndimsp != NULL){ mpierr = MPI_Bcast(ndimsp , 1, MPI_OFFSET, ios->ioroot, ios->my_comm);\n"; + print F " file->varlist[varid].ndims = (*ndimsp);}\n"; + print F " if(nattsp != NULL) mpierr = MPI_Bcast(nattsp,1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " if(name != NULL){ \n"; + print F " int slen;\n"; + print F " if(ios->iomaster)\n"; + print F " slen = (int) strlen(name) + 1;\n"; + print F " mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " mpierr = MPI_Bcast(name, slen, MPI_CHAR, ios->ioroot, ios->my_comm);\n }\n"; + + print F " if(dimidsp != NULL) {int ndims;\n"; + print F " PIOc_inq_varndims(file->fh, varid, \&ndims);\n"; + print F " mpierr = MPI_Bcast(dimidsp , ndims, MPI_INT, ios->ioroot, ios->my_comm);\n "; + print F " }\n"; + + + + }elsif($func =~ /inq_dim$/){ + print F " if(name != NULL){ \n"; + print F " int slen;\n"; + print F " if(ios->iomaster)\n"; + print F " slen = (int) strlen(name) + 1;\n"; + print F " mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " mpierr = MPI_Bcast(name, slen, MPI_CHAR, ios->ioroot, ios->my_comm);\n }\n"; + print F " if(lenp != NULL) mpierr = MPI_Bcast(lenp , 1, MPI_OFFSET, ios->ioroot, ios->my_comm);\n"; + }elsif($func =~ /inq_dimname/ || $func =~ /inq_varname/ || $func =~ /inq_attname/){ + print F " if(name != NULL){\n"; + print F " int slen;\n"; + print F " if(ios->iomaster)\n"; + print F " slen = (int) strlen(name) + 1;\n"; + print F " mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm);\n"; + print F " mpierr = MPI_Bcast(name, slen, MPI_CHAR, ios->ioroot, ios->my_comm);\n }\n"; + }elsif($func =~ /inq_vardimid/){ + print F " if(ierr==PIO_NOERR){\n"; + print F " int ndims;\n"; + print F " PIOc_inq_varndims(file->fh, varid, \&ndims);\n"; + print F " mpierr = MPI_Bcast(dimidsp , ndims, MPI_INT, ios->ioroot, ios->my_comm);\n "; + print F " }\n"; + }elsif($func =~ /get_att_(\w+)/){ + my $atype = $1; + print F " if(ierr == PIO_NOERR){\n"; + print F " PIO_Offset attlen;\n"; + print F " PIOc_inq_attlen(file->fh, varid, name, \&attlen);\n"; + print F " mpierr = MPI_Bcast(ip , (int) attlen, $typemap->{$atype}, ios->ioroot, ios->my_comm);\n "; + print F " }\n"; + }elsif($func =~/inq$/){ + print F " if(ndimsp != NULL)\n"; + print F " mpierr = MPI_Bcast(ndimsp, 1, MPI_INT, ios->ioroot, ios->my_comm);\n "; + print F " if(nvarsp != NULL)\n"; + print F " mpierr = MPI_Bcast(nvarsp, 1, MPI_INT, ios->ioroot, ios->my_comm);\n "; + print F " if(ngattsp != NULL)\n"; + print F " mpierr = MPI_Bcast(ngattsp, 1, MPI_INT, ios->ioroot, ios->my_comm);\n "; + print F " if(unlimdimidp != NULL)\n"; + print F " mpierr = MPI_Bcast(unlimdimidp, 1, MPI_INT, ios->ioroot, ios->my_comm);\n "; + + } + + } + } + +# print "$func $functions->{$func}{pnetcdf} $functions->{$func}{netcdf}\n"; + print F "\n"; + } +} +close(F); diff --git a/src/externals/pio2/src/clib/ncputgetparser.pl b/src/externals/pio2/src/clib/ncputgetparser.pl new file mode 100644 index 00000000000..f4bb89c6b95 --- /dev/null +++ b/src/externals/pio2/src/clib/ncputgetparser.pl @@ -0,0 +1,352 @@ +#!/usr/bin/perl +use strict; + +my $netcdf_incdir = $ARGV[0]; +my $pnetcdf_incdir = $ARGV[1]; + +my $netcdf_inc = "$netcdf_incdir/netcdf.h"; +my $pnetcdf_inc = "$pnetcdf_incdir/pnetcdf.h"; + +my $functions; + +my $typemap = {text=>"MPI_CHAR", short=>"MPI_SHORT", uchar=>"MPI_UNSIGNED_CHAR", + schar =>"MPI_CHAR", float=>"MPI_FLOAT", ushort=>"MPI_UNSIGNED_SHORT", + ulonglong=>"MPI_UNSIGNED_LONG_LONG",longlong=>"MPI_LONG_LONG", + double=>"MPI_DOUBLE",uint=>"MPI_UNSIGNED",int=>"MPI_INT",long=>"MPI_LONG"}; + + +open(PF,$pnetcdf_inc) or die "Could not open $pnetcdf_inc"; +my @file = ; +my $func=""; +foreach my $line (@file){ + chomp($line); + next if($line =~ /^\s*\/\*/); + next if($line =~ /^\s*[#\*]/); + $line =~ s/\s+/ /g; + if($line =~ / ncmpi_(.*)(\(.*)$/) { + $func = $1; + + $functions->{$func}{pnetcdf} = $2; + }elsif($func ne ""){ + $functions->{$func}{pnetcdf} .= $line; + } + $func="" if($line =~ /\;\s*$/); +} +close(PF); + +open(NF,$netcdf_inc) or die "Could not open $netcdf_inc"; +my @file = ; + +my $func=""; +foreach my $line (@file){ + chomp($line); + next if($line =~ /^\s*\/\*/); + next if($line =~ /^\s*[#\*]/); + $line =~ s/\s+/ /g; + if($line =~ /^\s*nc_([^_].*)(\(.*)$/) { + $func = $1; + $functions->{$func}{netcdf} = $2; + }elsif($func ne ""){ + $functions->{$func}{netcdf} .= $line; + } + $func="" if($line =~ /\;\s*$/); +} +close(NF); + +my $func=""; + +open(F,">pio_put_nc.c"); +print F "#include +#include \n\n"; + + open(T,"pio_c_put_template.c") or die "Could not open file pio_c_put_template.c"; + my @template = ; + close(T); + +foreach my $func (keys %{$functions}){ + next unless($func=~/put_v/); + + my @tmptmp = @template; + + if($functions->{$func}{pnetcdf} =~ /ngattsp/){ + $functions->{$func}{netcdf} =~ s/nattsp/ngattsp/g; + } + + if(defined ($functions->{$func}{pnetcdf}) && defined($functions->{$func}{netcdf})){ +# && defined($functions->{$func}{pio})){ + my $bfunc = "b".$func; + my $pnetfunc; + if(defined $functions->{$bfunc}{pnetcdf}){ + $pnetfunc = $functions->{$bfunc}{pnetcdf}; + }else{ + $pnetfunc = $functions->{$func}{pnetcdf}; + undef $bfunc; + } + + my $buf=0; + foreach my $line (@tmptmp){ + if($line =~ /msg = 0/){ + my $msg = "PIO_MSG_".$func; + $msg =~ tr/a-z/A-Z/; + $line =~ s/msg = 0/msg = $msg/; +# print " $msg,\n"; + } + if($line =~/function/){ + if($line =~ s/PIO_function/PIOc_$func/){ + $line =~ s/\(\)/ $pnetfunc / ; +# $line =~ s/int ncid/file_desc_t *file/; + $line =~ s/MPI_Offset/PIO_Offset/g; + $line =~ s/\;//; + +# PIO handles requests internally, remove it from the argument list + + $line =~ s/, int \*request//; + + + }else{ + my $args; + if(defined $bfunc){ + if($line =~ s/ncmpi_function/ncmpi_$bfunc/){ + $args = $pnetfunc ; +# $args =~ s/request/&request/; + } + }else{ + if($line =~ s/ncmpi_function/ncmpi_$func/){ + $args = $pnetfunc ; + } + } + if($line =~ s/nc_function/nc_$func/){ + $args = $functions->{$func}{netcdf} ; + if($pnetfunc =~ /void \*buf/ ){ + $args =~ s/\*op/ buf/g; + $args =~ s/\*ip/ buf/g; + } + if($pnetfunc =~ /\*ip/ ){ + $args =~ s/\*op/ ip/g; + } + } + $args =~ s/int ncid/file->fh/; +# $args =~ s/int varid/vdesc->varid/; + $args =~ s/const //g; + $args =~ s/unsigned //g; + $args =~ s/signed //g; + $args =~ s/char //g; + $args =~ s/nc_type //g; + $args =~ s/MPI_Offset //g; + $args =~ s/MPI_Datatype //g; + $args =~ s/int //g; + $args =~ s/short //g; + $args =~ s/long //g; + $args =~ s/float //g; + $args =~ s/double //g; + $args =~ s/void//g; + $args =~ s/MPI_Info //g; + $args =~ s/,\s+\*/, /g; + $args =~ s/\[\]//g; + + $args =~ s/size_t \*indexp/\(size_t \*\) index/g; + $args =~ s/size_t \*startp/\(size_t \*\) start/g; + $args =~ s/size_t \*countp/\(size_t \*\) count/g; + $args =~ s/ptrdiff_t \*stridep/\(ptrdiff_t \*\) stride/g; + $args =~ s/ptrdiff_t \*\s*imapp/\(ptrdiff_t \*\) imap/g; + + +# $args =~ s/ptrdiff_t \*/\(ptrdiff_t \*\)/g; +# if($args =~ s/size_t \*/\(size_t \*\)/g){ +# }else{ +# $args =~ s/size_t /\(size_t\)/g; +# } + + $line =~ s/\(\)/$args/; + } + } +# if($line =~ /chkerr =/ && $func =~ /def_var/){ +# print F " file->varlist[*varidp].record=-1;\n"; +# print F " file->varlist[*varidp].buffer=NULL;\n"; +# } + print F $line; + + } + + + print F "\n"; + } +} +close(F); + + +open(F,">pio_get_nc.c"); +print F "#include +#include \n\n"; + +open(T,"pio_c_get_template.c") or die "Could not open file pio_c_get_template.c"; +my @template = ; +close(T); + +foreach my $func (keys %{$functions}){ + next unless($func=~/get_var/); + + my $bufcount; + my $buftype; + if($func =~ /_([^_]+)\s*$/ || $func =~ /_([^_]+)_all/){ + my $nctype = $1; +# print "nctype $nctype\n"; + $buftype = $typemap->{$nctype}; + } + + if($func =~ /var1/){ + $bufcount = 1; + } +# print "$func $buftype\n"; + + my @tmptmp = @template; + + if($functions->{$func}{pnetcdf} =~ /ngattsp/){ + $functions->{$func}{netcdf} =~ s/nattsp/ngattsp/g; + } + + if(defined ($functions->{$func}{pnetcdf}) && defined($functions->{$func}{netcdf})){ +# && defined($functions->{$func}{pio})){ + my $buf=0; + foreach my $line (@tmptmp){ + if($line =~ /PIO_NOERR/){ + if( $functions->{$func}{pnetcdf} =~ /buf/){ + print F " ibufcnt = bufcount;\n"; + print F " ibuftype = buftype;\n"; + }else{ + print F " ibuftype = $buftype;\n"; + if(defined($bufcount)){ + print F " ibufcnt = $bufcount;\n"; + }elsif($func =~ /vara/){ + print F " ierr = PIOc_inq_varndims(file->fh, varid, &ndims);\n"; + print F " ibufcnt = 1;\n"; + print F " for(int i=0;ifh, varid, &ndims);\n"; + print F " ibufcnt = 1;\n"; + print F " for(int i=0;ifh, varid, &ndims);\n"; + print F " int dimid[ndims];\n"; + print F " PIO_Offset dimsize;\n"; + print F " ibufcnt = 1;\n"; + print F " PIOc_inq_vardimid(file->fh, varid, dimid);\n"; + print F " for(int i=0;ifh, dimid[i], &dimsize);\n"; + print F " ibufcnt *= dimsize;\n"; + print F " }\n"; + } + } + + + } + if($line =~ /msg = 0/){ + my $msg = "PIO_MSG_".$func; + $msg =~ tr/a-z/A-Z/; + $line =~ s/msg = 0/msg = $msg/; +# print " $msg,\n"; + } + my $preline; + my $postline; + if($line =~/function/){ + if($line =~ s/PIO_function/PIOc_$func/){ + $line =~ s/\(\)/ $functions->{$func}{pnetcdf} / ; +# $line =~ s/int ncid/file_desc_t *file/; + $line =~ s/MPI_Offset/PIO_Offset/g; + $line =~ s/\;//; + $line =~ s/\*ip/\*buf/; + }else{ + my $allfunc=0; + my $args; + my $tall = $func."_all"; + if(defined($functions->{$tall}{pnetcdf})){ + if($line =~ s/ncmpi_function_all/ncmpi_$tall/){ + $args = $functions->{$tall}{pnetcdf}; + $postline = "#endif\n"; + } + $allfunc=1; + }elsif($line =~ /ncmpi_function_all/){ + $line = " "; + } + + if($line =~ s/ncmpi_function\(/ncmpi_$func\(/){ + if($allfunc==1){ + $preline = "#ifdef PNET_READ_AND_BCAST\n"; + } + $preline .= " ncmpi_begin_indep_data(file->fh);\n if(ios->iomaster){\n"; + $args = $functions->{$func}{pnetcdf} ; + $postline = " };\n ncmpi_end_indep_data(file->fh);\n bcast=true;\n"; + if($allfunc==1){ + $postline.="#else\n"; + } + } + + if($line =~ s/nc_function/nc_$func/){ + $args = $functions->{$func}{netcdf} ; + } + $args =~ s/int ncid/file->fh/; + + if($functions->{$func}{pnetcdf} =~ /void \*buf/ ){ + $args =~ s/\*op/ buf/g; + $args =~ s/\*ip/ buf/g; + } + if($functions->{$func}{pnetcdf} =~ /\*ip/ ){ + $args =~ s/\*ip/ buf/g; + } + if($functions->{$func}{pnetcdf} =~ /\*op/ ){ + $args =~ s/\*op/ buf/g; + } +# $args =~ s/int varid/vdesc->varid/; + $args =~ s/const //g; + $args =~ s/unsigned //g; + $args =~ s/signed //g; + $args =~ s/char //g; + $args =~ s/nc_type //g; + $args =~ s/MPI_Offset //g; + $args =~ s/MPI_Datatype //g; + $args =~ s/int //g; + $args =~ s/short //g; + $args =~ s/long //g; + $args =~ s/float //g; + $args =~ s/double //g; + $args =~ s/void//g; + $args =~ s/MPI_Info //g; + $args =~ s/,\s+\*/, /g; + $args =~ s/\[\]//g; + + $args =~ s/size_t \*indexp/\(size_t \*\) index/g; + $args =~ s/size_t \*startp/\(size_t \*\) start/g; + $args =~ s/size_t \*countp/\(size_t \*\) count/g; + $args =~ s/ptrdiff_t \*stridep/\(ptrdiff_t \*\) stride/g; + $args =~ s/ptrdiff_t \*\s*imapp/\(ptrdiff_t \*\) imap/g; + + +# $args =~ s/ptrdiff_t \*/\(ptrdiff_t \*\)/g; +# if($args =~ s/size_t \*/\(size_t \*\)/g){ +# }else{ +# $args =~ s/size_t /\(size_t\)/g; +# } + + $line =~ s/\(\)/$args/; + } + } +# if($line =~ /chkerr =/ && $func =~ /def_var/){ +# print F " file->varlist[*varidp].record=-1;\n"; +# print F " file->varlist[*varidp].buffer=NULL;\n"; +# } + print F $preline if(defined $preline); + print F $line; + print F $postline if(defined $postline); + + + } + +# print "$func $functions->{$func}{pnetcdf} $functions->{$func}{netcdf}\n"; + print F "\n"; + } +} +close(F); diff --git a/src/externals/pio2/src/clib/pio_c_get_template.c b/src/externals/pio2/src/clib/pio_c_get_template.c new file mode 100644 index 00000000000..e846a021679 --- /dev/null +++ b/src/externals/pio2/src/clib/pio_c_get_template.c @@ -0,0 +1,62 @@ +int PIO_function() +{ + int ierr; + int msg; + int mpierr; + iosystem_desc_t *ios; + file_desc_t *file; + MPI_Datatype ibuftype; + int ndims; + int ibufcnt; + bool bcast = false; + + file = pio_get_file_from_id(ncid); + if(file == NULL) + return PIO_EBADID; + ios = file->iosystem; + msg = 0; + ierr = PIO_NOERR; + + if(ios->async_interface && ! ios->ioproc){ + if(ios->compmaster) + mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); + mpierr = MPI_Bcast(&(file->fh),1, MPI_INT, 0, ios->intercomm); + } + + + if(ios->ioproc){ + switch(file->iotype){ +#ifdef _NETCDF +#ifdef _NETCDF4 + case PIO_IOTYPE_NETCDF4P: + ierr = nc_function(); + break; + case PIO_IOTYPE_NETCDF4C: +#endif + case PIO_IOTYPE_NETCDF: + bcast = true; + if(ios->iomaster){ + ierr = nc_function(); + } + break; +#endif +#ifdef _PNETCDF + case PIO_IOTYPE_PNETCDF: + ierr = ncmpi_function(); + ierr = ncmpi_function_all(); + break; +#endif + default: + ierr = iotype_error(file->iotype,__FILE__,__LINE__); + } + } + + ierr = check_netcdf(file, ierr, __FILE__,__LINE__); + + if(ios->async_interface || bcast || + (ios->num_iotasks < ios->num_comptasks)){ + MPI_Bcast(buf, ibufcnt, ibuftype, ios->ioroot, ios->my_comm); + } + + return ierr; +} diff --git a/src/externals/pio2/src/clib/pio_c_put_template.c b/src/externals/pio2/src/clib/pio_c_put_template.c new file mode 100644 index 00000000000..6ffc2e93e71 --- /dev/null +++ b/src/externals/pio2/src/clib/pio_c_put_template.c @@ -0,0 +1,77 @@ +/// +/// PIO interface to nc_function +/// +/// This routine is called collectively by all tasks in the communicator ios.union_comm. +/// +/// Refer to the netcdf documentation. +/// +int PIO_function() +{ + int ierr; + int msg; + int mpierr; + iosystem_desc_t *ios; + file_desc_t *file; + var_desc_t *vdesc; + PIO_Offset usage; + int *request; + + ierr = PIO_NOERR; + + file = pio_get_file_from_id(ncid); + if(file == NULL) + return PIO_EBADID; + ios = file->iosystem; + msg = 0; + + if(ios->async_interface && ! ios->ioproc){ + if(ios->compmaster) + mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); + mpierr = MPI_Bcast(&(file->fh),1, MPI_INT, 0, ios->intercomm); + } + + + if(ios->ioproc){ + switch(file->iotype){ +#ifdef _NETCDF +#ifdef _NETCDF4 + case PIO_IOTYPE_NETCDF4P: + ierr = nc_var_par_access(file->fh, varid, NC_COLLECTIVE); + ierr = nc_function(); + break; + case PIO_IOTYPE_NETCDF4C: +#endif + case PIO_IOTYPE_NETCDF: + if(ios->io_rank==0){ + ierr = nc_function(); + } + break; +#endif +#ifdef _PNETCDF + case PIO_IOTYPE_PNETCDF: + vdesc = file->varlist + varid; + + if(vdesc->nreqs%PIO_REQUEST_ALLOC_CHUNK == 0 ){ + vdesc->request = realloc(vdesc->request, + sizeof(int)*(vdesc->nreqs+PIO_REQUEST_ALLOC_CHUNK)); + } + request = vdesc->request+vdesc->nreqs; + + if(ios->io_rank==0){ + ierr = ncmpi_function(); + }else{ + *request = PIO_REQ_NULL; + } + vdesc->nreqs++; + flush_output_buffer(file, false, 0); + break; +#endif + default: + ierr = iotype_error(file->iotype,__FILE__,__LINE__); + } + } + + ierr = check_netcdf(file, ierr, __FILE__,__LINE__); + + return ierr; +} diff --git a/src/externals/pio2/src/clib/pio_c_template.c b/src/externals/pio2/src/clib/pio_c_template.c new file mode 100644 index 00000000000..033cfb98663 --- /dev/null +++ b/src/externals/pio2/src/clib/pio_c_template.c @@ -0,0 +1,54 @@ +int PIO_function() +{ + int ierr; + int msg; + int mpierr; + iosystem_desc_t *ios; + file_desc_t *file; + char *errstr; + + errstr = NULL; + ierr = PIO_NOERR; + + file = pio_get_file_from_id(ncid); + if(file == NULL) + return PIO_EBADID; + ios = file->iosystem; + msg = 0; + + if(ios->async_interface && ! ios->ioproc){ + if(ios->compmaster) + mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); + mpierr = MPI_Bcast(&(file->fh),1, MPI_INT, 0, ios->intercomm); + } + + + if(ios->ioproc){ + switch(file->iotype){ +#ifdef _NETCDF +#ifdef _NETCDF4 + case PIO_IOTYPE_NETCDF4P: + ierr = nc_function(); + break; + case PIO_IOTYPE_NETCDF4C: +#endif + case PIO_IOTYPE_NETCDF: + if(ios->io_rank==0){ + ierr = nc_function(); + } + break; +#endif +#ifdef _PNETCDF + case PIO_IOTYPE_PNETCDF: + ierr = ncmpi_function(); + break; +#endif + default: + ierr = iotype_error(file->iotype,__FILE__,__LINE__); + } + } + + ierr = check_netcdf(file, ierr, errstr,__LINE__); + if(errstr != NULL) free(errstr); + return ierr; +} diff --git a/src/externals/pio2/tests/general/pio_decomp_fillval2.F90 b/src/externals/pio2/tests/general/pio_decomp_fillval2.F90 new file mode 100644 index 00000000000..e4701ed690d --- /dev/null +++ b/src/externals/pio2/tests/general/pio_decomp_fillval2.F90 @@ -0,0 +1,227 @@ +! nc write 1d array with fillvalues (the holes are explicitly specified) + +SUBROUTINE nc_read_1d_implicit_fval_PIO_double_real_kind_fc_double___ +USE pio_tutil + ! pio_decomp_fillval.F90.in:274 + implicit none ! pio_decomp_fillval.F90.in:275 + integer, parameter :: VEC_LOCAL_SZ = 7 ! pio_decomp_fillval.F90.in:276 + type(var_desc_t) :: pio_var ! pio_decomp_fillval.F90.in:277 + type(file_desc_t) :: pio_file ! pio_decomp_fillval.F90.in:278 + character(len=PIO_TF_MAX_STR_LEN) :: filename ! pio_decomp_fillval.F90.in:279 + type(io_desc_t) :: wiodesc, riodesc ! pio_decomp_fillval.F90.in:280 + integer, dimension(:), allocatable :: rcompdof ! pio_decomp_fillval.F90.in:281 + integer :: rcompdof_sz ! pio_decomp_fillval.F90.in:282 + integer, dimension(VEC_LOCAL_SZ) :: wcompdof, compdof_rel_disps ! pio_decomp_fillval.F90.in:283 + real(kind=fc_double), dimension(:), allocatable :: rbuf, exp_val ! pio_decomp_fillval.F90.in:284 + real(kind=fc_double), dimension(VEC_LOCAL_SZ) :: wbuf ! pio_decomp_fillval.F90.in:285 + integer, parameter :: BUF_FILLVAL = -2 ! pio_decomp_fillval.F90.in:286 + integer, dimension(1) :: dims ! pio_decomp_fillval.F90.in:287 + integer :: pio_dim ! pio_decomp_fillval.F90.in:288 + integer :: i, ierr, lsz ! pio_decomp_fillval.F90.in:289 + ! iotypes = valid io types ! pio_decomp_fillval.F90.in:290 + integer, dimension(:), allocatable :: iotypes ! pio_decomp_fillval.F90.in:291 + character(len=PIO_TF_MAX_STR_LEN), dimension(:), allocatable :: iotype_descs ! pio_decomp_fillval.F90.in:292 + integer :: num_iotypes ! pio_decomp_fillval.F90.in:293 + ! pio_decomp_fillval.F90.in:294 + ! compdof is only specified for valid data values, the data holes are ! pio_decomp_fillval.F90.in:295 + ! implicitly stated (by not specifying them rather than filling it with 0s) ! pio_decomp_fillval.F90.in:296 + rcompdof_sz = min(pio_tf_world_rank_+1, VEC_LOCAL_SZ) ! pio_decomp_fillval.F90.in:297 + allocate(rcompdof(rcompdof_sz)) ! pio_decomp_fillval.F90.in:298 + allocate(rbuf(rcompdof_sz)) ! pio_decomp_fillval.F90.in:299 + allocate(exp_val(rcompdof_sz)) ! pio_decomp_fillval.F90.in:300 + ! pio_decomp_fillval.F90.in:301 + do i=1,VEC_LOCAL_SZ ! pio_decomp_fillval.F90.in:302 + compdof_rel_disps(i) = i ! pio_decomp_fillval.F90.in:303 + end do ! pio_decomp_fillval.F90.in:304 + dims(1) = VEC_LOCAL_SZ * pio_tf_world_sz_ ! pio_decomp_fillval.F90.in:305 + ! We only read 1 value on rank0, 2 values on rank1, ... ! pio_decomp_fillval.F90.in:306 + do i=1,rcompdof_sz ! pio_decomp_fillval.F90.in:307 + rcompdof(i) = VEC_LOCAL_SZ * pio_tf_world_rank_ + compdof_rel_disps(i) ! pio_decomp_fillval.F90.in:308 + end do ! pio_decomp_fillval.F90.in:309 + ! Write everything - we only read some of these values ! pio_decomp_fillval.F90.in:310 + wcompdof = VEC_LOCAL_SZ * pio_tf_world_rank_ + compdof_rel_disps ! pio_decomp_fillval.F90.in:311 + wbuf = wcompdof ! pio_decomp_fillval.F90.in:312 + ! pio_decomp_fillval.F90.in:313 + rbuf = BUF_FILLVAL ! pio_decomp_fillval.F90.in:314 + do i=1,rcompdof_sz ! pio_decomp_fillval.F90.in:315 + exp_val(i) = wbuf(i) ! pio_decomp_fillval.F90.in:316 + end do ! pio_decomp_fillval.F90.in:317 + ! pio_decomp_fillval.F90.in:318 + call PIO_initdecomp(pio_tf_iosystem_, PIO_double, dims, wcompdof, wiodesc) ! pio_decomp_fillval.F90.in:319 + call PIO_initdecomp(pio_tf_iosystem_, PIO_double, dims, rcompdof, riodesc) ! pio_decomp_fillval.F90.in:320 + ! pio_decomp_fillval.F90.in:321 + num_iotypes = 0 ! pio_decomp_fillval.F90.in:322 + call PIO_TF_Get_nc_iotypes(iotypes, iotype_descs, num_iotypes) ! pio_decomp_fillval.F90.in:323 + filename = "test_pio_decomp_fillval_tests.testfile" ! pio_decomp_fillval.F90.in:324 + do i=1,1 !num_iotypes ! pio_decomp_fillval.F90.in:325 + + IF (pio_tf_world_rank_ == 0) THEN + IF (pio_tf_log_level_ >= 0) THEN + WRITE(*,"(A)",ADVANCE="NO") "PIO_TF: " + WRITE(*,*) "Testing : PIO_double : ", iotype_descs(i) + END IF + END IF ! pio_decomp_fillval.F90.in:326 + ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) ! pio_decomp_fillval.F90.in:327 + + IF (.NOT. (PIO_TF_Passert_((ierr) == PIO_NOERR))) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Function failed:",& + "Could not create file " // trim(filename),& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:328)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:328 + ! pio_decomp_fillval.F90.in:329 + ierr = PIO_def_dim(pio_file, 'PIO_TF_test_dim', dims(1), pio_dim) ! pio_decomp_fillval.F90.in:330 + + IF (.NOT. (PIO_TF_Passert_((ierr) == PIO_NOERR))) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Function failed:",& + "Failed to define a dim : " // trim(filename),& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:331)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:331 + ! pio_decomp_fillval.F90.in:332 + ierr = PIO_def_var(pio_file, 'PIO_TF_test_var', PIO_double, (/pio_dim/), pio_var) ! pio_decomp_fillval.F90.in:333 + + IF (.NOT. (PIO_TF_Passert_((ierr) == PIO_NOERR))) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Function failed:",& + "Failed to define a var : " // trim(filename),& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:334)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:334 + ! pio_decomp_fillval.F90.in:335 + ierr = PIO_enddef(pio_file) ! pio_decomp_fillval.F90.in:336 + + IF (.NOT. (PIO_TF_Passert_((ierr) == PIO_NOERR))) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Function failed:",& + "Failed to end redef mode : " // trim(filename),& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:337)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:337 + ! pio_decomp_fillval.F90.in:338 + call PIO_write_darray(pio_file, pio_var, wiodesc, wbuf, ierr) ! pio_decomp_fillval.F90.in:339 + + IF (.NOT. (PIO_TF_Passert_((ierr) == PIO_NOERR))) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Function failed:",& + "Failed to write darray : " // trim(filename),& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:340)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:340 + ! pio_decomp_fillval.F90.in:341 + call PIO_syncfile(pio_file) ! pio_decomp_fillval.F90.in:342 + ! pio_decomp_fillval.F90.in:343 + ! Read only part of the written data ! pio_decomp_fillval.F90.in:344 + call PIO_read_darray(pio_file, pio_var, riodesc, rbuf, ierr) ! pio_decomp_fillval.F90.in:345 + + IF (.NOT. (PIO_TF_Passert_((ierr) == PIO_NOERR))) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Function failed:",& + "Failed to read darray : " // trim(filename),& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:346)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:346 + ! pio_decomp_fillval.F90.in:347 + + IF (.NOT. PIO_TF_Check_val_(rbuf, exp_val)) THEN + pio_tf_retval_utest_ = -1 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: PIO Check failed:",& + "Got wrong val",& + ":", __FILE__, ":", __LINE__,& + "(pio_decomp_fillval.F90.in:348)" + END IF + RETURN + END IF ! pio_decomp_fillval.F90.in:348 + ! pio_decomp_fillval.F90.in:349 + call PIO_closefile(pio_file) ! pio_decomp_fillval.F90.in:350 + call PIO_deletefile(pio_tf_iosystem_, filename) ! pio_decomp_fillval.F90.in:351 + end do ! pio_decomp_fillval.F90.in:352 + if(allocated(iotypes)) then ! pio_decomp_fillval.F90.in:353 + deallocate(iotypes) ! pio_decomp_fillval.F90.in:354 + deallocate(iotype_descs) ! pio_decomp_fillval.F90.in:355 + end if ! pio_decomp_fillval.F90.in:356 + ! pio_decomp_fillval.F90.in:357 + call PIO_freedecomp(pio_tf_iosystem_, riodesc) ! pio_decomp_fillval.F90.in:358 + call PIO_freedecomp(pio_tf_iosystem_, wiodesc) ! pio_decomp_fillval.F90.in:359 + deallocate(exp_val) ! pio_decomp_fillval.F90.in:360 + deallocate(rbuf) ! pio_decomp_fillval.F90.in:361 + deallocate(rcompdof) ! pio_decomp_fillval.F90.in:362 +END SUBROUTINE nc_read_1d_implicit_fval_PIO_double_real_kind_fc_double___ ! pio_decomp_fillval.F90.in:363 + ! pio_decomp_fillval.F90.in:363 + + + SUBROUTINE PIO_TF_Test_driver_ + USE pio_tutil + IMPLICIT NONE + pio_tf_retval_utest_ = 0 + IF (pio_tf_world_rank_ == 0) THEN + PRINT *, "PIO_TF: Starting nc_read_1d_implicit_fval_PIO_double_real_kind_fc_double___" + END IF + CALL nc_read_1d_implicit_fval_PIO_double_real_kind_fc_double___() + IF (pio_tf_retval_utest_ /= 0) THEN + pio_tf_nerrs_total_ = pio_tf_nerrs_total_ + 1 + END IF + IF (pio_tf_world_rank_ == 0) THEN + IF (pio_tf_retval_utest_ == 0) THEN + WRITE(*,PIO_TF_TEST_RES_FMT) "PIO_TF:Test 30:",& + "nc_read_1d_implicit_fval_PIO_double_real_kind_fc_double___","-----------", "PASSED" + ELSE + WRITE(*,PIO_TF_TEST_RES_FMT) "PIO_TF:Test 30:",& + "nc_read_1d_implicit_fval_PIO_double_real_kind_fc_double___","-----------", "FAILED" + END IF + END IF + END SUBROUTINE PIO_TF_Test_driver_ + + + PROGRAM PIO_TF_Test_main_ + USE pio_tutil + IMPLICIT NONE + INTEGER ierr + + pio_tf_nerrs_total_=0 + pio_tf_retval_utest_=0 + CALL MPI_Init(ierr) + CALL PIO_TF_Init_() + CALL PIO_TF_Test_driver_() + CALL PIO_TF_Finalize_() + IF (pio_tf_world_rank_ == 0) THEN + IF (pio_tf_nerrs_total_ == 0) THEN + IF (pio_tf_retval_utest_ == 0) THEN + WRITE(*,PIO_TF_TEST_RES_FMT) "PIO_TF: ",& + "All tests", "---------", "PASSED" + ELSE + WRITE(*,PIO_TF_TEST_RES_FMT) "PIO_TF: ",& + "Test driver", "---------", "FAILED" + END IF + ELSE + WRITE(*,PIO_TF_TEST_RES_FMT2) "PIO_TF:[",& + pio_tf_nerrs_total_,"] Tests",& + "----- FAILED" + END IF + END IF + CALL MPI_Finalize(ierr) + IF (pio_tf_nerrs_total_ /= 0) THEN + STOP 99 + END IF + END PROGRAM diff --git a/src/externals/pio2/tests/unit/README b/src/externals/pio2/tests/unit/README new file mode 100644 index 00000000000..cd4b24928c1 --- /dev/null +++ b/src/externals/pio2/tests/unit/README @@ -0,0 +1,5 @@ +1) Make sure pio is built in ../pio + +3) Determine what tests to run by setting namelist values in input.nl + +4) Use your machine's mpirun to launch "piotest" with the desired number of tasks diff --git a/src/externals/pio2/tests/unit/test_names.c b/src/externals/pio2/tests/unit/test_names.c new file mode 100644 index 00000000000..ea493ddc0f5 --- /dev/null +++ b/src/externals/pio2/tests/unit/test_names.c @@ -0,0 +1,416 @@ +/** + * @file + * Tests for names of vars, atts, and dims. + * + */ +#include +#ifdef TIMING +#include +#endif + +#define NUM_NETCDF_FLAVORS 4 +#define NDIM 3 +#define X_DIM_LEN 400 +#define Y_DIM_LEN 400 +#define NUM_TIMESTEPS 6 +#define VAR_NAME "foo" +#define ATT_NAME "bar" +#define START_DATA_VAL 42 +#define ERR_AWFUL 1111 +#define VAR_CACHE_SIZE (1024 * 1024) +#define VAR_CACHE_NELEMS 10 +#define VAR_CACHE_PREEMPTION 0.5 + +/** Handle MPI errors. This should only be used with MPI library + * function calls. */ +#define MPIERR(e) do { \ + MPI_Error_string(e, err_buffer, &resultlen); \ + fprintf(stderr, "MPI error, line %d, file %s: %s\n", __LINE__, __FILE__, err_buffer); \ + MPI_Finalize(); \ + return ERR_AWFUL; \ + } while (0) + +/** Handle non-MPI errors by finalizing the MPI library and exiting + * with an exit code. */ +#define ERR(e) do { \ + fprintf(stderr, "Error %d in %s, line %d\n", e, __FILE__, __LINE__); \ + MPI_Finalize(); \ + return e; \ + } while (0) + +/** Global err buffer for MPI. */ +char err_buffer[MPI_MAX_ERROR_STRING]; +int resultlen; + +/** The dimension names. */ +char dim_name[NDIM][NC_MAX_NAME + 1] = {"timestep", "x", "y"}; + +/** Length of the dimensions in the sample data. */ +int dim_len[NDIM] = {NC_UNLIMITED, X_DIM_LEN, Y_DIM_LEN}; + +/** Length of chunksizes to use in netCDF-4 files. */ +size_t chunksize[NDIM] = {2, X_DIM_LEN/2, Y_DIM_LEN/2}; + +/** Check the dimension names. + * + * @param my_rank rank of process + * @param ncid ncid of open netCDF file + * + * @returns 0 for success, error code otherwise. */ +int +check_dim_names(int my_rank, int ncid, int verbose) +{ + char dim_name[NC_MAX_NAME + 1]; + char zero_dim_name[NC_MAX_NAME + 1]; + int ret; + + for (int d = 0; d < NDIM; d++) + { + strcpy(dim_name, "11111111111111111111111111111111"); + if ((ret = PIOc_inq_dimname(ncid, d, dim_name))) + return ret; + if (verbose) + printf("my_rank %d dim %d name %s\n", my_rank, d, dim_name); + + /* Did other ranks get the same name? */ + if (!my_rank) + strcpy(zero_dim_name, dim_name); + /* if (verbose) */ + /* printf("rank %d dim_name %s zero_dim_name %s\n", my_rank, dim_name, zero_dim_name); */ + if ((ret = MPI_Bcast(&zero_dim_name, strlen(dim_name) + 1, MPI_CHAR, 0, + MPI_COMM_WORLD))) + MPIERR(ret); + if (strcmp(dim_name, zero_dim_name)) + return ERR_AWFUL; + } + return 0; +} + +/** Check the variable name. + * + * @param my_rank rank of process + * @param ncid ncid of open netCDF file + * + * @returns 0 for success, error code otherwise. */ +int +check_var_name(int my_rank, int ncid, int verbose) +{ + char var_name[NC_MAX_NAME + 1]; + char zero_var_name[NC_MAX_NAME + 1]; + int ret; + + strcpy(var_name, "11111111111111111111111111111111"); + if ((ret = PIOc_inq_varname(ncid, 0, var_name))) + return ret; + if (verbose) + printf("my_rank %d var name %s\n", my_rank, var_name); + + /* Did other ranks get the same name? */ + if (!my_rank) + strcpy(zero_var_name, var_name); + if ((ret = MPI_Bcast(&zero_var_name, strlen(var_name) + 1, MPI_CHAR, 0, + MPI_COMM_WORLD))) + MPIERR(ret); + if (strcmp(var_name, zero_var_name)) + return ERR_AWFUL; + return 0; +} + +/** Check the attribute name. + * + * @param my_rank rank of process + * @param ncid ncid of open netCDF file + * + * @returns 0 for success, error code otherwise. */ +int +check_att_name(int my_rank, int ncid, int verbose) +{ + char att_name[NC_MAX_NAME + 1]; + char zero_att_name[NC_MAX_NAME + 1]; + int ret; + + strcpy(att_name, "11111111111111111111111111111111"); + if ((ret = PIOc_inq_attname(ncid, NC_GLOBAL, 0, att_name))) + return ret; + if (verbose) + printf("my_rank %d att name %s\n", my_rank, att_name); + + /* Did everyone ranks get the same length name? */ +/* if (strlen(att_name) != strlen(ATT_NAME)) + return ERR_AWFUL;*/ + if (!my_rank) + strcpy(zero_att_name, att_name); + if ((ret = MPI_Bcast(&zero_att_name, strlen(att_name) + 1, MPI_CHAR, 0, + MPI_COMM_WORLD))) + MPIERR(ret); + if (strcmp(att_name, zero_att_name)) + return ERR_AWFUL; + return 0; +} + +/** Run Tests for NetCDF-4 Functions. + * + * @param argc argument count + * @param argv array of arguments + */ +int +main(int argc, char **argv) +{ + int verbose = 1; + + /** Zero-based rank of processor. */ + int my_rank; + + /** Number of processors involved in current execution. */ + int ntasks; + + /** Specifies the flavor of netCDF output format. */ + int iotype; + + /** Different output flavors. */ + int format[NUM_NETCDF_FLAVORS] = {PIO_IOTYPE_PNETCDF, + PIO_IOTYPE_NETCDF, + PIO_IOTYPE_NETCDF4C, + PIO_IOTYPE_NETCDF4P}; + + /** Names for the output files. */ + char filename[NUM_NETCDF_FLAVORS][NC_MAX_NAME + 1] = {"test_names_pnetcdf.nc", + "test_names_classic.nc", + "test_names_serial4.nc", + "test_names_parallel4.nc"}; + + /** Number of processors that will do IO. In this test we + * will do IO from all processors. */ + int niotasks; + + /** Stride in the mpi rank between io tasks. Always 1 in this + * test. */ + int ioproc_stride = 1; + + /** Number of the aggregator? Always 0 in this test. */ + int numAggregator = 0; + + /** Zero based rank of first processor to be used for I/O. */ + int ioproc_start = 0; + + /** The dimension IDs. */ + int dimids[NDIM]; + + /** Array index per processing unit. */ + PIO_Offset elements_per_pe; + + /** The ID for the parallel I/O system. */ + int iosysid; + + /** The ncid of the netCDF file. */ + int ncid = 0; + + /** The ID of the netCDF varable. */ + int varid; + + /** Storage of netCDF-4 files (contiguous vs. chunked). */ + int storage; + + /** Chunksizes set in the file. */ + size_t my_chunksize[NDIM]; + + /** The shuffle filter setting in the netCDF-4 test file. */ + int shuffle; + + /** Non-zero if deflate set for the variable in the netCDF-4 test file. */ + int deflate; + + /** The deflate level set for the variable in the netCDF-4 test file. */ + int deflate_level; + + /** Non-zero if fletcher32 filter is used for variable. */ + int fletcher32; + + /** Endianness of variable. */ + int endianness; + + /* Size of the file chunk cache. */ + size_t chunk_cache_size; + + /* Number of elements in file cache. */ + size_t nelems; + + /* File cache preemption. */ + float preemption; + + /* Size of the var chunk cache. */ + size_t var_cache_size; + + /* Number of elements in var cache. */ + size_t var_cache_nelems; + + /* Var cache preemption. */ + float var_cache_preemption; + + /** The I/O description ID. */ + int ioid; + + /** A buffer for sample data. */ + float *buffer; + + /** A buffer for reading data back from the file. */ + int *read_buffer; + + /** The decomposition mapping. */ + PIO_Offset *compdof; + + /** Return code. */ + int ret; + + /** Index for loops. */ + int fmt, d, d1, i; + +#ifdef TIMING + /* Initialize the GPTL timing library. */ + if ((ret = GPTLinitialize ())) + return ret; +#endif + + /* Initialize MPI. */ + if ((ret = MPI_Init(&argc, &argv))) + MPIERR(ret); + + /* Learn my rank and the total number of processors. */ + if ((ret = MPI_Comm_rank(MPI_COMM_WORLD, &my_rank))) + MPIERR(ret); + if ((ret = MPI_Comm_size(MPI_COMM_WORLD, &ntasks))) + MPIERR(ret); + + /* Check that a valid number of processors was specified. */ + if (!(ntasks == 1 || ntasks == 2 || ntasks == 4 || + ntasks == 8 || ntasks == 16)) + fprintf(stderr, "Number of processors must be 1, 2, 4, 8, or 16!\n"); + if (verbose) + printf("%d: ParallelIO Library example1 running on %d processors.\n", + my_rank, ntasks); + + /* keep things simple - 1 iotask per MPI process */ + niotasks = ntasks; + + /* Initialize the PIO IO system. This specifies how + * many and which processors are involved in I/O. */ + if ((ret = PIOc_Init_Intracomm(MPI_COMM_WORLD, niotasks, ioproc_stride, + ioproc_start, PIO_REARR_SUBSET, &iosysid))) + ERR(ret); + + /* Describe the decomposition. This is a 1-based array, so add 1! */ + elements_per_pe = X_DIM_LEN * Y_DIM_LEN / ntasks; + if (!(compdof = malloc(elements_per_pe * sizeof(PIO_Offset)))) + return PIO_ENOMEM; + for (i = 0; i < elements_per_pe; i++) { + compdof[i] = my_rank * elements_per_pe + i + 1; + } + + /* Create the PIO decomposition for this test. */ + if (verbose) + printf("rank: %d Creating decomposition...\n", my_rank); + if ((ret = PIOc_InitDecomp(iosysid, PIO_FLOAT, 2, &dim_len[1], (PIO_Offset)elements_per_pe, + compdof, &ioid, NULL, NULL, NULL))) + ERR(ret); + free(compdof); + + /* How many flavors will we be running for? */ + int num_flavors = 0; + int fmtidx = 0; +#ifdef _PNETCDF + num_flavors++; + format[fmtidx++] = PIO_IOTYPE_PNETCDF; +#endif +#ifdef _NETCDF + num_flavors++; + format[fmtidx++] = PIO_IOTYPE_NETCDF; +#endif +#ifdef _NETCDF4 + num_flavors += 2; + format[fmtidx++] = PIO_IOTYPE_NETCDF4C; + format[fmtidx] = PIO_IOTYPE_NETCDF4P; +#endif + + /* Use PIO to create the example file in each of the four + * available ways. */ + for (fmt = 0; fmt < num_flavors; fmt++) + { + /* Create the netCDF output file. */ + if (verbose) + printf("rank: %d Creating sample file %s with format %d...\n", + my_rank, filename[fmt], format[fmt]); + if ((ret = PIOc_createfile(iosysid, &ncid, &(format[fmt]), filename[fmt], + PIO_CLOBBER))) + ERR(ret); + + /* Define netCDF dimensions and variable. */ + if (verbose) + printf("rank: %d Defining netCDF metadata...\n", my_rank); + for (d = 0; d < NDIM; d++) { + if (verbose) + printf("rank: %d Defining netCDF dimension %s, length %d\n", my_rank, + dim_name[d], dim_len[d]); + if ((ret = PIOc_def_dim(ncid, dim_name[d], (PIO_Offset)dim_len[d], &dimids[d]))) + ERR(ret); + } + + /* Check the dimension names. */ + if ((ret = check_dim_names(my_rank, ncid, verbose))) + ERR(ret); + + /* Define a global attribute. */ + int att_val = 42; + if ((ret = PIOc_put_att_int(ncid, NC_GLOBAL, ATT_NAME, NC_INT, 1, &att_val))) + ERR(ret); + + /* Check the attribute name. */ + if ((ret = check_att_name(my_rank, ncid, verbose))) + ERR(ret); + + /* Define a variable. */ + if ((ret = PIOc_def_var(ncid, VAR_NAME, PIO_FLOAT, NDIM, dimids, &varid))) + ERR(ret); + + /* Check the variable name. */ + if ((ret = check_var_name(my_rank, ncid, verbose))) + ERR(ret); + + if ((ret = PIOc_enddef(ncid))) + ERR(ret); + + /* Close the netCDF file. */ + if (verbose) + printf("rank: %d Closing the sample data file...\n", my_rank); + if ((ret = PIOc_closefile(ncid))) + ERR(ret); + + /* Put a barrier here to make verbose output look better. */ + if ((ret = MPI_Barrier(MPI_COMM_WORLD))) + MPIERR(ret); + + } + + /* Free the PIO decomposition. */ + if (verbose) + printf("rank: %d Freeing PIO decomposition...\n", my_rank); + if ((ret = PIOc_freedecomp(iosysid, ioid))) + ERR(ret); + + /* Finalize the IO system. */ + if (verbose) + printf("rank: %d Freeing PIO resources...\n", my_rank); + if ((ret = PIOc_finalize(iosysid))) + ERR(ret); + + /* Finalize the MPI library. */ + MPI_Finalize(); + +#ifdef TIMING + /* Finalize the GPTL timing library. */ + if ((ret = GPTLfinalize ())) + return ret; +#endif + + + return 0; +} diff --git a/src/externals/pio2/tests/unit/test_nc4.c b/src/externals/pio2/tests/unit/test_nc4.c new file mode 100644 index 00000000000..b748f7a420f --- /dev/null +++ b/src/externals/pio2/tests/unit/test_nc4.c @@ -0,0 +1,506 @@ +/** + * @file + * Tests for NetCDF-4 Functions. + * + * There are some functions that apply only to netCDF-4 files. This + * test checks those functions. PIO will return an error if these + * functions are called on non-netCDF-4 files, and that is tested in + * this code as well. + * + */ +#include + +#ifdef TIMING +#include +#endif + +/** The number of possible output netCDF output flavors available to + * the ParallelIO library. */ +#define NUM_NETCDF_FLAVORS 4 + +/** The number of dimensions in the example data. In this test, we + * are using three-dimensional data. */ +#define NDIM 3 + +/** The length of our sample data along each dimension. */ +/**@{*/ +#define X_DIM_LEN 400 +#define Y_DIM_LEN 400 +/**@}*/ + +/** The number of timesteps of data to write. */ +#define NUM_TIMESTEPS 6 + +/** The name of the variable in the netCDF output file. */ +#define VAR_NAME "foo" + +/** The meaning of life, the universe, and everything. */ +#define START_DATA_VAL 42 + +/** Error code for when things go wrong. */ +#define ERR_AWFUL 1111 + +/** Values for some netcdf-4 settings. */ +/**@{*/ +#define VAR_CACHE_SIZE (1024 * 1024) +#define VAR_CACHE_NELEMS 10 +#define VAR_CACHE_PREEMPTION 0.5 +/**@}*/ + + +/** Handle MPI errors. This should only be used with MPI library + * function calls. */ +#define MPIERR(e) do { \ + MPI_Error_string(e, err_buffer, &resultlen); \ + fprintf(stderr, "MPI error, line %d, file %s: %s\n", __LINE__, __FILE__, err_buffer); \ + MPI_Finalize(); \ + return ERR_AWFUL; \ + } while (0) + +/** Handle non-MPI errors by finalizing the MPI library and exiting + * with an exit code. */ +#define ERR(e) do { \ + fprintf(stderr, "Error %d in %s, line %d\n", e, __FILE__, __LINE__); \ + MPI_Finalize(); \ + return e; \ + } while (0) + +/** Global err buffer for MPI. When there is an MPI error, this buffer + * is used to store the error message that is associated with the MPI + * error. */ +char err_buffer[MPI_MAX_ERROR_STRING]; + +/** This is the length of the most recent MPI error message, stored + * int the global error string. */ +int resultlen; + +/** The dimension names. */ +char dim_name[NDIM][NC_MAX_NAME + 1] = {"timestep", "x", "y"}; + +/** Length of the dimensions in the sample data. */ +int dim_len[NDIM] = {NC_UNLIMITED, X_DIM_LEN, Y_DIM_LEN}; + +/** Length of chunksizes to use in netCDF-4 files. */ +size_t chunksize[NDIM] = {2, X_DIM_LEN/2, Y_DIM_LEN/2}; + +/** Run Tests for NetCDF-4 Functions. + * + * @param argc argument count + * @param argv array of arguments + */ +int +main(int argc, char **argv) +{ + int verbose = 1; + + /** Zero-based rank of processor. */ + int my_rank; + + /** Number of processors involved in current execution. */ + int ntasks; + + /** Specifies the flavor of netCDF output format. */ + int iotype; + + /** Different output flavors. */ + int format[NUM_NETCDF_FLAVORS] = {PIO_IOTYPE_PNETCDF, + PIO_IOTYPE_NETCDF, + PIO_IOTYPE_NETCDF4C, + PIO_IOTYPE_NETCDF4P}; + + /** Names for the output files. */ + char filename[NUM_NETCDF_FLAVORS][NC_MAX_NAME + 1] = {"test_nc4_pnetcdf.nc", + "test_nc4_classic.nc", + "test_nc4_serial4.nc", + "test_nc4_parallel4.nc"}; + + /** Number of processors that will do IO. In this test we + * will do IO from all processors. */ + int niotasks; + + /** Stride in the mpi rank between io tasks. Always 1 in this + * test. */ + int ioproc_stride = 1; + + /** Number of the aggregator? Always 0 in this test. */ + int numAggregator = 0; + + /** Zero based rank of first processor to be used for I/O. */ + int ioproc_start = 0; + + /** The dimension IDs. */ + int dimids[NDIM]; + + /** Array index per processing unit. */ + PIO_Offset elements_per_pe; + + /** The ID for the parallel I/O system. */ + int iosysid; + + /** The ncid of the netCDF file. */ + int ncid = 0; + + /** The ID of the netCDF varable. */ + int varid; + + /** Storage of netCDF-4 files (contiguous vs. chunked). */ + int storage; + + /** Chunksizes set in the file. */ + size_t my_chunksize[NDIM]; + + /** The shuffle filter setting in the netCDF-4 test file. */ + int shuffle; + + /** Non-zero if deflate set for the variable in the netCDF-4 test file. */ + int deflate; + + /** The deflate level set for the variable in the netCDF-4 test file. */ + int deflate_level; + + /** Endianness of variable. */ + int endianness; + + /* Size of the var chunk cache. */ + PIO_Offset var_cache_size; + + /* Number of elements in var cache. */ + PIO_Offset var_cache_nelems; + + /* Var cache preemption. */ + float var_cache_preemption; + + /** The I/O description ID. */ + int ioid; + + /** A buffer for sample data. */ + float *buffer; + + /** A buffer for reading data back from the file. */ + int *read_buffer; + + /** The decomposition mapping. */ + PIO_Offset *compdof; + + /** Return code. */ + int ret; + + /** Index for loops. */ + int fmt, d, d1, i; + + /** For setting the chunk cache. */ + size_t chunk_cache_size = 1024*1024; + size_t chunk_cache_nelems = 1024; + float chunk_cache_preemption = 0.5; + + /* For reading the chunk cache. */ + size_t chunk_cache_size_in; + size_t chunk_cache_nelems_in; + float chunk_cache_preemption_in; + + char varname[15]; + +#ifdef TIMING + /* Initialize the GPTL timing library. */ + if ((ret = GPTLinitialize ())) + return ret; +#endif + + /* Initialize MPI. */ + if ((ret = MPI_Init(&argc, &argv))) + MPIERR(ret); + + /* Learn my rank and the total number of processors. */ + if ((ret = MPI_Comm_rank(MPI_COMM_WORLD, &my_rank))) + MPIERR(ret); + if ((ret = MPI_Comm_size(MPI_COMM_WORLD, &ntasks))) + MPIERR(ret); + + /* Check that a valid number of processors was specified. */ + if (!(ntasks == 1 || ntasks == 2 || ntasks == 4 || + ntasks == 8 || ntasks == 16)) + fprintf(stderr, "Number of processors must be 1, 2, 4, 8, or 16!\n"); + if (verbose) + printf("%d: ParallelIO Library test_nc4 running on %d processors.\n", + my_rank, ntasks); + + /* keep things simple - 1 iotask per MPI process */ + niotasks = ntasks; + + /* Initialize the PIO IO system. This specifies how + * many and which processors are involved in I/O. */ + if ((ret = PIOc_Init_Intracomm(MPI_COMM_WORLD, niotasks, ioproc_stride, + ioproc_start, PIO_REARR_SUBSET, &iosysid))) + ERR(ret); + + /* Describe the decomposition. This is a 1-based array, so add 1! */ + elements_per_pe = X_DIM_LEN * Y_DIM_LEN / ntasks; + if (!(compdof = malloc(elements_per_pe * sizeof(PIO_Offset)))) + return PIO_ENOMEM; + for (i = 0; i < elements_per_pe; i++) { + compdof[i] = my_rank * elements_per_pe + i + 1; + } + + /* Create the PIO decomposition for this test. */ + if (verbose) + printf("rank: %d Creating decomposition...\n", my_rank); + if ((ret = PIOc_InitDecomp(iosysid, PIO_FLOAT, 2, &dim_len[1], (PIO_Offset)elements_per_pe, + compdof, &ioid, NULL, NULL, NULL))) + ERR(ret); + free(compdof); + +#ifdef HAVE_MPE + /* Log with MPE that we are done with INIT. */ + if ((ret = MPE_Log_event(event_num[END][INIT], 0, "end init"))) + MPIERR(ret); +#endif /* HAVE_MPE */ + + /* How many flavors will we be running for? */ + int num_flavors = 0; + int fmtidx = 0; +#ifdef _PNETCDF + num_flavors++; + format[fmtidx++] = PIO_IOTYPE_PNETCDF; +#endif +#ifdef _NETCDF + num_flavors++; + format[fmtidx++] = PIO_IOTYPE_NETCDF; +#endif +#ifdef _NETCDF4 + num_flavors += 2; + format[fmtidx++] = PIO_IOTYPE_NETCDF4C; + format[fmtidx] = PIO_IOTYPE_NETCDF4P; +#endif + + /* Use PIO to create the example file in each of the four + * available ways. */ + for (fmt = 0; fmt < num_flavors; fmt++) + { +#ifdef HAVE_MPE + /* Log with MPE that we are starting CREATE. */ + if ((ret = MPE_Log_event(event_num[START][CREATE_PNETCDF+fmt], 0, "start create"))) + MPIERR(ret); +#endif /* HAVE_MPE */ + + if (verbose) + printf("rank: %d Setting chunk cache for file %s with format %d...\n", + my_rank, filename[fmt], format[fmt]); + + /* Try to set the chunk cache with invalid preemption to check error handling. */ + chunk_cache_preemption = 50.0; + ret = PIOc_set_chunk_cache(iosysid, format[fmt], chunk_cache_size, + chunk_cache_nelems, chunk_cache_preemption); + if (format[fmt] == PIO_IOTYPE_NETCDF4C || format[fmt] == PIO_IOTYPE_NETCDF4P) + { + if (ret != NC_EINVAL) + ERR(ERR_AWFUL); + } + else + { + if (ret != NC_ENOTNC4) + ERR(ERR_AWFUL); + } + + /* Try to set the chunk cache. */ + chunk_cache_preemption = 0.5; + ret = PIOc_set_chunk_cache(iosysid, format[fmt], chunk_cache_size, + chunk_cache_nelems, chunk_cache_preemption); + + /* Should only have worked for netCDF-4 iotypes. */ + if (format[fmt] == PIO_IOTYPE_NETCDF4C || format[fmt] == PIO_IOTYPE_NETCDF4P) + { + if (ret != PIO_NOERR) + ERR(ret); + } + else + { + if (ret != PIO_ENOTNC4) + ERR(ERR_AWFUL); + } + + /* Now check the chunk cache. */ + ret = PIOc_get_chunk_cache(iosysid, format[fmt], &chunk_cache_size_in, + &chunk_cache_nelems_in, &chunk_cache_preemption_in); + + /* Should only have worked for netCDF-4 iotypes. */ + if (format[fmt] == PIO_IOTYPE_NETCDF4C || format[fmt] == PIO_IOTYPE_NETCDF4P) + { + /* Check that there was no error. */ + if (ret != PIO_NOERR) + ERR(ret); + + /* Check that we got the correct values. */ + if (chunk_cache_size_in != chunk_cache_size || chunk_cache_nelems_in != chunk_cache_nelems || + chunk_cache_preemption_in != chunk_cache_preemption) + ERR(ERR_AWFUL); + } + else + { + if (ret != PIO_ENOTNC4) + ERR(ERR_AWFUL); + } + + /* Create the netCDF output file. */ + if (verbose) + printf("rank: %d Creating sample file %s with format %d...\n", + my_rank, filename[fmt], format[fmt]); + if ((ret = PIOc_createfile(iosysid, &ncid, &(format[fmt]), filename[fmt], + PIO_CLOBBER))) + ERR(ret); + + /* Set error handling. */ + PIOc_Set_File_Error_Handling(ncid, PIO_BCAST_ERROR); + + /* Define netCDF dimensions and variable. */ + if (verbose) + printf("rank: %d Defining netCDF metadata...\n", my_rank); + for (d = 0; d < NDIM; d++) { + if (verbose) + printf("rank: %d Defining netCDF dimension %s, length %d\n", my_rank, + dim_name[d], dim_len[d]); + if ((ret = PIOc_def_dim(ncid, dim_name[d], (PIO_Offset)dim_len[d], &dimids[d]))) + ERR(ret); + } + if (verbose) + printf("rank: %d Defining netCDF variable %s, ndims %d\n", my_rank, VAR_NAME, NDIM); + if ((ret = PIOc_def_var(ncid, VAR_NAME, PIO_FLOAT, NDIM, dimids, &varid))) + ERR(ret); + + /* For netCDF-4 files, set the chunksize to improve performance. */ + if (format[fmt] == PIO_IOTYPE_NETCDF4C || format[fmt] == PIO_IOTYPE_NETCDF4P) + { + if (verbose) + printf("rank: %d Defining chunksizes\n", my_rank); + if ((ret = PIOc_def_var_chunking(ncid, 0, NC_CHUNKED, chunksize))) + ERR(ret); + + /** Check that the inq_varname function works. */ + if (verbose) + printf("rank: %d Checking varname\n", my_rank); + ret = PIOc_inq_varname(ncid, 0, varname); + printf("rank: %d ret: %d varname: %s\n", my_rank, ret, varname); + + /** Check that the inq_var_chunking function works. */ + if (verbose) + printf("rank: %d Checking chunksizes\n"); + if ((ret = PIOc_inq_var_chunking(ncid, 0, &storage, my_chunksize))) + ERR(ret); + if (verbose) + { + printf("rank: %d ret: %d storage: %d\n", my_rank, ret, storage); + for (d1 = 0; d1 < NDIM; d1++) + { + printf("chunksize[%d]=%d\n", d1, my_chunksize[d1]); + } + } + + /** Check the answers. */ + if (format[fmt] == PIO_IOTYPE_NETCDF4C || + format[fmt] == PIO_IOTYPE_NETCDF4P) + { + if (storage != NC_CHUNKED) + ERR(ERR_AWFUL); + for (d1 = 0; d1 < NDIM; d1++) + if (my_chunksize[d1] != chunksize[d1]) + ERR(ERR_AWFUL); + } + + /* Check that the inq_var_deflate functions works. */ + if ((ret = PIOc_inq_var_deflate(ncid, 0, &shuffle, &deflate, &deflate_level))) + ERR(ret); + + /** For serial netCDF-4 deflate is turned on by default */ + if (format[fmt] == PIO_IOTYPE_NETCDF4C) + if (shuffle || !deflate || deflate_level != 1) + ERR(ERR_AWFUL); + + /* For parallel netCDF-4, no compression available. :-( */ + if (format[fmt] == PIO_IOTYPE_NETCDF4P) + if (shuffle || deflate) + ERR(ERR_AWFUL); + + /* Check setting the chunk cache for the variable. */ + printf("rank: %d PIOc_set_var_chunk_cache...\n", my_rank); + if ((ret = PIOc_set_var_chunk_cache(ncid, 0, VAR_CACHE_SIZE, VAR_CACHE_NELEMS, + VAR_CACHE_PREEMPTION))) + ERR(ret); + + /* Check getting the chunk cache values for the variable. */ + printf("rank: %d PIOc_get_var_chunk_cache...\n", my_rank); + if ((ret = PIOc_get_var_chunk_cache(ncid, 0, &var_cache_size, &var_cache_nelems, + &var_cache_preemption))) + ERR(ret); + PIO_Offset len; + if ((ret = PIOc_inq_dimlen(ncid, 0, &len))) + ERR(ret); + + /* Check that we got expected values. */ + printf("rank: %d var_cache_size = %d\n", my_rank, var_cache_size); + if (var_cache_size != VAR_CACHE_SIZE) + ERR(ERR_AWFUL); + if (var_cache_nelems != VAR_CACHE_NELEMS) + ERR(ERR_AWFUL); + if (var_cache_preemption != VAR_CACHE_PREEMPTION) + ERR(ERR_AWFUL); + } else { + /* Trying to set or inq netCDF-4 settings for non-netCDF-4 + * files results in the PIO_ENOTNC4 error. */ + if ((ret = PIOc_def_var_chunking(ncid, 0, NC_CHUNKED, chunksize)) != PIO_ENOTNC4) + ERR(ERR_AWFUL); + if ((ret = PIOc_inq_var_chunking(ncid, 0, &storage, my_chunksize)) != PIO_ENOTNC4) + ERR(ERR_AWFUL); + if ((ret = PIOc_inq_var_deflate(ncid, 0, &shuffle, &deflate, &deflate_level)) + != PIO_ENOTNC4) + ERR(ret); + if ((ret = PIOc_def_var_endian(ncid, 0, 1)) != PIO_ENOTNC4) + ERR(ret); + if ((ret = PIOc_inq_var_endian(ncid, 0, &endianness)) != PIO_ENOTNC4) + ERR(ret); + if ((ret = PIOc_set_var_chunk_cache(ncid, 0, VAR_CACHE_SIZE, VAR_CACHE_NELEMS, + VAR_CACHE_PREEMPTION)) != PIO_ENOTNC4) + ERR(ret); + if ((ret = PIOc_get_var_chunk_cache(ncid, 0, &var_cache_size, &var_cache_nelems, + &var_cache_preemption)) != PIO_ENOTNC4) + ERR(ret); + if ((ret = PIOc_set_chunk_cache(iosysid, format[fmt], chunk_cache_size, chunk_cache_nelems, + chunk_cache_preemption)) != PIO_ENOTNC4) + ERR(ret); + if ((ret = PIOc_get_chunk_cache(iosysid, format[fmt], &chunk_cache_size, + &chunk_cache_nelems, &chunk_cache_preemption)) != PIO_ENOTNC4) + ERR(ret); + } + + if ((ret = PIOc_enddef(ncid))) + ERR(ret); + + /* Close the netCDF file. */ + if (verbose) + printf("rank: %d Closing the sample data file...\n", my_rank); + if ((ret = PIOc_closefile(ncid))) + ERR(ret); + } + + /* Free the PIO decomposition. */ + if (verbose) + printf("rank: %d Freeing PIO decomposition...\n", my_rank); + if ((ret = PIOc_freedecomp(iosysid, ioid))) + ERR(ret); + + /* Finalize the IO system. */ + if (verbose) + printf("rank: %d Freeing PIO resources...\n", my_rank); + if ((ret = PIOc_finalize(iosysid))) + ERR(ret); + + /* Finalize the MPI library. */ + MPI_Finalize(); + +#ifdef TIMING + /* Finalize the GPTL timing library. */ + if ((ret = GPTLfinalize ())) + return ret; +#endif + + + return 0; +} diff --git a/tests/unit/test_names.c b/tests/unit/test_names.c new file mode 100644 index 00000000000..ea493ddc0f5 --- /dev/null +++ b/tests/unit/test_names.c @@ -0,0 +1,416 @@ +/** + * @file + * Tests for names of vars, atts, and dims. + * + */ +#include +#ifdef TIMING +#include +#endif + +#define NUM_NETCDF_FLAVORS 4 +#define NDIM 3 +#define X_DIM_LEN 400 +#define Y_DIM_LEN 400 +#define NUM_TIMESTEPS 6 +#define VAR_NAME "foo" +#define ATT_NAME "bar" +#define START_DATA_VAL 42 +#define ERR_AWFUL 1111 +#define VAR_CACHE_SIZE (1024 * 1024) +#define VAR_CACHE_NELEMS 10 +#define VAR_CACHE_PREEMPTION 0.5 + +/** Handle MPI errors. This should only be used with MPI library + * function calls. */ +#define MPIERR(e) do { \ + MPI_Error_string(e, err_buffer, &resultlen); \ + fprintf(stderr, "MPI error, line %d, file %s: %s\n", __LINE__, __FILE__, err_buffer); \ + MPI_Finalize(); \ + return ERR_AWFUL; \ + } while (0) + +/** Handle non-MPI errors by finalizing the MPI library and exiting + * with an exit code. */ +#define ERR(e) do { \ + fprintf(stderr, "Error %d in %s, line %d\n", e, __FILE__, __LINE__); \ + MPI_Finalize(); \ + return e; \ + } while (0) + +/** Global err buffer for MPI. */ +char err_buffer[MPI_MAX_ERROR_STRING]; +int resultlen; + +/** The dimension names. */ +char dim_name[NDIM][NC_MAX_NAME + 1] = {"timestep", "x", "y"}; + +/** Length of the dimensions in the sample data. */ +int dim_len[NDIM] = {NC_UNLIMITED, X_DIM_LEN, Y_DIM_LEN}; + +/** Length of chunksizes to use in netCDF-4 files. */ +size_t chunksize[NDIM] = {2, X_DIM_LEN/2, Y_DIM_LEN/2}; + +/** Check the dimension names. + * + * @param my_rank rank of process + * @param ncid ncid of open netCDF file + * + * @returns 0 for success, error code otherwise. */ +int +check_dim_names(int my_rank, int ncid, int verbose) +{ + char dim_name[NC_MAX_NAME + 1]; + char zero_dim_name[NC_MAX_NAME + 1]; + int ret; + + for (int d = 0; d < NDIM; d++) + { + strcpy(dim_name, "11111111111111111111111111111111"); + if ((ret = PIOc_inq_dimname(ncid, d, dim_name))) + return ret; + if (verbose) + printf("my_rank %d dim %d name %s\n", my_rank, d, dim_name); + + /* Did other ranks get the same name? */ + if (!my_rank) + strcpy(zero_dim_name, dim_name); + /* if (verbose) */ + /* printf("rank %d dim_name %s zero_dim_name %s\n", my_rank, dim_name, zero_dim_name); */ + if ((ret = MPI_Bcast(&zero_dim_name, strlen(dim_name) + 1, MPI_CHAR, 0, + MPI_COMM_WORLD))) + MPIERR(ret); + if (strcmp(dim_name, zero_dim_name)) + return ERR_AWFUL; + } + return 0; +} + +/** Check the variable name. + * + * @param my_rank rank of process + * @param ncid ncid of open netCDF file + * + * @returns 0 for success, error code otherwise. */ +int +check_var_name(int my_rank, int ncid, int verbose) +{ + char var_name[NC_MAX_NAME + 1]; + char zero_var_name[NC_MAX_NAME + 1]; + int ret; + + strcpy(var_name, "11111111111111111111111111111111"); + if ((ret = PIOc_inq_varname(ncid, 0, var_name))) + return ret; + if (verbose) + printf("my_rank %d var name %s\n", my_rank, var_name); + + /* Did other ranks get the same name? */ + if (!my_rank) + strcpy(zero_var_name, var_name); + if ((ret = MPI_Bcast(&zero_var_name, strlen(var_name) + 1, MPI_CHAR, 0, + MPI_COMM_WORLD))) + MPIERR(ret); + if (strcmp(var_name, zero_var_name)) + return ERR_AWFUL; + return 0; +} + +/** Check the attribute name. + * + * @param my_rank rank of process + * @param ncid ncid of open netCDF file + * + * @returns 0 for success, error code otherwise. */ +int +check_att_name(int my_rank, int ncid, int verbose) +{ + char att_name[NC_MAX_NAME + 1]; + char zero_att_name[NC_MAX_NAME + 1]; + int ret; + + strcpy(att_name, "11111111111111111111111111111111"); + if ((ret = PIOc_inq_attname(ncid, NC_GLOBAL, 0, att_name))) + return ret; + if (verbose) + printf("my_rank %d att name %s\n", my_rank, att_name); + + /* Did everyone ranks get the same length name? */ +/* if (strlen(att_name) != strlen(ATT_NAME)) + return ERR_AWFUL;*/ + if (!my_rank) + strcpy(zero_att_name, att_name); + if ((ret = MPI_Bcast(&zero_att_name, strlen(att_name) + 1, MPI_CHAR, 0, + MPI_COMM_WORLD))) + MPIERR(ret); + if (strcmp(att_name, zero_att_name)) + return ERR_AWFUL; + return 0; +} + +/** Run Tests for NetCDF-4 Functions. + * + * @param argc argument count + * @param argv array of arguments + */ +int +main(int argc, char **argv) +{ + int verbose = 1; + + /** Zero-based rank of processor. */ + int my_rank; + + /** Number of processors involved in current execution. */ + int ntasks; + + /** Specifies the flavor of netCDF output format. */ + int iotype; + + /** Different output flavors. */ + int format[NUM_NETCDF_FLAVORS] = {PIO_IOTYPE_PNETCDF, + PIO_IOTYPE_NETCDF, + PIO_IOTYPE_NETCDF4C, + PIO_IOTYPE_NETCDF4P}; + + /** Names for the output files. */ + char filename[NUM_NETCDF_FLAVORS][NC_MAX_NAME + 1] = {"test_names_pnetcdf.nc", + "test_names_classic.nc", + "test_names_serial4.nc", + "test_names_parallel4.nc"}; + + /** Number of processors that will do IO. In this test we + * will do IO from all processors. */ + int niotasks; + + /** Stride in the mpi rank between io tasks. Always 1 in this + * test. */ + int ioproc_stride = 1; + + /** Number of the aggregator? Always 0 in this test. */ + int numAggregator = 0; + + /** Zero based rank of first processor to be used for I/O. */ + int ioproc_start = 0; + + /** The dimension IDs. */ + int dimids[NDIM]; + + /** Array index per processing unit. */ + PIO_Offset elements_per_pe; + + /** The ID for the parallel I/O system. */ + int iosysid; + + /** The ncid of the netCDF file. */ + int ncid = 0; + + /** The ID of the netCDF varable. */ + int varid; + + /** Storage of netCDF-4 files (contiguous vs. chunked). */ + int storage; + + /** Chunksizes set in the file. */ + size_t my_chunksize[NDIM]; + + /** The shuffle filter setting in the netCDF-4 test file. */ + int shuffle; + + /** Non-zero if deflate set for the variable in the netCDF-4 test file. */ + int deflate; + + /** The deflate level set for the variable in the netCDF-4 test file. */ + int deflate_level; + + /** Non-zero if fletcher32 filter is used for variable. */ + int fletcher32; + + /** Endianness of variable. */ + int endianness; + + /* Size of the file chunk cache. */ + size_t chunk_cache_size; + + /* Number of elements in file cache. */ + size_t nelems; + + /* File cache preemption. */ + float preemption; + + /* Size of the var chunk cache. */ + size_t var_cache_size; + + /* Number of elements in var cache. */ + size_t var_cache_nelems; + + /* Var cache preemption. */ + float var_cache_preemption; + + /** The I/O description ID. */ + int ioid; + + /** A buffer for sample data. */ + float *buffer; + + /** A buffer for reading data back from the file. */ + int *read_buffer; + + /** The decomposition mapping. */ + PIO_Offset *compdof; + + /** Return code. */ + int ret; + + /** Index for loops. */ + int fmt, d, d1, i; + +#ifdef TIMING + /* Initialize the GPTL timing library. */ + if ((ret = GPTLinitialize ())) + return ret; +#endif + + /* Initialize MPI. */ + if ((ret = MPI_Init(&argc, &argv))) + MPIERR(ret); + + /* Learn my rank and the total number of processors. */ + if ((ret = MPI_Comm_rank(MPI_COMM_WORLD, &my_rank))) + MPIERR(ret); + if ((ret = MPI_Comm_size(MPI_COMM_WORLD, &ntasks))) + MPIERR(ret); + + /* Check that a valid number of processors was specified. */ + if (!(ntasks == 1 || ntasks == 2 || ntasks == 4 || + ntasks == 8 || ntasks == 16)) + fprintf(stderr, "Number of processors must be 1, 2, 4, 8, or 16!\n"); + if (verbose) + printf("%d: ParallelIO Library example1 running on %d processors.\n", + my_rank, ntasks); + + /* keep things simple - 1 iotask per MPI process */ + niotasks = ntasks; + + /* Initialize the PIO IO system. This specifies how + * many and which processors are involved in I/O. */ + if ((ret = PIOc_Init_Intracomm(MPI_COMM_WORLD, niotasks, ioproc_stride, + ioproc_start, PIO_REARR_SUBSET, &iosysid))) + ERR(ret); + + /* Describe the decomposition. This is a 1-based array, so add 1! */ + elements_per_pe = X_DIM_LEN * Y_DIM_LEN / ntasks; + if (!(compdof = malloc(elements_per_pe * sizeof(PIO_Offset)))) + return PIO_ENOMEM; + for (i = 0; i < elements_per_pe; i++) { + compdof[i] = my_rank * elements_per_pe + i + 1; + } + + /* Create the PIO decomposition for this test. */ + if (verbose) + printf("rank: %d Creating decomposition...\n", my_rank); + if ((ret = PIOc_InitDecomp(iosysid, PIO_FLOAT, 2, &dim_len[1], (PIO_Offset)elements_per_pe, + compdof, &ioid, NULL, NULL, NULL))) + ERR(ret); + free(compdof); + + /* How many flavors will we be running for? */ + int num_flavors = 0; + int fmtidx = 0; +#ifdef _PNETCDF + num_flavors++; + format[fmtidx++] = PIO_IOTYPE_PNETCDF; +#endif +#ifdef _NETCDF + num_flavors++; + format[fmtidx++] = PIO_IOTYPE_NETCDF; +#endif +#ifdef _NETCDF4 + num_flavors += 2; + format[fmtidx++] = PIO_IOTYPE_NETCDF4C; + format[fmtidx] = PIO_IOTYPE_NETCDF4P; +#endif + + /* Use PIO to create the example file in each of the four + * available ways. */ + for (fmt = 0; fmt < num_flavors; fmt++) + { + /* Create the netCDF output file. */ + if (verbose) + printf("rank: %d Creating sample file %s with format %d...\n", + my_rank, filename[fmt], format[fmt]); + if ((ret = PIOc_createfile(iosysid, &ncid, &(format[fmt]), filename[fmt], + PIO_CLOBBER))) + ERR(ret); + + /* Define netCDF dimensions and variable. */ + if (verbose) + printf("rank: %d Defining netCDF metadata...\n", my_rank); + for (d = 0; d < NDIM; d++) { + if (verbose) + printf("rank: %d Defining netCDF dimension %s, length %d\n", my_rank, + dim_name[d], dim_len[d]); + if ((ret = PIOc_def_dim(ncid, dim_name[d], (PIO_Offset)dim_len[d], &dimids[d]))) + ERR(ret); + } + + /* Check the dimension names. */ + if ((ret = check_dim_names(my_rank, ncid, verbose))) + ERR(ret); + + /* Define a global attribute. */ + int att_val = 42; + if ((ret = PIOc_put_att_int(ncid, NC_GLOBAL, ATT_NAME, NC_INT, 1, &att_val))) + ERR(ret); + + /* Check the attribute name. */ + if ((ret = check_att_name(my_rank, ncid, verbose))) + ERR(ret); + + /* Define a variable. */ + if ((ret = PIOc_def_var(ncid, VAR_NAME, PIO_FLOAT, NDIM, dimids, &varid))) + ERR(ret); + + /* Check the variable name. */ + if ((ret = check_var_name(my_rank, ncid, verbose))) + ERR(ret); + + if ((ret = PIOc_enddef(ncid))) + ERR(ret); + + /* Close the netCDF file. */ + if (verbose) + printf("rank: %d Closing the sample data file...\n", my_rank); + if ((ret = PIOc_closefile(ncid))) + ERR(ret); + + /* Put a barrier here to make verbose output look better. */ + if ((ret = MPI_Barrier(MPI_COMM_WORLD))) + MPIERR(ret); + + } + + /* Free the PIO decomposition. */ + if (verbose) + printf("rank: %d Freeing PIO decomposition...\n", my_rank); + if ((ret = PIOc_freedecomp(iosysid, ioid))) + ERR(ret); + + /* Finalize the IO system. */ + if (verbose) + printf("rank: %d Freeing PIO resources...\n", my_rank); + if ((ret = PIOc_finalize(iosysid))) + ERR(ret); + + /* Finalize the MPI library. */ + MPI_Finalize(); + +#ifdef TIMING + /* Finalize the GPTL timing library. */ + if ((ret = GPTLfinalize ())) + return ret; +#endif + + + return 0; +} diff --git a/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map.nml b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map.nml new file mode 100644 index 00000000000..aeaccdfaba9 --- /dev/null +++ b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map.nml @@ -0,0 +1,15 @@ + &input_nml + gridtype = 'rtm' + file_roff = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rtmdata/rdirc.05.061026' + file_ocn = '/glade/p/cesm/cseg/mapping/grids/gx3v7_120309.nc' + file_nn = 'map_r05_to_gx3v7_nn_130507.nc ' + file_smooth = 'map_gx3v7_to_gx3v7_sm_e1000r300_130507.nc ' + file_new = 'map_r05_to_gx3v7_nnsm_e1000r300_130507.nc' + title = 'runoff map: r05 -> gx3v7, nearest neighbor and smoothed ' + eFold = 1000000.0 + rMax = 300000.0 + step1 = .true. + step2 = .true. + step3 = .true. + + / diff --git a/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_r05_gx3v7.nml b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_r05_gx3v7.nml new file mode 100644 index 00000000000..aeaccdfaba9 --- /dev/null +++ b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_r05_gx3v7.nml @@ -0,0 +1,15 @@ + &input_nml + gridtype = 'rtm' + file_roff = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rtmdata/rdirc.05.061026' + file_ocn = '/glade/p/cesm/cseg/mapping/grids/gx3v7_120309.nc' + file_nn = 'map_r05_to_gx3v7_nn_130507.nc ' + file_smooth = 'map_gx3v7_to_gx3v7_sm_e1000r300_130507.nc ' + file_new = 'map_r05_to_gx3v7_nnsm_e1000r300_130507.nc' + title = 'runoff map: r05 -> gx3v7, nearest neighbor and smoothed ' + eFold = 1000000.0 + rMax = 300000.0 + step1 = .true. + step2 = .true. + step3 = .true. + + / diff --git a/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_rx1_gx1v6.nml b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_rx1_gx1v6.nml new file mode 100644 index 00000000000..ca05bd97185 --- /dev/null +++ b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_rx1_gx1v6.nml @@ -0,0 +1,15 @@ + &input_nml + gridtype = 'obs' + file_roff = '/glade/p/cesm/cseg/inputdata/lnd/dlnd7/RX1/runoff.daitren.annual.090225.nc' + file_ocn = '/glade/p/cesm/cseg/mapping/grids/gx1v6_090205.nc' + file_nn = 'map_rx1_to_gx1v6_nearestdtos_131212.nc ' + file_smooth = 'map_gx1v6_to_gx1v6_smooth_131212.nc ' + file_new = 'map_rx1_to_gx1v6_e1000r300_131212.nc' + title = 'runoff map: rx1 -> gx1v6, smoothed ' + eFold = 1000000.0 + rMax = 300000.0 + step1 = .true. + step2 = .true. + step3 = .true. + + / diff --git a/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_tx01.nml b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_tx01.nml new file mode 100644 index 00000000000..da76b89f378 --- /dev/null +++ b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_tx01.nml @@ -0,0 +1,15 @@ + &input_nml + gridtype = 'obs' + file_roff = '/fs/cgd/csm/inputdata/lnd/clm2/rtmdata/rdirc.05.061026' + file_ocn = '/fs/cgd/csm/mapping/grids/tx0.1v2_070911.nc' + file_nn = 'map_nn_tx01v2.nc ' + file_smooth = 'map_smoother_tx01v2.nc ' + file_new = 'map_r05_to_tx01v2_tctest.nc' + title = 'runoff map: r05 -> tx01v2 test ' + eFold = 1000000.0 + rMax = 50000.0 + step1 = .false. + step2 = .false. + step3 = .true. + + / diff --git a/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_ar9v4.nml b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_ar9v4.nml new file mode 100644 index 00000000000..c6c2a7c87bf --- /dev/null +++ b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_ar9v4.nml @@ -0,0 +1,15 @@ + &input_nml + gridtype = 'scrip' + file_roff = '/glade/p/cesm/cseg/mapping/grids/wr50a_090614.nc' + file_ocn = '/glade/p/cesm/cseg/mapping/grids/ar9v4_100920.nc' + file_nn = 'map_wr50a_to_ar9v4_nn_130508.nc ' + file_smooth = 'map_ar9v4_to_ar9v4_sm_e1000r300_130508.nc ' + file_new = 'map_wr50a_to_ar9v4_nnsm_e1000r300_130508.nc' + title = 'runoff map: wr50a -> ar9v4, nearest neighbor and smoothed ' + eFold = 1000000.0 + rMax = 300000.0 + step1 = .true. + step2 = .true. + step3 = .true. + + / diff --git a/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_gx3v7.nml b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_gx3v7.nml new file mode 100644 index 00000000000..59a37c5bc5f --- /dev/null +++ b/tools/mapping/gen_mapping_files/runoff_to_ocn/runoff_map_wr50a_gx3v7.nml @@ -0,0 +1,15 @@ + &input_nml + gridtype = 'scrip' + file_roff = '/glade/p/cesm/cseg/mapping/grids/wr50a_090614.nc' + file_ocn = '/glade/p/cesm/cseg/mapping/grids/gx3v7_120309.nc' + file_nn = 'map_wr50a_gx3v7_nn_130507.nc ' + file_smooth = 'map_gx3v7_gx3v7_smoother_130507.nc ' + file_new = 'map_wr50a_to_gx3v7_e1000r300_130507.nc' + title = 'runoff map: wr50a -> gx3v7, smoothed ' + eFold = 1000000.0 + rMax = 300000.0 + step1 = .true. + step2 = .true. + step3 = .true. + + /