[nco] 01/06: Imported Upstream version 4.5.0

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Sat Jun 13 12:50:14 UTC 2015


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository nco.

commit 6d71641b8395ffcb11d4764765236c74591ba1c0
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Jun 13 14:08:56 2015 +0200

    Imported Upstream version 4.5.0
---
 .travis.yml           |   14 +
 bld/nco.spec          |    2 +-
 bm/NCO_rgr.pm         |  193 ++----
 bm/nco_bm.pl          |    2 +-
 config.h.in           |    3 +
 configure             |   28 +-
 configure.ac          |   13 +-
 configure.eg          |    2 +-
 data/in.cdl           |   11 +-
 debian/changelog      |    4 +-
 doc/ANNOUNCE          |  149 ++--
 doc/ChangeLog         |  250 ++++++-
 doc/MANIFEST          |    3 +
 doc/index.shtml       |   63 +-
 doc/nco.texi          |  644 ++++++++++++++++--
 man/ncks.1            |   10 +-
 man/ncra.1            |    2 +
 src/nco++/ncap2.cc    |    4 +-
 src/nco/mpncbo.c      |    1 +
 src/nco/mpncecat.c    |    1 +
 src/nco/mpncflint.c   |    3 +
 src/nco/mpncpdq.c     |    1 +
 src/nco/mpncra.c      |    1 +
 src/nco/mpncwa.c      |    1 +
 src/nco/ncap.c        |    2 +
 src/nco/ncbo.c        |    3 +-
 src/nco/ncecat.c      |   12 +-
 src/nco/ncflint.c     |   21 +-
 src/nco/ncks.c        |  185 +++--
 src/nco/nco.h         |   31 +-
 src/nco/nco_att_utl.c |  238 ++++++-
 src/nco/nco_att_utl.h |   17 +
 src/nco/nco_aux.c     |   36 +-
 src/nco/nco_aux.h     |    7 +-
 src/nco/nco_cnk.c     |    8 +-
 src/nco/nco_cnk.h     |    2 +-
 src/nco/nco_cnv_csm.c |    2 +-
 src/nco/nco_ctl.c     |   28 +-
 src/nco/nco_grp_trv.c |   45 +-
 src/nco/nco_grp_trv.h |   10 +-
 src/nco/nco_grp_utl.c |   52 +-
 src/nco/nco_grp_utl.h |    2 +-
 src/nco/nco_msa.c     |    3 +-
 src/nco/nco_mss_val.c |   66 ++
 src/nco/nco_mss_val.h |    6 +
 src/nco/nco_netcdf.c  |   33 +-
 src/nco/nco_netcdf.h  |    4 +
 src/nco/nco_omp.c     |   34 +-
 src/nco/nco_ppc.c     |  408 ++++++++++-
 src/nco/nco_ppc.h     |   29 +
 src/nco/nco_prn.c     |    7 +
 src/nco/nco_rgr.c     | 1793 +++++++++++++++++++++++++++++++++++++++++++------
 src/nco/nco_rgr.h     |   58 +-
 src/nco/nco_rth_utl.c |    2 +-
 src/nco/nco_sld.c     |    2 +-
 src/nco/nco_sng_utl.c |   27 +-
 src/nco/nco_sng_utl.h |   10 +-
 src/nco/nco_var_avg.c |    4 +-
 src/nco/nco_var_lst.c |   71 +-
 src/nco/nco_var_rth.c |  370 ----------
 src/nco/nco_var_rth.h |   18 -
 src/nco/nco_var_utl.c |  139 ++--
 src/nco/nco_var_utl.h |    3 +-
 src/nco/ncpdq.c       |   11 +-
 src/nco/ncra.c        |   24 +-
 src/nco/ncwa.c        |   23 +-
 66 files changed, 3921 insertions(+), 1330 deletions(-)

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..57a4e47
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: c
+compiler:
+  - gcc
+  - clang
+
+before_install:
+  - sudo apt-get update -qq
+  - sudo apt-get install -y -qq libnetcdf6 libnetcdf-dev netcdf-bin
+  - ./configure
+  export DATA=/home/travis
+
+script:
+  - make -j 4
+  - make test
diff --git a/bld/nco.spec b/bld/nco.spec
index c7d8e29..b1fc894 100644
--- a/bld/nco.spec
+++ b/bld/nco.spec
@@ -108,7 +108,7 @@ fi
 # %{_libdir}/libnco++.so
 
 %changelog
-* Thu Jun 21 2015 Charlie Zender <zender at uci.edu> - 4.5.0-1
+* Thu Jun 11 2015 Charlie Zender <zender at uci.edu> - 4.5.0-1
 - new upstream 4.5.0
 
 * Thu May 21 2015 Charlie Zender <zender at uci.edu> - 4.4.9-1
diff --git a/bm/NCO_rgr.pm b/bm/NCO_rgr.pm
index 2b60af3..2f70b9d 100644
--- a/bm/NCO_rgr.pm
+++ b/bm/NCO_rgr.pm
@@ -2394,8 +2394,8 @@ print "\n";
 	
 #ncks #99
 # Test DSD attribute does not overwrite pre-existing rounder values
-# ncks -4 -O -C -v ppc_dbl,ppc_big --ppc .?=4 --ppc ppc_big=-2 ~/nco/data/in.nc ~/foo.nc
-# ncks -4 -O -C -v ppc_dbl,ppc_big --ppc ppc_big,ppc_dbl=3 ~/foo.nc ~/foo2.nc
+# ncks -4 -O -C -v ppc_dbl,ppc_big --ppc .?=4 --ppc ppc_big=.-2 ~/nco/data/in.nc ~/foo.nc
+# ncks -4 -O -C -v ppc_dbl,ppc_big --ppc ppc_big,ppc_dbl=.3 ~/foo.nc ~/foo2.nc
 # ncks -m -v ppc_big ~/foo2.nc
     $dsc_sng="Test DSD attribute does not overwrite pre-existing rounder values";
     $tst_cmd[0]="ncks -O $nco_D_flg -4 -C -v ppc_dbl,ppc_big --ppc .?=.4 --ppc ppc_big=.-2 $in_pth_arg in.nc %tmp_fl_00";
@@ -2531,7 +2531,6 @@ print "\n";
 #####################    
     
 #ncpdq #1
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -a -lat -v lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%g' -v lat -d lat,0 %tmp_fl_00%";
     $dsc_sng="Reverse coordinate -a -lat -v lat";
@@ -2542,7 +2541,6 @@ print "\n";
     
 #ncpdq #2
 #three_dmn_var(lat,lev,lon);
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -a -lat,-lev,-lon -v three_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_var -d lat,0 -d lev,0 -d lon,0 %tmp_fl_00%";
     $dsc_sng="Reverse 3D variable a -lat,-lev,-lon -v three_dmn_var";
@@ -2552,7 +2550,8 @@ print "\n";
     $#tst_cmd=0; # Reset array
     
 #ncpdq #3 NEW NCO 4.3.2
-    
+# ncpdq -h -O -C -a lon,lat -v three_dmn_var ~/nco/data/in.nc ~/foo.nc
+# ncks -C -H -s '%f' -v three_dmn_var -d lat,0 -d lev,2 -d lon,3 ~/foo.nc
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -C -a lon,lat -v three_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_var -d lat,0 -d lev,2 -d lon,3 %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable (no associated coordinates) -C -a lon,lat -v three_dmn_var ";
@@ -2562,7 +2561,6 @@ print "\n";
     $#tst_cmd=0; # Reset array    
     
 #ncpdq #4 
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -a lon,lat -v three_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_var -d lat,0 -d lev,2 -d lon,3 %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable (associated coordinates) -a lon,lat -v three_dmn_var ";
@@ -2574,7 +2572,6 @@ print "\n";
 #ncpdq #5
 #three_dmn_var_dbl(time,lat,lon);
 #ncpdq -h -O -C -a lat,lon,time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3 in.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -a lat,lon,time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_var_dbl -d lat,0 -d lon,1 -d time,2 %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable with MSA -C -a lat,lon,time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3";
@@ -2586,7 +2583,6 @@ print "\n";
 #NEW NCO 4.3.2 
 #ncpdq #6 (same run as #5) 
 #make sure first dimension is record
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -a lat,lon,time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -v three_dmn_var_dbl %tmp_fl_00% | grep  'three_dmn_var_dbl dimension 0: lat, size = 2 (Record non-coordinate dimension)'";
     $dsc_sng="Re-order 3D variable with MSA -C -a lat,lon,time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3";
@@ -2600,7 +2596,6 @@ print "\n";
 #ncpdq -h -O -a lat,lon,time -d time,1,3,2 -d lat,1,1,1 -d lon,1,3,2 -v three_dmn_var_dbl in.nc ~/foo.nc 
 #ncks -C -H -v three_dmn_var_dbl -d lat,0,0 -d lon,1,1 -d time,0 ~/foo.nc
 #lat[0]=90 lon[1]=270 time[0]=2 three_dmn_var_dbl[2]=16 
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -a lat,lon,time -d time,1,3,2 -d lat,1,1,1 -d lon,1,3,2 -v three_dmn_var_dbl  $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v three_dmn_var_dbl -d lat,0,0 -d lon,1,1 -d time,0 %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable with MSA (stride) -a lat,lon,time -d time,1,3,2 -d lat,1,1,1 -d lon,1,3,2 -v three_dmn_var_dbl";
@@ -2610,7 +2605,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
    
 #ncpdq #8
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -a lat,lon,-time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_var_dbl -d lat,1 -d lon,1 -d time,4 %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable with MSA+ reversal of time dim -C -a lat,lon,-time -v three_dmn_var_dbl -d time,0,3 -d time,9,9 -d lon,0,0 -d lon,3,3";
@@ -2620,7 +2614,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
 
 #ncpdq #9
-    
      $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -a lon,lat -v three_dmn_var_dbl -d time,0,2 -d time,4 -d lat,1 -d lat,1 --msa_usr_rdr $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%2.f,' -v three_dmn_var_dbl -d time,1 -d lon,0 %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable with MSA and --msa_usr_rdr flag -C -a lon,lat -v three_dmn_var_dbl -d time,0,2 -d time,4 -d lat,1 -d lat,1 --msa_usr_rdr";
@@ -2648,7 +2641,6 @@ print "\n";
 # two_dmn_var (lat,lev) -C, no MSA (no associated coordinates)
 # ncpdq -O -C -a lev,lat -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks -v two_dmn_var -d lat,1,1 -d lev,1,1 ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -C -a lev,lat -v two_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_var -d lat,1,1 -d lev,1,1 %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable (-C, no MSA) -v two_dmn_var -a lev,lat";
@@ -2663,7 +2655,6 @@ print "\n";
 # ncpdq -O -a lev,lat -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks -C -d lat,1,1 -d lev,1,1 ~/foo.nc
 #$tst_cmd[2]="lev[1]=500 lat[1]=90 two_dmn_var[3]=17.5 fraction";
-
   $tst_cmd[0]="ncpdq $omp_flg -O $fl_fmt $nco_D_flg -a lev,lat -v two_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -C -v two_dmn_var -d lat,1,1 -d lev,1,1 %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable (no -C, no MSA) -v two_dmn_var -a lev,lat";
@@ -2671,14 +2662,12 @@ print "\n";
   $tst_cmd[3]="SS_OK";
   if($mpi_prc == 0 || ($mpi_prc > 0 && !($localhostname =~ /pbs/))){NCO_bm::tst_run(\@tst_cmd);} # ncpdq hangs with MPI TODO nco772
   $#tst_cmd=0; # Reset array     
-   
 
 #NEW NCO 4.3.2
 #ncpdq #13
 # two_dmn_var (lat,lev) -C, MSA (no associated coordinates)
 # ncpdq -O -C -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg -O -C $fl_fmt $nco_D_flg -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_var %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable (-C, MSA) -v two_dmn_var -a lev,lat -d lat,1,1 -d lev,1,1";
@@ -2692,7 +2681,6 @@ print "\n";
 # two_dmn_var (lat,lev) MSA (associated coordinates)
 # ncpdq -O -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg -O $fl_fmt $nco_D_flg -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_var %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable (no -C, MSA) -v two_dmn_var -a lev,lat -d lat,1,1 -d lev,1,1";
@@ -2706,7 +2694,6 @@ print "\n";
 # two_dmn_rec_var(time,lev) 2D variable with record  (-C, no MSA)
 # ncpdq -O -C -a lev,time -v two_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
 # ncks -d time,1,1 -d lev,1,1 ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg -O $fl_fmt $nco_D_flg -C -a lev,time -v two_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_rec_var -d time,1,1 -d lev,1,1 %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable with record (-C, no MSA) -v two_dmn_rec_var -C -a lev,time";
@@ -2721,7 +2708,6 @@ print "\n";
 # two_dmn_rec_var(time,lev) 2D variable with record  (no MSA)
 # ncpdq -O -a lev,time -v two_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
 # ncks -d time,1,1 -d lev,1,1 ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg -O $fl_fmt $nco_D_flg -a lev,time -v two_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_rec_var -d time,1,1 -d lev,1,1 %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable with record (no -C, no MSA) -v two_dmn_rec_var -a lev,time";
@@ -2735,7 +2721,6 @@ print "\n";
 # two_dmn_rec_var(time,lev) 2D variable with record  (MSA)
 # ncpdq -O -C -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
 # ncks ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg -O $fl_fmt $nco_D_flg -C -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_rec_var %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable with record (-C, MSA) -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var";
@@ -2749,7 +2734,6 @@ print "\n";
 # two_dmn_rec_var(time,lev) 2D variable with record  (MSA)
 # ncpdq -O -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
 # ncks ~/foo.nc
-
   $tst_cmd[0]="ncpdq $omp_flg -O $fl_fmt $nco_D_flg -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
   $tst_cmd[1]="ncks -v two_dmn_rec_var %tmp_fl_00%";
   $dsc_sng="Re-order 2D variable with record (no -C, MSA) -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var";
@@ -2762,7 +2746,6 @@ print "\n";
 #ncpdq #19
 #three_dmn_var_dbl(time,lat,lon);
 #ncpdq -h -O -a lat,time -v three_dmn_var -d time,1,1 -d lat,1,1 -d lon,1,1 in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -a -lat,-time -v three_dmn_var_dbl -d time,1,6,2 -d lat,0,1 -d lon,1,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -H -C -v three_dmn_var_dbl -d lat,1,1 -d time,2,2 %tmp_fl_00%";
     $dsc_sng="Reverse/Re-order 3D variable -a -lat,-time -v three_dmn_var_dbl -d time,1,1 -d lat,1,1 -d lon,1,1";
@@ -2776,7 +2759,6 @@ print "\n";
 #three_dmn_rec_var(time,lat,lon);
 #ty(time,lat);
 #ncpdq -h -O -a lat,time -v ty,three_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v ty,three_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v ty -d time,1,1 -d lat,1,1 %tmp_fl_00%";
     $dsc_sng="Re-order several variables -a lat,time -v ty,three_dmn_rec_var (no MSA) Test1";
@@ -2790,7 +2772,6 @@ print "\n";
 #three_dmn_rec_var(time,lat,lon);
 #ty(time,lat);
 #ncpdq -h -O -a lat,time -v ty,three_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v ty,three_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v three_dmn_rec_var -d time,1,1 -d lat,1,1 -d lon,1,1 %tmp_fl_00%";
     $dsc_sng="Re-order several variables -a lat,time -v ty,three_dmn_rec_var (no MSA) Test2";
@@ -2804,7 +2785,6 @@ print "\n";
 #three_dmn_rec_var(time,lat,lon); MSA
 #ty(time,lat);
 #ncpdq -h -O -a lat,time -v ty,three_dmn_rec_var -d time,1,6,2 -d lat,1,1 in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v ty,three_dmn_rec_var -d time,1,6,2 -d lat,1,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v ty -d time,2,2 %tmp_fl_00%";
     $dsc_sng="Re-order several variables -a lat,time -v ty,three_dmn_rec_var (MSA) Test1 read ty";
@@ -2818,7 +2798,6 @@ print "\n";
 #three_dmn_rec_var(time,lat,lon); MSA
 #ty(time,lat);
 #ncpdq -h -O -a lat,time -v ty,three_dmn_rec_var -d time,1,6,2 -d lat,1,1 in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v ty,three_dmn_rec_var -d time,1,6,2 -d lat,1,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v three_dmn_rec_var -d lat,0,0 -d time,1,1 -d lon,1,1 %tmp_fl_00%";
     $dsc_sng="Re-order several variables -a lat,time -v ty,three_dmn_rec_var (MSA) Test2 read three_dmn_rec_var";
@@ -2832,7 +2811,6 @@ print "\n";
 #three_dmn_rec_var(time,lat,lon); 
 #ty(time,lat);
 #ncpdq -h -O -a lat,time -v ty,three_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v ty,three_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -m -C -v three_dmn_rec_var %tmp_fl_00% | grep 'three_dmn_rec_var dimension 0: lat, size = 2 NC_FLOAT (Record coordinate is lat)'";
     $dsc_sng="Re-order several variables -a lat,time -v ty,three_dmn_rec_var Test3 check record for lat";
@@ -2846,7 +2824,6 @@ print "\n";
 #three_dmn_rec_var(time,lat,lon); 
 #ty(time,lat);
 #ncpdq -h -O -a lat,time -v ty,three_dmn_rec_var ~/nco/data/in.nc ~/foo.nc
-    
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v ty,three_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -m -C -v three_dmn_rec_var %tmp_fl_00% | grep 'three_dmn_rec_var dimension 1: time, size = 10 NC_DOUBLE (Coordinate is time)'";
     $dsc_sng="Re-order several variables -a lat,time -v ty,three_dmn_rec_var Test4 check non record for time";
@@ -2860,7 +2837,6 @@ print "\n";
 #four_dmn_rec_var(time,lat,lev,lon); MSA
 #ncpdq -h -O -a lev,time,-lon,-lat -v four_dmn_rec_var -d time,1,6,2 -d lat,1,1 -d lon,1,1 -d lev,1,1 in.nc ~/foo.nc
 #ncks -C -H -v four_dmn_rec_var -d time,2,2 ~/foo.nc
-
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lev,time,-lon,-lat -v four_dmn_rec_var -d time,1,6,2 -d lat,1,1 -d lon,1,1 -d lev,1,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v four_dmn_rec_var -d time,2,2 %tmp_fl_00%";
     $dsc_sng="Reverse/Re-order 4D variable -a lev,time,-lon,-lat -v four_dmn_rec_var (MSA)";
@@ -2875,7 +2851,6 @@ print "\n";
 #three_dmn_var_crd(lev,lat,lon);
 #ncpdq -h -O -a lat,time -v PS,three_dmn_var_crd -d lev,1,1 -d lat,1,1 -d lon,1,1 -d lev,1,1 in.nc ~/foo.nc
 #ncks -C -H -v three_dmn_var_crd ~/foo.nc
-
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -v PS,three_dmn_var_crd -d lev,1,1 -d lat,1,1 -d lon,1,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -H -C -v three_dmn_var_crd %tmp_fl_00%";
     $dsc_sng="Re-order 3D variable (only 1 in -a) -a lat,time -v PS,three_dmn_var_crd (MSA)";
@@ -2888,7 +2863,6 @@ print "\n";
 #ncpdq #28 
 #ncpdq -h -O -a lat,time -d time,1,6,2 -d lat,1,1 in.nc ~/foo.nc
 #ncks -C -H -v -d time,2,2 four_dmn_rec_var ~/foo.nc
-
     $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -h -O -a lat,time -d time,1,1 -d lat,1,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v four_dmn_rec_var -d lon,2,2 -d lev,2,2 %tmp_fl_00%";
     $dsc_sng="Re-order all variables -a lat,time (MSA)";
@@ -2902,7 +2876,6 @@ print "\n";
 #####################       
     
 #ncpdq #29
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -P all_new -v upk $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncpdq $omp_flg -h -O $fl_fmt $nco_D_flg -P upk -v upk %tmp_fl_00% %tmp_fl_00%";
     $tst_cmd[2]="ncks -C -H -s '%g' -v upk %tmp_fl_00%";
@@ -2913,7 +2886,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
 
 #ncpdq #30
-    
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P upk -v rec_var_dbl_mss_val_dbl_pck -d time,0,4 -d time,6 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v rec_var_dbl_mss_val_dbl_pck -d time,5 %tmp_fl_00%";
     $dsc_sng="Unpack 1D variable with MSA -C P upk -v rec_var_dbl_mss_val_dbl_pck -d time,0,4 -d time,6";
@@ -2923,7 +2895,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
 
 #ncpdq #31
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P all_xst -v three_dmn_var_dbl -d time,0,2 -d time,8,9 -d lon,0 -d lon,1 -d lat,1 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%i' -v three_dmn_var_dbl -d time,2 -d lon,1 -d lat,0 %tmp_fl_00%";
     $dsc_sng="Pack 3D variable with MSA -C -P all_xst -v three_dmn_var_dbl -d time,0,2 -d time,8,9 -d lon,0 -d lon,1 -d lat,1"; 
@@ -2933,8 +2904,7 @@ print "\n";
     if($mpi_prc == 0 || ($mpi_prc > 0 && !($localhostname =~ /pbs/))){NCO_bm::tst_run(\@tst_cmd);} # ncpdq hangs with MPI TODO nco772
     $#tst_cmd=0; # Reset array
 	
-	
-	#######################################
+    #######################################
     #### Group tests (requires netCDF4) ###
     #######################################
 
@@ -2950,7 +2920,6 @@ print "\n";
 # ncpdq -O -C -a lev,lat -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks -v two_dmn_var -d lat,1,1 -d lev,1,1 ~/foo.nc
 
-
 # same as previous but with group
     
 #NEW NCO 4.3.2
@@ -2961,8 +2930,6 @@ print "\n";
 # two_dmn_var (lat,lev) -C, no MSA (no associated coordinates)
 # ncpdq -O -C -g g19g1 -a lev,lat -v two_dmn_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -g g19g1 -v two_dmn_var -d lat,1,1 -d lev,1,1 ~/foo.nc
-
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -C -g g19g1 -a lev,lat -v two_dmn_var $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -g g19g1 -v two_dmn_var -d lat,1,1 -d lev,1,1 %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable (-C, no MSA) -v two_dmn_var -a lev,lat";
@@ -2978,7 +2945,6 @@ print "\n";
 # ncpdq -O -a lev,lat -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks -C -d lat,1,1 -d lev,1,1 ~/foo.nc
 
-
 # same as previous but with group
     
 #NEW NCO 4.3.2
@@ -2989,7 +2955,6 @@ print "\n";
 # two_dmn_var (lat,lev) no -C, no MSA 
 # ncpdq -O -g g19g1 -a lev,lat -v two_dmn_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -C -g g19g1 -v two_dmn_var -d lat,1,1 -d lev,1,1 ~/foo.nc
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -g g19g1 -a lev,lat -v two_dmn_var $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -C -g g19g1 -v two_dmn_var -d lat,1,1 -d lev,1,1 %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable (no -C, no MSA) -v two_dmn_var -a lev,lat";
@@ -3004,7 +2969,6 @@ print "\n";
 # ncpdq -O -C -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var ~/nco/data/in.nc ~/foo.nc
 # ncks ~/foo.nc
 
-
 # same as previous but with group
     
 #NEW NCO 4.3.2
@@ -3015,8 +2979,6 @@ print "\n";
 # two_dmn_var (lat,lev) -C, MSA (no associated coordinates)
 # ncpdq -O -C -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks ~/foo.nc
-
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -g g19g1 -C -a lev,lat -v two_dmn_var -d lat,1,1 -d lev,1,1 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -g g19g1 -v two_dmn_var %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable (-C, MSA) -v two_dmn_var -a lev,lat";
@@ -3041,7 +3003,6 @@ print "\n";
 # two_dmn_var (lat,lev) MSA (associated coordinates)
 # ncpdq -O -g g19g1 -a lev,lat -d lat,1,1 -d lev,1,1 -v two_dmn_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -C -g g19g1 -v two_dmn_var ~/foo.nc
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -g g19g1 -a lev,lat -v two_dmn_var -d lat,1,1 -d lev,1,1 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -C -g g19g1 -v two_dmn_var %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable (no -C, MSA) -v two_dmn_var -a lev,lat";
@@ -3064,7 +3025,6 @@ print "\n";
 # dimensions:lat=2;lev=3;lon=4;time=unlimited;
 # ncpdq -O -g g19g2 -C -a lev,time -v two_dmn_rec_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -d time,1,1 -d lev,1,1 ~/foo.nc
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -g g19g2 -C -a lev,time -v two_dmn_rec_var $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -g g19g2 -v two_dmn_rec_var -d time,1,1 -d lev,1,1 %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable with record (-C, no MSA) -v two_dmn_rec_var -C -a lev,time";
@@ -3078,9 +3038,7 @@ print "\n";
 # two_dmn_rec_var(time,lev) 2D variable with record  (no -C, no MSA)
 # ncpdq -O -g g19g2 -a lev,time -v two_dmn_rec_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -C -g g19g2 -d time,1,1 -d lev,1,1 ~/foo.nc
-
 # same #16 as previous but with group
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -g g19g2 -a lev,time -v two_dmn_rec_var $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -C -g g19g2 -d time,1,1 -d lev,1,1 %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable with record (no -C, no MSA) -v two_dmn_rec_var -C -a lev,time";
@@ -3094,9 +3052,7 @@ print "\n";
 # two_dmn_rec_var(time,lev) 2D variable with record  (MSA)
 # ncpdq -O -C -a lev,time -d time,1,1 -d lev,1,1 -v two_dmn_rec_var ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -g g19g2 -v two_dmn_rec_var ~/foo.nc
-
 # same as #17 but with group
-
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -C -g g19g2 -a lev,time -v two_dmn_rec_var -d time,1,1 -d lev,1,1 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -g g19g2 -v two_dmn_rec_var %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable with record (-C, MSA) -v two_dmn_rec_var -C -a lev,time";
@@ -3112,7 +3068,6 @@ print "\n";
 # ncks -C -g g19g2 -v two_dmn_rec_var ~/foo.nc
 # $tst_cmd[2]="lev[0]=500 time[0]=2 two_dmn_rec_var[0]=2.1 watt meter-2";
 # same as #18 but with group
-  
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -g g19g2 -a lev,time -v two_dmn_rec_var -d time,1,1 -d lev,1,1 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -C -g g19g2 -v two_dmn_rec_var %tmp_fl_00%";
    $dsc_sng="(Groups) Re-order 2D variable with record (no -C, MSA) -v two_dmn_rec_var";
@@ -3123,7 +3078,6 @@ print "\n";
 
 #NEW NCO 4.3.5
 #ncpdq -O -a -lat -g g23,g24 ~/nco/data/in_grp_3.nc ~/foo.nc
-  
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -a -lat -g g23,g24 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -v lat -g g23 %tmp_fl_00%";
    $dsc_sng="(Groups) Reverse -a lat -g g23 several groups";
@@ -3134,7 +3088,6 @@ print "\n";
 
 #NEW NCO 4.3.5
 #ncpdq -O -a -lat -g g23,g24 ~/nco/data/in_grp_3.nc ~/foo.nc
-  
    $tst_cmd[0]="ncpdq $omp_flg $fl_fmt $nco_D_flg -O -a -lat -g g23,g24 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -v lat -g g24 %tmp_fl_00%";
    $dsc_sng="(Groups) Reverse -a lat -g g24 several groups";
@@ -3182,7 +3135,6 @@ print "\n";
 #ncpdq #46
 # ncpdq -O -4 -a lon,lat --cnk_min=1 --cnk_plc=xpl --cnk_dmn lat,1 --cnk_dmn lon,2 -v lat_2D_rct ~/nco/data/in.nc ~/foo.nc
 # ncks -m ~/foo.nc | grep 'lat_2D_rct dimension 0'
-
    $dsc_sng="Chunking -a lon,lat --cnk_min=1 --cnk_plc=xpl --cnk_dmn lat,1 --cnk_dmn lon,2 -v lat_2D_rct";
    $tst_cmd[0]="ncpdq $omp_flg -4 $nco_D_flg -a lon,lat --cnk_min=1 --cnk_plc=xpl --cnk_dmn lat,1 --cnk_dmn lon,2 -v lat_2D_rct $in_pth_arg in.nc %tmp_fl_00%";
    $tst_cmd[1]="ncks -m %tmp_fl_00% | grep 'lat_2D_rct dimension 0'";
@@ -3194,7 +3146,6 @@ print "\n";
 } ##### Group tests	
 	
 #ncpdq #42
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P upk -v pck_7 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P upk -v pck_7 %tmp_fl_00% %tmp_fl_01%";
     $tst_cmd[2]="ncks -C -H -s '%f' -v pck_7 %tmp_fl_01%";
@@ -3205,7 +3156,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
 	
 #ncpdq #43	
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P upk -v pck_7 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v pck_7 %tmp_fl_00%";
     $dsc_sng="Unpack 1D variable with netCDF convention";
@@ -3215,7 +3165,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
 	
 #ncpdq #44	
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P upk --hdf_upk -v pck_7 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v pck_7 %tmp_fl_00%";
     $dsc_sng="Unpack 1D variable with HDF convention";
@@ -3225,7 +3174,6 @@ print "\n";
     $#tst_cmd=0; # Reset array
 	
 #ncpdq #45	
-
     $tst_cmd[0]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P xst_new --hdf_upk -v pck_7 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncpdq $omp_flg -h -O -C $fl_fmt $nco_D_flg -P upk -v pck_7 %tmp_fl_00% %tmp_fl_01%";
     $tst_cmd[2]="ncks -C -H -s '%f' -v pck_7 %tmp_fl_01%";
@@ -3234,8 +3182,6 @@ print "\n";
     $tst_cmd[4]="SS_OK";
     if($mpi_prc == 0 || ($mpi_prc > 0 && !($localhostname =~ /pbs/))){NCO_bm::tst_run(\@tst_cmd);} # ncpdq hangs with MPI TODO nco772
     $#tst_cmd=0; # Reset array	
-	
-
 
 ####################
 #### ncrcat tests ## OK !
@@ -4026,23 +3972,23 @@ if(0){
 ####################
 
 #ncwa #1
+    $dsc_sng="Creating %tmp_fl_03% again (FAILURE netCDF4 ncrename nco821) ";
     $tst_cmd[0]="ncks -h -O $fl_fmt $nco_D_flg -v lat_T42,lon_T42,gw_T42 $in_pth_arg in.nc %tmp_fl_03%";
     $tst_cmd[1]="ncrename -h -O $nco_D_flg -d lat_T42,lat -d lon_T42,lon -v lat_T42,lat -v gw_T42,gw -v lon_T42,lon %tmp_fl_03%";
     $tst_cmd[2]="ncap2 -h -O $fl_fmt $nco_D_flg -s 'one[lat,lon]=lat*lon*0.0+1.0' -s 'zero[lat,lon]=lat*lon*0.0' %tmp_fl_03% %tmp_fl_04%";
     $tst_cmd[3]="ncks -C -H -s '%g' -v one -F -d lon,128 -d lat,64 %tmp_fl_04%";
-    $dsc_sng="Creating %tmp_fl_03% again (FAILURE netCDF4 ncrename nco821) ";
     $tst_cmd[4]="1";
     $tst_cmd[5]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     @tst_cmd=(); # really reset array.
 
 #ncwa #2
+    $dsc_sng="normalize by denominator upper hemisphere (FAILURE netCDF4 ncrename nco821)";
     push(@tst_cmd, "ncks -h -O $fl_fmt $nco_D_flg -v lat_T42,lon_T42,gw_T42 $in_pth_arg in.nc %tmp_fl_03%");
     push(@tst_cmd, "ncrename -h -O $nco_D_flg -d lat_T42,lat -d lon_T42,lon -v lat_T42,lat -v gw_T42,gw -v lon_T42,lon %tmp_fl_03%");
     push(@tst_cmd, "ncap2 -h -O $fl_fmt $nco_D_flg -s 'one[lat,lon]=lat*lon*0.0+1.0' -s 'zero[lat,lon]=lat*lon*0.0' %tmp_fl_03% %tmp_fl_04%");
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a lat,lon -w gw -d lat,0.0,90.0 %tmp_fl_04% %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%g' -v one %tmp_fl_00%");
-    $dsc_sng="normalize by denominator upper hemisphere (FAILURE netCDF4 ncrename nco821)";
     $prsrv_fl=1; # save previously generated files.
 #	$nsr_xpc= 1;
 # tst_run();
@@ -4054,153 +4000,154 @@ if(0){
 #ncwa #3
 # 20140207: Behavior changed to comply with documentation that coordinate variables always return averages, never extrema or other statistics
 # Hence request for min(lat) should actually return avg(lat) = 0 != -90
+# ncwa -O -y min -v lat ~/nco/data/in.nc ~/foo.nc
+    $dsc_sng="return average coordinate coordinate variable during minimization for non-coordinate variables";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%g' -v lat %tmp_fl_00%";
-    $dsc_sng="return average coordinate coordinate variable during minimization for non-coordinate variables";
     $tst_cmd[2]="0";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #4
+    $dsc_sng="pass through non-averaged (i.e., non-processed) packed data to output";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a time -v pck,one_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%d' -v pck %tmp_fl_00%";
-    $dsc_sng="pass through non-averaged (i.e., non-processed) packed data to output";
     $tst_cmd[2]="1";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #5
+    $dsc_sng="do not normalize by denominator (FAILURE netCDF4 nco946)";
     $tst_cmd[0]="ncwa -N $omp_flg -h -O $fl_fmt $nco_D_flg -a lat,lon -w gw $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v mask %tmp_fl_00%";
-    $dsc_sng="do not normalize by denominator (FAILURE netCDF4 nco946)";
     $tst_cmd[2]="50";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #6
+    $dsc_sng="average with missing value attribute";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a lon -v mss_val $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v mss_val %tmp_fl_00%";
-    $dsc_sng="average with missing value attribute";
     $tst_cmd[2]="73";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #7
+    $dsc_sng="average without missing value attribute";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a lon -v no_mss_val $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%g' -v no_mss_val %tmp_fl_00%";
-    $dsc_sng="average without missing value attribute";
     $tst_cmd[2]="5.0e35";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #8
+    $dsc_sng="average masked coordinate";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lat -m lat -M 90.0 -T eq -a lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v lat %tmp_fl_00%";
-    $dsc_sng="average masked coordinate";
     $tst_cmd[2]="90.0";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #9
+    $dsc_sng="average masked variable";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lat_var -m lat -M 90.0 -T eq -a lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v lat_var %tmp_fl_00%";
-    $dsc_sng="average masked variable";
     $tst_cmd[2]="2.0";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #10
+    $dsc_sng="average masked, weighted coordinate";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev -m lev -M 100.0 -T eq -a lev -w lev_wgt $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v lev %tmp_fl_00%";
-    $dsc_sng="average masked, weighted coordinate";
     $tst_cmd[2]="100.0";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #11
+    $dsc_sng="average masked, weighted variable";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev_var -m lev -M 100.0 -T gt -a lev -w lev_wgt $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v lev_var %tmp_fl_00%";
-    $dsc_sng="average masked, weighted variable";
     $tst_cmd[2]="666.6667";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #12
+    $dsc_sng="weight conforms to variable first time";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lat -a lat -w gw -d lat,0 $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v lat %tmp_fl_00%";
-    $dsc_sng="weight conforms to variable first time";
     $tst_cmd[2]="-90.0";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #13
+    $dsc_sng="average all missing values with weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v mss_val_all -a lon -w lon $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H --no_blank -s '%g' -v mss_val_all %tmp_fl_00%";
-    $dsc_sng="average all missing values with weights";
     $tst_cmd[2]="1.0e36";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #14
+    $dsc_sng="average some missing values with unity weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v val_one_mss -a lat -w wgt_one $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v val_one_mss %tmp_fl_00%";
-    $dsc_sng="average some missing values with unity weights";
     $tst_cmd[2]="1.0";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #15
+    $dsc_sng="average masked variable with some missing values";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v msk_prt_mss_prt -m msk_prt_mss_prt -M 1.0 -T lt -a lon $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v msk_prt_mss_prt %tmp_fl_00%";
-    $dsc_sng="average masked variable with some missing values";
     $tst_cmd[2]="0.5";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #16
+    $dsc_sng="average uniform field with uniform weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -w area -v area -a lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v area %tmp_fl_00%";
-    $dsc_sng="average uniform field with uniform weights";
     $tst_cmd[2]="10";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #17
+    $dsc_sng="average uniform field with asymmetric weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -w area_asm -v area -a lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v area %tmp_fl_00%";
-    $dsc_sng="average uniform field with asymmetric weights";
     $tst_cmd[2]="10";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #18
+    $dsc_sng="average asymmetric field with asymmetric weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -w area_asm -v area2 -a lat $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v area2 %tmp_fl_00%";
-    $dsc_sng="average asymmetric field with asymmetric weights";
     $tst_cmd[2]="10";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #19
+    $dsc_sng="min switch on type double, some missing values";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v rec_var_flt_mss_val_dbl $in_pth_arg in.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%e' -v rec_var_flt_mss_val_dbl %tmp_fl_00%";
-    $dsc_sng="min switch on type double, some missing values";
     $tst_cmd[2]="2";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4208,11 +4155,11 @@ if(0){
 
 #ncwa #20
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction with min switch and missing values";
     @tst_cmd=(); # really reset array. $#tst_cmd=0; sets last index=0 --> list has one element.
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_var_dbl -a lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%f' -v three_dmn_var_dbl -d time,3 -d lat,0 %tmp_fl_00%");
     # used to cut for field 7. (1 + 3x2 + 0x1=7)
-    $dsc_sng="Dimension reduction with min switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4220,10 +4167,10 @@ if(0){
 
 #ncwa #21
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction with min switch";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_var_dbl -a lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%f' -v three_dmn_var_dbl -d time,9 -d lat,1 %tmp_fl_00%");
     # used to cut for field 20. (1 + 9x2 + 1x1 = 20)
-    $dsc_sng="Dimension reduction with min switch";
     $prsrv_fl=1; ## this is not needed anymore-- now independent from prev test-- remove this line soon
     push(@tst_cmd,"77");
     push(@tst_cmd, "SS_OK");
@@ -4232,10 +4179,10 @@ if(0){
 
 #ncwa #22
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type int with min switch and missing values";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_var_int -a lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%d' -v three_dmn_var_int -d time,2 -d lat,0 %tmp_fl_00%");
     # used to cut field 5: (1 + 2x2 + 0x1 = 5) 
-    $dsc_sng="Dimension reduction on type int with min switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4243,10 +4190,10 @@ if(0){
 
 #ncwa #23
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type int variable";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_var_int -a lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%d' -v three_dmn_var_int -d time,3 -d lat,0 %tmp_fl_00%");
     # used to cut field 7: (1 + 3x2 + 0x1 = 7) 
-    $dsc_sng="Dimension reduction on type int variable";
     $prsrv_fl=1;
     push(@tst_cmd, "25");
     push(@tst_cmd, "SS_OK");
@@ -4255,10 +4202,10 @@ if(0){
 
 #ncwa #24
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type short variable with min switch and missing values";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_var_sht -a lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%d' -v three_dmn_var_sht -d time,9 -d lat,1 %tmp_fl_00%");
     # used to cut field 20: (1 + 9x2 + 1x1 = 20) 
-    $dsc_sng="Dimension reduction on type short variable with min switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4266,10 +4213,10 @@ if(0){
 
 #ncwa #25
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type short variable";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_var_sht -a lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%d' -v three_dmn_var_sht -d time,3 -d lat,1 %tmp_fl_00%");
     # used to cut field 8: (1 + 3x2 + 1x1 = 8) 
-    $dsc_sng="Dimension reduction on type short variable";
     $prsrv_fl=1;
     push(@tst_cmd, "29");
     push(@tst_cmd, "SS_OK");
@@ -4277,18 +4224,18 @@ if(0){
     @tst_cmd=(); # Reset array
 
 #ncwa #26
+    $dsc_sng="Dimension reduction with min flag on type float variable";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -v three_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_rec_var %tmp_fl_00%";
-     $dsc_sng="Dimension reduction with min flag on type float variable";
     $tst_cmd[2]="1";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     @tst_cmd=(); # Reset array
 
 #ncwa #27
+    $dsc_sng="Max flag on type float variable";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v four_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v four_dmn_rec_var %tmp_fl_00%";
-    $dsc_sng="Max flag on type float variable";
     $tst_cmd[2]="240";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4297,10 +4244,10 @@ if(0){
 #ncwa #28
 # ncwa -h -O -y max -v three_dmn_var_dbl -a lat,lon in.nc ~/foo.nc
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type double variable with max switch and missing values";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v three_dmn_var_dbl -a lat,lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%f' -v three_dmn_var_dbl -d time,3 %tmp_fl_00%");
     # used to cut field 4: (1 + 3x1=4) 
-    $dsc_sng="Dimension reduction on type double variable with max switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4308,10 +4255,10 @@ if(0){
 
 #ncwa #29
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type double variable";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v three_dmn_var_dbl -a lat,lon $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%f' -v three_dmn_var_dbl -d time,4 %tmp_fl_00%"); 
     # used to cut field 5: (1 + 4x1=5) 
-    $dsc_sng="Dimension reduction on type double variable";
     $prsrv_fl=1;
     push(@tst_cmd, "40");
     push(@tst_cmd, "SS_OK");
@@ -4320,10 +4267,10 @@ if(0){
 
 #ncwa #30
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type int variable with min switch and missing values";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v three_dmn_var_int -a lat $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%d' -v three_dmn_var_int -d time,2 -d lon,0 %tmp_fl_00%");
     # used to cut field 9: (1 + 2x4 + 0x1=9) 
-    $dsc_sng="Dimension reduction on type int variable with min switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4331,10 +4278,10 @@ if(0){
 
 #ncwa #31
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type int variable";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v three_dmn_var_int -a lat $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%d' -v three_dmn_var_int -d time,3 -d lon,0 %tmp_fl_00%");
     # used to cut field 13 = 1 + 3x4 + 0x1
-    $dsc_sng="Dimension reduction on type int variable";
     $prsrv_fl=1;
     push(@tst_cmd, "29");
     push(@tst_cmd, "SS_OK");
@@ -4343,10 +4290,10 @@ if(0){
 
 #ncwa #32
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type short variable with max switch and missing values";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v three_dmn_var_sht -a lat $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%d' -v three_dmn_var_sht -d time,9 -d lon,0 %tmp_fl_00%");
     # used to cut field 37 = 1 + 9x4 + 0x1
-    $dsc_sng="Dimension reduction on type short variable with max switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4354,10 +4301,10 @@ if(0){
 
 #ncwa #33
 # will fail SS - ncks not the last cmd
+    $dsc_sng="Dimension reduction on type short, max switch variable";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -v three_dmn_var_sht -a lat $in_pth_arg in.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%d' -v three_dmn_var_sht -d time,8 -d lon,0 %tmp_fl_00%");
     # used to cut field 33 = 1 + 8x4 + 0x1
-    $dsc_sng="Dimension reduction on type short, max switch variable";
     $prsrv_fl=1;
     push(@tst_cmd, "69");
     push(@tst_cmd, "SS_OK");
@@ -4365,18 +4312,18 @@ if(0){
     @tst_cmd=(); # Reset array
 
 #ncwa #34
+    $dsc_sng="rms with weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y rms -w lat_wgt -v lat_cpy $in_pth_arg in.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v lat_cpy %tmp_fl_00%";;
-    $dsc_sng="rms with weights";
     $tst_cmd[2]="90";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #35
+    $dsc_sng="weights would cause SIGFPE without dbl_prc patch";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -w val_half_half -v val_one_one_int $in_pth_arg in.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%d' -v val_one_one_int %tmp_fl_00%";;
-    $dsc_sng="weights would cause SIGFPE without dbl_prc patch";
     $tst_cmd[2]="1";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4392,9 +4339,9 @@ if(0){
     $#tst_cmd=0; # Reset array
 
 #ncwa #37
+    $dsc_sng="test wrapped ttl with dbl_prc patch (harmless failure expected/OK on all chips since wrap behavior is not IEEE-specified)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y ttl -v val_max_max_sht $in_pth_arg in.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%d' -v val_max_max_sht %tmp_fl_00%";
-    $dsc_sng="test wrapped ttl with dbl_prc patch (harmless failure expected/OK on all chips since wrap behavior is not IEEE-specified)";
 #    $nsr_xpc= -31536 ; # Expected on Pentium IV GCC Debian 3.4.3-13, PowerPC xlc
 #    $nsr_xpc= -32768 ; # Expected on Xeon GCC Fedora 3.4.2-6.fc3
 #    $nsr_xpc= -32768 ; # Expected on Opteron
@@ -4406,54 +4353,54 @@ if(0){
     $#tst_cmd=0; # Reset array
 
 #ncwa #38
+    $dsc_sng="min with weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -a lat -v lat_cpy -w gw $in_pth_arg in.nc %tmp_fl_00%";;
     $tst_cmd[1]="ncks -C -H -s '%g' -v lat_cpy %tmp_fl_00%";;
-    $dsc_sng="min with weights";
     $tst_cmd[2]="-900";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #39
+    $dsc_sng="max with weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -a lat -v lat_cpy -w gw $in_pth_arg in.nc %tmp_fl_00%";;
     $tst_cmd[1]="ncks -C -H -s '%g' -v lat_cpy %tmp_fl_00%";;
-    $dsc_sng="max with weights";
     $tst_cmd[2]="900";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #40
+    $dsc_sng="Return mean time coordinate (when computing totals)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y ttl -a time -w one -v time,one_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%f' -v time %tmp_fl_00%";
-    $dsc_sng="Return mean time coordinate (when computing totals)";
     $tst_cmd[2]="5.5";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 
 #ncwa #41
+    $dsc_sng="Return total record (when computing totals)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y ttl -a time -w one -v time,one_dmn_rec_var $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -s '%d' -v one_dmn_rec_var %tmp_fl_00%";
-    $dsc_sng="Return total record (when computing totals)";
     $tst_cmd[2]="55";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 	
 #ncwa #42
+    $dsc_sng="Retain degenerate dimensions (one variable)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a lon -b -v lon $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v lon %tmp_fl_00%";
-    $dsc_sng="Retain degenerate dimensions (one variable)";
     $tst_cmd[2]="lon[0]=135";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array	
 	
 #ncwa #43
+    $dsc_sng="Retain degenerate dimensions (all variables)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a lon -b  $in_pth_arg in.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -v lon %tmp_fl_00%";
-    $dsc_sng="Retain degenerate dimensions (all variables)";
     $tst_cmd[2]="lon[0]=135";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4474,9 +4421,9 @@ if(0){
 #$tst_cmd[1]="ncks -C -H -s '%f' -v three_dmn_rec_var %tmp_fl_00%";
 #$dsc_sng="Dimension reduction with min flag on type float variable";
 #$tst_cmd[2]="1";
+    $dsc_sng="(Groups) Dimension reduction with min flag on type float variable";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y min -g g10 -v three_dmn_rec_var $in_pth_arg in_grp.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%f' -g g10 -v three_dmn_rec_var %tmp_fl_00%";
-    $dsc_sng="(Groups) Dimension reduction with min flag on type float variable";
     $tst_cmd[2]="1";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4485,13 +4432,13 @@ if(0){
 #ncwa #45
 #NEW NCO 4.3.3
 #same as #ncwa #27
-# ncwa -h -O -y max -g g19g3 -v three_dmn_var_dbl -a lat,lon in_grp_3.nc ~/foo.nc
+# ncwa -O -y max -g g19g3 -v three_dmn_var_dbl -a lat,lon ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -C -H --no_blank -s '%f' -g g19g3 -v three_dmn_var_dbl -d time,3 ~/foo.nc
 # will fail SS - ncks not the last cmd
+    $dsc_sng="(Groups) Dimension reduction on type double variable with max switch and missing values";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -g g19g3 -v three_dmn_var_dbl -a lat,lon $in_pth_arg in_grp_3.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H --no_blank -s '%f' -g g19g3 -v three_dmn_var_dbl -d time,3 %tmp_fl_00%");
     # used to cut field 4: (1 + 3x1=4) 
-    $dsc_sng="(Groups) Dimension reduction on type double variable with max switch and missing values";
     push(@tst_cmd, "-99");
     push(@tst_cmd, "SS_OK");
     NCO_bm::tst_run(\@tst_cmd);
@@ -4500,13 +4447,13 @@ if(0){
 #ncwa #46
 #NEW NCO 4.3.3
 #same as #ncwa #28
-# ncwa -h -O  -y max -g g19g3 -v three_dmn_var_dbl -a lat,lon in_grp_3.nc ~/foo.nc
+# ncwa -h -O  -y max -g g19g3 -v three_dmn_var_dbl -a lat,lon ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -C -H -s '%f' -g g19g3 -v three_dmn_var_dbl -d time,4 ~/foo.nc 
 # will fail SS - ncks not the last cmd
+    $dsc_sng="(Groups) Dimension reduction on type double variable";
     push(@tst_cmd, "ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y max -g g19g3 -v three_dmn_var_dbl -a lat,lon $in_pth_arg in_grp_3.nc %tmp_fl_00%");
     push(@tst_cmd, "ncks -C -H -s '%f' -g g19g3 -v three_dmn_var_dbl -d time,4 %tmp_fl_00%"); 
     # used to cut field 5: (1 + 4x1=5) 
-    $dsc_sng="(Groups) Dimension reduction on type double variable";
     $prsrv_fl=1;
     push(@tst_cmd, "40");
     push(@tst_cmd, "SS_OK");
@@ -4516,11 +4463,11 @@ if(0){
 #ncwa #47
 #NEW NCO 4.3.3
 #same as #ncwa #33
-# ncwa -h -O -y rms -w lat_wgt -g g20g1 -v lat_cpy in_grp_3.nc ~/foo.nc
+# ncwa -h -O -y rms -w lat_wgt -g g20g1 -v lat_cpy ~/nco/data/in_grp_3.nc ~/foo.nc
 # ncks -C -H -s '%f' -g g20g1 -v lat_cpy ~/foo.nc
+    $dsc_sng="(Groups) rms with weights";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -y rms -w lat_wgt -g g20g1 -v lat_cpy $in_pth_arg in_grp_3.nc %tmp_fl_00% 2> %tmp_fl_02%";
     $tst_cmd[1]="ncks -C -H -s '%f' -g g20g1 -v lat_cpy %tmp_fl_00%";;
-    $dsc_sng="(Groups) rms with weights";
     $tst_cmd[2]="90";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4528,34 +4475,34 @@ if(0){
 
 #ncwa #48
 #NEW NCO 4.3.6
-#ncwa -O -w gw_lat -d lat,1,2 -d lon,0,1 -a lat,lon -g g26 in_grp_3.nc ~/foo.nc
+#ncwa -O -w gw_lat -d lat,1,2 -d lon,0,1 -a lat,lon -g g26 ~/nco/data/in_grp_3.nc ~/foo.nc
+    $dsc_sng="(Groups) Weights and hyperslabs";
     $tst_cmd[0]="ncwa $omp_flg -O $fl_fmt $nco_D_flg -w gw_lat -d lat,1,2 -d lon,0,1 -a lat,lon -g g26 $in_pth_arg in_grp_3.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -v a %tmp_fl_00%";;
-    $dsc_sng="(Groups) Weights and hyperslabs";
     $tst_cmd[2]="a = 35.5803";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array
 	
 #ncwa #49
-# ncwa -h -O -v lev -a lev -w lev_wgt in_grp_3.nc ~/foo.nc
+# ncwa -h -O -v lev -a lev -w lev_wgt ~/nco/data/in_grp_3.nc ~/foo.nc
 # lev = 230.769 lev_wgt=10,2,1; /g19/lev
 # lev = 241.667 lev_wgt=9,2,1;  /g8/lev
+    $dsc_sng="(Groups) Weights and groups (relative weight name test 1)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev -a lev -w lev_wgt $in_pth_arg in_grp_3.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -g g8 -v lev %tmp_fl_00%";
-    $dsc_sng="(Groups) Weights and groups (relative weight name test 1)";
     $tst_cmd[2]="lev = 241.667";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
     $#tst_cmd=0; # Reset array	
 	
 #ncwa #50
-# ncwa -h -O -v lev -a lev -w lev_wgt in_grp_3.nc ~/foo.nc
+# ncwa -h -O -v lev -a lev -w lev_wgt ~/nco/data/in_grp_3.nc ~/foo.nc
 # lev = 230.769 lev_wgt=10,2,1; /g19/lev
 # lev = 241.667 lev_wgt=9,2,1;  /g8/lev
+    $dsc_sng="(Groups) Weights and groups (relative weight name test 2)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev -a lev -w lev_wgt $in_pth_arg in_grp_3.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -g g19 -v lev %tmp_fl_00%";
-    $dsc_sng="(Groups) Weights and groups (relative weight name test 2)";
     $tst_cmd[2]="lev = 230.769";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4565,9 +4512,9 @@ if(0){
 #ncwa #51
 # ncwa -h -O -a time -b -v time ~/nco/data/in_grp.nc ~/foo.nc
 # ncks ~/foo.nc | grep 'time dimension 0'
+    $dsc_sng="(Groups) retain degenerate record dimension";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -a time -b -v time $in_pth_arg in_grp.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -H -v /g2/time %tmp_fl_00% | grep '=5.5'";
-    $dsc_sng="(Groups) retain degenerate record dimension";
     $tst_cmd[2]="time[0]=5.5";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4575,12 +4522,12 @@ if(0){
 	
 #NEW 4.4.0	
 #ncwa #52 Use -w /g8/lev_wgt
-# ncwa -h -O -v lev -a lev -w /g8/lev_wgt in_grp_3.nc ~/foo.nc
+# ncwa -h -O -v lev -a lev -w /g8/lev_wgt ~/nco/data/in_grp_3.nc ~/foo.nc
 # lev = 230.769 lev_wgt=10,2,1; /g19/lev
 # lev = 241.667 lev_wgt=9,2,1;  /g8/lev
+    $dsc_sng="(Groups) Weights and groups (absolute weight name -w /g8/lev_wgt test 1)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev -a lev -w /g8/lev_wgt $in_pth_arg in_grp_3.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -g g8 -v lev %tmp_fl_00%";
-    $dsc_sng="(Groups) Weights and groups (absolute weight name -w /g8/lev_wgt test 1)";
     $tst_cmd[2]="lev = 241.667";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4588,12 +4535,12 @@ if(0){
 
 #NEW 4.4.0		
 #ncwa #53 Use -w /g8/lev_wgt
-# ncwa -h -O -v lev -a lev -w /g19/lev_wgt in_grp_3.nc ~/foo.nc
+# ncwa -h -O -v lev -a lev -w /g19/lev_wgt ~/nco/data/in_grp_3.nc ~/foo.nc
 # lev = 230.769 lev_wgt=10,2,1; /g19/lev
 # lev = 241.667 lev_wgt=9,2,1;  /g8/lev
+    $dsc_sng="(Groups) Weights and groups (absolute weight name -w /g19/lev_wgt test 2)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev -a lev -w /g8/lev_wgt $in_pth_arg in_grp_3.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -g g19 -v lev %tmp_fl_00%";
-    $dsc_sng="(Groups) Weights and groups (absolute weight name -w /g19/lev_wgt test 2)";
     $tst_cmd[2]="lev = 241.667";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4602,12 +4549,12 @@ if(0){
 #NEW 4.4.0	
 #ncwa #54 
 #Use -a /g8/lev, -w /g8/lev_wgt
-# ncwa -h -O -v lev -a /g8/lev -w /g8/lev_wgt in_grp_3.nc ~/foo.nc
+# ncwa -h -O -v lev -a /g8/lev -w /g8/lev_wgt ~/nco/data/in_grp_3.nc ~/foo.nc
 # lev = 230.769 lev_wgt=10,2,1; /g19/lev
 # lev = 241.667 lev_wgt=9,2,1;  /g8/lev
+    $dsc_sng="(Groups) Weights and groups (absolute dimension name -a /g8/lev)";
     $tst_cmd[0]="ncwa $omp_flg -h -O $fl_fmt $nco_D_flg -v lev -a /g8/lev -w /g8/lev_wgt $in_pth_arg in_grp_3.nc %tmp_fl_00%";
     $tst_cmd[1]="ncks -C -H -g g8 -v lev %tmp_fl_00%";
-    $dsc_sng="(Groups) Weights and groups (absolute dimension name -a /g8/lev)";
     $tst_cmd[2]="lev = 241.667";
     $tst_cmd[3]="SS_OK";
     NCO_bm::tst_run(\@tst_cmd);
@@ -4650,7 +4597,7 @@ if(0){
 	
 #NEW 4.4.2	
 #ncwa #58
-#ncwa -O -y avg -a time301 -v time301 -C in_grp_3.nc ~/foo.nc
+#ncwa -O -y avg -a time301 -v time301 -C ~/nco/data/in_grp_3.nc ~/foo.nc
 #ncks -m ~/foo.nc
     $dsc_sng="Groups (Cell methods) (Create, average) -y avg -a time -v time";
     $tst_cmd[0]="ncwa $omp_flg $nco_D_flg -O -y avg -a time301 -v time301 -C $in_pth_arg in_grp_3.nc %tmp_fl_00%";
@@ -4662,7 +4609,7 @@ if(0){
 	
 #NEW 4.4.2	
 #ncwa #59
-#ncwa -O -y max -a time301 -v time301 -C in_grp_3.nc ~/foo.nc	  
+#ncwa -O -y max -a time301 -v time301 -C ~/nco/data/in_grp_3.nc ~/foo.nc	  
 #ncks -m ~/foo.nc	
     $dsc_sng="Groups (Cell methods) (Create, maximum) -y max -a time -v time";
     $tst_cmd[0]="ncwa $omp_flg $nco_D_flg -O -y max -a time301 -v time301 -C $in_pth_arg in_grp_3.nc %tmp_fl_00%";
diff --git a/bm/nco_bm.pl b/bm/nco_bm.pl
index b75b801..99f7a22 100755
--- a/bm/nco_bm.pl
+++ b/bm/nco_bm.pl
@@ -209,7 +209,7 @@ if (-e "$ENV{'HOME'}/.ncorc" && -r "$ENV{'HOME'}/.ncorc" && !-z "$ENV{'HOME'}/.n
 	$ln_cnt++;
 	if ($_ !~ /^#/) { # Ignore comments
 	    my $N = my @L = split('=');
-	    chomp $L[1]; # Get rid of \n, if any
+	    chomp $L[1]; # Eliminate \n, if any
 	    if ($N != 2) {print "ERR: typo in ~/.ncorc file on line $ln_cnt.\nFormat is: 'Name=value'\nIgnoring error for now\n";}
 	    $NCO_RC{$L[0]} = $L[1];
 	}
diff --git a/config.h.in b/config.h.in
index d8b7afc..790ce8d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -27,6 +27,9 @@
 /* Define to 1 if libnetcdf.a contains netCDF4 functions */
 #undef ENABLE_NETCDF4
 
+/* Compile operators with OpenMP support */
+#undef ENABLE_OPENMP
+
 /* Fastest possible execution (slowest compilation) */
 #undef ENABLE_OPTIMIZE_CUSTOM
 
diff --git a/configure b/configure
index 0fd4137..2ce4e5f 100755
--- a/configure
+++ b/configure
@@ -1490,8 +1490,8 @@ Optional Features:
                           enable-netcdf-4) [[default=yes]]
   --enable-netcdf-4       Enable netCDF Version 4 features (same as
                           enable-netcdf4) [[default=yes]]
-  --disable-openmp        do not use OpenMP
   --enable-openmp         Build NCO with OpenMP [[default=yes]]
+  --disable-openmp        do not use OpenMP
   --enable-dap            Build DAP-enabled NCO with netCDF-provided DAP
                           [[default=yes]]
   --enable-ncoxx          Build libnco++ and ncap2 (same as enable-ncap2)
@@ -17809,6 +17809,15 @@ fi
 fi
 
 # Begin OpenMP
+# Check whether --enable-openmp was given.
+if test "${enable_openmp+set}" = set; then :
+  enableval=$enable_openmp; enable_openmp=${enableval}
+else
+  enable_openmp=yes
+fi
+
+# Enable OpenMP unless told not to
+if ((test "x${enable_openmp}" != 'xno') && (test "x${enable_netcdf4}" = 'xyes')); then
 
   OPENMP_CFLAGS=
   # Check whether --enable-openmp was given.
@@ -17876,15 +17885,11 @@ $as_echo "$ac_cv_prog_c_openmp" >&6; }
 
 
 
-# Check whether --enable-openmp was given.
-if test "${enable_openmp+set}" = set; then :
-  enableval=$enable_openmp; enable_openmp=${enableval}
-else
-  enable_openmp=yes
-fi
 
-# Enable OpenMP unless told not to
-if ((test "${enable_openmp}" != 'no') && (test "${enable_netcdf4}" = 'xyes')); then
+$as_echo "#define ENABLE_OPENMP 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: OpenMP support enabled" >&5
+$as_echo "$as_me: OpenMP support enabled" >&6;}
     CFLAGS="${CFLAGS} ${OPENMP_CFLAGS}"
 fi
 # End OpenMP
@@ -20242,7 +20247,9 @@ case ${host} in
 	case ${CC} in
 	    como* ) CFLAGS="${CFLAGS} --c99" ; ;;
 # 20150109: fxm Introduce -D_DEFAULT_SOURCE in place of deprecated (as of gcc 4.9.2) -D_BSD_SOURCE -D_POSIX_SOURCE
-	    icc* ) CFLAGS="${CFLAGS} -std=c99" ; CPPFLAGS="${CPPFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE -no-gcc" ; ;;
+# 20150525: fxm Remove -no-gcc from icc flags as per ocehugo
+#	    icc* ) CFLAGS="${CFLAGS} -std=c99" ; CPPFLAGS="${CPPFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE -no-gcc" ; ;;
+	    icc* ) CFLAGS="${CFLAGS} -std=c99" ; CPPFLAGS="${CPPFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE" ; ;;
 	    pathcc* ) CFLAGS="${CFLAGS} -std=c99" ; ;;
 	    pgcc* ) CFLAGS="${CFLAGS} -c9x" ; CPPFLAGS="${CPPFLAGS} -DPGI_CC" ; ;;
 	esac
@@ -23532,6 +23539,7 @@ echo "ENABLE_DAP........... ${enable_dap}"
 echo "ENABLE_ESMF...........${enable_esmf}"
 echo "ENABLE_GSL........... ${enable_gsl}"
 echo "ENABLE_NETCDF4....... ${enable_netcdf4}"
+echo "ENABLE_OPENMP........ ${enable_openmp}"
 echo "ENABLE_UDUNITS....... ${enable_udunits}"
 echo "ENABLE_UDUNITS2...... ${enable_udunits2}"
 echo "GSL_ROOT............. ${GSL_ROOT}"
diff --git a/configure.ac b/configure.ac
index ea2bd98..2f7408f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -304,11 +304,13 @@ if (test "x${enable_netcdf4}" = 'xyes' && test "x${header_defines_nc_chunked}" =
 fi
 
 # Begin OpenMP
-AC_OPENMP
-AC_SUBST(OPENMP_CFLAGS)
 AC_ARG_ENABLE(openmp,AS_HELP_STRING([--enable-openmp],[Build NCO with OpenMP [[default=yes]]]),enable_openmp=${enableval},enable_openmp=yes)
 # Enable OpenMP unless told not to
-if ((test "${enable_openmp}" != 'no') && (test "${enable_netcdf4}" = 'xyes')); then
+if ((test "x${enable_openmp}" != 'xno') && (test "x${enable_netcdf4}" = 'xyes')); then
+    AC_OPENMP
+    AC_SUBST(OPENMP_CFLAGS)
+    AC_DEFINE([ENABLE_OPENMP],[1],[Compile operators with OpenMP support])
+    AC_MSG_NOTICE([OpenMP support enabled])
     CFLAGS="${CFLAGS} ${OPENMP_CFLAGS}"
 fi
 # End OpenMP
@@ -790,7 +792,9 @@ case ${host} in
 	case ${CC} in
 	    como* ) CFLAGS="${CFLAGS} --c99" ; ;;
 # 20150109: fxm Introduce -D_DEFAULT_SOURCE in place of deprecated (as of gcc 4.9.2) -D_BSD_SOURCE -D_POSIX_SOURCE 
-	    icc* ) CFLAGS="${CFLAGS} -std=c99" ; CPPFLAGS="${CPPFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE -no-gcc" ; ;;
+# 20150525: fxm Remove -no-gcc from icc flags as per ocehugo
+#	    icc* ) CFLAGS="${CFLAGS} -std=c99" ; CPPFLAGS="${CPPFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE -no-gcc" ; ;;
+	    icc* ) CFLAGS="${CFLAGS} -std=c99" ; CPPFLAGS="${CPPFLAGS} -D_BSD_SOURCE -D_POSIX_SOURCE" ; ;;
 	    pathcc* ) CFLAGS="${CFLAGS} -std=c99" ; ;;
 	    pgcc* ) CFLAGS="${CFLAGS} -c9x" ; CPPFLAGS="${CPPFLAGS} -DPGI_CC" ; ;;
 	esac
@@ -1229,6 +1233,7 @@ echo "ENABLE_DAP........... ${enable_dap}"
 echo "ENABLE_ESMF...........${enable_esmf}"
 echo "ENABLE_GSL........... ${enable_gsl}"
 echo "ENABLE_NETCDF4....... ${enable_netcdf4}"
+echo "ENABLE_OPENMP........ ${enable_openmp}"
 echo "ENABLE_UDUNITS....... ${enable_udunits}"
 echo "ENABLE_UDUNITS2...... ${enable_udunits2}"
 echo "GSL_ROOT............. ${GSL_ROOT}"
diff --git a/configure.eg b/configure.eg
index cef9655..0252c36 100644
--- a/configure.eg
+++ b/configure.eg
@@ -266,7 +266,7 @@ module avail
 module add intel gsl
 export LD_LIBRARY_PATH='/sw/redhat6/netcdf/4.1.3/rhel6.4_intel13.1.3/lib:/sw/redhat6/szip/2.1/rhel6.6_gnu4.8.2/lib':${LD_LIBRARY_PATH}
 export NETCDF_ROOT='/sw/redhat6/netcdf/4.1.3/rhel6.4_intel13.1.3' 
-cd ~/nco/bld;make ANTLR_ROOT=${HOME} NETCDF_ROOT='/sw/redhat6/netcdf/4.1.3/rhel6.4_intel13.1.3' SZ=Y SZ_LIB='/sw/redhat6/szip/2.1/rhel6.6_gnu4.8.2/lib' UDUNITS_INC='/sw/redhat6/udunits/2.1.24/rhel6.4_intel13.1.3/include' UDUNITS_LIB='/sw/redhat6/udunits/2.1.24/rhel6.4_intel13.1.3/lib' OPTS=D allinone;cd -
+cd ~/nco/bld;make ANTLR_ROOT=${HOME} NETCDF_ROOT='/sw/redhat6/netcdf/4.1.3/rhel6.4_intel13.1.3' SZ=Y SZ_LIB='/sw/redhat6/szip/2.1/rhel6.6_gnu4.8.2/lib' UDUNITS_INC='/sw/redhat6/udunits/2.1.24/rhel6.4_intel13.1.3/include' UDUNITS_LIB='/sw/redhat6/udunits/2.1.24/rhel6.4_intel13.1.3/lib' OPTS=D OMP=Y allinone;cd -
 
 # Commands used for Configure builds
 module add intel gsl netcdf
diff --git a/data/in.cdl b/data/in.cdl
index 6bd774b..0b6d2a7 100644
--- a/data/in.cdl
+++ b/data/in.cdl
@@ -65,10 +65,11 @@ netcdf in {
 dimensions:
   dgn=1,bnd=2,lat=2,lat_grd=3,lev=3,rlev=3,lon=4,lon_grd=5,char_dmn_lng80=80,char_dmn_lng26=26,char_dmn_lng04=4,date_dmn=5,fl_dmn=3,lsmlev=6,wvl=2,time_udunits=3;lon_T42=128,lat_T42=64,lat_times_lon=8,gds_crd=8,gds_ncd=8,vrt_nbr=2,lon_cal=10,lat_cal=10,Lon=4,Lat=2,time=unlimited;
 variables:
-	:Conventions = "CF-1.0";
-	:history = "History global attribute.\nAttributes like this often have embedded newlines to enhance legibility.\nSuch newlines should serve as linebreaks on the screen, hence,\nfriendly CDL converters print a single NC_CHAR attribute as a comma-separated list of strings\nwhere each embedded delimiter marks a linebreak.\nOtherwise it would be harder for humans to read the CDL.";
-	:julian_day = 200000.04;
-	:RCS_Header = "$Header$";
+  :Conventions = "CF-1.5";
+  :history = "History global attribute.\nTextual attributes like history often have embedded newlines like this.\nSuch newlines should serve as linebreaks on the screen to enhance legibility like this.\nFriendly CDL converters print a single NC_CHAR attribute as a comma-separated list of strings where each embedded delimiter marks a linebreak.\nThis makes poetry embedded in CDL much nicer to read:\nA POET by Hafiz\n\nA poet is someone\nWho can pour light into a cup,\nThen raise it to nou [...]
+  :lorem_ipsum = "The Lorem Ipsum attribute demonstrates the legibility of text without embedded linebreaks:\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lady Gaga amat indueris vestimento laetus. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Exce [...]
+  :julian_day = 200000.04;
+  :RCS_Header = "$Header$";
 
 	int date_int(date_dmn);
 	date_int:long_name = "Date (as array of ints: YYYY,MM,DD,HH,MM)";
@@ -1712,7 +1713,7 @@ data:
 				0.5,0.5,0.5,0.5,0.5,0.5,0.5,-999,
 				0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
 				0.5,0.5,2.5,0.5,0.5,2.5,0.5,0.5;
-}
+} // end netcdf
 
 
 
diff --git a/debian/changelog b/debian/changelog
index 35067cf..22525f6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,8 @@
 nco (4.5.0-1) unstable; urgency=low
 
-  * new upstream version (fxm)
+  * new upstream version --map, --rnr=wgt, -A provenance, [date/time]_written, ncdismember
 
- -- Charlie Zender <zender at uci.edu>  Thu, 21 Jun 2014 12:25:08 -0700
+ -- Charlie Zender <zender at uci.edu>  Thu, 11 Jun 2014 12:25:08 -0700
 
 nco (4.4.9-1) unstable; urgency=low
 
diff --git a/doc/ANNOUNCE b/doc/ANNOUNCE
index 07351b2..2ac29db 100644
--- a/doc/ANNOUNCE
+++ b/doc/ANNOUNCE
@@ -5,105 +5,84 @@ The netCDF Operators NCO version 4.5.0 are ready.
 http://nco.sf.net (Homepage)
 http://dust.ess.uci.edu/nco (Homepage "mirror")
 
-This release includes small feature improvements in chunking,
-deflation, and attribute handling during dimension reduction.
-Also improvements in clarity and consistency of messages.
-While chunking is an esoteric feature for many, its importance
-is increasing as the move to netCDF4 (classic) continues.
-The chunking defaults and flexibility have reached a new level
-of robustness in this release. 
-
-The main new awesome feature is that ncra understands weights.
-Finally. Applying uneven weights to different input files was
-too clunky. This release is dedicated to the intrepid souls who
-use NCO to generate climatologies that require uneven weights. 
-This release should make that task much easier.
-
-Work on NCO 4.5.0 has commenced and will support regridding, 
-additional ncra flexibility with weights, and easier builds on
-supercomputer systems that use modules. 
+This is the first NCO release that supports regridding datasets,
+currently limited to global datasets. These features build on
+infrastructure pioneered by Phil Jones (SCRIP), and the multi-agency
+Earth System Modeling Framework (ESMF). 
+
+Work on NCO 4.5.1 has commenced and will support more regridding, 
+additional ncra flexibility with weights, better threading, and easier
+builds on supercomputer systems that use modules. 
 
 Enjoy,
 Charlie
 
 NEW FEATURES (full details always in ChangeLog):
 
-A. NCO has improved default performance of deflation and chunking.
-   Our "best practices" chunking (map/policy=nco) is now default when 
-   manually deflating netCDF3 files into netCDF4 files.
-   This invokes Rew's balanced chunking for three-dimensional
-   variables, and LeFter-Product (cnk_map=lfp) chunking for others. 
-   LFP chunking, in turn, implements more reasonable defaults when
-   the variable size is smaller than a single chunksize.
-   This reduces excessive chunk sizes for many small variables.
-   Shuffle is now turned-on by default when manually deflating files.
-   This restores behavior from the NCO 4.3.x series, and can improve
-   compression ratios by 10-30% relative to not shuffling.
-   Copying multi-dimensional record variables from netCDF3 to netCDF4 
-   files no longer invokes the MM3 workaround.
-   This speeds-up deflation of netCDF3 datasets.
-   ncks -O -4 -L 1 netCDF3.nc netCDF4.nc
-   http://nco.sf.net/nco.html#cnk
-
-B. ncwa now eliminates dimensions from the "coordinates" attribute
-   after collapsing them. This helps ensure that rank-reduced
-   variables become completely independent from their former
-   dimensions. The former presence of collapsed dimensions continues
-   to be indicated by the "cell_methods" attribute.
-   ncwa -O -a lat in.nc out.nc
-   http://nco.sf.net/nco.html#coordinates
-   http://nco.sf.net/nco.html#cell_methods
-   http://nco.sf.net/nco.html#ncwa
-
-C. NCO now warns users and suggest workarounds in situations when
-   operators behave correctly, though perhaps not as expected,
-   including:
-   1. When coordinate variables intended to be excluded by -x and -C
-      may nonetheless appear in output file, and suggest workaround
-   2. When hyperslabs are specified for multi-dimensional
-      "coordinates"  
-
-D. NCO now respects the CF "climatology" attribute: The variable
-   pointed to by this attribute is treated as a pseudo-coordinate
-   variable, and is extracted by default with any referring variable.
-   Climatology variables now obey the same arithmetic rules as
-   coordinates and are exempted from certain operations.
-   Their treatment is identical to that of "bounds" variables.
-   This command now retrieves the named variable, its coordinates (if
-   any), and any variables named in the "ancillary_variable",
-   "bounds", "climatology", and "coordinates" attributes:
-   ncks -v temperature in.nc out.nc
-   http://nco.sf.net/nco.html#climatology
-
-E. ncra now accepts user-specified weights with the -w switch.
-   When no weight is specified, ncra continues its old behavior
-   and weights each record (e.g., time slice) equally.
-   Weights specified with -w wgt may take one of two forms.
-   Fist, the wgt argument may be a comma-separated list of values by
-   which to weight each input file. Or, the wgt argument may be
-   the name of a weighting variable present in every input file.
-   The variable may be a scalar or a one-dimensional record variable. 
-   Scalar weights are applied uniformly to the entire file (i.e., a 
-   per-file weight), while one-dimensional weights apply to each
-   corresponding record (i.e., per-record weights). Two applications
-   of weights with ncra include easier generation of accurate averages
-   of seasonal statistics, and of accurate averages of quantities
-   sampled with a dynamically changing timestep.
-   ncra -w 31,31,28 dec.nc jan.nc feb.nc out.nc 
-   ncra -w delta_tm in1.nc in2.nc in3.nc out.nc 
-   http://nco.sf.net/nco.html#ncra
-
+A. Regrid global datasets with ESMF or SCRIP remap files.
+   Given a map-file that contains source-to-destination grid weights,
+   ncks will regrid and input file to the destination grid.
+   Acceptable file formats for map-files are described here:
+   http://www.earthsystemcog.org/projects/regridweightgen
+   http://oceans11.lanl.gov/svn/SCRIP/trunk/SCRIP
+   ncks supports 1D->1D, 1D->2D, 2D->1D, and 2D->2D regridding for any
+   unstructured 1D grid and any rectangular 2D grid. It has been
+   tested converting among and between Gaussian, equiangular, FV, and
+   unstructured cubed-sphere grids. Support for irregular 2D and
+   regional grids (e.g., swath-like data) is planned. ncks
+   automatically annotates the output with relevant metadata such as
+   coordinate bounds, axes, and vertices (à la CF). When used with an
+   identity remapping files, this feature can signficantly improve the
+   metadata and usability of the original dataset.
+   # Regrid entire file, same output format as input:
+   ncks --map=map.nc in.nc out.nc
+   # Deflated netCDF4 output, threading, selected variables:
+   ncks -4 -L 1 -t 8 -v FS.?,T --map=map.nc in.nc out.nc
+   http://nco.sf.net/nco.html#regrid
+
+B. ncdismember is a one-stop shop for flattening and CF-checking.
+   When specifically requested, or when it cannot find a local
+   cfchecker command, ncdismember will now upload each file (or,
+   in the case of netCDF4 hierarchical files, each group) to the NERC
+   CF compliance-checker, print the report summary, and save the full
+   HTML reports for viewing after Orange is the New Black is over. 
+   Previously, ncdismember required a local cfchecker command to check
+   files, though few users have managed to install a cfchecker.
+   This need is obviated by automatic uploads to the NERC web service.
+   To conserve bandwidth, ncdismember first "smallifies" the data file
+   by hyperslabbing the dataset into a single element of latitude,
+   longitude, and time---only then does it upload. Thanks to Phil
+   Rasch for this idea and sample code.
+   Using no checker, default (Decker) checker, NERC checker:
+   ncdismember ~/nco/data/mdl_1.nc /tmp
+   ncdismember ~/nco/data/mdl_1.nc /tmp decker
+   ncdismember ~/nco/data/mdl_1.nc /tmp nerc
+   http://nco.sf.net/nco.html#ncdismember
+
+C. NCO introduces a convention to retain the history-attribute
+   contents of all files that were appended to a file. This convention  
+   stores those contents in the new global attribute called
+   history_of_appended_files. This complements the history-attribute
+   to provide a more complete provenance. The optional -h switch
+   turns-off this behavior.
+   http://nco.sf.net/nco.html#history
+
+D. When copying the variables date_written or time_written to the
+   output file, NCO now updates their contents the GMT time reported
+   by the system-supplied gmtime().
+   http://nco.sf.net/nco.html#cnv_acme
+   
 BUG FIXES:
 
-A. Fix ncecat in group aggregation mode (i.e., ncecat --gag) so it
-   can no longer use uninitialized file pointers. 
+A. Fix ncatted so it preserves global attributes (including history) 
+   from the output file when in append (-A) mode.
 
 KNOWN PROBLEMS DUE TO NCO:
 
    This section of ANNOUNCE reports and reminds users of the
    existence and severity of known, not yet fixed, problems. 
    These problems occur with NCO 4.5.0 built/tested with netCDF
-   4.3.3-rc3 (20150129) on top of HDF5 hdf5-1.8.13 with:
+   4.4.0-rc1 (20150610) on top of HDF5 hdf5-1.8.13 with:
 
    cd ~/nco;./configure # Configure mechanism -or-
    cd ~/nco/bld;make dir;make allinone # Old Makefile mechanism
diff --git a/doc/ChangeLog b/doc/ChangeLog
index f52ea4a..24cd959 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,19 +1,257 @@
-2015-05-22  Charlie Zender  <zender at uci.edu>
+2015-06-11  Charlie Zender  <zender at uci.edu>
 
 	* NCO 4.5.0 release procedure:
- 	Changes since nco-4.4.9: fxm
-	cd ~/nco;git commit -a -m "Version 4.5.0 release: "
+ 	Changes since nco-4.4.9: --map, --rnr=wgt, -A provenance, [date/time]_written, ncdismember
+	cd ~/nco;git commit -a -m 'Version 4.5.0 release final changes'
 	git tag -d 4.5.0;git push origin :refs/tags/4.5.0
-	git tag -a 4.5.0 -m 'Version 4.5.0: ';git push --tags
+	git tag -a 4.5.0 -m 'Version 4.5.0: Even Keel';git push --tags
+
+	* Always cast latitudes to float before diagnosing grid type to	avoid failures with strangely-off grids
+
+2015-06-10  Charlie Zender  <zender at uci.edu>
+
+	* Make renormalize algorithm consider number of valid inputs when wgt_thr = 0.0, weight of valid inputs when wgt_thr > 0.0.
+
+	* Reduce thr_nbr_max_fsh from 8 to 1 for ncwa stability with 4.5.0 release
+
+	* Verify OpenMP with ncwa is flaky
+
+	* Add nco_open_mem() prototype introduced in netCDF 4.4.0-rc1
+
+	* NCO 4.5.0-beta9 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta9 final changes'
+	git tag -a 4.5.0-beta9 -m 'Version 4.5.0-beta9 tag: --rnr, kvm clean-up, date_written/time_written handling';git push --tags
+
+	* Complete --rnr/--rgr_rnr/--renormalization implementation
+
+2015-06-09  Charlie Zender  <zender at uci.edu>
+
+	* Implement infrastructure to renormalize destinations affected by missing values
+
+	* Remove extraneous last character from history_of_appended_files
+
+	* Do not attempt date_written/time_written update when var_sz != 8
+
+	* Fix buffer overwrite in nco_xcp_prc(), and double-free caused by nco_rgr()
+
+	* Allow allow all grid dimension/variable names to be command-line specified
+
+	* Re-do rgr_nfo creation and destruction routines to facilitate	kvm arguments
+
+	* Fix kvm infrastructure
+
+2015-06-08  Charlie Zender  <zender at uci.edu>
+
+	* Update time-stamps of date_written, time_written during all output
+
+	* Document regridding
+
+	* Change time-stamp update from localtime() to gmtime()
+
+	* Broke kvm infrastructure by simplifying nco_sng2kvm() prototype
+
+2015-06-06  Charlie Zender  <zender at uci.edu>
+
+	* Update time-stamps of date_written, time_written during regridding
+
+2015-06-04  Charlie Zender  <zender at uci.edu>
+
+	* NCO 4.5.0-beta8 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta8 final changes'
+	git tag -a 4.5.0-beta8 -m 'Version 4.5.0-beta8 tag: history_of_appended_files';git push --tags
+
+	* Add history_of_appended_files global attribute to improve provenance
+
+2015-06-03  Charlie Zender  <zender at uci.edu>
+
+	* NCO 4.5.0-beta7 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta7 final changes'
+	git tag -a 4.5.0-beta7 -m 'Version 4.5.0-beta7 tag: Supports 1D->1D, 1D->2D, 2D->1D, and 2D->2D regridding for any unstructured 1D grid and any rectangular 2D grid';git push --tags
+
+	* Write coordinates attribute after all others, fix lat metadata
+
+	* Do second sweep for associated CF variables when creating extraction list
+
+	* Correct bounds names to vertices for 1D output grids
+
+	* Verified ne30->ne120 works and perfectly conserves FSNT
+
+	* Verified fv129x256->fv257x512 works and perfectly conserves FSNT
+
+	* Complete grid description and metadata decoration for 2D->2D mappings
+
+	* Annotate lat and lon variables with "axis = X/Y" attributes
+
+	* Annotate variables with "coordinates" attribute for auxiliary coordinate variables lat and lon
+
+	* Complete grid description for 2D->1D remappings, use nv and vertices instead of nbnd and bounds
+
+2015-06-02  Charlie Zender  <zender at uci.edu>
+
+	* Dogfood?
+
+	* NCO 4.5.0-beta6 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta6 final changes'
+	git tag -a 4.5.0-beta6 -m 'Version 4.5.0-beta6 tag: Gaussian and equiangular offset grids';git push --tags
+
+	* Verified ne30->T42 works and conserves perfectly
+
+	* Gaussian grid diagnosis works
+
+	* Fix numerical bugs in nco_lat_wgt_gss(): fabs() != abs()
+
+2015-06-01  Charlie Zender  <zender at uci.edu>
+
+	* Reverse latitudes and weight generated for Gaussian grids from N->S to S->N
+
+2015-05-31  Charlie Zender  <zender at uci.edu>
+
+	* Add Gaussian grid detection and required functions nco_lat_wgt_gss() and nco_bsl_zero()
+
+	* Improve ncdismember documentation
+
+	* Fuzzy test for latitude weight normalization
+
+	* Move bitmask() and around() routines from nco_var_rth.[ch] to nco_ppc.[ch]
+
+	* Infrastructure for detecting correct type of latitude grid
+
+2015-05-30  Charlie Zender  <zender at uci.edu>
+
+	* Clarify Conventions warnings
+
+	* Activate OpenMP on ncwa, thr_nbr_max=8
+
+	* Diagnose input and output grid sizes and conversion type for dogfood logic
+
+	* Activate OpenMP in autoconf/configure NCO builds (clang does not yet support OpenMP)
+
+	* Verified that regridding works on MACOSX---ne30 ~5x faster on aerosol than roulee
+
+2015-05-29  Charlie Zender  <zender at uci.edu>
+
+	* Document threading
+
+	* NCO 4.5.0-beta5 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta5 final changes'
+	git tag -a 4.5.0-beta5 -m 'Version 4.5.0-beta5 tag: OpenMP and area cell_methods';git push --tags
+
+	* Verified threading works with netCDF4 output with netCDF 4.3.3.1 (rhea has 4.1.3)
+
+	* Use firstprivate(tally) and now multiple threads work (exactly) on roulee
+
+	* Added regrid report to summarize variables regridded, copied,	omitted, created
+
+	* Demonstrated that four threads can produce exactly correct answers
+
+	* Allow up to eight threads for ncks only
+
+	* All regressions still pass but only one-thread used
+
+	* Clean-up threading in ncks.c and nco_rgr()
+
+	* Carry per-thread file IDs in trv_tbl
+
+2015-05-28  Charlie Zender  <zender at uci.edu>
+
+	* Surprisingly, all regressions still pass. Probably because thr_nbr is prescribed to be one :)
+
+	* Update ncra OpenMP threading infrastructure to compile
+
+	* Add OpenMP threading infrastructure to ncks and nco_rgr() in specific
+
+	* Add cell_methods = sum attribute to area variable during regridding
+
+	* NCO 4.5.0-beta4 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta4: final changes'
+	git tag -a 4.5.0-beta4 -m 'Version 4.5.0-beta4: Deprecate missing value warning. Fix cnk_map_xst handling.';git push --tags
+
+	* Fix typo bug in nco_cnk_ini() reported by ocehugo. Caused existing chunk maps to be ignored.
+
+	* NCO 4.5.0-beta3 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta3: final changes'
+	git tag -a 4.5.0-beta3 -m 'Version 4.5.0-beta3: Missing values work. Fix gw bug in beta2.';git push --tags
+
+	* Fix gw problem introduced in beta2
+
+2015-05-27  Charlie Zender  <zender at uci.edu>
+
+	* Handle missing values in regridding. Be liberal: Any valid input points make valid output
+
+	* NCO 4.5.0-beta2 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta2: final changes'
+	git tag -a 4.5.0-beta2 -m 'Version 4.5.0-beta2: Correct output grid bounds, precision';git push --tags
+
+	* Fix output grid bounds (internal bounds were stored with weird memory layout that did not write to disk as expected)
+
+	* Change dgr2rdn from float (oops!) to double to prevent precision loss
+
+	* NCO 4.5.0-beta1 release procedure:
+	cd ~/nco;git commit -a -m 'Version 4.5.0-beta1: final changes'
+	git tag -a 4.5.0-beta1 -m 'Version 4.5.0-beta1: Correct area output variable';git push --tags
+
+	* Read and output area variable directly from remap file rather than regridding it
+
+2015-05-25  Charlie Zender  <zender at uci.edu>
+
+	* NCO 4.5.0-alpha1 release procedure:
+ 	Changes since nco-4.4.9: --map
+	cd ~/nco;git commit -a -m 'Version 4.5.0-alpha1: final changes'
+	git tag -d 4.5.0-alpha1;git push origin :refs/tags/4.5.0-alpha1
+	git tag -a 4.5.0-alpha1 -m 'Version 4.5.0-alpha1: Regridding with external mapfile';git push --tags
+
+	* Reorganize global attribute writing, catenate history attribute
+
+	* Verified NCO gives identical results as Taylor/Truesdale NCL script for 2-D & 3-D variables
+
+	* Handle lefter aka leftmost aka vertical and time dimensions in regridding
+
+	* Optimize row/column access by pre-subtracting one to account for Fortran index offset relative to C
+
+	* Clean-up debugging output
+
+	* Skip date_written and time_written variables when regridding
+
+	* Document (sort of) --map, --rgr_map
+
+	* Re-plumb I/O to regrid straight to fl_out (ignore --rgr_out)
+
+	* Add NCO version to global metadata of regridding
+
+	* Exempt /lat and /lon from regridding
+
+	* Regridding appears to work for 2D variables! Yay!
+
+	* Weight variables and copy values to regridded file
+
+2015-05-24  Charlie Zender  <zender at uci.edu>
+
+	* Define regridded-variables in and copy their metadata to regridded file
+
+	* Copy global and fixed-variable metadata to regridded file
+
+	* Define fixed-variables in and copy their data to regridded file
+
+	* Set new flg_rgr for input variables that contain "ncol" dimension
+
+	* Complete grid metadata for output file
+
+	* Add equi-angle latitude weights (also named "gw") to nco_rgr_map()
+
+	* Add nco_vrs_att_cat() to all operators (was only in ncks, ncbo)
+
+2015-05-22  Charlie Zender  <zender at uci.edu>
+
+	* Output destination grid and coordinate metadata looks good in nco_rgr_map()
 
-	* Undo crippling of ncra --wgt wgt_nm for further debugging
+	* Bump to 4.5.0-alpha1. Undo crippling of ncra --wgt wgt_nm for further debugging
 
 	* NCO 4.4.9 release procedure:
  	Changes since nco-4.4.8: git, -x warn, crd att, cnk nco lfp, shuffle on, MM3->MM4 off, ncecat fix, climatology, ncra wgt
 	cd ~/nco;git commit -a -m "Version 4.4.9 release: "
 	git tag -d nco-4.4.9;git push origin :refs/tags/nco-4.4.9
 	git tag -d 4.4.9;git push origin :refs/tags/4.4.9
-	git tag -a 4.4.9 -m 'Version 4.4.9: ';git push --tags
+	git tag -a 4.4.9 -m 'Version 4.4.9: Final Release';git push --tags
 
 	* Cripple ncra. Re-tag. Re-release with new tag format so GitHub tarball naming conventions work.
 
diff --git a/doc/MANIFEST b/doc/MANIFEST
index 24ec183..a0a2065 100644
--- a/doc/MANIFEST
+++ b/doc/MANIFEST
@@ -30,7 +30,10 @@ libtool(v)
 Makefile	Top-level Makefile created by configure from Makefile.in
 Makefile.am	NCO directory structure used by automake to create Makefile.in
 Makefile.in	Makefile template created from Makefile.am by automake and used by autoconf
+README.md	GitHub Repository description in markdown format
 stamp-h1(v)	Time-stamp
+.gitignore	Git ignore
+.travis.yml	Travis automated test-builds
 
 Top-level directories:
 nco/autobld	Files related to and used by autotools: autoconf/automake/autolib
diff --git a/doc/index.shtml b/doc/index.shtml
index 5a7313c..e585148 100644
--- a/doc/index.shtml
+++ b/doc/index.shtml
@@ -149,8 +149,9 @@ and
 <h2>Recent Releases & Milestones</h2>
 
 <ul>
-<li>2015 Jun ??: 4.5.0 (<i>In progress</i>)
-<li>2015 May 21: 4.5.0 (<tt>ncra</tt> weights)
+<li>2015 Jul ??: 4.5.1 (<i>In progress</i>)
+<li>2015 Jun 11: 4.5.0 (Regridding)
+<li>2015 May 21: 4.4.9 (<tt>ncra</tt> weights)
 <li>2015 Feb 16: 4.4.8 (Precision-preserving Compression)
 <li>2014 Dec 15: DOE ACME <a href="#prp_acme">project</a> commences</li>
 <li>2014 Nov 26: 4.4.7 (Chunking features)
@@ -658,18 +659,22 @@ Stable releases receive unique tags and their tarballs are stored
 <a href="http://nco.sf.net/src">here</a> on SourceForge and
 <a href="https://github.com/czender/nco/releases">here</a> at GitHub.
 You may also retrieve the source of tagged versions directly
-<a name="#Source">with <tt>git clone -b "nco-4.5.0" http://github.com/czender/nco.git nco-4.5.0</tt></a>.
+<a name="#Source">with <tt>git clone -b 4.5.0 http://github.com/czender/nco.git nco-4.5.0</tt></a>.
 <ul>
-<li><b>NCO 4.5.1</b>: (<i>Future</i>) 
+<li><b>NCO 4.5.2</b>: (<i>Future</i>) 
 <tt>ncks</tt> prints human-legible ISO8601 dates;
 <a href="http://nco.sf.net/nco.html#cnk">Chunking</a> bytes not elements, caching;
 extensive hashing?;
 netCDF4 compound types?;
 Optimize diskless files?;</li>
-<li><b>NCO 4.5.0</b>: (<i>In Progress, features completed or being worked on include</i>)
-<tt>ncra</tt> weights with </tt>--wgt wgt_nm</tt>;
-Regridding;</li>
-<li><b>NCO 4.4.9</b>: (<i>Current Stable Release</i>)
+<li><b>NCO 4.5.1</b>: (<i>In Progress, features completed or being worked on include</i>)
+<tt>ncra</tt> weights with </tt>--wgt wgt_nm</tt>;</li>
+<li><b>NCO 4.5.0</b>: (<i>Current Stable Release</i>)
+Regridding with <tt>ncks --map</tt>;
+<tt>date/time_written</tt> updates;
+<tt>history</tt> provenance with <tt>-A</tt> (append-mode);
+<tt>ncdismember</tt> uploads to NERC;</li>
+<li><b>NCO 4.4.9</b>: 
 Output chunking map/policy nco/nco = rew/all is default for netCDF3 input;
 Turn-off MM3 workaround for MM3->MM4 copying to speed-up compression-induced chunking;
 LFP chunking uses “reasonable defaults” when variable smaller than default chunksize;
@@ -830,7 +835,7 @@ Thanks to NSF for supporting AIX machines at NCAR over the years.
 <h3><a href="http://www.debian.org">Debian</a> and <a href="http://www.ubuntu.com">Ubuntu</a> GNU/Linux</a></h3>
 <ul>
 <!--
-<li><a href="http://www.debian.org">Debian</a> and <a href="http://www.ubuntu.com">Ubuntu</a> GNU/Linux-compatible Intel systems, prebuilt binary executable <a href="http://www.debian.org">deb</a>: <a href="http://packages.debian.org/testing/math/nco.html">nco-4.4.9</a></li>
+<li><a href="http://www.debian.org">Debian</a> and <a href="http://www.ubuntu.com">Ubuntu</a> GNU/Linux-compatible Intel systems, prebuilt binary executable <a href="http://www.debian.org">deb</a>: <a href="http://packages.debian.org/testing/math/nco.html">nco-4.5.0</a></li>
 -->
 <a href="http://packages.debian.org/unstable/science/nco">Debian NCO</a> and 
 <a href="http://packages.ubuntu.com/natty/nco">Ubuntu NCO</a> homepages.
@@ -838,12 +843,12 @@ Thanks to NSF for supporting AIX machines at NCAR over the years.
 NCO packages in the Debian/Ubuntu repositories (i.e., Sid and Raring) generally lag the packages distributed here by 6–12 months.
 <a name="beta"></a><a name="prerelease"> <!-- http://nco.sf.net#beta -->
 Newer (beta- or pre-release) packages are often available for intrepid Debian/Ubuntu users as described <a href="https://github.com/czender/nco/tree/master/doc/beta.txt">here</a>.
-<dt>Debian package for most recent NCO release (install with, e.g., ‘<tt>dpkg --install nco_4.4.9-1_i386.deb</tt>’):</dt>
-<li><a href="src/nco_4.4.9-1_amd64.deb">nco_4.4.9-1_amd64.deb</a> (<!--#fsize file="src/nco_4.4.9-1_amd64.deb"-->): Executables AMD64-compatible (last updated <!--#flastmod file="src/nco_4.4.9-1_amd64.deb"-->)</li>
-<li><a href="src/nco_4.4.9-1.dsc">nco_4.4.9-1.dsc</a> (<!--#fsize file="src/nco_4.4.9-1.dsc"-->): Description (last updated <!--#flastmod file="src/nco_4.4.9-1.dsc"-->)</li>
-<li><a href="src/nco_4.4.9-1_amd64.changes">nco_4.4.9-1_amd64.changes</a> (<!--#fsize file="src/nco_4.4.9-1_amd64.changes"-->): Changes since last deb package (last updated <!--#flastmod file="src/nco_4.4.9-1_amd64.changes"-->)</li>
-<li><a href="src/nco_4.4.9.orig.tar.gz">nco_4.4.9.orig.tar.gz</a> (<!--#fsize file="src/nco_4.4.9.orig.tar.gz"-->): Upstream Source (last updated <!--#flastmod file="src/nco_4.4.9.orig.tar.gz"-->)</li>
-<li><a href="src/nco_4.4.9-1.diff.gz">nco_4.4.9-1.diff.gz</a> (<!--#fsize file="src/nco_4.4.9-1_amd64.changes"-->): Debian patch to upstream source (last updated <!--#flastmod file="src/nco_4.4.9-1_amd64.changes"-->)</li>
+<dt>Debian package for most recent NCO release (install with, e.g., ‘<tt>dpkg --install nco_4.5.0-1_i386.deb</tt>’):</dt>
+<li><a href="src/nco_4.5.0-1_amd64.deb">nco_4.5.0-1_amd64.deb</a> (<!--#fsize file="src/nco_4.5.0-1_amd64.deb"-->): Executables AMD64-compatible (last updated <!--#flastmod file="src/nco_4.5.0-1_amd64.deb"-->)</li>
+<li><a href="src/nco_4.5.0-1.dsc">nco_4.5.0-1.dsc</a> (<!--#fsize file="src/nco_4.5.0-1.dsc"-->): Description (last updated <!--#flastmod file="src/nco_4.5.0-1.dsc"-->)</li>
+<li><a href="src/nco_4.5.0-1_amd64.changes">nco_4.5.0-1_amd64.changes</a> (<!--#fsize file="src/nco_4.5.0-1_amd64.changes"-->): Changes since last deb package (last updated <!--#flastmod file="src/nco_4.5.0-1_amd64.changes"-->)</li>
+<li><a href="src/nco_4.5.0.orig.tar.gz">nco_4.5.0.orig.tar.gz</a> (<!--#fsize file="src/nco_4.5.0.orig.tar.gz"-->): Upstream Source (last updated <!--#flastmod file="src/nco_4.5.0.orig.tar.gz"-->)</li>
+<li><a href="src/nco_4.5.0-1.diff.gz">nco_4.5.0-1.diff.gz</a> (<!--#fsize file="src/nco_4.5.0-1_amd64.changes"-->): Debian patch to upstream source (last updated <!--#flastmod file="src/nco_4.5.0-1_amd64.changes"-->)</li>
 Thanks to Daniel Baumann, Barry deFreese, Francesco Lovergine, 
 Brian Mays, Rorik Peterson, and Matej Vela for their help packaging
 NCO for Debian over the years. 
@@ -890,10 +895,10 @@ Thanks to Gavin Burris and Kyle Wilcox for documenting build procedures for RHEL
 <!-- 
 # Mac OS X 10.10 (Yosemite) systems (aerosol):
 /usr/bin/scp ~/nco/doc/index.shtml zender,nco at web.sf.net:/home/project-web/nco/htdocs
-cd ~/bin/MACOSX;tar cvzf ${DATA}/nco-4.4.9.macosx.10.10.tar.gz nc*;scp ${DATA}/nco-4.4.9.macosx.10.10.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
+cd ~/bin/MACOSX;tar cvzf ${DATA}/nco-4.5.0.macosx.10.10.tar.gz nc*;scp ${DATA}/nco-4.5.0.macosx.10.10.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src
 -->
 The most up-to-date binaries are probably those in the tarball below. Those unfamiliar with installing executables from tarballs may try the (older) <a href="http://en.wikipedia.org/wiki/Apple_Disk_Image">DMG</a> files (you may need to add <tt>/opt/local/bin</tt> to your executable path to access those operators).
-<li><a href="src/nco-4.4.9.macosx.10.10.tar.gz">nco-4.4.9.macosx.10.10.tar.gz</a> (<!--#fsize file="src/nco-4.4.9.macosx.10.10.tar.gz"-->): Executables MacOSX 10.10-compatible (last updated <!--#flastmod file="src/nco-4.4.9.macosx.10.10.tar.gz"-->). 
+<li><a href="src/nco-4.5.0.macosx.10.10.tar.gz">nco-4.5.0.macosx.10.10.tar.gz</a> (<!--#fsize file="src/nco-4.5.0.macosx.10.10.tar.gz"-->): Executables MacOSX 10.10-compatible (last updated <!--#flastmod file="src/nco-4.5.0.macosx.10.10.tar.gz"-->). 
 (NB: These executables require
   the <a href="http://trac.macosforge.org/projects/macports/wiki">MacPorts</a>
   <a href="#bld_macports">dependencies</a> for <a href="http://svn.macports.org/repository/macports/trunk/dports/science/nco">NCO</a>). Maintained by NCO Project.</li>
@@ -1083,11 +1088,11 @@ site.</li>
 The simplest way to acquire the source is to download the compressed tarball:
 <ul>
 <li>
-<!-- scp ${DATA}/nco-4.4.9.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src -->
-<a href="src/nco-4.4.9.tar.gz">nco-4.4.9.tar.gz</a> 
-(<!--#fsize file="src/nco-4.4.9.tar.gz"--> compressed tar-file)<br>
-<!--#exec cmd="openssl dgst -md5 src/nco-4.4.9.tar.gz"--><br>
-<!--#exec cmd="openssl dgst -sha1 src/nco-4.4.9.tar.gz"--> 
+<!-- scp ${DATA}/nco-4.5.0.tar.gz zender,nco at web.sf.net:/home/project-web/nco/htdocs/src -->
+<a href="src/nco-4.5.0.tar.gz">nco-4.5.0.tar.gz</a> 
+(<!--#fsize file="src/nco-4.5.0.tar.gz"--> compressed tar-file)<br>
+<!--#exec cmd="openssl dgst -md5 src/nco-4.5.0.tar.gz"--><br>
+<!--#exec cmd="openssl dgst -sha1 src/nco-4.5.0.tar.gz"--> 
 </li>
 </ul>
 
@@ -1106,17 +1111,17 @@ You may retrieve any NCO distribution you wish from
 <a href="https://help.github.com">GitHub</a>. 
 Usually you wish to retrieve a recent tagged (i.e., released) version.
 This command retrieves the entire NCO repository (< 20 MB) and
-then checks out NCO version <tt>4.4.9</tt>:
-<p><tt>git clone https://github.com/czender/nco.git;cd nco;git checkout -b nco-4.4.9</tt></p>
+then checks out NCO version <tt>4.5.0</tt>:
+<p><tt>git clone https://github.com/czender/nco.git;cd nco;git checkout -b 4.5.0</tt></p>
 This command retrieves the current (“bleeding edge”)
 development version of NCO into a local directory named <tt>nco</tt>:
 <p><tt>git clone https://github.com/czender/nco.git ~/nco</tt></p>
 Track changes to the development version using
 <p><tt>cd ~/nco;git pull</tt></p>
 One difference between running a "tagged" release 
-(e.g., <tt>nco-4.4.9</tt>) and the development version is that the
+(e.g., <tt>4.5.0</tt>) and the development version is that the
 tagged release operators will print a valid version number (e.g.,
-<tt>4.4.9</tt>) when asked to do so with the <tt>-r</tt> flag
+<tt>4.5.0</tt>) when asked to do so with the <tt>-r</tt> flag
 (e.g., <tt>ncks -r</tt>).
 The development version simply places today's date in place of the
 version.
@@ -1244,9 +1249,9 @@ Users should instead first download and install the Antlr found <a href="http://
   then build the latest stable NCO and install it in,
   e.g., <tt>/usr/local</tt> with: 
 <tt>
-<dt>wget http://dust.ess.uci.edu/nco/nco.tar.gz</dt>
-<dt>tar xvzf nco.tar.gz</dt>
-<dt>cd nco-4.4.9</dt>
+<dt>wget https://github.com/czender/nco/archive/4.5.0.tar.gz</dt>
+<dt>tar xvzf 4.5.0.tar.gz</dt>
+<dt>cd nco-4.5.0</dt>
 <dt>./configure --prefix=/usr/local</dt>
 <dt>make</dt>
 <dt>sudo make install</dt>
diff --git a/doc/nco.texi b/doc/nco.texi
index 4910067..fff0f83 100644
--- a/doc/nco.texi
+++ b/doc/nco.texi
@@ -76,6 +76,9 @@ texi2html: Index sub-divided by first character
            Misprints title
            Includes @ifinfo sections by default
 
+Official TeXInfo documentation:
+http://www.gnu.org/software/texinfo/manual/texinfo/texinfo.html
+
 Legend (defined in "highlighting" section of TeXInfo manual):
 @code{}: Program text, e.g., @code{if(foo) x=y;}
 @command{}: Commands, e.g., @command{ncra}
@@ -118,8 +121,8 @@ Octave TeXInfo manual shows clean TeXInfo structure
 @set doc-edition 4.5.0
 @set copyright-years 1995--2015
 @set update-year 2015
- at set update-date 21 May 2015
- at set update-month May 2015
+ at set update-date 10 June 2015
+ at set update-month June 2015
 
 @settitle @acronym{NCO} @value{nco-edition} User Guide
 
@@ -2062,6 +2065,7 @@ filenames to @acronym{NCO} in environment-limited situations.
 <a name="stdin"></a> <!-- http://nco.sf.net/nco.html#stdin -->
 @end html
 @cindex standard input
+ at cindex provenance
 @cindex @code{stdin}
 The recommended method for sending very large numbers (hundreds or
 more, typically) of input filenames to the multi-file operators is
@@ -2168,6 +2172,7 @@ automatically generate the filnames of the symbolic links.
 This circumvents any @acronym{OS} and shell limits on command line size.
 The symbolic links are easily removed once @acronym{NCO} is finished.
 @cindex @code{history}
+ at cindex provenance
 One drawback to this method is that the @code{history} attribute
 (@pxref{History Attribute}) retains the filename list of the symbolic
 links, rather than the data files themselves. 
@@ -2536,6 +2541,7 @@ feature is automatic and cannot be controlled by the user.
 * Multislabs::
 * Wrapped Coordinates::
 * Auxiliary Coordinates::
+* Regridding::
 * UDUnits Support::
 * Rebasing Time Coordinate::
 * Multiple Record Dimensions::
@@ -4497,7 +4503,7 @@ level.
 In other words, @acronym{GPE} is tolerant of specifying too many group
 components to delete. 
 It deletes as many as possible, without complaint, and then begins to
-flatten the file (which will fail if namespace conflicts arise).
+flatten the file (which fails if namespace conflicts arise).
 
 In Truncate-mode, @var{lvl_nbr} is a negative integer which specifies
 the maximum number of group path components (i.e., groups) that
@@ -4663,40 +4669,47 @@ directory @var{drc_out} specified by the second argument:
 @example
 @verbatim
 cat > ~/ncdismember << 'EOF'
+#!/bin/sh
+
 # Purpose: Dismember netCDF4/HDF5 hierarchical files. CF-check them.
 # Place each input file group in separate netCDF3 output file
 # Described in NCO User Guide at http://nco.sf.net/nco.html#dismember
 # Requirements: NCO 4.3.x+, UNIX shell utilities awk, grep, sed
-# Optional: CFchecker command https://bitbucket.org/mde_/cfchecker
+# Optional: Decker CFchecker https://bitbucket.org/mde_/cfchecker
 
 # Usage:
-# ncdismember <fl_in> <drc_out> [flg_cf] [cf_vrs] [opt]
-# where fl_in is input file/URL to dismember, drc_out is output directory,
-# CF-compliance check is performed when optional third argument is 'cf',
+# ncdismember <fl_in> <drc_out> [cf_chk] [cf_vrs] [opt]
+# where fl_in is input file/URL to dismember, drc_out is output directory
+# CF-compliance check is performed when optional third argument is not '0'
+# Default checker is Decker's cfchecker installed locally
+# Specify cf_chk=nerc for smallified uploads to NERC checker
 # Optional fourth argument cf_vrs is CF version to check
-# Optional fifth argument opt passes straight through to ncks
+# Optional fifth argument opt passes straight-through to ncks
+# Arguments must not use shell expansion/globbing
+# NB: ncdismember does not clean-up output directory, so user must
 # chmod a+x ~/sh/ncdismember
-# ncdismember ~/nco/data/mdl_1.nc /data/zender/nco/tmp
-# ncdismember ~/nco/data/mdl_1.nc /data/zender/nco/tmp
-# ncdismember http://dust.ess.uci.edu/nco/mdl_1.nc /data/zender/nco/tmp
-# ncdismember http://thredds-test.ucar.edu/thredds/dodsC/testdods/foo.nc /data/zender/nco/tmp
+# Examples:
+# ncdismember ~/nco/data/mdl_1.nc /data/zender/tmp
+# ncdismember http://dust.ess.uci.edu/nco/mdl_1.nc /tmp
+# ncdismember http://thredds-test.ucar.edu/thredds/dodsC/testdods/foo.nc /tmp
 # ncdismember ~/nco/data/mdl_1.nc /data/zender/nco/tmp cf
+# ncdismember ~/nco/data/mdl_1.nc /data/zender/nco/tmp nerc
 # ncdismember ~/nco/data/mdl_1.nc /data/zender/nco/tmp cf 1.3
 # ncdismember ~/nco/data/mdl_1.nc /data/zender/nco/tmp cf 1.5 --fix_rec_dmn=all
 
-# Command line argument defaults
+# Command-line argument defaults
 fl_in="${HOME}/nco/data/mdl_1.nc" # [sng] Input file to dismember/check
 drc_out="${DATA}/nco/tmp" # [sng] Output directory
-flg_cf='0' # [flg] Perform CF-compliance check
+cf_chk='0' # [flg] Perform CF-compliance check? Which checker?
 cf_vrs='1.5' # [sng] Compliance-check this CF version (e.g., '1.5')
 opt='' # [flg] Additional ncks options (e.g., '--fix_rec_dmn=all')
 # Use single quotes to pass multiple arguments to opt=${5}
 # Otherwise arguments would be seen as ${5}, ${6}, ${7} ...
 
-# Command line argument option parsing
+# Command-line argument option parsing
 if [ -n "${1}" ]; then fl_in=${1}; fi
 if [ -n "${2}" ]; then drc_out=${2}; fi
-if [ -n "${3}" ]; then flg_cf=${3}; fi
+if [ -n "${3}" ]; then cf_chk=${3}; fi
 if [ -n "${4}" ]; then cf_vrs=${4}; fi
 if [ -n "${5}" ]; then opt=${5}; fi
 
@@ -4706,6 +4719,15 @@ fl_stb=$(basename ${fl_in})
 drc_out=${drc_out}/${fl_stb}
 mkdir -p ${drc_out}
 cd ${drc_out}
+chk_dck='n'
+chk_nrc='n'
+if [ ${cf_chk} = 'nerc' ]; then
+    chk_nrc='y'
+fi # chk_nrc
+if [ ${cf_chk} != '0' ] && [ ${cf_chk} != 'nerc' ]; then
+    chk_dck='y'
+    hash cfchecker 2>/dev/null || { echo >&2 "Local cfchecker command not found, will smallify and upload to NERC checker instead"; chk_nrc='y'; chk_dck='n'; }
+fi # !cf_chk
 # Obtain group list
 grp_lst=`ncks --cdl -m ${fl_in} | grep '// group' | awk '{$1=$2=$3="";sub(/^  */,"",$0);print}'`
 IFS=$'\n' # Change Internal-Field-Separator from <Space><Tab><Newline> to <Newline>
@@ -4719,18 +4741,43 @@ for grp_in in ${grp_lst} ; do
     cmd="ncks -O -3 -G : -g ${grp_in}/ -h --no_tmp_fl --hdr_pad=40 ${hdf4} ${opt} ${fl_in} ${drc_out}/${grp_out}.nc"
     # Use eval in case ${opt} contains multiple arguments separated by whitespace
     eval ${cmd}
-    if [ ${flg_cf} = 'cf' ]; then
-       # cfchecker needs Conventions <= 1.5
+    if [ ${chk_dck} = 'y' ]; then
+       # Decker checker needs Conventions <= 1.6
        no_bck_sls=`echo ${drc_out}/${grp_out} | sed 's/\\\ / /g'`
        ncatted -h -a Conventions,global,o,c,CF-${cf_vrs} ${no_bck_sls}.nc
-    else # !flg_cf
+    else # !chk_dck
        echo ${drc_out}/${grp_out}.nc
-    fi # !flg_cf
+    fi # !chk_dck
 done
-if [ ${flg_cf} = 'cf' ]; then
-    echo "CFchecker reports CF-compliance of each group in flat netCDF3 format"
+if [ ${chk_dck} = 'y' ]; then
+    echo 'Decker CFchecker reports CF-compliance of each group in flat netCDF3 format'
     cfchecker -c ${cf_vrs} *.nc
-fi # !flg_cf
+fi
+if [ ${chk_nrc} = 'y' ]; then
+    # Smallification and NERC upload from qdcf script by Phil Rasch (PJR)
+    echo 'Using remote CFchecker http://puma.nerc.ac.uk/cgi-bin/cf-checker.pl'
+    cf_lcn='http://puma.nerc.ac.uk/cgi-bin/cf-checker.pl'
+    for fl in ${drc_out}/*.nc ; do
+	fl_sml=${fl}
+	cf_out=${fl%.nc}.html
+	dmns=`ncdump -h ${fl_in} | sed -n -e '/dimensions/,/variables/p' | grep = | sed -e 's/=.*//'`
+	hyp_sml=''
+	for dmn in ${dmns}; do
+	    dmn_lc=`echo ${dmn} | tr "[:upper:]" "[:lower:]"`
+	    if [ ${dmn_lc} = 'lat' ] || [ ${dmn_lc} = 'latitude' ] || [ ${dmn_lc} = 'lon' ] || [ ${dmn_lc} = 'longitude' ] || [ ${dmn_lc} = 'time' ]; then
+		hyp_sml=`echo ${hyp_sml}" -d ${dmn},0"`
+	    fi # !dmn_lc
+	done
+	# Create small version of input file by sampling only first element of lat, lon, time
+	ncks -O ${hyp_sml} ${fl} ${fl_sml}
+	# Send small file to NERC checker
+	curl --form cfversion=1.6 --form upload=@${fl_sml} --form press="Check%20file" ${cf_lcn} -o ${cf_out}
+	# Strip most HTML to improve readability
+	cat ${cf_out} | sed -e "s/<[^>]*>//g" -e "/DOCTYPE/,/\]\]/d" -e "s/CF-Convention//g" -e "s/Output of//g" -e "s/Compliance Checker//g" -e "s/Check another//g" -e "s/CF-Checker follows//g" -e "s/Received//g" -e "s/for NetCDF//g" -e "s/NetCDF format//g" -e "s/against CF version 1//g" -e "s/\.\.\.//g"
+	echo "Full NERC compliance-check log for ${fl} in ${cf_out}"
+    done
+fi # !nerc
+
 EOF
 chmod 755 ~/ncdismember # Make command executable
 /bin/mv -f ~/ncdismember ~/sh # Store in location on $PATH, e.g., /usr/local/bin
@@ -5718,12 +5765,13 @@ values (@pxref{Hyperslabs}).
 <a name="std_nm"></a> <!-- http://nco.sf.net/nco.html#std_nm -->
 <a name="standard_name"></a> <!-- http://nco.sf.net/nco.html#standard_name -->
 @end html
- at node Auxiliary Coordinates, UDUnits Support, Wrapped Coordinates, Shared features
+ at node Auxiliary Coordinates, Regridding, Wrapped Coordinates, Shared features
 @section Auxiliary Coordinates
 @cindex @code{-X}
 @cindex @code{--auxiliary}
 @cindex @code{standard_name}
 @cindex @code{coordinates}
+ at cindex auxiliary coordinates
 @cindex @acronym{CF} conventions
 @cindex @code{-X @var{lon_min}, at var{lon_max}, at var{lat_min}, at var{lat_max}}
 @cindex @code{--auxiliary @var{lon_min}, at var{lon_max}, at var{lat_min}, at var{lat_max}}
@@ -5739,22 +5787,23 @@ Utilize auxiliary coordinates specified in values of the coordinate
 variable's @code{standard_name} attributes, if any, when interpreting 
 hyperslab and multi-slab options. 
 Also @samp{--auxiliary}.
-This switch supports hyperslabbing cell-based grids over coordinate
-ranges. 
+This switch supports hyperslabbing cell-based grids (aka unstructured
+grids) over coordinate ranges. 
 This works on datasets that associate coordinate variables to
 grid-mappings using the @acronym{CF}-convention (@pxref{CF Conventions})   
 @code{coordinates} and @code{standard_name} attributes described 
 @uref{http://cfconventions.org/1.6.html#coordinate-system, here}. 
 Currently, @acronym{NCO} understands auxiliary coordinate variables 
-pointed to by the @code{standard_name} attributes for @var{latitude} and 
+pointed to by the @code{standard_name} attributes for @var{latitude} and  
 @var{longitude}.   
 Cells that contain a value within the user-specified range 
 [@var{lon_min}, at var{lon_max}, at var{lat_min}, at var{lat_max}] are
 included in the output hyperslab.  
 
- at cindex cell-based grids
-A cell-based grid collapses the horizontal spatial information 
-(latitude and longitude) and stores it along a one-dimensional
+ at cindex unstructured grid
+ at cindex cell-based grid
+A cell-based or unstructured grid collapses the horizontal spatial
+information  (latitude and longitude) and stores it along a one-dimensional
 coordinate that has a one-to-one mapping to both latitude and longitude
 coordinates. 
 Rectangular (in longitude and latitude) horizontal hyperslabs cannot
@@ -5858,10 +5907,449 @@ We recommend always using decimal points with @samp{-X} arguments
 to avoid confusion.
 
 @html
+<a name="map"></a> <!-- http://nco.sf.net/nco.html#map -->
+<a name="esmf"></a> <!-- http://nco.sf.net/nco.html#esmf -->
+<a name="scrip"></a> <!-- http://nco.sf.net/nco.html#scrip -->
+<a name="rgr"></a> <!-- http://nco.sf.net/nco.html#rgr -->
+<a name="rgr_map"></a> <!-- http://nco.sf.net/nco.html#rgr_map -->
+<a name="regrid"></a> <!-- http://nco.sf.net/nco.html#regrid -->
+ at end html
+ at node Regridding, UDUnits Support, Auxiliary Coordinates, Shared features
+ at section Regridding
+ at cindex map
+ at cindex regridding
+ at cindex @code{--map}
+ at cindex @acronym{ESMF}
+ at cindex @acronym{SCRIP}
+ at cindex OpenMP
+ at cindex @code{--rgr @var{key}=@var{val}}
+ at cindex @code{--rgr_map}
+ at cindex @var{--map-file}
+ at cartouche
+Availability: @command{ncks}@* 
+Short options: None@*
+Long options: 
+ at samp{--map @var{map-file}} or @samp{--rgr_map @var{map-file}}@*
+ at samp{--rgr @var{key}=@var{val}} (multiple invocations allowed)@*
+ at samp{--rnr=@var{wgt_thr}} or @samp{--rgr_rnr=@var{wgt_thr}} or 
+ at samp{--renormalize=@var{wgt_thr}}@*
+ at end cartouche
+
+As of @acronym{NCO} version 4.5.0 (June, 2015), @command{ncks} supports 
+horizontal regridding of global datasets where the grids and weights are
+all stored in an external @var{map-file}.
+Use the @samp{--map} or @samp{--rgr_map} options to specify the
+ at var{map-file}, and @acronym{NCO} will regrid the @var{input-file} to
+a new (or possibly the same, aka, an identity mapping) horizontal grid
+in the @var{output-file}, using the input and output grids and mapping
+weights specified in the @acronym{ESMF}- or @acronym{SCRIP}-format
+ at var{map-file}. 
+Currently @acronym{NCO} understands only the mapfile format pioneered by 
+ at acronym{SCRIP} 
+(@url{http://oceans11.lanl.gov/svn/SCRIP/trunk/SCRIP})
+and later extended by @acronym{ESMF} 
+(@uref{http://www.earthsystemcog.org/projects/regridweightgen}).
+See those references for additional documentation on map formats.
+
+The regridding currently supported by @acronym{NCO} could equally well
+be called weight-application.
+ at acronym{NCO} reads-in pre-stored weights from the @var{map-file} and
+applies them to (almost) every variable, thereby creating a regridded
+ at var{output-file}. 
+Specify regridding with a standard @command{ncks} command and options
+along with the additional specification of a @var{map-file}: 
+ at example
+ at verbatim
+# Regrid entire file, same output format as input:
+ncks --map=map.nc in.nc out.nc
+# Entire file, netCDF4 output:
+ncks -4 --map=map.nc in.nc out.nc
+# Deflated netCDF4 output
+ncks -4 -L 1 --map=map.nc in.nc out.nc
+# Selected variables
+ncks -v FS.?,T --map=map.nc in.nc out.nc
+# Threading
+ncks -t 8 --map=map.nc in.nc out.nc
+# Deflated netCDF4 output, threading, selected variables:
+ncks -4 -L 1 -t 8 -v FS.?,T --map=map.nc in.nc out.nc
+ at end verbatim
+ at end example
+OpenMP threading works well with regridding large datasets.
+Threading improves throughput of regridding @w{1--10 GB} files by 
+factors of 2--5.
+Options specific to regridding are described below.
+
+ at cindex equiangular grid
+ at cindex Gaussian grid
+ at cindex cubed-sphere grid
+ at cindex @acronym{FV} grid
+ at acronym{NCO} supports 1D at result{}1D, 1D at result{}2D, 2D at result{}1D, and
+2D at result{}2D regridding for any unstructured 
+1D-grid and any rectangular 2D-grid.  
+This has been tested by converting among and between Gaussian,
+equiangular, @acronym{FV}, and unstructured cubed-sphere grids.
+Support for irregular 2D- and for regional grids (e.g., swath-like data)  
+is planned. 
+
+ at cindex conservative regridding
+ at cindex renormalized regridding
+ at cindex missing values
+ at cindex data, missing 
+ at cindex @code{missing_value}
+ at cindex @code{_FillValue}
+ at cindex @code{--rnr}
+ at cindex @code{--renormalize}
+ at cindex @code{--rgr_rnr}
+First-order-accurate data regridding is a straightforward procedure of 
+identifying gridcell overlap and apportioning values correctly
+from source to destination.
+The presence of missing values forces a decision on how to handle
+destination gridcells where some but not all source cells are valid. 
+ at acronym{NCO} implements one of two procedures: ``conservative'' or
+``renormalized''. 
+The ``conservative'' algorithm uses all valid data from the input grid
+on the output grid once and only once.
+Destination cells receive the weighted valid values of the source cells.
+This is conservative because the global integrals of the source and
+destination fields are equal.
+The ``renormalized'' algorithm divides the destination value by the sum
+of the valid weights.
+This returns ``reasonable'' values, i.e., the mean of the valid input
+values. 
+However, renormalization is equivalent to extrapolating valid data to
+missing regions. 
+Input and output integrals are unequal and renormalized regridding is
+not conservative.  
+
+ at cindex @var{wgt_thr}
+By default, @acronym{NCO} implements the ``conservative'' algorithm.
+To employ the ``renormalized'' algorithm instead, use the @samp{--rnr},
+ at samp{--rgr_rnr}, or @samp{--renormalize} options to supply
+ at var{wgt_thr}, the threshold weight for valid destination values.
+Valid values must cover at least the fraction @var{wgt_thr} of the
+destination gridcell to meet the threshold for a non-missing destination
+value. 
+When @var{wgt_thr} is exceeded, the mean valid value is renormalized by
+the valid area and placed in the destination gridcell. 
+If the valid area covers less than @var{wgt_thr}, then the destination
+gridcell is assigned the missing value.
+Valid values of @var{wgt_thr} range from zero to one.
+Keep in mind though, that this threshold is potentially a divisor, and 
+values of zero or very near to zero can lead to floating-point underflow
+and divide-by-zero errors.
+For convenience @acronym{NCO} permits users to specify a 
+ at math{@var{wgt_thr} = 0.0} threshold weight.
+This indicates that any valid data should be represented and
+renormalized on the output grid. 
+ at example
+ at verbatim
+ncks           --map=map.nc in.nc out.nc # Conservative regridding
+ncks --rnr=0.1 --map=map.nc in.nc out.nc # Renormalized regridding
+ at end verbatim
+ at end example
+The first example uses the default conservative algorithm.
+The second example specifies that valid values must cover at least 10%
+of the destination gridcell to meet the threshold for a non-missing
+destination value. 
+For a valid destination area of, say 25%, the renormalized algorithm
+produces a destination value four-times greater than the conservative
+algorithm.  
+
+ at acronym{NCO} automatically annotates the output with relevant metadata
+such as coordinate bounds, axes, and vertices (@w{@`{a} la} @acronym{CF}). 
+These annotations include
+ at enumerate
+ at cindex @var{lat_nm}
+ at cindex @var{lon_nm}
+ at cindex @samp{--rgr lon=@var{lon_nm}}
+ at cindex @samp{--rgr lat=@var{lat_nm}}
+ at item The name of the horizontal spatial dimensions assumed to represent
+    latitude and longitude in 2D rectangular input files are
+    @var{lat_nm} and @var{lon_nm}, which default to @code{lat} and
+    @code{lon}, respectively.  
+    Variables that contain a @var{lat_nm}-dimension and a
+    @var{lon_nm}-dimension on a 2D-rectangular input grid will be 
+    regridded, and variables regridded to a 2D-rectangular output grid 
+    will all contain the @var{lat_nm}- and @var{lon_nm}-dimensions,
+    and variables regridded to a 1D-unstructured output grid will have
+    @var{lat_nm} and @var{lon_nm} as auxiliary coordinate variables.
+    To treat different dimensions and variables as latitude and
+    longitude, use the options @samp{--rgr lat=@var{lat_nm}} and 
+    @samp{--rgr lon=@var{lon_nm}}.  
+    Note that, for now at least, @var{lat_nm} and @var{lon_nm} indicate
+    both the variable names associated @emph{and}, where applicable
+    (i.e., on 2D-grids), the dimensions of the horizontal coordinates.
+ at cindex @code{ncol}
+ at cindex @var{col_nm}
+ at cindex @samp{--rgr col=@var{col_nm}}
+ at item The name of the horizontal spatial dimension assumed to delineate
+    an unstructured grid is @var{col_nm}, which defaults to @code{ncol}
+    (number of columns).
+    Variables that contain the @var{col_nm}-dimension on an
+    unstructured input grid will be regridded, and regridded variables
+    written to an unstructured output grid will all contain the 
+    @var{col_nm}-dimension.
+    To treat a different dimension as unstructured, use the option
+    @samp{--rgr ncol=@var{col_nm}}. 
+    Note: Often there is no coordinate variable for the
+    @var{col_nm}-dimension, i.e., there is no variable named
+    @var{col_nm}, although such a coordinate could contain useful
+    information about the unstructured grid.
+ at cindex @acronym{CF}
+ at cindex @code{latitude}
+ at cindex @code{longitude}
+ at cindex @code{axes}
+ at cindex @code{standard_name}
+ at cindex @code{degrees_east}
+ at cindex @code{degrees_north}
+ at cindex @code{units}
+ at cindex @code{X} axis
+ at cindex @code{Y} axis
+ at cindex auxiliary coordinates
+ at item Longitude and latitude coordinates (both regular and auxiliary,
+    i.e., for unstructured grids) receive @acronym{CF}
+    @code{standard_name} values of @code{latitude} and @code{longitude},
+    @acronym{CF} @code{axes} attributes with values @code{X} and
+    @code{Y}, and @code{units} attributes with values
+    @code{degrees_east} and @code{degrees_north}, respectively.
+ at cindex @code{lat}
+ at cindex @code{lon}
+ at item Unstructured grid auxiliary coordinates for longitude and latitude
+    receive @acronym{CF} @code{coordinates} attributes with values
+    @code{lon} and @code{lat}, respectively.
+ at cindex @code{lon_bnds}
+ at cindex @code{lat_bnds}
+ at cindex @code{nbnd}
+ at cindex @code{time_bnds}
+ at cindex @var{lat_bnd_nm}
+ at cindex @var{lon_bnd_nm}
+ at cindex @samp{--rgr lat_bnd=@var{lat_bnd_nm}}
+ at cindex @samp{--rgr lon_bnd=@var{lon_bnd_nm}}
+ at item Structured grids with 1D-coordinates use the dimension
+    @var{bnd_nm} (which defaults to @code{nbnd}) with the spatial bounds
+    variables in @var{lat_bnd_nm} and @var{lon_bnd_nm} which default to
+    @code{lon_bnds} and @code{lat_bnds}, respectively.
+    By default spatial bounds for such structured grids parallel the
+    oft-used temporal bounds dimension (@code{nbnd=2}) and variable 
+    (@code{time_bnds}).
+    Bounds are attached to the horizontal spatial dimensions via their
+    @code{bounds} attributes. 
+    Change the spatial bounds dimension with the option 
+    @samp{--rgr bnd=@var{bnd_nm}}.
+    Rename the spatial bounds variables with the options 
+    @samp{--rgr lat_bnd=@var{lat_bnd_nm}} and 
+    @samp{--rgr lon_bnd=@var{lon_bnd_nm}}.
+ at cindex @code{lat_vertices}
+ at cindex @code{lon_vertices}
+ at cindex @code{nv}
+ at cindex @code{bounds}
+ at item Unstructured grids with 1D-coordinates use the dimension
+    @var{bnd_nm} (which defaults to @code{nv}, number of vertices) 
+    for the spatial bounds variables @var{lat_bnd_nm} and
+    @var{lon_bnd_nm} which default to @code{lat_vertices} and
+    @code{lon_vertices}, respectively. 
+    It may be impossible to re-use the temporal bounds dimension (often
+    @code{nbnd}) for unstructure grids, because the gridcells are not
+    rectangles, and thus require specification of all vertices for each
+    gridpoint, rather than only two parallel interfaces per dimension.
+    These bounds are attached to the horizontal spatial dimensions
+    via their @code{bounds} attributes.
+    Change the spatial bounds dimension with the option 
+    @samp{--rgr bnd=@var{bnd_nm}}.
+    Rename the spatial bounds variables with the options 
+    @samp{--rgr lat_bnd=@var{lat_bnd_nm}} and
+    @samp{--rgr lon_bnd=@var{lon_bnd_nm}}.
+    The temporal bounds dimension in unstructured grid output remains as
+    in the @var{input-file}, usually @code{nbnd}.
+ at cindex @code{area}
+ at cindex @code{cell_methods}
+ at cindex @code{cell_area}
+ at cindex @code{steradian}
+ at cindex @samp{--rgr area=@var{area_nm}}
+ at cindex @var{area_nm}
+ at cindex @acronym{SI}
+ at cindex solid angle
+ at cindex extensive variable
+ at item The variable @var{area_nm} (which defaults to @code{area}) is
+    always (re-)created in the @var{output_file} to hold the gridcell
+    area in steradians.     
+    To store the area in a different variable, use the option
+    @samp{--rgr area=@var{area_nm}}.
+    The @var{area_nm} variable receives a @code{standard_name} attribute 
+    of @code{cell_area}, a @code{units} attribute of @code{steradian}
+    (the @acronym{SI} unit of solid angle),
+    and a @code{cell_methods} attribute with value @code{lat, lon: sum},
+    which indicates that @var{area_nm} is @dfn{extensive}, meaning 
+    that its value depends on the gridcell boundaries.  
+    Since @var{area_nm} is a property of the grid, it is read directly
+    from the @var{map-file} rather than regridded itself. 
+ at cindex @code{gw}
+ at cindex @samp{--rgr lat_weight=@var{lat_wgt_nm}}
+ at cindex @var{lat_wgt_nm}
+ at cindex Gaussian weight
+ at item Rectangular 2D-grids use the variable @var{lat_wgt_nm}, which
+    defaults to @code{gw} (originally for ``Gaussian weight''), to store 
+    the 1D-weight appropriate for area-weighting the latitude grid.
+    To store the latitude weight in a different variable, use the option
+    @samp{--rgr lat_wgt=@var{lat_wgt_nm}}.
+    The @var{lat_wgt_nm} variable will not appear in 1D-grid output.
+    Weighting statistics by latitude (i.e., by @var{lat_wgt_nm}will
+    produce the same answers (up-to round-off error) as weighting by
+    area (i.e., by @var{area_nm}) in grids which have both variables.
+    The former requires less memory because @var{lat_wgt_nm} is 1D), 
+    whereas the latter is more general because @var{area_nm} works on
+    @emph{any} grid.
+ at cindex @code{mapping_file}
+ at cindex @code{source_file}
+ at item The @var{map-file} and @var{input-file} names are stored in the
+    @var{output-file} global attributes @code{mapping_file} and
+    @code{source_file}, respectively.
+ at end enumerate
+
+One may supply muliple @samp{--rgr @var{key}=@var{value}} options
+to simultaneously customize multiple grid-field names.
+The following examples may all be assumed to end with the standard
+options @samp{--map=map.nc in.nc out.nc}.
+ at example
+ at verbatim
+ncks --rgr lat=latitude --rgr lon=longitude
+ncks --rgr col=column --rgr lat_wgt=lat_wgt
+ncks --rgr bnd=bounds --rgr lat_bnd=lat_bounds --rgr lon_bnd=lon_bounds
+ncks --rgr bnd=vertices --rgr lat_bnd=lat_vrt --rgr lon_bnd=lon_vrt
+ at end verbatim
+ at end example
+The first command causes the regridder to associate the latitude and
+longitude dimensions with the dimension names @code{latitude} and
+ at code{longitude} (instead of @code{lat} and @code{lon}).
+The second command causes the regridder to associate the independent
+columns in an unstructured grid with the dimension name @code{column}
+(instead of @code{ncol}) and the variable containing latitude weights
+to be named @code{lat_wgt} (instead of @code{gw}).
+The third command associates the latitude and longitude bounds with the
+dimension @code{bounds} (instead of @code{nbnd}) and the variables
+ at code{lat_bounds} and @code{lon_bounds} (instead of @code{lat_bnds} and 
+ at code{lon_bnds}, respectively). 
+The fourth command associates the latitude and longitude bounds with the
+dimension @code{vertices} (instead of @code{nv}) and the variables
+ at code{lat_vrt} and @code{lon_vrt} (instead of @code{lat_vertices} and 
+ at code{lon_vertices}, respectively). 
+
+When used with an identity remapping files, regridding can signficantly
+enhance the metadata and therefore the dataset usability.
+Consider these selected metadata (those unchanged are not shown for
+brevity) associated with the variable @code{FSNT} from typical
+unstructured grid (@acronym{CAM-SE} cubed-sphere) output before and
+after an identity regridding: 
+ at example
+ at verbatim
+# Raw model output before regridding
+netcdf ne30_FSNT {
+  dimensions:
+    nbnd = 2 ;
+    ncol = 48602 ;
+    time = UNLIMITED ; // (1 currently)
+
+  variables:
+    float FSNT(time,ncol) ;
+      FSNT:long_name = "Net solar flux at top of model" ;
+
+    double time(time) ;
+      time:long_name = "time" ;
+      time:bounds = "time_bnds" ;
+
+    double time_bnds(time,nbnd) ;
+      time_bnds:long_name = "time interval endpoints" ;
+} // group /
+
+# Same model output after identity regridding
+netcdf dogfood {
+  dimensions:
+    nbnd = 2 ;
+    ncol = 48602 ;
+    nv = 5 ;
+    time = 1 ;
+
+  variables:
+    float FSNT(time,ncol) ;
+      FSNT:long_name = "Net solar flux at top of model" ;
+      FSNT:coordinates = "lat lon" ;
+
+    double lat(ncol) ;
+      lat:long_name = "latitude" ;
+      lat:standard_name = "latitude" ;
+      lat:units = "degrees_north" ;
+      lat:axis = "Y" ;
+      lat:bounds = "lat_vertices" ;
+      lat:coordinates = "lat lon" ;
+
+    double lat_vertices(ncol,nv) ;
+      lat_vertices:long_name = "gridcell latitude vertices" ;
+
+    double lon(ncol) ;
+      lon:long_name = "longitude" ;
+      lon:standard_name = "longitude" ;
+      lon:units = "degrees_east" ;
+      lon:axis = "X" ;
+      lon:bounds = "lon_vertices" ;
+      lon:coordinates = "lat lon" ;
+
+    double lon_vertices(ncol,nv) ;
+      lon_vertices:long_name = "gridcell longitude vertices" ;
+
+    double time(time) ;
+      time:long_name = "time" ;
+      time:bounds = "time_bnds" ;
+
+    double time_bnds(time,nbnd) ;
+      time_bnds:long_name = "time interval endpoints" ;
+} // group /
+ at end verbatim
+ at end example
+The raw model output lacks the @acronym{CF} @code{coordinates} and
+ at code{bounds} attributes that the regridder adds.
+The metadata turns @code{lat} and @code{lon} into auxiliary coordinate
+variables (@pxref{Auxiliary Coordinates}) which can then be hyperslabbed
+(with @samp{-X}) using latitude/longitude coordinates bounding the
+region of interest:
+ at example
+ at verbatim
+% ncks -u -H -X 314.6,315.3,-35.6,-35.1 -v FSNT dogfood.nc
+time[0]=31 ncol[0] FSNT[0]=344.575 W/m2
+
+ncol[0] lat[0]=-35.2643896828 degrees_north
+
+ncol[0] nv[0] lat_vertices[0]=-35.5977213708 
+ncol[0] nv[1] lat_vertices[1]=-35.5977213708 
+ncol[0] nv[2] lat_vertices[2]=-35.0972113817 
+ncol[0] nv[3] lat_vertices[3]=-35.0972113817 
+ncol[0] nv[4] lat_vertices[4]=-35.0972113817 
+
+ncol[0] lon[0]=315 degrees_east
+
+ncol[0] nv[0] lon_vertices[0]=315 
+ncol[0] nv[1] lon_vertices[1]=315 
+ncol[0] nv[2] lon_vertices[2]=315.352825437 
+ncol[0] nv[3] lon_vertices[3]=314.647174563 
+ncol[0] nv[4] lon_vertices[4]=314.647174563 
+
+time[0]=31 days since 1979-01-01 00:00:00
+
+time[0]=31 nbnd[0] time_bnds[0]=0 
+time[0]=31 nbnd[1] time_bnds[1]=31 
+ at end verbatim
+ at end example
+Thus auxiliary coordinate variables help to structure unstructured grids.
+The expanded metadata annotations from an identity regridding may
+obviate the need to place unstructured data on a rectangular grid. 
+For example, statistics for regions that can be expressed as unions of 
+rectangular regions can now be performed on the native (unstructured)
+grid. 
+
+ at html
 <a name="UDUnits"></a> <!-- http://nco.sf.net/nco.html#UDUnits -->
 <a name="UDUnits2"></a> <!-- http://nco.sf.net/nco.html#UDUnits2 -->
 @end html
- at node UDUnits Support, Rebasing Time Coordinate, Auxiliary Coordinates, Shared features
+ at node UDUnits Support, Rebasing Time Coordinate, Regridding, Shared features
 @section UDUnits Support 
 @cindex UDUnits
 @cindex Unidata
@@ -9355,32 +9843,68 @@ All operators automatically append a @code{history} global attribute to
 any file they create or modify.
 The @code{history} attribute consists of a timestamp and the full string
 of the invocation command to the operator, e.g., @samp{Mon May 26 20:10:24
-1997: ncks in.nc foo.nc}.
+1997: ncks in.nc out.nc}.
 The full contents of an existing @code{history} attribute are copied
 from the first @var{input-file} to the @var{output-file}.
 The timestamps appear in reverse chronological order, with the most
 recent timestamp appearing first in the @code{history} attribute.
-Since @acronym{NCO} and many other netCDF operators adhere to the
- at code{history} convention, the entire data processing path of a given
-netCDF file may often be deduced from examination of its @code{history}
-attribute. 
+Since @acronym{NCO} adheres to the @code{history} convention, the entire
+data processing path of a given netCDF file may often be deduced from
+examination of its @code{history} attribute. 
 As of May, 2002, @acronym{NCO} is case-insensitive to the spelling
 of the @code{history} attribute name.
 Thus attributes named @code{History} or @code{HISTORY} (which are
 non-standard and not recommended) will be treated as valid history
 attributes. 
 When more than one global attribute fits the case-insensitive search
-for ``history'', the first one found will be used.
- at code{history} attribute
+for ``history'', the first one found is used.
 @cindex @command{ncatted}
 To avoid information overkill, all operators have an optional switch
 (@samp{-h}, @samp{--hst}, or @samp{--history}) to override
 automatically appending the @code{history} attribute 
 (@pxref{ncatted netCDF Attribute Editor}).   
 Note that the @samp{-h} switch also turns off writing the
- at code{nco_input_file_list} attribute for multi-file operators
+ at code{nco_input_file_list}-attribute for multi-file operators
 (@pxref{File List Attributes}).
 
+ at cindex @code{history_of_appended_files}
+ at cindex provenance
+As of @acronym{NCO} version 4.5.0 (June, 2015), @acronym{NCO} 
+supports its own convention to retain the @code{history}-attribute 
+contents of all files that were appended to a file
+ at footnote{Note that before version 4.5.0, @acronym{NCO} could,
+in append (@samp{-A}) mode only, inadvertently overwrite the global
+metadata (including  @code{history}) of the output file with that of the
+input file. 
+This is the opposite behavior most would want.}.
+This convention stores those contents in the
+ at code{history_of_appended_files} attribute, which complements
+the @code{history}-attribute to provide a more complete provenance.
+These attributes may appear something like this in output:
+ at example
+ at verbatim
+// global attributes:
+:history = "Thu Jun  4 14:19:04 2015: ncks -A /home/zender/foo3.nc /home/zender/tmp.nc\n",
+  "Thu Jun  4 14:19:04 2015: ncks -A /home/zender/foo2.nc /home/zender/tmp.nc\n",
+  "Thu Jun  4 14:19:04 2015: ncatted -O -a att1,global,o,c,global metadata only in foo1 /home/zender/foo1.nc\n",
+  "original history from the ur-file serving as the basis for subsequent appends." ;
+:history_of_appended_files = "Thu Jun  4 14:19:04 2015: Appended file \
+  /home/zender/foo3.nc had following \"history\" attribute:\n",
+  "Thu Jun  4 14:19:04 2015: ncatted -O -a att2,global,o,c,global metadata only in foo3 /home/zender/foo3.nc\n",
+  "history from foo3 from which data was appended to foo1 after data from foo2 was appended\n",
+  "Thu Jun  4 14:19:04 2015: Appended file /home/zender/foo2.nc had following \"history\" attribute:\n",
+  "Thu Jun  4 14:19:04 2015: ncatted -O -a att2,global,o,c,global metadata only in foo2 /home/zender/foo2.nc\n",
+  "history of some totally different file foo2 from which data was appended to foo1 before foo3 was appended\n",
+:att1 = "global metadata only in foo1" ;
+ at end verbatim
+ at end example
+Note that the @code{history_of_appended_files}-attribute is only
+created, and will only exist, in a file that is, or descends from
+a file that was, appended to.
+The optional switch @samp{-h} (or @samp{--hst} or @samp{--history})  
+also overrides automatically appending the
+ at code{history_of_appended_files} attribute.
+
 @html
 <a name="fl_lst_in_att"></a> <!-- http://nco.sf.net/nco.html#fl_lst_in_att -->
 @end html
@@ -9432,11 +9956,15 @@ may amount to many thousands of filenames in a metadata attribute.
 @html
 <a name="CF"></a> <!-- http://nco.sf.net/nco.html#CF -->
 <a name="cnv"></a> <!-- http://nco.sf.net/nco.html#cnv -->
+<a name="cnv_ACME"></a> <!-- http://nco.sf.net/nco.html#cnv_ACME -->
+<a name="ACME"></a> <!-- http://nco.sf.net/nco.html#ACME -->
+<a name="acme"></a> <!-- http://nco.sf.net/nco.html#acme -->
 <a name="cnv_CF"></a> <!-- http://nco.sf.net/nco.html#cnv_CF -->
 <a name="cnv_CCSM"></a> <!-- http://nco.sf.net/nco.html#cnv_CCSM -->
 @end html
 @node CF Conventions, ARM Conventions, File List Attributes, Shared features
 @section @acronym{CF} Conventions
+ at cindex @acronym{ACME} conventions
 @cindex @acronym{CF} conventions
 @cindex @acronym{CCSM} conventions
 @cindex UDUnits
@@ -9555,6 +10083,20 @@ The handling of @code{msk_*} is exceptional in that @emph{any} variable
 name beginning with the string @code{msk_} is considered to be a
 ``mask'' and is thus preserved (not operated on arithmetically).
 
+As of @acronym{NCO} version 4.5.0 (June, 2015), @acronym{NCO} began
+to support behavior required for the @acronym{DOE} @acronym{ACME}
+program, and we refer to these rules collectively as the @acronym{ACME} 
+convention. 
+ at cindex @acronym{GMT}
+ at cindex @code{date_written}
+ at cindex @code{time_written}
+ at cindex @code{gmtime()}
+The first @acronym{ACME} rule implemented is that the contents of
+ at var{input-file} variables named @code{date_written} and
+ at code{time_written}, if any, will be updated to the current 
+system-supplied (with @code{gmtime()}) @acronym{GMT}-time as the
+variables are copied to the @var{output-file}.
+
 You must spoof @acronym{NCO} if you would like any grid properties
 or other special @acronym{CF} fields processed normally.
 For example rename the variables first with @command{ncrename}, 
@@ -14906,6 +15448,8 @@ as positional arguments on the command line
 
 @cindex @code{-M}
 @cindex @code{--glb_mtd_spp}
+ at cindex @code{history}
+ at cindex provenance
 @cindex metadata, global 
 Suppress global metadata copying.
 By default @acronym{NCO}'s multi-file operators copy the global metadata
@@ -15303,9 +15847,9 @@ ncks [-3] [-4] [-5] [-6] [-7] [-A] [-a] [-b @var{binary-file}] [-C] [-c] [--cdl]
 [--cnk_dmn nm,sz] [--cnk_map map] [--cnk_min sz] [--cnk_plc plc] [--cnk_scl sz]
 [-D @var{dbg}] [-d @var{dim},[@var{min}][,[@var{max}][,[@var{stride}]]] [-F] [--fix_rec_dmn @var{dim}] 
 [-G @var{gpe_dsc}] [-g @var{grp}[, at dots{}]] [--grp_xtr_var_xcl] [-H] [-h] [--hdn] [--hdr_pad @var{nbr}]
-[-L @var{dfl_lvl}] [-l @var{path}] [-M] [-m] [--mk_rec_dmn @var{dim}] [--md5_digest]
+[-L @var{dfl_lvl}] [-l @var{path}] [-M] [-m] [--map @var{map-file}] [--md5_digest] [--mk_rec_dmn @var{dim}]
 [--no_blank] [--no_tmp_fl] [-O] [-o @var{output-file}] [-P] [-p @var{path}] [--ppc ...]
-[-Q] [-q] [-R] [-r] [--rad] [--ram_all] [-s @var{format}] 
+[-Q] [-q] [-R] [-r] [--rad] [--ram_all] [--rnr=wgt] [-s @var{format}] 
 [-u] [--unn] [-V] [-v @var{var}[, at dots{}]] [-X ...] [-x] [--xml]
 @var{input-file} [[@var{output-file}]]
 @end example
@@ -15318,8 +15862,9 @@ The nickname ``kitchen sink'' is a catch-all because @command{ncks}
 combines most features of @command{ncdump} and @command{nccopy} with
 extra features to extract, hyperslab, multi-slab, sub-set, and translate  
 into one versatile utility. 
- at command{ncks} extracts (a subset of the) data from @var{input-file} and 
-and writes (or pastes) it in netCDF format to @var{output-file}, and 
+ at command{ncks} extracts (a subset of the) data from @var{input-file},
+regrids it according to @var{map-file} if specified,
+then writes in netCDF format to @var{output-file}, and 
 optionally writes it in flat binary format to @file{binary-file}, and
 optionally prints it to screen.
 
@@ -15809,7 +16354,6 @@ file.
 @cindex missing values
 @item --no_blank
 Print numeric representation of missing values.
-As of @acronym{NCO}
 As of @acronym{NCO} version 4.2.2 (October, 2012), @acronym{NCO} prints
 missing values as blanks (i.e., the underscore character @samp{_}) by default.
 To enable the old behavior of printing the numeric representation of
@@ -18992,12 +19536,20 @@ Here is an example showing:
 
 @html
 <a name="parallel"></a> <!-- http://nco.sf.net/nco.html#parallel -->
+<a name="prl"></a> <!-- http://nco.sf.net/nco.html#prl -->
+<a name="swift"></a> <!-- http://nco.sf.net/nco.html#swift -->
+<a name="swf"></a> <!-- http://nco.sf.net/nco.html#swf -->
+<a name="Parallel"></a> <!-- http://nco.sf.net/nco.html#Parallel -->
+<a name="Swift"></a> <!-- http://nco.sf.net/nco.html#Swift -->
 @end html
 @node Parallel, CCSM Example, CMIP5 Example, Top
 @chapter Parallel
+ at cindex Parallel
+ at cindex Swift
 @cindex @command{parallel}
-This section will describe scripting strategies, including the use of
- at acronym{GNU} Parallel, to @acronym{NCO}.
+This section will describe @acronym{NCO} scripting strategies.
+Many techniques can be used to exploit script-level parallelism,
+including @acronym{GNU} Parallel and Swift.
 @example
 @verbatim
 ls *historical*.nc | parallel ncks -O -d time,"1950-01-01","2000-01-01" {} 50y/{}
diff --git a/man/ncks.1 b/man/ncks.1
index 935cd43..3d48a0c 100644
--- a/man/ncks.1
+++ b/man/ncks.1
@@ -42,7 +42,8 @@ dbg_lvl]
 .IR dfl_lvl ] 
 [\-l 
 .IR path ]
-[\-M] [\-m] [\-\-md5]  [\-\-mk_rec_dmn
+[\-M] [\-m] [\-\-map
+.IR map-file ] [\-\-md5]  [\-\-mk_rec_dmn
 .IR dim ] [\-\-msa] [\-\-no_blank] [\-\-no_tmp_fl] [\-O] [\-o 
 .IR output-file ] 
 [\-P] [\-p 
@@ -52,9 +53,10 @@ dbg_lvl]
 .IR var2 [,...]]=
 .IR prc ]]
 [-Q] [\-q]
-[\-R] [\-r] [\-\-rad] [\-\-ram_all] [\-s 
-.IR format ]
-[\-u] [\--unn] [\-V] [\-v 
+[\-R] [\-r] [\-\-rad] [\-\-ram_all] [\--rnr
+.IR wgt ] [\-s 
+.IR format ] [\-t
+.IR thr_nbr ] [\-u] [\--unn] [\-V] [\-v 
 .IR var [,...]] 
 [\-X 
 .IR box ] 
diff --git a/man/ncra.1 b/man/ncra.1
index 049dfd5..4140c7a 100644
--- a/man/ncra.1
+++ b/man/ncra.1
@@ -47,6 +47,8 @@ ncra [\-3] [\-4] [\-6] [\-7] [\-A] [\-\-bfr
 .IR thr_nbr ]
 [\--unn] [\-v 
 .IR var [,...]]
+[\-w 
+.IR wgt ]
 [\-X 
 .IR box ] 
 [\-x] [\-y 
diff --git a/src/nco++/ncap2.cc b/src/nco++/ncap2.cc
index 7a4d496..95e7582 100644
--- a/src/nco++/ncap2.cc
+++ b/src/nco++/ncap2.cc
@@ -652,7 +652,7 @@ main(int argc,char **argv)
     (void)nco_redef(out_id);
   } /* Existing file */
   
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   /* Copy global attributes */
@@ -660,6 +660,8 @@ main(int argc,char **argv)
 
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
 
   /* Take output file out of define mode */
diff --git a/src/nco/mpncbo.c b/src/nco/mpncbo.c
index c4afb2d..075569e 100644
--- a/src/nco/mpncbo.c
+++ b/src/nco/mpncbo.c
@@ -723,6 +723,7 @@ main(int argc,char **argv)
     
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     
     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
     
diff --git a/src/nco/mpncecat.c b/src/nco/mpncecat.c
index 0bb0452..e3a77b5 100644
--- a/src/nco/mpncecat.c
+++ b/src/nco/mpncecat.c
@@ -592,6 +592,7 @@ main(int argc,char **argv)
     
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     
     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
     
diff --git a/src/nco/mpncflint.c b/src/nco/mpncflint.c
index d454d6e..6fd27ef 100644
--- a/src/nco/mpncflint.c
+++ b/src/nco/mpncflint.c
@@ -650,6 +650,7 @@ main(int argc,char **argv)
     
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     
     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
     
@@ -954,6 +955,8 @@ main(int argc,char **argv)
     /* ncflint-specific memory */
     if(fl_in_1) fl_in_1=(char *)nco_free(fl_in_1);
     if(fl_in_2) fl_in_2=(char *)nco_free(fl_in_2);
+    if(in_id_arr_1) in_id_arr_1=(int *)nco_free(in_id_arr_1);
+    if(in_id_arr_2) in_id_arr_2=(int *)nco_free(in_id_arr_2);
     var_prc_1=(var_sct **)nco_free(var_prc_1);
     var_prc_2=(var_sct **)nco_free(var_prc_2);
     if(wgt_1) wgt_1=(var_sct *)nco_var_free(wgt_1);
diff --git a/src/nco/mpncpdq.c b/src/nco/mpncpdq.c
index e0d98d7..ff935ad 100644
--- a/src/nco/mpncpdq.c
+++ b/src/nco/mpncpdq.c
@@ -692,6 +692,7 @@ main(int argc,char **argv)
     
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     
     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
     
diff --git a/src/nco/mpncra.c b/src/nco/mpncra.c
index 6cacdb1..a8260cf 100644
--- a/src/nco/mpncra.c
+++ b/src/nco/mpncra.c
@@ -704,6 +704,7 @@ main(int argc,char **argv)
     
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     
     /* Add input file list global attribute */
     if(FL_LST_IN_APPEND && HISTORY_APPEND && FL_LST_IN_FROM_STDIN) (void)nco_fl_lst_att_cat(out_id,fl_lst_in,fl_nbr);
diff --git a/src/nco/mpncwa.c b/src/nco/mpncwa.c
index 00fde32..3d0722b 100644
--- a/src/nco/mpncwa.c
+++ b/src/nco/mpncwa.c
@@ -781,6 +781,7 @@ main(int argc,char **argv)
     
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     
     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
     
diff --git a/src/nco/ncap.c b/src/nco/ncap.c
index 1dcabd9..907f422 100644
--- a/src/nco/ncap.c
+++ b/src/nco/ncap.c
@@ -658,6 +658,8 @@ main(int argc,char **argv)
   
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   
   /* Take output file out of define mode */
   if(hdr_pad == 0UL){
diff --git a/src/nco/ncbo.c b/src/nco/ncbo.c
index 4762cd0..f5ed20c 100644
--- a/src/nco/ncbo.c
+++ b/src/nco/ncbo.c
@@ -614,7 +614,7 @@ main(int argc,char **argv)
   /* Open output file */
   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
 
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id_1,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   if(gpe){
@@ -632,6 +632,7 @@ main(int argc,char **argv)
   (void)nco_att_cpy(in_id_1,out_id,NC_GLOBAL,NC_GLOBAL,(nco_bool)True);
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in_1,in_id_1,out_id);
   if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
 
   /* Turn off default filling behavior to enhance efficiency */
diff --git a/src/nco/ncecat.c b/src/nco/ncecat.c
index 62283a5..ae63278 100644
--- a/src/nco/ncecat.c
+++ b/src/nco/ncecat.c
@@ -625,7 +625,7 @@ main(int argc,char **argv)
   /* Open output file */
   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
 
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   /* ncecat-specific operations */
@@ -663,10 +663,12 @@ main(int argc,char **argv)
     } /* end loop over idx */
 
     /* Define dimensions, extracted groups, variables, and attributes in output file */
-    (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,True,True,False,nco_pck_plc_nil,rec_dmn_nm,trv_tbl);
+    (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,!FORCE_APPEND,True,False,nco_pck_plc_nil,rec_dmn_nm,trv_tbl);
 
     /* Catenate time-stamped command line to "history" global attribute */
     if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
     /* Add input file list global attribute */
     if(FL_LST_IN_APPEND && HISTORY_APPEND && FL_LST_IN_FROM_STDIN) (void)nco_fl_lst_att_cat(out_id,fl_lst_in,fl_nbr);
     if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
@@ -785,6 +787,7 @@ main(int argc,char **argv)
 
         /* Catenate time-stamped command line to "history" global attribute */
         if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
 
         /* Add input file list global attribute */
         if(FL_LST_IN_APPEND && HISTORY_APPEND && FL_LST_IN_FROM_STDIN) (void)nco_fl_lst_att_cat(out_id,fl_lst_in,fl_nbr);
@@ -888,9 +891,10 @@ main(int argc,char **argv)
         var_prc_out[idx]->id=var_out_id;
 
 	if(var_trv->ppc != NC_MAX_INT){
-	  if(var_trv->flg_nsd) (void)nco_var_bitmask(var_trv->ppc,var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->val); else (void)nco_var_around(var_trv->ppc,var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->val);
+	  if(var_trv->flg_nsd) (void)nco_ppc_bitmask(var_trv->ppc,var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->val); else (void)nco_ppc_around(var_trv->ppc,var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->val);
 	} /* endif ppc */
-
+	if(nco_is_xcp(var_trv->nm)) nco_xcp_prc(var_trv->nm,var_prc[idx]->type,var_prc[idx]->sz,(char *)var_prc[idx]->val.vp);
+ 
 #ifdef _OPENMP
 # pragma omp critical
 #endif /* _OPENMP */
diff --git a/src/nco/ncflint.c b/src/nco/ncflint.c
index 3da40dc..fa70628 100644
--- a/src/nco/ncflint.c
+++ b/src/nco/ncflint.c
@@ -155,7 +155,7 @@ main(int argc,char **argv)
   extern int optind;
 
   /* Using naked stdin/stdout/stderr in parallel region generates warning
-  Copy appropriate filehandle to variable scoped shared in parallel clause */
+     Copy appropriate filehandle to variable scoped shared in parallel clause */
   FILE * const fp_stderr=stderr; /* [fl] stderr filehandle CEWI */
   FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */
 
@@ -644,17 +644,19 @@ main(int argc,char **argv)
   /* Open output file */
   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
 
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id_1,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   /* Transfer variable type to table. NOTE: Using var/xtr_nbr containing all variables (processed, fixed) */
   (void)nco_var_typ_trv(xtr_nbr,var,trv_tbl);         
 
   /* Define dimensions, extracted groups, variables, and attributes in output file */
-  (void)nco_xtr_dfn(in_id_1,out_id,&cnk,dfl_lvl,gpe,md5,True,True,False,nco_pck_plc_nil,(char *)NULL,trv_tbl);
+  (void)nco_xtr_dfn(in_id_1,out_id,&cnk,dfl_lvl,gpe,md5,!FORCE_APPEND,True,False,nco_pck_plc_nil,(char *)NULL,trv_tbl);
 
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in_1,in_id_1,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
 
   /* Turn off default filling behavior to enhance efficiency */
@@ -701,8 +703,8 @@ main(int argc,char **argv)
     if (xtr_nbr_ntp_1) ntp_1=var_ntp_1[0];
     if (xtr_nbr_ntp_2) ntp_2=var_ntp_2[0];
 
-    if(xtr_nbr_ntp_1 == 0 || xtr_nbr_ntp_2 == 0){
-      (void)fprintf(fp_stdout,"%s: ERROR Variable <%s> is not present in input file. ncflint assumes same file structure for both input files\n",nco_prg_nm_get(),ntp_nm);
+    if(!xtr_nbr_ntp_1 || !xtr_nbr_ntp_2){
+      (void)fprintf(fp_stdout,"%s: ERROR Variable %s is not present in input file. ncflint assumes same file structure for both input files\n",nco_prg_nm_get(),ntp_nm);
       nco_exit(EXIT_FAILURE);
     } /* endif */
     
@@ -859,18 +861,15 @@ main(int argc,char **argv)
     var_prc_out[idx]->id=var_out_id;
 
     if(var_trv_1->ppc != NC_MAX_INT){
-    if(var_trv_1->flg_nsd) (void)nco_var_bitmask(var_trv_1->ppc,var_prc_2[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_2[idx]->val); else (void)nco_var_around(var_trv_1->ppc,var_prc_2[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_2[idx]->val);
+    if(var_trv_1->flg_nsd) (void)nco_ppc_bitmask(var_trv_1->ppc,var_prc_2[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_2[idx]->val); else (void)nco_ppc_around(var_trv_1->ppc,var_prc_2[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_2[idx]->val);
     } /* endif ppc */
+    if(nco_is_xcp(var_trv_1->nm)) nco_xcp_prc(var_trv_1->nm,var_prc_2[idx]->type,var_prc_out[idx]->sz,(char *)var_prc_2[idx]->val.vp);
 #ifdef _OPENMP
 # pragma omp critical
 #endif /* _OPENMP */
     { /* begin OpenMP critical */
       /* Copy interpolations to output file */
-    if(var_prc_out[idx]->nbr_dim == 0){
-    (void)nco_put_var1(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_2[idx]->val.vp,var_prc_2[idx]->type);
-  }else{ /* end if variable is scalar */
-        (void)nco_put_vara(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_2[idx]->val.vp,var_prc_2[idx]->type);
-      } /* end else */
+      if(!var_prc_out[idx]->nbr_dim) (void)nco_put_var1(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_2[idx]->val.vp,var_prc_2[idx]->type); else (void)nco_put_vara(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_2[idx]->val.vp,var_prc_2[idx]->type);
     } /* end OpenMP critical */
 
     /* Free dynamically allocated buffers */
diff --git a/src/nco/ncks.c b/src/nco/ncks.c
index 839d822..3f49915 100644
--- a/src/nco/ncks.c
+++ b/src/nco/ncks.c
@@ -111,6 +111,7 @@ int
 main(int argc,char **argv)
 {
   nco_bool ALPHABETIZE_OUTPUT=True; /* Option a */
+  nco_bool CPY_GRP_METADATA; /* [flg] Copy group metadata (attributes) */
   nco_bool EXCLUDE_INPUT_LIST=False; /* Option x */
   nco_bool EXTRACT_ALL_COORDINATES=False; /* Option c */
   nco_bool EXTRACT_ASSOCIATED_COORDINATES=True; /* Option C */
@@ -197,7 +198,7 @@ main(int argc,char **argv)
 
   const char * const CVS_Id="$Id$"; 
   const char * const CVS_Revision="$Revision$";
-  const char * const opt_sht_lst="34567aABb:CcD:d:FG:g:HhL:l:MmOo:Pp:qQrRs:uVv:X:xz-:";
+  const char * const opt_sht_lst="34567aABb:CcD:d:FG:g:HhL:l:MmOo:Pp:qQrRs:t:uVv:X:xz-:";
 
   cnk_sct cnk; /* [sct] Chunking structure */
 
@@ -208,6 +209,8 @@ main(int argc,char **argv)
   ddra_info_sct ddra_info={.flg_ddra=False};
 #endif /* !__cplusplus */
 
+  double wgt_vld_thr=NC_MIN_DOUBLE; /* [frc] Weight threshold for valid destination value */
+
   extern char *optarg;
   extern int optind;
 
@@ -215,6 +218,8 @@ main(int argc,char **argv)
 
   gpe_sct *gpe=NULL; /* [sng] Group Path Editing (GPE) structure */
 
+  int *in_id_arr; /* [id] netCDF file IDs used by OpenMP code */
+
   int abb_arg_nbr=0;
   int att_glb_nbr;
   int att_grp_nbr;
@@ -241,12 +246,13 @@ main(int argc,char **argv)
   int ppc_nbr=0; /* [nbr] Number of PPC arguments */
   int rgr_nbr=0; /* [nbr] Number of regridding arguments */
   int rcd=NC_NOERR; /* [rcd] Return code */
+  int thr_idx; /* [idx] Index of current thread */
+  int thr_nbr=int_CEWI; /* [nbr] Thread number Option t */
   int var_lst_in_nbr=0;
   int var_nbr_fl;
   int var_ntm_fl;
   int xtr_nbr=0; /* xtr_nbr will not otherwise be set for -c with no -v */
 
-  /* DYW */
   kvm_sct *sld_nfo=NULL; /* [sct] Container for SLD/SCRIP information */
 
   md5_sct *md5=NULL; /* [sct] MD5 configuration */
@@ -364,11 +370,14 @@ main(int argc,char **argv)
       {"rgr",required_argument,0,0}, /* [sng] Regridding */
       {"regridding",required_argument,0,0}, /* [sng] Regridding */
       {"rgr_in",required_argument,0,0}, /* [sng] File containing fields to be regridded */
-      {"rgr_out",required_argument,0,0}, /* [sng] File containing regridded fields */
       {"rgr_grd_src",required_argument,0,0}, /* [sng] File containing input grid */
       {"rgr_grd_dst",required_argument,0,0}, /* [sng] File containing destination grid */
       {"rgr_map",required_argument,0,0}, /* [sng] File containing mapping weights from source to destination grid */
+      {"map_file",required_argument,0,0}, /* [sng] File containing mapping weights from source to destination grid */
       {"rgr_var",required_argument,0,0}, /* I [sng] Variable for special regridding treatment */
+      {"rgr_rnr",required_argument,0,0}, /* [flg] Renormalize destination values by valid area */
+      {"rnr",required_argument,0,0}, /* [flg] Renormalize destination values by valid area */
+      {"renormalize",required_argument,0,0}, /* [flg] Renormalize destination values by valid area */
       {"scrip",required_argument,0,0}, /* SCRIP file */
       {"tst_udunits",required_argument,0,0},
       {"xml_spr_chr",required_argument,0,0}, /* [flg] Separator for XML character types */
@@ -430,6 +439,9 @@ main(int argc,char **argv)
       {"spinlock",no_argument,0,'S'}, /* [flg] Suspend with signal handler to facilitate debugging */
       {"sng_fmt",required_argument,0,'s'},
       {"string",required_argument,0,'s'},
+      {"thr_nbr",required_argument,0,'t'},
+      {"threads",required_argument,0,'t'},
+      {"omp_num_threads",required_argument,0,'t'},
       {"units",no_argument,0,'u'},
       {"var_val",no_argument,0,'V'}, /* [flg] Print variable values only */
       {"variable",required_argument,0,'v'},
@@ -574,24 +586,26 @@ main(int argc,char **argv)
       if(!strcmp(opt_crr,"no_blank") || !strcmp(opt_crr,"no-blank") || !strcmp(opt_crr,"noblank")) PRN_MSS_VAL_BLANK=!PRN_MSS_VAL_BLANK;
       if(!strcmp(opt_crr,"no_clb") || !strcmp(opt_crr,"no-clobber") || !strcmp(opt_crr,"no_clobber") || !strcmp(opt_crr,"noclobber")) FORCE_NOCLOBBER=!FORCE_NOCLOBBER;
       if(!strcmp(opt_crr,"no_nm_prn") || !strcmp(opt_crr,"no_dmn_var_nm")) PRN_DMN_VAR_NM=False; /* endif "no_nm_prn" */
-      if(!strcmp(opt_crr,"ppc") || !strcmp(opt_crr,"precision_preserving_compression") || !strcmp(opt_crr,"quantize")){
-        ppc_arg[ppc_nbr]=(char *)strdup(optarg);
-        ppc_nbr++;
-      } /* endif "ppc" */
+      if(!strcmp(opt_crr,"ppc") || !strcmp(opt_crr,"precision_preserving_compression") || !strcmp(opt_crr,"quantize")) ppc_arg[ppc_nbr++]=(char *)strdup(optarg);
       if(!strcmp(opt_crr,"rad") || !strcmp(opt_crr,"retain_all_dimensions") || !strcmp(opt_crr,"orphan_dimensions") || !strcmp(opt_crr,"rph_dmn")) RETAIN_ALL_DIMS=True;
       if(!strcmp(opt_crr,"ram_all") || !strcmp(opt_crr,"create_ram") || !strcmp(opt_crr,"diskless_all")) RAM_CREATE=True; /* [flg] Open (netCDF3) file(s) in RAM */
       if(!strcmp(opt_crr,"ram_all") || !strcmp(opt_crr,"open_ram") || !strcmp(opt_crr,"diskless_all")) RAM_OPEN=True; /* [flg] Create file in RAM */
       if(!strcmp(opt_crr,"rgr") || !strcmp(opt_crr,"regridding")){
         flg_rgr=True;
-        rgr_nbr++;
-        rgr_arg=(char **)nco_realloc(rgr_arg,rgr_nbr*sizeof(char *));
-        rgr_arg[rgr_nbr-1]=(char *)strdup(optarg);
+        rgr_arg=(char **)nco_realloc(rgr_arg,(rgr_nbr+1)*sizeof(char *));
+        rgr_arg[rgr_nbr++]=(char *)strdup(optarg);
       } /* endif "rgr" */
       if(!strcmp(opt_crr,"rgr_in")) rgr_in=(char *)strdup(optarg);
-      if(!strcmp(opt_crr,"rgr_out")) rgr_out=(char *)strdup(optarg);
       if(!strcmp(opt_crr,"rgr_grd_src")) rgr_grd_src=(char *)strdup(optarg);
       if(!strcmp(opt_crr,"rgr_grd_dst")) rgr_grd_dst=(char *)strdup(optarg);
-      if(!strcmp(opt_crr,"rgr_map")) rgr_map=(char *)strdup(optarg);
+      if(!strcmp(opt_crr,"rgr_map") || !strcmp(opt_crr,"map_file")){
+        flg_rgr=True;
+	rgr_map=(char *)strdup(optarg);
+      } /* endif rgr_map */
+      if(!strcmp(opt_crr,"rnr") || !strcmp(opt_crr,"rgr_rnr") || !strcmp(opt_crr,"renormalize")){
+        wgt_vld_thr=strtod(optarg,&sng_cnv_rcd);
+        if(*sng_cnv_rcd) nco_sng_cnv_err(optarg,"strtod",sng_cnv_rcd);
+      } /* endif rgr_rnr */
       if(!strcmp(opt_crr,"rgr_var")) rgr_var=(char *)strdup(optarg);
       if(!strcmp(opt_crr,"secret") || !strcmp(opt_crr,"scr") || !strcmp(opt_crr,"shh")){
         (void)fprintf(stdout,"Hidden/unsupported NCO options:\nCompiler used\t\t--cmp, --compiler\nCopyright\t\t--cpy, --copyright, --license\nHidden functions\t--scr, --ssh, --secret\nLibrary used\t\t--lbr, --library\nMemory clean\t\t--mmr_cln, --cln, --clean\nMemory dirty\t\t--mmr_drt, --drt, --dirty\nMPI implementation\t--mpi_implementation\nNo-clobber files\t--no_clb, --no-clobber\nPseudonym\t\t--pseudonym, -Y (ncra only)\nRegridding\t\t--rgr...\nSpinlock\t\t--spinlock\nStreams\t\t\t [...]
@@ -759,6 +773,10 @@ main(int argc,char **argv)
     case 's': /* User specified delimiter string for printed output */
       dlm_sng=(char *)strdup(optarg);
       break;
+    case 't': /* Thread number */
+      thr_nbr=(int)strtol(optarg,&sng_cnv_rcd,NCO_SNG_CNV_BASE10);
+      if(*sng_cnv_rcd) nco_sng_cnv_err(optarg,"strtol",sng_cnv_rcd);
+      break;
     case 'u': /* Toggle printing dimensional units */
       PRN_DMN_UNITS_TGL=True;
       break;
@@ -825,7 +843,6 @@ main(int argc,char **argv)
 #endif /* !_LANGINFO_H */
 
   /* Initialize traversal table */
-
   (void)trv_tbl_init(&trv_tbl);
  
   /* Get program info for regressions tests */
@@ -834,14 +851,21 @@ main(int argc,char **argv)
   /* Process positional arguments and fill in filenames */
   fl_lst_in=nco_fl_lst_mk(argv,argc,optind,&fl_nbr,&fl_out,&FL_LST_IN_FROM_STDIN);
   
+  /* Initialize thread information */
+  thr_nbr=nco_openmp_ini(thr_nbr);
+  in_id_arr=(int *)nco_malloc(thr_nbr*sizeof(int));
+  trv_tbl->thr_nbr=thr_nbr;
+  trv_tbl->in_id_arr=in_id_arr;
+
   /* Parse filename */
   fl_in=nco_fl_nm_prs(fl_in,0,&fl_nbr,fl_lst_in,abb_arg_nbr,fl_lst_abb,fl_pth);
   /* Make sure file is on local system and is readable or die trying */
   fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FL_RTR_RMT_LCN);
   /* Open file using appropriate buffer size hints and verbosity */
   if(RAM_OPEN) md_open=NC_NOWRITE|NC_DISKLESS; else md_open=NC_NOWRITE;
-  rcd+=nco_fl_open(fl_in,md_open,&bfr_sz_hnt,&in_id);
-
+  for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) rcd+=nco_fl_open(fl_in,md_open,&bfr_sz_hnt,in_id_arr+thr_idx);
+  in_id=in_id_arr[0];
+  
   /* Construct GTT (Group Traversal Table), check -v and -g input names and create extraction list */
   (void)nco_bld_trv_tbl(in_id,trv_pth,lmt_nbr,lmt_arg,aux_nbr,aux_arg,MSA_USR_RDR,FORTRAN_IDX_CNV,grp_lst_in,grp_lst_in_nbr,var_lst_in,xtr_nbr,EXTRACT_ALL_COORDINATES,GRP_VAR_UNN,GRP_XTR_VAR_XCL,EXCLUDE_INPUT_LIST,EXTRACT_ASSOCIATED_COORDINATES,nco_pck_plc_nil,&flg_dne,trv_tbl);
 
@@ -936,70 +960,94 @@ main(int argc,char **argv)
 
     /* Regridding */
     if(flg_rgr){
-      rgr_sct rgr_nfo;
+      rgr_sct *rgr_nfo;
       /* Initialize regridding structure */
       rgr_in=(char *)strdup(fl_in);
-      rcd=nco_rgr_ini(in_id,rgr_arg,rgr_nbr,rgr_in,rgr_out,rgr_grd_src,rgr_grd_dst,rgr_map,rgr_var,&rgr_nfo);
-      rgr_nfo.fl_out_tmp=nco_fl_out_open(rgr_nfo.fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&rgr_nfo.out_id);
+      rgr_out=(char *)strdup(fl_out);
+      rgr_nfo=nco_rgr_ini(in_id,rgr_arg,rgr_nbr,rgr_in,rgr_out,rgr_grd_src,rgr_grd_dst,rgr_map,rgr_var,wgt_vld_thr);
+      rgr_nfo->fl_out_tmp=nco_fl_out_open(rgr_nfo->fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
+
+      /* Copy Global Metadata */
+      rgr_nfo->out_id=out_id;
+      //      out_id=rgr_nfo->out_id;
+      nco_bool PCK_ATT_CPY=True; /* [flg] Copy attributes "scale_factor", "add_offset" */
+      (void)nco_att_cpy(in_id,out_id,NC_GLOBAL,NC_GLOBAL,PCK_ATT_CPY);
+      /* Catenate time-stamped command line to "history" global attribute */
+      if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+      if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
+      if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
+
       /* Regrid fields */
-      rcd=nco_rgr_ctl(&rgr_nfo);
+      rcd=nco_rgr_ctl(rgr_nfo,trv_tbl);
       /* Change from NCO_NOERR to NC_NOERR */
       rcd=NC_NOERR;
-    } /* endif !flg_rgr */
 
-    /* Initialize, decode, and set PPC information */
-    if(ppc_nbr > 0) nco_ppc_ini(in_id,&dfl_lvl,fl_out_fmt,ppc_arg,ppc_nbr,trv_tbl);
+      /* Close output file and move it from temporary to permanent location */
+      (void)nco_fl_out_cls(rgr_nfo->fl_out,rgr_nfo->fl_out_tmp,out_id);
 
-    /* Verify output file format supports requested actions */
-    (void)nco_fl_fmt_vet(fl_out_fmt,cnk_nbr,dfl_lvl);
+      /* Free regridding structure */
+      rgr_nfo=nco_rgr_free(rgr_nfo);
+    } /* endif !flg_rgr */
 
-    /* Open output file */
-    fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
+    if(!flg_rgr){
+      
+      /* Initialize, decode, and set PPC information */
+      if(ppc_nbr > 0) nco_ppc_ini(in_id,&dfl_lvl,fl_out_fmt,ppc_arg,ppc_nbr,trv_tbl);
+      
+      /* Verify output file format supports requested actions */
+      (void)nco_fl_fmt_vet(fl_out_fmt,cnk_nbr,dfl_lvl);
+      
+      /* Open output file */
+      fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
     
-    /* Create structure with all chunking information */
-    if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
+      /* Initialize chunking from user-specified inputs */
+      if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
-    /* Define extracted groups, variables, and attributes in output file */
-    (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,PRN_GLB_METADATA,PRN_VAR_METADATA,RETAIN_ALL_DIMS,nco_pck_plc_nil,rec_dmn_nm,trv_tbl);
+      /* Define extracted groups, variables, and attributes in output file */
+      CPY_GRP_METADATA = FORCE_APPEND ? False : PRN_GLB_METADATA;
+      (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,CPY_GRP_METADATA,PRN_VAR_METADATA,RETAIN_ALL_DIMS,nco_pck_plc_nil,rec_dmn_nm,trv_tbl);
 
-    /* Catenate time-stamped command line to "history" global attribute */
-    if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
-    if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
+      /* Catenate time-stamped command line to "history" global attribute */
+      if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+      if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+      if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
 #ifdef ENABLE_MPI
-    if(prc_rnk == rnk_mgr)
-      if(prc_nbr > 0 && HISTORY_APPEND) (void)nco_mpi_att_cat(out_id,prc_nbr);
+      if(prc_rnk == rnk_mgr)
+	if(prc_nbr > 0 && HISTORY_APPEND) (void)nco_mpi_att_cat(out_id,prc_nbr);
 #endif /* !ENABLE_MPI */
+      
+      /* Turn off default filling behavior to enhance efficiency */
+      nco_set_fill(out_id,NC_NOFILL,&fll_md_old);
+      
+      /* Take output file out of define mode */
+      if(hdr_pad == 0UL){
+	(void)nco_enddef(out_id);
+      }else{
+	(void)nco__enddef(out_id,hdr_pad);
+	if(nco_dbg_lvl >= nco_dbg_scl) (void)fprintf(stderr,"%s: INFO Padding header with %lu extra bytes\n",nco_prg_nm_get(),(unsigned long)hdr_pad);
+      } /* hdr_pad */
 
-    /* Turn off default filling behavior to enhance efficiency */
-    nco_set_fill(out_id,NC_NOFILL,&fll_md_old);
-
-    /* Take output file out of define mode */
-    if(hdr_pad == 0UL){
-      (void)nco_enddef(out_id);
-    }else{
-      (void)nco__enddef(out_id,hdr_pad);
-      if(nco_dbg_lvl >= nco_dbg_scl) (void)fprintf(stderr,"%s: INFO Padding header with %lu extra bytes\n",nco_prg_nm_get(),(unsigned long)hdr_pad);
-    } /* hdr_pad */
-
-    /* [fnc] Open unformatted binary data file for writing */
-    if(fl_bnr) fp_bnr=nco_bnr_open(fl_bnr);
-
-    /* Timestamp end of metadata setup and disk layout */
-    rcd+=nco_ddra((char *)NULL,(char *)NULL,&ddra_info);
-    ddra_info.tmr_flg=nco_tmr_rgl;
-    /* Write extracted data to output file */
-    if(PRN_VAR_DATA) (void)nco_xtr_wrt(in_id,out_id,gpe,fp_bnr,md5,HAVE_LIMITS,trv_tbl);
-
-    /* [fnc] Close unformatted binary data file */
-    if(fp_bnr) (void)nco_bnr_close(fp_bnr,fl_bnr);
-
-    if(nco_dbg_lvl_get() == 14){
-      (void)nco_wrt_trv_tbl(in_id,trv_tbl,True);
-      (void)nco_wrt_trv_tbl(out_id,trv_tbl,True);
-    } /* endif dbg */
+      /* [fnc] Open unformatted binary data file for writing */
+      if(fl_bnr) fp_bnr=nco_bnr_open(fl_bnr);
+      
+      /* Timestamp end of metadata setup and disk layout */
+      rcd+=nco_ddra((char *)NULL,(char *)NULL,&ddra_info);
+      ddra_info.tmr_flg=nco_tmr_rgl;
+      /* Write extracted data to output file */
+      if(PRN_VAR_DATA) (void)nco_xtr_wrt(in_id,out_id,gpe,fp_bnr,md5,HAVE_LIMITS,trv_tbl);
+      
+      /* [fnc] Close unformatted binary data file */
+      if(fp_bnr) (void)nco_bnr_close(fp_bnr,fl_bnr);
+      
+      if(nco_dbg_lvl_get() == 14){
+	(void)nco_wrt_trv_tbl(in_id,trv_tbl,True);
+	(void)nco_wrt_trv_tbl(out_id,trv_tbl,True);
+      } /* endif dbg */
 
-    /* Close output file and move it from temporary to permanent location */
-    (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id);
+      /* Close output file and move it from temporary to permanent location */
+      (void)nco_fl_out_cls(fl_out,fl_out_tmp,out_id);
+    
+    } /* flg_rgr */
     
   }else{ /* !fl_out */
 
@@ -1132,8 +1180,8 @@ main(int argc,char **argv)
   /* goto close_and_free */
 close_and_free: 
 
-  /* Close input netCDF file */
-  nco_close(in_id);
+  /* Close input netCDF files */
+  for(thr_idx=0;thr_idx<thr_nbr;thr_idx++) nco_close(in_id_arr[thr_idx]);
 
   /* Remove local copy of file */
   if(FL_RTR_RMT_LCN && RM_RMT_FL_PST_PRC) (void)nco_fl_rm(fl_in);
@@ -1143,12 +1191,11 @@ close_and_free:
     /* ncks-specific memory */
     if(fl_bnr) fl_bnr=(char *)nco_free(fl_bnr);
     if(rec_dmn_nm) rec_dmn_nm=(char *)nco_free(rec_dmn_nm); 
-    /* DYW */
     if(fl_scrip){
       fl_scrip=(char *)nco_free(fl_scrip);
       idx=0;
       if(nco_dbg_lvl > nco_dbg_fl) while(sld_nfo[idx].key) nco_kvm_prn(sld_nfo[idx++]);
-      if(sld_nfo) nco_kvm_free(sld_nfo);
+      if(sld_nfo) sld_nfo=nco_kvm_lst_free(sld_nfo,idx);
     } /* endif fl_scrip */
     /* NCO-generic clean-up */
     /* Free individual strings/arrays */
@@ -1160,6 +1207,7 @@ close_and_free:
     if(fl_out_tmp) fl_out_tmp=(char *)nco_free(fl_out_tmp);
     if(fl_pth) fl_pth=(char *)nco_free(fl_pth);
     if(fl_pth_lcl) fl_pth_lcl=(char *)nco_free(fl_pth_lcl);
+    if(in_id_arr) in_id_arr=(int *)nco_free(in_id_arr);
     if(spr_nmr) spr_nmr=(char *)nco_free(spr_nmr);
     if(spr_chr) spr_chr=(char *)nco_free(spr_chr);
     /* Free lists of strings */
@@ -1172,7 +1220,6 @@ close_and_free:
     for(idx=0;idx<aux_nbr;idx++) aux_arg[idx]=(char *)nco_free(aux_arg[idx]);
     for(idx=0;idx<lmt_nbr;idx++) lmt_arg[idx]=(char *)nco_free(lmt_arg[idx]);
     for(idx=0;idx<ppc_nbr;idx++) ppc_arg[idx]=(char *)nco_free(ppc_arg[idx]);
-    if(rgr_nbr > 0) rgr_arg=nco_sng_lst_free(rgr_arg,rgr_nbr);
     /* Free chunking information */
     for(idx=0;idx<cnk_nbr;idx++) cnk_arg[idx]=(char *)nco_free(cnk_arg[idx]);
     if(cnk_nbr > 0) cnk.cnk_dmn=(cnk_dmn_sct **)nco_cnk_lst_free(cnk.cnk_dmn,cnk_nbr);
diff --git a/src/nco/nco.h b/src/nco/nco.h
index b76c8fc..3519be5 100644
--- a/src/nco/nco.h
+++ b/src/nco/nco.h
@@ -289,10 +289,10 @@ extern "C" {
 # define NCO_VERSION_MAJOR 4
 #endif /* !NCO_VERSION_MAJOR */
 #ifndef NCO_VERSION_MINOR
-# define NCO_VERSION_MINOR 4
+# define NCO_VERSION_MINOR 5
 #endif /* !NCO_VERSION_MINOR */
 #ifndef NCO_VERSION_PATCH
-# define NCO_VERSION_PATCH 9
+# define NCO_VERSION_PATCH 0
 #endif /* !NCO_VERSION_PATCH */
 #ifndef NCO_VERSION_NOTE
 # define NCO_VERSION_NOTE  "" /* May be blank */
@@ -302,7 +302,7 @@ extern "C" {
 # define NCO_LIB_VERSION ( NCO_VERSION_MAJOR * 100 + NCO_VERSION_MINOR * 10 + NCO_VERSION_PATCH )
 #endif /* !NCO_LIB_VERSION */
 #ifndef NCO_VERSION
-# define NCO_VERSION "4.4.9"
+# define NCO_VERSION "4.5.0"
 #endif /* !NCO_VERSION */
 
 /* Compatibility tokens new to netCDF4 netcdf.h: */
@@ -879,6 +879,7 @@ extern "C" {
   
   /* Regrid structure */
   typedef struct{ /* rgr_sct */
+    // File names specifiable with individual command line switches
     char *drc_tps; /* [sng] Data directory for Tempest grids, meshes, and weights */
     char *fl_grd_src; /* [sng] File containing input grid */
     char *fl_grd_dst; /* [sng] File containing destination grid */
@@ -886,15 +887,30 @@ extern "C" {
     char *fl_out; /* [sng] File containing regridded fields */
     char *fl_out_tmp; /* [sng] Temporary file containing regridded fields */
     char *fl_map; /* [sng] File containing mapping weights from source to destination grid */
-    char **rgr_arg; /* [sng] Regridding arguments */
     char *var_nm; /* [sng] Variable for special regridding treatment */
-    int rgr_nbr; /* [nbr] Number of regridding arguments */
+    // Grid names specifiable with key-value syntax
+    char **rgr_arg; /* [sng] Regridding arguments */
+    char *area_nm; /* [sng] Name of variable containing gridcell area */
+    char *bnd_nm; /* [sng] Name of dimension to employ for spatial bounds */
+    char *bnd_tm_nm; /* [sng] Name of dimension to employ for temporal bounds */
+    char *col_nm; /* [sng] Name of horizontal spatial dimension on unstructured grid */
+    char *lat_bnd_nm; /* [sng] Name of rectangular boundary variable for latitude */
+    char *lat_nm; /* [sng] Name of dimension to recognize as latitude */
+    char *lat_vrt_nm; /* [sng] Name of non-rectangular boundary variable for latitude */
+    char *lat_wgt_nm; /* [sng] Name of variable containing latitude weights */
+    char *lon_bnd_nm; /* [sng] Name of rectangular boundary variable for longitude */
+    char *lon_nm; /* [sng] Name of dimension to recognize as longitude */
+    char *lon_vrt_nm; /* [sng] Name of non-rectangular boundary variable for longitude */
+    char *vrt_nm; /* [sng] Name of dimension to employ for vertices */
+    double wgt_vld_thr; /* [frc] Weight threshold for valid destination value */
     int in_id; /* [id] Input netCDF file ID */
     int out_id; /* [id] Output netCDF file ID */
+    int rgr_nbr; /* [nbr] Number of regridding arguments */
     nco_bool flg_usr_rqs; /* [flg] User requested regridding */
     nco_bool flg_grd_src; /* [flg] User-specified input grid */
     nco_bool flg_grd_dst; /* [flg] User-specified destination grid */
     nco_bool flg_map; /* [flg] User-specified mapping weights */
+    nco_bool flg_rnr; /* [flg] Renormalize destination values by valid area */
   } rgr_sct;
 
   /* Key-value structure */
@@ -992,7 +1008,7 @@ extern "C" {
   } aux_crd_sct; 
 
   /* GTT Variable dimensions:
-  Dimension have name and size, and can have an associated variable (coordinate variable) */
+     Dimensions have name and size, and maybe an associated (coordinate) variable */
   typedef struct{ 
     char *dmn_nm_fll;        /* [sng] Full dimension name */
     char *dmn_nm;            /* [sng] Dimension name */
@@ -1058,6 +1074,7 @@ extern "C" {
     nco_bool flg_ncs;                 /* [flg] Group is ancestor of specified group or variable */
     nco_bool flg_nsx;                 /* [flg] Object matches intersection criteria */
     nco_bool flg_rcr;                 /* [flg] Extract group recursively */
+    nco_bool flg_rgr;                 /* [flg] Regrid variable */ 
     nco_bool flg_unn;                 /* [flg] Object matches union criteria */
     nco_bool flg_vfp;                 /* [flg] Variable matches full path specification */
     nco_bool flg_vsg;                 /* [flg] Variable selected because group matches */
@@ -1153,6 +1170,8 @@ extern "C" {
     int nsm_nbr;            /* [nbr] (ncge) Number of ensembles (i.e., number in first file) */ 
     nsm_sct *nsm;           /* [lst] (ncge) List of ensembles (size is nsm_nbr) */ 
     char *nsm_sfx;          /* [sng] (ncge) Ensemble suffix (e.g., /cesm + _avg). Store here instead of passing as function parameters (ncge only) */
+    int thr_nbr; /* [nbr] Thread number Option t */
+    int *in_id_arr; /* [id] netCDF file IDs used by OpenMP code */
   } trv_tbl_sct;
  
   /* GPE duplicate name check structure */
diff --git a/src/nco/nco_att_utl.c b/src/nco/nco_att_utl.c
index bb0a056..4ea5d2f 100644
--- a/src/nco/nco_att_utl.c
+++ b/src/nco/nco_att_utl.c
@@ -58,7 +58,7 @@ nco_aed_prc /* [fnc] Process single attribute edit for single variable */
     (void)nco_inq_var(nc_id,var_id,var_nm,(nc_type *)NULL,(int *)NULL,(int *)NULL,&nbr_att);
   } /* end else */
   
-  if(nco_dbg_lvl_get() >= nco_dbg_var && nco_dbg_lvl_get() != nco_dbg_dev) (void)fprintf(stdout,"%s: INFO %s examining variable %s\n",nco_prg_nm_get(),fnc_nm,var_nm);
+  if(nco_dbg_lvl_get() >= nco_dbg_crr && nco_dbg_lvl_get() != nco_dbg_dev) (void)fprintf(stdout,"%s: INFO %s examining variable %s\n",nco_prg_nm_get(),fnc_nm,var_nm);
 
   /* Query attribute metadata when attribute name was specified */
   if(aed.att_nm) rcd_inq_att=nco_inq_att_flg(nc_id,var_id,aed.att_nm,&att_typ,&att_sz);
@@ -561,11 +561,144 @@ nco_fl_lst_att_cat /* [fnc] Add input file list global attribute */
 } /* end nco_fl_lst_att_cat() */
  
 void 
+nco_prv_att_cat /* [fnc] Add provenance (history contents) of appended file to provenance attribute */
+(const char * const fl_in, /* I [sng] Name of input-file */
+ const int in_id, /* I [id] netCDF input-file ID */
+ const int out_id) /* I [id] netCDF output-file ID */
+{
+  /* Purpose: Add provenance (history contents) of appended file to provenance attribute
+     NB: "Provenance" means, to NCO, the contents of the history attribute 
+     This is an operational definition that may change in the future
+     Other defensible definitions of "provenance" would be the contents of ALL global attributes, not just history */
+  
+  /* Length of string + NUL required to hold output of ctime() */
+#define TIME_STAMP_SNG_LNG 25 
+  
+  char *ctime_sng;
+  char *hst_sng;
+  char *hst_crr=NULL;
+  char *prv_crr=NULL;
+  char *prv_new;
+
+  char att_nm[NC_MAX_NAME];
+  char time_stamp_sng[TIME_STAMP_SNG_LNG];
+  
+  const char att_nm_prv[]="history_of_appended_files"; /* [sng] Lowercase name of provenance attribute */
+  const char att_nm_hst[]="history"; /* [sng] Lowercase name of history attribute */
+  
+  int idx;
+  int glb_att_nbr;
+  int rcd=NC_NOERR; /* [rcd] Return code */
+
+  long att_sz=0L;
+
+  nc_type att_typ;
+  
+  time_t time_crr_time_t;
+
+  /* Create timestamp string */
+  time_crr_time_t=time((time_t *)NULL);
+  ctime_sng=ctime(&time_crr_time_t);
+  /* NUL-terminate time_stamp_sng */
+  time_stamp_sng[TIME_STAMP_SNG_LNG-1]='\0';
+  /* Eliminate carriage return in ctime_sng */
+  (void)strncpy(time_stamp_sng,ctime_sng,TIME_STAMP_SNG_LNG-1UL);
+
+  /* Get number of global attributes in input file */
+  (void)nco_inq(in_id,(int *)NULL,(int *)NULL,&glb_att_nbr,(int *)NULL);
+
+  for(idx=0;idx<glb_att_nbr;idx++){
+    (void)nco_inq_attname(in_id,NC_GLOBAL,idx,att_nm);
+    if(!strcasecmp(att_nm,att_nm_hst)) break;
+  } /* end loop over att */
+
+  if(idx == glb_att_nbr){
+    /* Input file does not contain Global attribute "[hH]istory" */
+    char hst_sng_fmt[]="Appended file %s had no \"%s\" attribute\n";
+
+    att_sz=strlen(hst_sng_fmt)+strlen(time_stamp_sng)+strlen(fl_in)+strlen(att_nm_hst);
+    hst_sng=(char *)nco_malloc((att_sz+1L)*sizeof(char));
+    hst_sng[att_sz]='\0';
+    (void)sprintf(hst_sng,hst_sng_fmt,time_stamp_sng,fl_in,att_nm_hst);
+  }else{
+    /* Input file contains Global attribute "[hH]istory" */
+    char hst_sng_fmt[]="Appended file %s had following \"%s\" attribute:\n%s\n";
+
+    (void)nco_inq_att(in_id,NC_GLOBAL,att_nm,&att_typ,&att_sz);
+    if(att_typ != NC_CHAR){
+      if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: WARNING the \"%s\" global attribute is type %s, not %s. Therefore contents will not be appended to %s in output file.\n",nco_prg_nm_get(),att_nm,nco_typ_sng(att_typ),nco_typ_sng(NC_CHAR),att_nm);
+      return;
+    } /* end if */
+
+    /* Allocate and NUL-terminate space for current history attribute
+       If history attribute is of size zero then ensure strlen(hst_crr) == 0 */
+    hst_crr=(char *)nco_malloc((att_sz+1L)*sizeof(char));
+    hst_crr[att_sz]='\0';
+    if(att_sz > 0) (void)nco_get_att(in_id,NC_GLOBAL,att_nm,(void *)hst_crr,NC_CHAR);
+
+    att_sz=strlen(hst_sng_fmt)+strlen(fl_in)+strlen(att_nm)+strlen(hst_crr);
+    hst_sng=(char *)nco_malloc((att_sz+1L)*sizeof(char));
+    hst_sng[att_sz]='\0';
+    (void)sprintf(hst_sng,hst_sng_fmt,fl_in,att_nm,hst_crr);
+  } /* endif history global attribute exists in input file */
+
+  /* Get number of global attributes in output file */
+  (void)nco_inq(out_id,(int *)NULL,(int *)NULL,&glb_att_nbr,(int *)NULL);
+
+  for(idx=0;idx<glb_att_nbr;idx++){
+    (void)nco_inq_attname(out_id,NC_GLOBAL,idx,att_nm);
+    if(!strcasecmp(att_nm,att_nm_prv)) break;
+  } /* end loop over att */
+
+  /* Fill-in provenance string */
+  if(idx == glb_att_nbr){
+    /* Global attribute for provenance does not yet exist in output */
+
+    /* Add 3 for formatting characters */
+    att_sz=strlen(hst_sng)+strlen(time_stamp_sng)+2UL;
+    prv_new=(char *)nco_malloc((att_sz+1L)*sizeof(char));
+    prv_new[att_sz]='\0';
+    (void)sprintf(prv_new,"%s: %s",time_stamp_sng,hst_sng);
+    /* Set attribute name to default */
+    (void)strcpy(att_nm,att_nm_prv);
+
+  }else{ 
+    /* Global provenance attribute currently exists */
+  
+    /* NB: ncattinq(), unlike strlen(), counts terminating NUL for stored NC_CHAR arrays */
+    (void)nco_inq_att(out_id,NC_GLOBAL,att_nm,&att_typ,&att_sz);
+    if(att_typ != NC_CHAR){
+      if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: WARNING the \"%s\" global attribute is type %s, not %s. Therefore contents will not be appended to %s in output file.\n",nco_prg_nm_get(),att_nm,nco_typ_sng(att_typ),nco_typ_sng(NC_CHAR),att_nm);
+      return;
+    } /* end if */
+
+    /* Allocate and NUL-terminate space for current provenance attribute
+       If provenance attribute is of size zero then ensure strlen(prv_crr) = 0 */
+    prv_crr=(char *)nco_malloc((att_sz+1L)*sizeof(char));
+    prv_crr[att_sz]='\0';
+    if(att_sz > 0) (void)nco_get_att(out_id,NC_GLOBAL,att_nm,(void *)prv_crr,NC_CHAR);
+
+    /* Add 4 for formatting characters */
+    prv_new=(char *)nco_malloc((strlen(prv_crr)+strlen(hst_sng)+strlen(time_stamp_sng)+4UL)*sizeof(char));
+    (void)sprintf(prv_new,"%s: %s%s",time_stamp_sng,hst_sng,prv_crr);
+  } /* endif provenance global attribute currently exists */
+
+  rcd+=nco_put_att(out_id,NC_GLOBAL,att_nm,NC_CHAR,(long int)(strlen(prv_new)),(void *)prv_new);
+
+  if(hst_sng) hst_sng=(char *)nco_free(hst_sng);
+  if(hst_crr) hst_crr=(char *)nco_free(hst_crr);
+  if(prv_crr) prv_crr=(char *)nco_free(prv_crr);
+  if(prv_new) prv_new=(char *)nco_free(prv_new);
+
+  return; /* 20050109: fxm added return to void function to squelch unwelcome gcc-3.4.2 warning */ 
+} /* end nco_prv_att_cat() */
+
+void 
 nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
 (const int out_id, /* I [id] netCDF output-file ID */
  const char * const hst_sng) /* I [sng] String to add to history attribute */
 {
-  /* Purpose: Add command line and date stamp to existing history attribute, if any,
+  /* Purpose: Add command line and date stamp to existing history attribute, if any, 
      and write them to specified output file */
   
   /* Length of string + NUL required to hold output of ctime() */
@@ -573,11 +706,11 @@ nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
   
   char att_nm[NC_MAX_NAME];
   char *ctime_sng;
-  char *history_crr=NULL;
-  char *history_new;
+  char *hst_crr=NULL;
+  char *hst_new;
   char time_stamp_sng[TIME_STAMP_SNG_LNG];
   
-  const char sng_history[]="history"; /* [sng] Possible name of history attribute */
+  const char att_nm_hst[]="history"; /* [sng] Lowercase name of history attribute */
   
   int idx;
   int glb_att_nbr;
@@ -594,7 +727,7 @@ nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
   ctime_sng=ctime(&time_crr_time_t);
   /* NUL-terminate time_stamp_sng */
   time_stamp_sng[TIME_STAMP_SNG_LNG-1]='\0';
-  /* Get rid of carriage return in ctime_sng */
+  /* Eliminate carriage return in ctime_sng */
   (void)strncpy(time_stamp_sng,ctime_sng,TIME_STAMP_SNG_LNG-1UL);
 
   /* Get number of global attributes in file */
@@ -602,7 +735,7 @@ nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
 
   for(idx=0;idx<glb_att_nbr;idx++){
     (void)nco_inq_attname(out_id,NC_GLOBAL,idx,att_nm);
-    if(!strcasecmp(att_nm,sng_history)) break;
+    if(!strcasecmp(att_nm,att_nm_hst)) break;
   } /* end loop over att */
 
   /* Fill-in history string */
@@ -610,10 +743,10 @@ nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
     /* Global attribute "[hH]istory" does not yet exist */
 
     /* Add 3 for formatting characters */
-    history_new=(char *)nco_malloc((strlen(hst_sng)+strlen(time_stamp_sng)+3UL)*sizeof(char));
-    (void)sprintf(history_new,"%s: %s",time_stamp_sng,hst_sng);
+    hst_new=(char *)nco_malloc((strlen(hst_sng)+strlen(time_stamp_sng)+3UL)*sizeof(char));
+    (void)sprintf(hst_new,"%s: %s",time_stamp_sng,hst_sng);
     /* Set attribute name to default */
-    (void)strcpy(att_nm,sng_history);
+    (void)strcpy(att_nm,att_nm_hst);
 
   }else{ 
     /* Global attribute "[hH]istory" currently exists */
@@ -626,22 +759,22 @@ nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
     } /* end if */
 
     /* Allocate and NUL-terminate space for current history attribute
-       If history attribute is of size zero then ensure strlen(history_crr) = 0 */
-    history_crr=(char *)nco_malloc((att_sz+1)*sizeof(char));
-    history_crr[att_sz]='\0';
-    if(att_sz > 0) (void)nco_get_att(out_id,NC_GLOBAL,att_nm,(void *)history_crr,NC_CHAR);
+       If history attribute is of size zero then ensure strlen(hst_crr) = 0 */
+    hst_crr=(char *)nco_malloc((att_sz+1L)*sizeof(char));
+    hst_crr[att_sz]='\0';
+    if(att_sz > 0) (void)nco_get_att(out_id,NC_GLOBAL,att_nm,(void *)hst_crr,NC_CHAR);
 
     /* Add 4 for formatting characters */
-    history_new=(char *)nco_malloc((strlen(history_crr)+strlen(hst_sng)+strlen(time_stamp_sng)+4UL)*sizeof(char));
-    (void)sprintf(history_new,"%s: %s\n%s",time_stamp_sng,hst_sng,history_crr);
+    hst_new=(char *)nco_malloc((strlen(hst_crr)+strlen(hst_sng)+strlen(time_stamp_sng)+4UL)*sizeof(char));
+    (void)sprintf(hst_new,"%s: %s\n%s",time_stamp_sng,hst_sng,hst_crr);
   } /* endif history global attribute currently exists */
 
-  rcd+=nco_put_att(out_id,NC_GLOBAL,att_nm,NC_CHAR,(long int)(strlen(history_new)+1UL),(void *)history_new);
+  rcd+=nco_put_att(out_id,NC_GLOBAL,att_nm,NC_CHAR,(long int)(strlen(hst_new)+1UL),(void *)hst_new);
 
-  history_crr=(char *)nco_free(history_crr);
-  history_new=(char *)nco_free(history_new);
+  hst_crr=(char *)nco_free(hst_crr);
+  hst_new=(char *)nco_free(hst_new);
 
-  return; /* 20050109: fxm added return to void function to squelch erroneous gcc-3.4.2 warning */ 
+  return; /* 20050109: fxm added return to void function to squelch unwelcome gcc-3.4.2 warning */ 
 } /* end nco_hst_att_cat() */
 
 aed_sct * /* O [sct] List of attribute edit structures */
@@ -1468,7 +1601,7 @@ nco_vrs_att_cat /* [fnc] Add NCO version global attribute */
 
   /* Insert thread number into value */
   att_val.cp=vrs_sng;
-  /* Initialize nco_openmp_thread_number attribute edit structure */
+  /* Initialize NCO version attribute edit structure */
   vrs_sng_aed.att_nm=att_nm;
   vrs_sng_aed.var_nm=NULL;
   vrs_sng_aed.id=NC_GLOBAL;
@@ -1540,3 +1673,66 @@ nco_mpi_att_cat /* [fnc] Add MPI tasks global attribute */
   (void)nco_aed_prc(out_id,NC_GLOBAL,mpi_nbr_aed);
 
 } /* end nco_mpi_att_cat() */
+
+nco_bool /* [O] Perform exception processing on this variable */
+nco_is_xcp /* [fnc] Determine whether to perform exception processing */
+(const char * const var_nm) /* [sng] Variable name */
+{
+  /* Purpose: Determine whether to perform exception processing */
+  const char *var_xcp_lst[]={"date_written","time_written"};
+  const int var_xcp_lst_nbr=2; /* [nbr] Number of items on exception list */
+  int xcp_idx; /* [idx] Exception list index */
+  for(xcp_idx=0;xcp_idx<var_xcp_lst_nbr;xcp_idx++)
+    if(!strcmp(var_nm,var_xcp_lst[xcp_idx])) break;
+  if(xcp_idx < var_xcp_lst_nbr) return True; else return False;
+} /* end nco_is_xcp() */
+  
+void
+nco_xcp_prc /* [fnc] Perform exception processing on this variable */
+(const char * const var_nm, /* [sng] Variable name */
+ const nc_type var_typ, /* I [enm] netCDF type of operand */
+ const long var_sz, /* I [nbr] Size (in elements) of operand */
+ char * const var_val) /* I/O [sng] Values of string operand */
+ {
+  /* Purpose: Perform exception processing on this variable
+     Exception processing currently limited to variables of type NC_CHAR */
+   char *ctime_sng;
+   time_t time_crr_time_t;
+   struct tm *time_crr_tm;
+
+  /* Create timestamp string */
+  time_crr_time_t=time((time_t *)NULL);
+  /* NB: easy to replace with localtime() if desired */
+  time_crr_tm=gmtime(&time_crr_time_t);
+  ctime_sng=ctime(&time_crr_time_t);
+
+  /* Currently both variables in list are NC_CHAR of size 8 when written
+     Interestingly, date_written and time_written are 2D (time x char)
+     Thus operators like ncra, ncwa may need to reduce their rank and shrink their size 
+     Otherwise these variables would need a dummy dimension for time or char 
+     For now, do not attempt to update values when var_sz != 8 */
+  assert(var_typ == NC_CHAR);
+  if(var_sz != 8) return;
+  
+  /* One block for each variable in exception list in nco_is_xcp() */
+  if(!strcmp(var_nm,"date_written")){
+    /* Contents of these fields are demonstrated by:
+       ncks -C -H -v date_written,time_written ${DATA}/ne30/rgr/famipc5_ne30_v0.3_00003.cam.h0.1979-01.nc
+       time[0]=31 chars[0] date_written[0--7]='04/29/15' 
+       time[0]=31 chars[0] time_written[0--7]='23:05:05' */
+    char *var_val_p1;
+    var_val_p1=(char *)nco_malloc((var_sz+1L)*sizeof(char));
+    sprintf(var_val_p1,"%02d/%02d/%02d",time_crr_tm->tm_mon+1,time_crr_tm->tm_mday,time_crr_tm->tm_year%100);
+    /* Copy string (except for terminating NUL) into variable (which likely does not have room for terminating NUL */
+    strncpy(var_val,var_val_p1,var_sz);
+    var_val_p1=(char *)nco_free(var_val_p1);
+    return;
+  } /* !date_written */
+  if(!strcmp(var_nm,"time_written")){
+    /* Datestamp strings are formatted thusly: "Fri Jun  5 17:24:13 2015\n" */
+    strncpy(var_val,ctime_sng+11,8);
+    return;
+  } /* !time_written */
+  
+ } /* end nco_xcp_prc() */
+
diff --git a/src/nco/nco_att_utl.h b/src/nco/nco_att_utl.h
index 03c9e37..5d70abf 100644
--- a/src/nco/nco_att_utl.h
+++ b/src/nco/nco_att_utl.h
@@ -72,6 +72,12 @@ nco_hst_att_cat /* [fnc] Add command line, date stamp to history attribute */
  const char * const hst_sng); /* I [sng] String to add to history attribute */
 
 void 
+nco_prv_att_cat /* [fnc] Add provenance (history contents) of appended file to provenance attribute */
+(const char * const fl_in, /* I [sng] Name of input-file */
+ const int in_id, /* I [id] netCDF input-file ID */
+ const int out_id); /* I [id] netCDF output-file ID */
+
+void 
 nco_mpi_att_cat /* [fnc] Add MPI tasks global attribute */
 (const int out_id, /* I [id] netCDF output-file ID */
  const int mpi_nbr); /* I [nbr] MPI nodes/tasks number */
@@ -125,6 +131,17 @@ void
 nco_vrs_att_cat /* [fnc] Add NCO version global attribute */
 (const int out_id); /* I [id] netCDF output-file ID */
 
+nco_bool /* [O] Perform exception processing on this variable */
+nco_is_xcp /* [fnc] Determine whether to perform exception processing */
+(const char * const var_nm); /* [sng] Variable name */
+
+void
+nco_xcp_prc /* [fnc] Perform exception processing on this variable */
+(const char * const var_nm, /* [sng] Variable name */
+ const nc_type var_typ, /* I [enm] netCDF type of operand */
+ const long var_sz, /* I [nbr] Size (in elements) of operand */
+ char * const var_val); /* I/O [sng] Values of operand */
+
 #ifdef __cplusplus
 } /* end extern "C" */
 #endif /* __cplusplus */
diff --git a/src/nco/nco_aux.c b/src/nco/nco_aux.c
index b1be468..986ae34 100644
--- a/src/nco/nco_aux.c
+++ b/src/nco/nco_aux.c
@@ -350,10 +350,6 @@ nco_aux_prs
   if(bnd_bx_sng_tmp) bnd_bx_sng_tmp=(char *)nco_free(bnd_bx_sng_tmp);
   
   if(!strcmp(units,"radians")){
-    /* WIN32 math.h does not define M_PI */
-#ifndef M_PI
-# define M_PI		3.14159265358979323846
-#endif /* M_PI */
     const float dgr2rdn=M_PI/180.0;
     *lon_min*=dgr2rdn;
     *lon_max*=dgr2rdn;
@@ -362,7 +358,6 @@ nco_aux_prs
   } /* endif radians */
 } /* nco_aux_prs */
 
-
 lmt_sct **                           /* O [lst] Auxiliary coordinate limits */
 nco_aux_evl_trv
 (const int nc_id,                    /* I [ID] netCDF file ID */
@@ -543,10 +538,10 @@ nco_aux_evl_trv
 nco_bool 
 nco_find_lat_lon_trv
 (const int nc_id,                    /* I [ID] netCDF file ID */
- const trv_sct * const var_trv,      /* I [sct] Variable object that contains "standard_name" attribute */
- const char * const att_val_trg,     /* I [sng] Attribute value to find ( "latitude" or "longitude" ) */
+ const trv_sct * const var_trv,      /* I [sct] Variable to search for "standard_name" attribute */
+ const char * const att_val_trg,     /* I [sng] Attribute value to find ("latitude" or "longitude") */
  char **var_nm_fll,                  /* I/O [sng] Full name of variable that has "latitude" or "longitude" attributes */
- int *dmn_id,                        /* I/O [id] Dimension ID of the diension of "latitude" and "longitude" */
+ int *dmn_id,                        /* I/O [id] Dimension ID of "latitude" and "longitude" */
  nc_type *crd_typ,                   /* I/O [enm] netCDF type of both "latitude" and "longitude" */
  char units[])                       /* I/O [sng] Units of both "latitude" and "longitude" */
 {
@@ -584,31 +579,22 @@ nco_find_lat_lon_trv
 
   assert(var_att_nbr == var_trv->nbr_att);
 
-  /* Loop attributes */
   for(int idx_att=0;idx_att<var_att_nbr;idx_att++){
 
-    /* Get attribute name */
-    (void)nco_inq_attname(grp_id,var_id,idx_att,att_nm);
-
     /* Skip attribute if not "standard_name" */
+    (void)nco_inq_attname(grp_id,var_id,idx_att,att_nm);
     if(strcmp(att_nm,"standard_name")) continue;
 
     char att_val[NC_MAX_NAME+1];
-
     long att_lng;
-
     (void)nco_inq_attlen(grp_id,var_id,"standard_name",&att_lng);
-
-    NCO_GET_ATT_CHAR(grp_id,var_id,"standard_name",att_val);
+    (void)NCO_GET_ATT_CHAR(grp_id,var_id,"standard_name",att_val);
     att_val[att_lng]='\0';
 
     /* Match parameter name to find ("latitude" or "longitude") */
     if(!strcmp(att_val,att_val_trg)){
 
-      /* Export full name  */
-      *var_nm_fll=(char *)strdup(var_trv->nm_fll);
-
-      /* Get units; assume same for both lat and lon */
+      /* Assume same units (degrees or radians) for both lat and lon */
       int rcd=nco_inq_attlen_flg(grp_id,var_id,"units",&att_lng);
       if(rcd != NC_NOERR){
         if(nco_dbg_lvl_get() >= nco_dbg_var) (void)fprintf(stdout,"%s: %s reports CF convention requires \"latitude\" to have units attribute\n",nco_prg_nm_get(),fnc_nm);
@@ -619,16 +605,14 @@ nco_find_lat_lon_trv
 
       if(var_dmn_nbr > 1) (void)fprintf(stderr,"%s: WARNING %s reports latitude variable %s has %d dimensions. NCO only supports hyperslabbing of auxiliary coordinate variables with a single dimension. Continuing with unpredictable results...\n",nco_prg_nm_get(),fnc_nm,var_nm,var_dmn_nbr);
 
-      /* Assign type; assumed same for both lat and lon */
+      /* Copy values to export */
+      *var_nm_fll=(char *)strdup(var_trv->nm_fll);
       *crd_typ=var_typ;
-
-      /* Export the dimension ID */
       *dmn_id=var_dimid[0];
 
       return True;
-
-    } /* Match parameter name to find ( "latitude" or "longitude" ) */
-  } /* Loop attributes */
+    } /* strcmp() */
+  } /* end loop over attributes */
 
   return False;
 
diff --git a/src/nco/nco_aux.h b/src/nco/nco_aux.h
index 9df5adf..25454f3 100644
--- a/src/nco/nco_aux.h
+++ b/src/nco/nco_aux.h
@@ -30,7 +30,12 @@
 extern "C" {
 #endif /* __cplusplus */
 
-lmt_sct **
+/* WIN32 math.h does not define M_PI, needed for dgr2rdn and rdn2dgr */
+#ifndef M_PI
+# define M_PI		3.14159265358979323846
+#endif /* M_PI */
+
+  lmt_sct **
 nco_aux_evl
 (int in_id, 
  int aux_nbr, 
diff --git a/src/nco/nco_cnk.c b/src/nco/nco_cnk.c
index f83e602..2a59bd0 100644
--- a/src/nco/nco_cnk.c
+++ b/src/nco/nco_cnk.c
@@ -131,7 +131,7 @@ nco_dfl_case_cnk_plc_err(void) /* [fnc] Print error and exit for illegal switch(
 } /* end nco_dfl_case_cnk_plc_err() */
 
 int /* [rcd] Return code */
-nco_cnk_ini /* [fnc] Create structure with all chunking information */
+nco_cnk_ini /* [fnc] Initialize chunking from user-specified inputs */
 (const int in_id, /* I [id] netCDF input file ID */
  const char * const fl_out, /* I [sng] Output filename */
  CST_X_PTR_CST_PTR_CST_Y(char,cnk_arg), /* I [sng] List of user-specified chunksizes */
@@ -143,7 +143,7 @@ nco_cnk_ini /* [fnc] Create structure with all chunking information */
  const size_t cnk_sz_scl, /* I [nbr] Chunk size scalar */
  cnk_sct * const cnk) /* O [sct] Chunking structure */
 {
-  /* Purpose: Create structure with all chunking information */
+  /* Purpose: Initialize chunking from user-specified inputs */
   int rcd=0; /* [enm] Return code  */
 
   size_t fl_sys_blk_sz=0UL; /* [nbr] File system blocksize for I/O */
@@ -207,7 +207,7 @@ nco_cnk_ini /* [fnc] Create structure with all chunking information */
     /* Does _input_ file support chunking? */
     int fl_in_fmt=NCO_FORMAT_UNDEFINED; /* [enm] Input file format */
     (void)nco_inq_format(in_id,&fl_in_fmt);
-    if(fl_in_fmt == NC_FORMAT_NETCDF4 && fl_in_fmt == NC_FORMAT_NETCDF4_CLASSIC){
+    if(fl_in_fmt == NC_FORMAT_NETCDF4 || fl_in_fmt == NC_FORMAT_NETCDF4_CLASSIC){
       /* Input is netCDF4 so preserve chunking unless otherwise specified */
       cnk->cnk_map=nco_cnk_map_xst;
       cnk->cnk_plc=nco_cnk_plc_xst;
@@ -813,7 +813,7 @@ nco_cnk_sz_set_trv /* [fnc] Set chunksize parameters (GTT version of nco_cnk_sz_
      1) Instead of loop for all variables, this functions chunks one variable
      2) In dimension loop, dimension object is obtained from variable object
 
-     Unidata defaults set in libsrc4/nc4hdf.c, nc4var.c
+     Unidata sets netCDF chunking defaults in libsrc4/nc4hdf.c, nc4var.c
 
      netCDF 4.3.2 and later:
      DEFAULT_CHUNK_SIZE=4 MB
diff --git a/src/nco/nco_cnk.h b/src/nco/nco_cnk.h
index 6b53b33..e7b21ff 100644
--- a/src/nco/nco_cnk.h
+++ b/src/nco/nco_cnk.h
@@ -75,7 +75,7 @@ nco_cnk_plc_sng_get /* [fnc] Convert chunking policy enum to string */
 (const int nco_cnk_plc); /* I [enm] Chunking policy */
 
 int /* [rcd] [enm] Return code */
-nco_cnk_ini /* [fnc] Create structure with all chunking information */
+nco_cnk_ini /* [fnc] Initialize chunking from user-specified inputs */
 (const int in_id, /* I [id] netCDF input file ID */
  const char * const fl_out, /* I [sng] Output filename */
  CST_X_PTR_CST_PTR_CST_Y(char,cnk_arg), /* I [sng] List of user-specified chunksizes */
diff --git a/src/nco/nco_cnv_csm.c b/src/nco/nco_cnv_csm.c
index 5265d05..c54e6b2 100644
--- a/src/nco/nco_cnv_csm.c
+++ b/src/nco/nco_cnv_csm.c
@@ -55,7 +55,7 @@ nco_cnv_ccm_ccsm_cf_inq /* O [fnc] Check if file obeys CCM/CCSM/CF conventions *
       (void)fprintf(stderr,"%s: CONVENTION File \"%s\" attribute is \"%s\"\n",nco_prg_nm_get(),cnv_sng,att_val);
       if(cnv_sng == cnv_sng_LC) (void)fprintf(stderr,"%s: WARNING: This file uses a non-standard attribute (\"%s\") to indicate the netCDF convention. The correct attribute is \"%s\".\n",nco_prg_nm_get(),cnv_sng_LC,cnv_sng_UC);
       /* Only warn in arithmetic operators where conventions change behavior */
-      if(nco_dbg_lvl_get() >= nco_dbg_fl && nco_dbg_lvl_get() != nco_dbg_dev && nco_is_rth_opr(nco_prg_id_get())) (void)fprintf(stderr,"%s: INFO NCO has a unified (though incomplete) treatment of many related (official and unoffical) conventions including the older CCM and CCSM and newer CF conventions. To adhere to these conventions, NCO implements variable-specific exceptions in certain operators, e.g., ncbo will not subtract variables named \"date\" or \"gw\", and many operators will  [...]
+      if(nco_dbg_lvl_get() >= nco_dbg_fl && nco_dbg_lvl_get() != nco_dbg_dev && nco_is_rth_opr(nco_prg_id_get())) (void)fprintf(stderr,"%s: INFO NCO attempts to abide by many official and unoffical metadata conventions including ARM, CCM, CCSM, and CF. To adhere to these conventions, NCO implements variable-specific exceptions in certain operators, e.g., ncbo will not subtract variables named \"date\" or \"gw\", and many operators will always leave coordinate variables unchanged. The ful [...]
     } /* endif dbg */
     att_val=(char *)nco_free(att_val);
   } /* endif */
diff --git a/src/nco/nco_ctl.c b/src/nco/nco_ctl.c
index f19cece..fbd530e 100644
--- a/src/nco/nco_ctl.c
+++ b/src/nco/nco_ctl.c
@@ -461,7 +461,7 @@ nco_ddra /* [fnc] Count operations */
 		  var_idx,var_nm,(float)lmn_nbr,(float)flp_nbr,(float)ntg_nbr,tm_io,tm_crr,(float)lmn_nbr_ttl,(float)flp_nbr_ttl,(float)ntg_nbr_ttl,100.0*tm_frc_flp_ttl,100.0*tm_frc_ntg_ttl,100.0*tm_frc_rd_ttl,100.0*tm_frc_wrt_ttl,100.0*tm_frc_io_ttl,tm_ttl,tm_obs_ttl);
     break;
   case nco_tmr_end: /* [enm] Close timer (last timer call) */
-    if(ddra_info->flg_ddra || nco_dbg_lvl_get() >= nco_dbg_fl) (void)fprintf(stderr,"%s: TIMER Wallclock-elapsed time for command is %7.2f s\n",nco_prg_nm_get(),tm_obs_ttl);
+    if(ddra_info->flg_ddra || nco_dbg_lvl_get() >= nco_dbg_fl) (void)fprintf(stderr,"%s: TIMER Elapsed clock() time for command is %7.2f s\n",nco_prg_nm_get(),tm_obs_ttl);
     break;
   default: nco_dfl_case_tmr_typ_err(); break;
   } /* end switch */
@@ -696,7 +696,7 @@ nco_cnf_prn(void) /* [fnc] Print NCO configuration and help text */
 #define TKN2YESNO(x) ((x+0) ? ("No"):("Yes"))
   /* NB: Keep configuration option tokens consistent among configure.ac, bld/Makefile, and nco_ctl.c
      Alphabetize list by first word in English text description of token */
-  (void)fprintf(stdout,"Configuration Option:\tActive?\tMeaning or Reference:\nCheck _FillValue\t%s\thttp://nco.sf.net/nco.html#mss_val\nCheck missing_value\t%s\thttp://nco.sf.net/nco.html#mss_val\nDAP clients\t\t%s\thttp://nco.sf.net/nco.html#dap\nDebugging: Custom\t%s\tPedantic, bounds checking (slowest execution)\nDebugging: Symbols\t%s\tProduce symbols for debuggers (e.g., dbx, gdb)\nESMF Regridding\t\t%s\tpre-alpha\nGNU Scientific Library\t%s\thttp://nco.sf.net/nco.html#gsl\nHDF4 su [...]
+  (void)fprintf(stdout,"Configuration Option:\tActive?\tMeaning or Reference:\nCheck _FillValue\t%s\thttp://nco.sf.net/nco.html#mss_val\nCheck missing_value\t%s\thttp://nco.sf.net/nco.html#mss_val\nDAP clients\t\t%s\thttp://nco.sf.net/nco.html#dap\nDebugging: Custom\t%s\tPedantic, bounds checking (slowest execution)\nDebugging: Symbols\t%s\tProduce symbols for debuggers (e.g., dbx, gdb)\nESMF Library\t\t%s\thttp://nco.sf.net/nco.html#esmf\nGNU Scientific Library\t%s\thttp://nco.sf.net/nc [...]
 		(!strcmp("_FillValue",nco_mss_val_sng_get())) ? "Yes" : "No",
 		(!strcmp("missing_value",nco_mss_val_sng_get())) ? "Yes" : "No",
 #if defined(ENABLE_DAP) && (ENABLE_DAP)
@@ -808,7 +808,7 @@ nco_nmn_get(void) /* [fnc] Return mnemonic that describes current NCO version */
 { 
   /* Purpose: Return mnemonic describing current NCO version
      Always Include terminal \n so mnemonic does not dangle */
-  return "Tabu\n";
+  return "Even Keel\n";
 } /* end nco_nmn_get() */
 
 char * /* O [sng] nm_in stripped of any path (i.e., program name stub) */ 
@@ -931,11 +931,7 @@ nco_usg_prn(void)
     opt_sng=(char *)strdup("[-3] [-4] [-6] [-7] [-A] [--bfr sz] [-C] [-c] [--cnk_byt sz] [--cnk_dmn nm,sz] [--cnk_map map] [--cnk_min min] [--cnk_plc plc] [--cnk_scl sz] [-D nco_dbg_lvl] [-d ...] [-F] [--fix_rec_crd] [--fl_fmt fmt] [-h] [--hdf] [--hdr_pad nbr] [-i var,val] [-L lvl] [-l path] [--msa] [--no_tmp_fl] [-O] [-o out.nc] [-p path] [--ppc ...] [-R] [-r] [--ram_all] [-t thr_nbr] [-v ...] [-X box] [-x] [-w wgt_1[,wgt_2]] in_1.nc in_2.nc [out.nc]\n");
     break;
   case ncks:
-#ifdef ENABLE_ESMF
-    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [-a] [-b fl_bnr] [--bfr sz] [-C] [-c] [--cdl] [--cnk_byt sz] [--cnk_dmn nm,sz] [--cnk_map map] [--cnk_min min] [--cnk_plc plc] [--cnk_scl sz] [-D nco_dbg_lvl] [-d ...] [-F] [--fix_rec_dmn dim] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--grp_xtr_var_xcl] [-H] [-h] [--hdn] [--hdr_pad nbr] [-L lvl] [-l path] [-M] [-m] [--md5_dgs] [--md5_wrt] [--mk_rec_dmn dim] [--msa] [--no_blank] [--no_tmp_fl] [-O] [-o out.nc] [-P] [-p path] [--ppc ...] [...]
-#else /* !ENABLE_ESMF */
-    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [-a] [-b fl_bnr] [--bfr sz] [-C] [-c] [--cdl] [--cnk_byt sz] [--cnk_dmn nm,sz] [--cnk_map map] [--cnk_min min] [--cnk_plc plc] [--cnk_scl sz] [-D nco_dbg_lvl] [-d ...] [-F] [--fix_rec_dmn dim] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--grp_xtr_var_xcl] [-H] [-h] [--hdn] [--hdr_pad nbr] [-L lvl] [-l path] [-M] [-m] [--md5_dgs] [--md5_wrt] [--mk_rec_dmn dim] [--msa] [--no_blank] [--no_tmp_fl] [-O] [-o out.nc] [-P] [-p path] [--ppc ...] [...]
-#endif /* !ENABLE_ESMF */
+    opt_sng=(char *)strdup("[-3] [-4] [-5] [-6] [-7] [-A] [-a] [-b fl_bnr] [--bfr sz] [-C] [-c] [--cdl] [--cnk_byt sz] [--cnk_dmn nm,sz] [--cnk_map map] [--cnk_min min] [--cnk_plc plc] [--cnk_scl sz] [-D nco_dbg_lvl] [-d ...] [-F] [--fix_rec_dmn dim] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [--grp_xtr_var_xcl] [-H] [-h] [--hdn] [--hdr_pad nbr] [-L lvl] [-l path] [-M] [-m] [--map map.nc] [--md5_dgs] [--md5_wrt] [--mk_rec_dmn dim] [--msa] [--no_blank] [--no_tmp_fl] [-O] [-o out.nc] [-P] [-p pa [...]
     break;
   case ncpdq:
     opt_sng=(char *)strdup("[-3] [-4] [-6] [-7] [-A] [-a ...] [--bfr sz] [-C] [-c] [--cnk_byt sz] [--cnk_dmn nm,sz] [--cnk_map map] [--cnk_min min] [--cnk_plc plc] [--cnk_scl sz] [-D nco_dbg_lvl] [-d ...] [-F] [--fl_fmt fmt] [-G grp:lvl] [-g ...] [-h] [--hdf] [--hdr_pad nbr] [-L lvl] [-l path] [-M pck_map] [--mrd] [--msa] [--no_tmp_fl] [-O] [-o out.nc] [-P pck_plc] [-p path] [--ppc ...] [-R] [-r] [--ram_all] [-t thr_nbr] [--unn] [-U] [-v ...] [-X box] [-x] in.nc [out.nc]\n");
@@ -1049,6 +1045,7 @@ nco_usg_prn(void)
     if(prg_lcl == ncwa) (void)fprintf(stdout,"-m, --msk_nm, --msk_var, --mask-variable, --mask_variable mask_var\tMasking variable name\n");
     if(prg_lcl == ncks) (void)fprintf(stdout,"-m, --mtd, --metadata\tToggle printing variable metadata\n");
   } /* end if */
+  if(strstr(opt_sng,"--map")) (void)fprintf(stdout,"    --map, --rgr_map map.nc\tFile containing (ESMF- or SCRIP-format) weights to regrid input to output grid\n");
   if(strstr(opt_sng,"--md5_digest")) (void)fprintf(stdout,"    --md5_dgs, --md5_digest\tPerform MD5 digests\n");
   if(strstr(opt_sng,"--md5_wrt_att")) (void)fprintf(stdout,"   --md5_wrt, --md5_write\tWrite MD5 digests as attributes\n");
   if(strstr(opt_sng,"--mk_rec_dmn")) (void)fprintf(stdout,"    --mk_rec_dmn dim\tDefine dim as record dimension in output file\n");
@@ -1064,7 +1061,7 @@ nco_usg_prn(void)
   if(strstr(opt_sng,"--nsm_fl")) (void)fprintf(stdout,"    --nsm_fl, --ensemble_file\tEnsembles comprise equally weighted files\n");
   if(strstr(opt_sng,"--nsm_grp")) (void)fprintf(stdout,"    --nsm_grp, --ensemble_group\tEnsembles comprise equally weighted groups\n");
   if(strstr(opt_sng,"--nsm_sfx")) (void)fprintf(stdout,"    --nsm_sfx, --ensemble_suffix\tPlace ensemble output in group parent/parent+nsm_sfx\n");
-  if(strstr(opt_sng,"[-o")) (void)fprintf(stdout,"-o, --output, --fl_out fl_out\tOutput file name (or use last positional argument)\n");
+  if(strstr(opt_sng,"[-o")) (void)fprintf(stdout,"-o, --output, --fl_out out.nc\tOutput file name (or use last positional argument)\n");
   if(strstr(opt_sng,"[-O]")) (void)fprintf(stdout,"-O, --ovr, --overwrite\tOverwrite existing output file, if any\n");
   if(strstr(opt_sng,"[-P")){
     if(prg_lcl == ncks) (void)fprintf(stdout,"-P, --prn, --print\tPrint data, metadata, and units. Abbreviation for -C -H -M -m -u.\n");
@@ -1079,14 +1076,11 @@ nco_usg_prn(void)
   if(strstr(opt_sng,"--rad")) (void)fprintf(stdout,"    --orphan, --rph_dmn\tRetain or print all (including orphaned) dimensions\n");
   if(strstr(opt_sng,"--ram_all")) (void)fprintf(stdout,"    --ram_all, --diskless_all\tOpen netCDF3 files and create output files in RAM\n");
   if(strstr(opt_sng,"--rec_apn")) (void)fprintf(stdout,"    --rec_apn, --record_append\tAppend records directly to output file\n");
-#ifdef ENABLE_ESMF
-  if(strstr(opt_sng,"--rgr")) (void)fprintf(stdout,"    --rgr args\t\tTo activate regridding options use --rgr=Y\n");
-  if(strstr(opt_sng,"--rgr_grd_dst")) (void)fprintf(stdout,"    --rgr_grd_dst file\tDestination grid\n");
-  if(strstr(opt_sng,"--rgr_grd_src")) (void)fprintf(stdout,"    --rgr_grd_src file\tSource grid\n");
-  if(strstr(opt_sng,"--rgr_in")) (void)fprintf(stdout,"    --rgr_in file\tFile containing fields to be regridded\n");
-  if(strstr(opt_sng,"--rgr_out")) (void)fprintf(stdout,"    --rgr_out file\tFile containing regridded fields\n");
-  if(strstr(opt_sng,"--rgr_map")) (void)fprintf(stdout,"    --rgr_map file\tFile containing mapping weights from source to destination grid\n");
-#endif /* !ENABLE_ESMF */
+  if(strstr(opt_sng,"--rgr")) (void)fprintf(stdout,"    --rgr key=value\t\tSee http://nco.sf.net/nco.html#regrid for valid keys\n");
+  if(strstr(opt_sng,"--rnr")) (void)fprintf(stdout,"    --rnr=wgt, --renormalize\t\tWeight threshold for valid destination value\n");
+  // if(strstr(opt_sng,"--rgr_grd_dst")) (void)fprintf(stdout,"    --rgr_grd_dst file\tDestination grid\n");
+  // if(strstr(opt_sng,"--rgr_grd_src")) (void)fprintf(stdout,"    --rgr_grd_src file\tSource grid\n");
+  // if(strstr(opt_sng,"--rgr_in")) (void)fprintf(stdout,"    --rgr_in file\tFile containing fields to be regridded\n");
   if(strstr(opt_sng,"[-s")){
     if(prg_lcl != ncap) (void)fprintf(stdout,"-s, --sng_fmt, --string format\tString format for text output\n");
     if(prg_lcl == ncap) (void)fprintf(stdout,"-s, --spt, --script algebra\tAlgebraic command defining single output variable\n");
diff --git a/src/nco/nco_grp_trv.c b/src/nco/nco_grp_trv.c
index 374a64a..b3a1676 100644
--- a/src/nco/nco_grp_trv.c
+++ b/src/nco/nco_grp_trv.c
@@ -68,7 +68,7 @@ trv_tbl_free                           /* [fnc] GTT free memory */
     for(int dmn_idx=0;dmn_idx<tbl->lst[idx].nbr_dmn;dmn_idx++){
 
       /* If dimensions exist (only for variables ) */
-      if (tbl->lst[idx].var_dmn){
+      if(tbl->lst[idx].var_dmn){
         tbl->lst[idx].var_dmn[dmn_idx].dmn_nm_fll=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].dmn_nm_fll);
         tbl->lst[idx].var_dmn[dmn_idx].dmn_nm=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].dmn_nm);
         tbl->lst[idx].var_dmn[dmn_idx].grp_nm_fll=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].grp_nm_fll);
@@ -86,50 +86,30 @@ trv_tbl_free                           /* [fnc] GTT free memory */
           tbl->lst[idx].var_dmn[dmn_idx].crd->crd_grp_nm_fll=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].crd->crd_grp_nm_fll);
           tbl->lst[idx].var_dmn[dmn_idx].crd->dmn_grp_nm_fll=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].crd->dmn_grp_nm_fll);
           tbl->lst[idx].var_dmn[dmn_idx].crd->nm=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].crd->nm);
-
           tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.dmn_nm=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.dmn_nm);
-
-          for(int lmt_idx=0;lmt_idx<tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.lmt_dmn_nbr;lmt_idx++){
+          for(int lmt_idx=0;lmt_idx<tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.lmt_dmn_nbr;lmt_idx++)
             tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.lmt_dmn[lmt_idx]=nco_lmt_free(tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.lmt_dmn[lmt_idx]);
-          }
-
           tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.lmt_dmn=(lmt_sct **)nco_free(tbl->lst[idx].var_dmn[dmn_idx].crd->lmt_msa.lmt_dmn);
-
           tbl->lst[idx].var_dmn[dmn_idx].crd=(crd_sct *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].crd);
-
 #ifdef DEBUG_LEAKS
           crt_counter++;
 #endif
-
-        } /* Coordinate structure */ 
-
-        /* Pointer to non-coordinate dimension  */
-        else if(tbl->lst[idx].var_dmn[dmn_idx].ncd){
-
+        }else if(tbl->lst[idx].var_dmn[dmn_idx].ncd){
           tbl->lst[idx].var_dmn[dmn_idx].ncd->grp_nm_fll=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].ncd->grp_nm_fll);
           tbl->lst[idx].var_dmn[dmn_idx].ncd->nm_fll=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].ncd->nm_fll);
           tbl->lst[idx].var_dmn[dmn_idx].ncd->nm=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].ncd->nm);
-
           tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.dmn_nm=(char *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.dmn_nm);
-
-          for(int lmt_idx=0;lmt_idx<tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.lmt_dmn_nbr;lmt_idx++){
+          for(int lmt_idx=0;lmt_idx<tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.lmt_dmn_nbr;lmt_idx++)
             tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.lmt_dmn[lmt_idx]=nco_lmt_free(tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.lmt_dmn[lmt_idx]);
-          }
-
           tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.lmt_dmn=(lmt_sct **)nco_free(tbl->lst[idx].var_dmn[dmn_idx].ncd->lmt_msa.lmt_dmn);
-
           tbl->lst[idx].var_dmn[dmn_idx].ncd=(dmn_trv_sct *)nco_free(tbl->lst[idx].var_dmn[dmn_idx].ncd);
-
         }
-
-
       } /* Dimensions */
       
       tbl->lst[idx].var_dmn=(var_dmn_sct *)nco_free(tbl->lst[idx].var_dmn);
       tbl->lst[idx].dmn_idx_out_in=(int *)nco_free(tbl->lst[idx].dmn_idx_out_in);
       tbl->lst[idx].dmn_rvr_in=(nco_bool *)nco_free(tbl->lst[idx].dmn_rvr_in);
-
-    } /* If dimensions exist (only for variables ) */
+    } /* If dimensions exist (only for variables) */
   } /* Object (group/variable) list */ 
 
   tbl->lst=(trv_sct *)nco_free(tbl->lst);
@@ -140,7 +120,6 @@ trv_tbl_free                           /* [fnc] GTT free memory */
     tbl->lst_dmn[dmn_idx].nm_fll=(char *)nco_free(tbl->lst_dmn[dmn_idx].nm_fll);
     tbl->lst_dmn[dmn_idx].grp_nm_fll=(char *)nco_free(tbl->lst_dmn[dmn_idx].grp_nm_fll);
     tbl->lst_dmn[dmn_idx].lmt_msa.dmn_nm=(char *)nco_free(tbl->lst_dmn[dmn_idx].lmt_msa.dmn_nm);
-
     for(int lmt_idx=0;lmt_idx<tbl->lst_dmn[dmn_idx].lmt_msa.lmt_dmn_nbr;lmt_idx++)
       tbl->lst_dmn[dmn_idx].lmt_msa.lmt_dmn[lmt_idx]=nco_lmt_free(tbl->lst_dmn[dmn_idx].lmt_msa.lmt_dmn[lmt_idx]);
 
@@ -154,41 +133,29 @@ trv_tbl_free                           /* [fnc] GTT free memory */
       tbl->lst_dmn[dmn_idx].crd[crd_idx]->crd_grp_nm_fll=(char *)nco_free(tbl->lst_dmn[dmn_idx].crd[crd_idx]->crd_grp_nm_fll);
       tbl->lst_dmn[dmn_idx].crd[crd_idx]->dmn_grp_nm_fll=(char *)nco_free(tbl->lst_dmn[dmn_idx].crd[crd_idx]->dmn_grp_nm_fll);
       tbl->lst_dmn[dmn_idx].crd[crd_idx]->nm=(char *)nco_free(tbl->lst_dmn[dmn_idx].crd[crd_idx]->nm);
-
       tbl->lst_dmn[dmn_idx].crd[crd_idx]->lmt_msa.dmn_nm=(char *)nco_free(tbl->lst_dmn[dmn_idx].crd[crd_idx]->lmt_msa.dmn_nm);
-
-      for(int lmt_idx=0;lmt_idx<tbl->lst_dmn[dmn_idx].crd[crd_idx]->lmt_msa.lmt_dmn_nbr;lmt_idx++){
+      for(int lmt_idx=0;lmt_idx<tbl->lst_dmn[dmn_idx].crd[crd_idx]->lmt_msa.lmt_dmn_nbr;lmt_idx++)
         tbl->lst_dmn[dmn_idx].crd[crd_idx]->lmt_msa.lmt_dmn[lmt_idx]=nco_lmt_free(tbl->lst_dmn[dmn_idx].crd[crd_idx]->lmt_msa.lmt_dmn[lmt_idx]);
-      }
-
       tbl->lst_dmn[dmn_idx].crd[crd_idx]=(crd_sct *)nco_free(tbl->lst_dmn[dmn_idx].crd[crd_idx]);
     }  /* Coordinate structures */
 
     tbl->lst_dmn[dmn_idx].crd=(crd_sct **)nco_free(tbl->lst_dmn[dmn_idx].crd);
   } /* Dimension list */
-
   tbl->lst_dmn=(dmn_trv_sct *)nco_free(tbl->lst_dmn);
 
   /* Members used only by transformation operators (non-ncks) */
-
   /* (ncwa) Degenerate dimensions */
   tbl->dmn_dgn=(dmn_sct *)nco_free(tbl->dmn_dgn); 
 
   /* Ensembles */
   for(int idx_nsm=0;idx_nsm<tbl->nsm_nbr;idx_nsm++){
     tbl->nsm[idx_nsm].grp_nm_fll_prn=(char *)nco_free(tbl->nsm[idx_nsm].grp_nm_fll_prn);
-
     for(int idx=0;idx<tbl->nsm[idx_nsm].tpl_nbr;idx++) tbl->nsm[idx_nsm].tpl_mbr_nm[idx]=(char *)nco_free(tbl->nsm[idx_nsm].tpl_mbr_nm[idx]);
-
     for(int idx=0;idx<tbl->nsm[idx_nsm].skp_nbr;idx++) tbl->nsm[idx_nsm].skp_nm_fll[idx]=(char *)nco_free(tbl->nsm[idx_nsm].skp_nm_fll[idx]);
-
     tbl->nsm[idx_nsm].mbr=(nsm_grp_sct*)nco_free(tbl->nsm[idx_nsm].mbr);
   } /* Ensembles */
-
   tbl->nsm_sfx=(char *)nco_free(tbl->nsm_sfx);  
-
   tbl=(trv_tbl_sct *)nco_free(tbl);
-
 #ifdef DEBUG_LEAKS
   if(nco_dbg_lvl_get() >= nco_dbg_sup)(void)fprintf(stdout,"%s: DEBUG %s %d crd",nco_prg_nm_get(),fnc_nm,crt_counter);
 #endif
diff --git a/src/nco/nco_grp_trv.h b/src/nco/nco_grp_trv.h
index 75816d7..062eeed 100644
--- a/src/nco/nco_grp_trv.h
+++ b/src/nco/nco_grp_trv.h
@@ -66,6 +66,11 @@ trv_tbl_fnd_var_nm_fll                 /* [fnc] Check if "var_nm_fll" is in tabl
  const trv_tbl_sct * const trv_tbl);   /* I [sct] Traversal table */
 
 trv_sct *                              /* O [sct] Table object */
+trv_tbl_var_nm                         /* [fnc] Return variable object (relative name) */
+(const char * const var_nm,            /* I [sng] Variable name to find */
+ const trv_tbl_sct * const trv_tbl);   /* I [sct] Traversal table */
+
+trv_sct *                              /* O [sct] Table object */
 trv_tbl_var_nm_fll                     /* [fnc] Return object from full name key */
 (const char * const var_nm_fll,        /* I [sng] Variable name to find */
  const trv_tbl_sct * const trv_tbl);   /* I [sct] Traversal table */
@@ -190,11 +195,6 @@ nco_is_fll_pth                         /* [fnc] Utility function to inquire if a
 (const char * const str);              /* I [sng] A string to inquire */
 
 trv_sct *                              /* O [sct] Table object */
-trv_tbl_var_nm                         /* [fnc] Return variable object (relative name) */
-(const char * const var_nm,            /* I [sng] Variable name to find */
- const trv_tbl_sct * const trv_tbl);   /* I [sct] Traversal table */
-
-trv_sct *                              /* O [sct] Table object */
 trv_tbl_nsm_nm                         /* [fnc] Return variable object  */
 (const char * const var_nm,            /* I [sng] Variable name (relative) to find */
  const char * const grp_nm_fll_prn,    /* I [sng] Ensemble parent group */
diff --git a/src/nco/nco_grp_utl.c b/src/nco/nco_grp_utl.c
index d6b2d76..d3a8e11 100644
--- a/src/nco/nco_grp_utl.c
+++ b/src/nco/nco_grp_utl.c
@@ -1043,7 +1043,7 @@ nco_xtr_cf_add /* [fnc] Add to extraction list variables associated with CF conv
  trv_tbl_sct * const trv_tbl) /* I/O [sct] GTT (Group Traversal Table) */
 {
   /* Add to extraction list all variables associated with specified CF convention
-     Driver routine for nco_xtr_cf_prv_add()
+     Driver routine for nco_xtr_cf_var_add()
      Detect associated coordinates specified by CF "ancillary_variables", "bounds", and "coordinates" conventions
      http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.1/cf-conventions.html#coordinate-system */ 
 
@@ -1052,7 +1052,7 @@ nco_xtr_cf_add /* [fnc] Add to extraction list variables associated with CF conv
   /* Search for and add CF-compliant bounds and coordinates to extraction list */
   for(unsigned idx_tbl=0;idx_tbl<trv_tbl->nbr;idx_tbl++)
     if(trv_tbl->lst[idx_tbl].nco_typ == nco_obj_typ_var && trv_tbl->lst[idx_tbl].flg_xtr)
-      (void)nco_xtr_cf_prv_add(nc_id,&trv_tbl->lst[idx_tbl],cf_nm,trv_tbl);
+      (void)nco_xtr_cf_var_add(nc_id,&trv_tbl->lst[idx_tbl],cf_nm,trv_tbl);
 
   /* Print extraction list in debug mode */
   if(nco_dbg_lvl_get() == nco_dbg_old) (void)trv_tbl_prn_xtr(trv_tbl,fnc_nm);
@@ -1061,7 +1061,7 @@ nco_xtr_cf_add /* [fnc] Add to extraction list variables associated with CF conv
 } /* nco_xtr_cf_add() */
 
 void
-nco_xtr_cf_prv_add /* [fnc] Add variables associated (via CF) with specified variable to extraction list */
+nco_xtr_cf_var_add /* [fnc] Add variables associated (via CF) with specified variable to extraction list */
 (const int nc_id, /* I [ID] netCDF file ID */
  const trv_sct * const var_trv, /* I [sct] Variable (object) */
  const char * const cf_nm, /* I [sng] CF convention ("ancillary_variables", "bounds", "climatology", or "coordinates") */
@@ -1083,19 +1083,11 @@ nco_xtr_cf_prv_add /* [fnc] Add variables associated (via CF) with specified var
   int var_id; /* [id] Variable ID */
 
   assert(var_trv->nco_typ == nco_obj_typ_var);
-
-  /* Obtain group ID */
   (void)nco_inq_grp_full_ncid(nc_id,var_trv->grp_nm_fll,&grp_id);
-
-  /* Obtain variable ID */
   (void)nco_inq_varid(grp_id,var_trv->nm,&var_id);
-
-  /* Find number of attributes */
   (void)nco_inq_varnatts(grp_id,var_id,&nbr_att);
-
   assert(nbr_att == var_trv->nbr_att);
 
-  /* Loop attributes */
   for(int idx_att=0;idx_att<nbr_att;idx_att++){
 
     /* Get attribute name */
@@ -1121,7 +1113,7 @@ nco_xtr_cf_prv_add /* [fnc] Add variables associated (via CF) with specified var
       /* Split list into separate coordinate names
 	 Use nco_lst_prs_sgl_2D() not nco_lst_prs_2D() to avert TODO nco944 */
       cf_lst=nco_lst_prs_sgl_2D(att_val,dlm_sng,&nbr_cf);
-      /* ...for each coordinate in CF convention attribute, i.e., "ancillary_variables", "bounds", or "coordinate"... */
+      /* ...for each variable in CF convention attribute, i.e., for each variable listed in "ancillary_variables", or in "bounds", or in "coordinates"... */
       for(int idx_cf=0;idx_cf<nbr_cf;idx_cf++){
         char *cf_lst_var=cf_lst[idx_cf];
         if(!cf_lst_var) continue;
@@ -1177,7 +1169,7 @@ nco_xtr_cf_prv_add /* [fnc] Add variables associated (via CF) with specified var
   } /* end loop over attributes */
 
   return;
-} /* nco_xtr_cf_prv_add() */
+} /* nco_xtr_cf_var_add() */
 
 nm_id_sct *                           /* O [sct] Extraction list */  
 nco_trv_tbl_nm_id                     /* [fnc] Create extraction list of nm_id_sct from traversal table */
@@ -2197,6 +2189,7 @@ nco_grp_itr                            /* [fnc] Populate traversal table by exam
   trv_tbl->lst[idx].flg_mtd=False;                /* [flg] Group contains only metadata */
   trv_tbl->lst[idx].flg_ncs=False;                /* [flg] Group is ancestor of specified group or variable */
   trv_tbl->lst[idx].flg_nsx=False;                /* [flg] Object matches intersection criteria */
+  trv_tbl->lst[idx].flg_rgr=False;                /* [flg] Regrid variable */
   trv_tbl->lst[idx].flg_rcr=False;                /* [flg] Extract group recursively */
   trv_tbl->lst[idx].flg_unn=False;                /* [flg] Object matches union criteria */
   trv_tbl->lst[idx].flg_vfp=False;                /* [flg] Variable matches full path specification */
@@ -2299,6 +2292,7 @@ nco_grp_itr                            /* [fnc] Populate traversal table by exam
     trv_tbl->lst[idx].flg_ncs=False; 
     trv_tbl->lst[idx].flg_nsx=False; 
     trv_tbl->lst[idx].flg_rcr=False; 
+    trv_tbl->lst[idx].flg_rgr=False; 
     trv_tbl->lst[idx].flg_unn=False; 
     trv_tbl->lst[idx].flg_vfp=False; 
     trv_tbl->lst[idx].flg_vsg=False; 
@@ -3776,8 +3770,9 @@ nco_prc_cmn                            /* [fnc] Process objects (ncbo only) */
       } /* end case */
 
       if(trv_1->ppc != NC_MAX_INT){
-	if(trv_1->flg_nsd) (void)nco_var_bitmask(trv_1->ppc,var_prc_1->type,var_prc_out->sz,var_prc_out->has_mss_val,var_prc_out->mss_val,var_prc_1->val); else (void)nco_var_around(trv_1->ppc,var_prc_1->type,var_prc_out->sz,var_prc_out->has_mss_val,var_prc_out->mss_val,var_prc_1->val);
+	if(trv_1->flg_nsd) (void)nco_ppc_bitmask(trv_1->ppc,var_prc_1->type,var_prc_out->sz,var_prc_out->has_mss_val,var_prc_out->mss_val,var_prc_1->val); else (void)nco_ppc_around(trv_1->ppc,var_prc_1->type,var_prc_out->sz,var_prc_out->has_mss_val,var_prc_out->mss_val,var_prc_1->val);
       } /* endif ppc */
+      if(nco_is_xcp(trv_1->nm)) nco_xcp_prc(trv_1->nm,var_prc_1->type,var_prc_out->sz,(char *)var_prc_1->val.vp);
 
       /* Copy result to output file */
       if(var_prc_1->nbr_dim == 0) (void)nco_put_var1(grp_out_id,var_prc_out->id,var_prc_out->srt,var_prc_1->val.vp,var_prc_1->type); else (void)nco_put_vara(grp_out_id,var_prc_out->id,var_prc_out->srt,var_prc_out->cnt,var_prc_1->val.vp,var_prc_1->type);
@@ -6636,14 +6631,14 @@ nco_bld_trv_tbl                       /* [fnc] Construct GTT, Group Traversal Ta
      nco_bld_crd_var_trv()
      nco_has_crd_dmn_scp()
      nco_bld_var_dmn()
-     complete structures for the traversal table to be completed.
-     Then, user options functions are called:
+     Traversal table now has all necessary _structures_ complete
+     Next, call functions dependent on user-supplied options:
      nco_xtr_mk()
      nco_xtr_xcl()
      nco_xtr_crd_add()
      nco_xtr_crd_ass_add()
      nco_xtr_cf_add()
-     Limits related function must be called in order:
+     Limit-related functions must be called in order:
      nco_lmt_prs()
      nco_prs_aux_crd()
      nco_chk_dmn_in()
@@ -6703,11 +6698,16 @@ nco_bld_trv_tbl                       /* [fnc] Construct GTT, Group Traversal Ta
     CNV_CCM_CCSM_CF=True;
   } /* endif */
   if(CNV_CCM_CCSM_CF && EXTRACT_ASSOCIATED_COORDINATES){
-    /* Implement CF "ancillary_variables", "bounds", and "coordinates" */
+    /* Implement CF "ancillary_variables", "bounds", "climatology", and "coordinates" */
     (void)nco_xtr_cf_add(nc_id,"ancillary_variables",trv_tbl);
     (void)nco_xtr_cf_add(nc_id,"bounds",trv_tbl);
     (void)nco_xtr_cf_add(nc_id,"climatology",trv_tbl);
     (void)nco_xtr_cf_add(nc_id,"coordinates",trv_tbl);
+    /* Do all twice, so that, e.g., auxiliary coordinates retrieved because of "coordinates" come with their bounds variables */
+    (void)nco_xtr_cf_add(nc_id,"ancillary_variables",trv_tbl);
+    (void)nco_xtr_cf_add(nc_id,"climatology",trv_tbl);
+    (void)nco_xtr_cf_add(nc_id,"coordinates",trv_tbl);
+    (void)nco_xtr_cf_add(nc_id,"bounds",trv_tbl);
   } /* CNV_CCM_CCSM_CF */
 
   /* Mark extracted dimensions */
@@ -7880,16 +7880,11 @@ nco_lmt_std_att_lat_lon               /* [fnc] Apply limits to variable in table
   /* Loop table  */
   for(unsigned idx_tbl=0;idx_tbl<trv_tbl->nbr;idx_tbl++){
     /* Match variable that has 'standard_name' flag */
-    if(trv_tbl->lst[idx_tbl].nco_typ == nco_obj_typ_var && 
-      (trv_tbl->lst[idx_tbl].flg_std_att_lat || trv_tbl->lst[idx_tbl].flg_std_att_lon)){
-
+    if(trv_tbl->lst[idx_tbl].nco_typ == nco_obj_typ_var && (trv_tbl->lst[idx_tbl].flg_std_att_lat || trv_tbl->lst[idx_tbl].flg_std_att_lon)){
         trv_sct var_trv=trv_tbl->lst[idx_tbl];
-
-        /* Loop dimensions  */
         for(int idx_dmn=0;idx_dmn<var_trv.nbr_dmn;idx_dmn++)
           if(dmn_id == var_trv.var_dmn[idx_dmn].dmn_id)
-            (void)nco_lmt_aux(nc_id,lmt,nbr_nbr,FORTRAN_IDX_CNV,MSA_USR_RDR,idx_tbl,idx_dmn,trv_tbl);    
-
+	    (void)nco_lmt_aux(nc_id,lmt,nbr_nbr,FORTRAN_IDX_CNV,MSA_USR_RDR,idx_tbl,idx_dmn,trv_tbl);    
     } /* Match variable  */
   } /* Loop table  */
 
@@ -8140,7 +8135,7 @@ nco_bld_crd_aux /* [fnc] Build auxiliary coordinates information into table */
   /* Look for attributes 'standard_name' == 'latitude' and 'longitude' */
   char *var_nm_fll=NULL;
 
-  int dmn_id; /* [id] Dimension ID of dimension of 'latitude' and 'longitude' coordinate variables, e.g., lat_gds(gds_crd) */
+  int dmn_id; /* [id] Dimension ID for 'latitude' and 'longitude' coordinate variables, e.g., lat_gds(gds_crd) */
 
   nc_type crd_typ;
 
@@ -8246,7 +8241,7 @@ nco_bld_crd_aux /* [fnc] Build auxiliary coordinates information into table */
 		/* Check if possible 'longitude' (var_trv) is in scope */
 		if(nco_var_scp(&trv_tbl->lst[idx_crd],&var_trv,trv_tbl)){
 		  
-		  /* Mark the variable (e.g gds_var, gds_3dvar) as containing auxiliary coordinates */
+		  /* Mark variable (e.g., gds_var, gds_3dvar) as containing auxiliary coordinates */
 		  trv_tbl->lst[idx_crd].flg_aux=True;
 		  
 		  if(nco_dbg_lvl_get() >= nco_dbg_dev) (void)fprintf(stdout,"%s: DEBUG %s reports variable %s has auxiliary coordinates with dimension ID = %d\n",nco_prg_nm_get(),fnc_nm,trv_tbl->lst[idx_crd].nm_fll,var_dim_id); 
@@ -9394,7 +9389,7 @@ nco_prc_cmn_nsm                        /* [fnc] Process (define, write) variable
       } /* Loop group members */
     } /* Loop ensembles */
 
-  } else if(flg_grp_1 == False) {
+  }else if(flg_grp_1 == False){
 
   } /* ! flg_grp_1 */
 
@@ -9480,7 +9475,6 @@ nco_prc_nsm                            /* [fnc] Process (define, write) variable
 
           } /* List of fixed templates  */
 
-
           /* Loop list of variables from other file */
           for(int idx_var_2=0;idx_var_2<var_lst->nbr;idx_var_2++){
 
diff --git a/src/nco/nco_grp_utl.h b/src/nco/nco_grp_utl.h
index 5b42a90..520f934 100644
--- a/src/nco/nco_grp_utl.h
+++ b/src/nco/nco_grp_utl.h
@@ -162,7 +162,7 @@ nco_xtr_cf_add                        /* [fnc] Add to extraction list variable a
  trv_tbl_sct * const trv_tbl);        /* I/O [sct] Traversal table */
 
 void
-nco_xtr_cf_prv_add                    /* [fnc] Add specified CF-compliant coordinates of specified variable to extraction list */
+nco_xtr_cf_var_add                    /* [fnc] Add specified CF-compliant coordinates of specified variable to extraction list */
 (const int nc_id,                     /* I [ID] netCDF file ID */
  const trv_sct * const var_trv,       /* I [sct] Variable (object) */
  const char * const cf_nm,            /* I [sng] CF convention ( "coordinates" or "bounds") */
diff --git a/src/nco/nco_msa.c b/src/nco/nco_msa.c
index 150ed74..423e590 100644
--- a/src/nco/nco_msa.c
+++ b/src/nco/nco_msa.c
@@ -1353,8 +1353,9 @@ nco_cpy_var_val_mlt_lmt_trv         /* [fnc] Copy variable data from input to ou
       var_out.type=var_typ_out;
       var_out.id=var_out_id;
       nco_mss_val_get(out_id,&var_out);
-      if(flg_nsd) (void)nco_var_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_var_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
+      if(flg_nsd) (void)nco_ppc_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_ppc_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
     } /* endif */
+    if(nco_is_xcp(var_nm)) nco_xcp_prc(var_nm,var_typ_out,var_out.sz,(char *)var_out.val.vp);
 
     if(nbr_dim == 0) (void)nco_put_var1(out_id,var_out_id,0L,var_out.val.vp,var_typ_out); else (void)nco_put_vara(out_id,var_out_id,dmn_map_srt,dmn_map_cnt,var_out.val.vp,var_typ_out);
   } /* !flg_write */
diff --git a/src/nco/nco_mss_val.c b/src/nco/nco_mss_val.c
index d08d32e..3b19b4a 100644
--- a/src/nco/nco_mss_val.c
+++ b/src/nco/nco_mss_val.c
@@ -347,3 +347,69 @@ nco_mss_val_get /* [fnc] Update number of attributes, missing_value of variable
 
 } /* end nco_mss_val_get() */
 
+nco_bool /* O [flg] Variable has missing value */
+nco_mss_val_get_dbl /* [fnc] Return missing_value of variable, if any, as double precision number */
+(const int nc_id, /* I [id] netCDF input-file ID */
+ const int var_id, /* I [id] netCDF variable ID */
+ double *mss_val_dbl) /* O [frc] Missing value in double precision */
+{
+  /* Purpose: Return missing_value of variable, if any, as double precision number
+     Basically this is a stripped-down, fast version of nco_mss_val_get()
+     Created for use in regridding
+     No matter what type missing_value is on disk, this routine returns a double precision value */
+  
+  static nco_bool WRN_FIRST=True; /* [flg] No warnings yet for _FillValue/missing_value mismatch */
+  
+  char att_nm[NC_MAX_NAME];
+  char var_nm[NC_MAX_NAME];
+  int idx;
+  int var_nbr_att;
+  long att_sz;
+  nco_bool has_fll_val=False; /* [flg] Has _FillValue attribute */
+  nco_bool has_mss_val=False; /* [flg] Has missing value attribute */
+  nc_type att_typ;
+  
+  /* Refresh number of attributes for variable */
+  (void)nco_inq_varnatts(nc_id,var_id,&var_nbr_att);
+  
+  for(idx=0;idx<var_nbr_att;idx++){
+    (void)nco_inq_attname(nc_id,var_id,idx,att_nm);
+    if(WRN_FIRST && !(int)strcasecmp(att_nm,nco_not_mss_val_sng_get())) has_fll_val=True;
+    
+    if((int)strcasecmp(att_nm,nco_mss_val_sng_get())) continue;
+    (void)nco_inq_att(nc_id,var_id,att_nm,&att_typ,&att_sz);
+    if(att_sz != 1L){
+      (void)nco_inq_varname(nc_id,var_id,var_nm);
+      (void)fprintf(stderr,"%s: WARNING the \"%s\" attribute for %s has %li elements and so will not be used\n",nco_prg_nm_get(),att_nm,var_nm,att_sz);
+      continue;
+    } /* end if */
+    if(att_typ == NC_CHAR || att_typ == NC_STRING){
+      (void)nco_inq_varname(nc_id,var_id,var_nm);
+      (void)fprintf(stderr,"%s: WARNING the \"%s\" attribute for %s has type %s and so will not be used\n",nco_prg_nm_get(),att_nm,var_nm,nco_typ_sng(att_typ));
+      continue;
+    } /* end if */
+    /* If we got this far then retrieve attribute */
+    has_mss_val=True;
+    /* Oddly, ARM uses NC_CHAR for type of missing_value, so make allowances for this */
+    (void)nco_get_att(nc_id,var_id,att_nm,mss_val_dbl,NC_DOUBLE);
+    break;
+  } /* end loop over att */
+
+  /* Always warn when NCO looks for _FillValue but file has missing_value, and/or
+     always warn when NCO looks for missing_value but file has _FillValue.
+     20101129: This is a long warning, only print when nco_dbg_lvl > 0 */
+  if(nco_dbg_lvl_get() >= nco_dbg_std && has_fll_val && !has_mss_val && WRN_FIRST){
+    char sa[1000];
+    char sa1[1000];
+    char sa2[1000]; 
+    WRN_FIRST=False;
+    (void)sprintf(sa,"%s: WARNING Variable %s has attribute \"%s\" but not \"%s\". To comply with netCDF conventions, NCO ignores values that equal the %s attribute when performing arithmetic.",nco_prg_nm_get(),var_nm,nco_not_mss_val_sng_get(), nco_mss_val_sng_get(),nco_mss_val_sng_get()); 
+    (void)sprintf(sa1," Confusingly, values equal to the missing_value should also be neglected. However, it is tedious and (possibly) computationally expensive to check each value against multiple missing values during arithmetic on large variables. So NCO thinks that processing variables with a \"%s\" attribute and no \"%s\" attribute may produce undesired arithmetic results (i.e., where values that were intended to be neglected were not, in fact, neglected).",nco_not_mss_val_sng_get() [...]
+    (void)sprintf(sa2, " We suggest you rename all \"%s\" attributes to \"%s\" or include both \"%s\" and \"%s\" attributes (with the _same values_) for all variables that have either attribute. Because it is long, this message is only printed once per operator even though multiple variables may have the same attribute configuration. More information on missing values is given at:\nhttp://nco.sf.net/nco.html#mss_val\nExamples of renaming attributes are at:\nhttp://nco.sf.net/nco.html#xmp [...]
+    (void)fprintf(stderr,"%s%s%s",sa,sa1,sa2); 
+  } /* endif missing_value is and _FillValue is not defined */
+
+  return has_mss_val;
+  
+} /* end nco_mss_val_get_dbl() */
+
diff --git a/src/nco/nco_mss_val.h b/src/nco/nco_mss_val.h
index fc8bd2e..7f53d0e 100644
--- a/src/nco/nco_mss_val.h
+++ b/src/nco/nco_mss_val.h
@@ -60,6 +60,12 @@ nco_mss_val_get /* [fnc] Update number of attributes, missing_value of variable
 (const int nc_id, /* I [id] netCDF input-file ID */
  var_sct * const var); /* I/O [sct] Variable with missing_value to update */
 
+nco_bool /* O [flg] Variable has missing value */
+nco_mss_val_get_dbl /* [fnc] Return missing_value of variable, if any, as double precision number */
+(const int nc_id, /* I [id] netCDF input-file ID */
+ const int var_id, /* I [id] netCDF variable ID */
+ double *mss_val_dbl); /* O [frc] Missing value in double precision */
+
 #ifdef __cplusplus
 } /* end extern "C" */
 #endif /* __cplusplus */
diff --git a/src/nco/nco_netcdf.c b/src/nco/nco_netcdf.c
index 8c4c3d2..525326c 100644
--- a/src/nco/nco_netcdf.c
+++ b/src/nco/nco_netcdf.c
@@ -664,6 +664,37 @@ nco_open_flg(const char * const fl_nm,const int mode,int * const nc_id)
   return rcd;
 } /* end nco_open */
 
+#if NC_LIB_VERSION < 440
+int
+nc_open_mem(const char * const fl_nm,const int mode,const size_t sz,void * const void_ptr,int * const nc_id)
+{
+  /* Purpose: Pseudo-library stub function to open a netCDF file stored in RAM
+     This particular stub routine is only called by netCDF4-enabled code
+     when built against a netCDF library that it too old to have the nc_open_mem() function. */
+  int rcd;
+  const char fnc_nm[]="nc_open_mem()";
+  rcd=strlen(fl_nm)+mode+sz;
+  (void)fprintf(stdout,"ERROR: %s reports attempt to open file memory was foiled because libnetcdf.a does not contain nc_open_mem(). To obtain this functionality, please rebuild NCO against netCDF library version 4.4.0-rc1 (released ~20150610) or later.\nExiting...\n",fnc_nm);
+  nco_err_exit(rcd,fnc_nm);
+  *nc_id=*((int *)void_ptr);
+  return rcd;
+} /* end nc_open_mem() */
+#endif /* 4.4.0 */
+
+int
+nco_open_mem(const char * const fl_nm,const int mode,const size_t sz,void * const void_ptr,int * const nc_id)
+{
+  /* Purpose: Wrapper for nc_open_mem() */
+  const char fnc_nm[]="nco_open_mem()";
+  int rcd;
+  rcd=nc_open_mem(fl_nm,mode,sz,void_ptr,nc_id);
+  if(rcd != NC_NOERR){
+    (void)fprintf(stdout,"ERROR: %s unable to open_mem file \"%s\"\n",fnc_nm,fl_nm);
+    nco_err_exit(rcd,fnc_nm);
+  } /* endif */
+  return rcd;
+} /* end nco_open_mem() */
+
 #ifdef ENABLE_MPI
 # ifdef HAVE_NETCDF4_H
 /* netCDF4 routines defined by Unidata netCDF4 Library libnetcdf.a 
@@ -1000,7 +1031,7 @@ nc_rename_grp(int grp_id,const char * const grp_nm)
   rcd=NC_NOERR;
   rcd+=nco_inq_grpname(grp_id,grp_nm_old);
   (void)fprintf(stdout,"INFO: %s reports attempt to rename group \"%s\" to \"%s\" was foiled because libnetcdf.a does not contain nc_rename_grp(). To obtain this functionality, please rebuild NCO against netCDF library version 4.3.1-pre1 (released ~201309) or later.\nContinuing as though nothing untoward happened...\n",fnc_nm,grp_nm_old,grp_nm);
-  if(rcd != NC_NOERR) nco_err_exit(rcd,"nc_rename_grp()");
+  if(rcd != NC_NOERR) nco_err_exit(rcd,fnc_nm);
   return rcd;
 } /* end nc_rename_grp() */
 #endif /* NC_HAVE_RENAME_GRP */
diff --git a/src/nco/nco_netcdf.h b/src/nco/nco_netcdf.h
index 0ea7ac6..d5a5474 100644
--- a/src/nco/nco_netcdf.h
+++ b/src/nco/nco_netcdf.h
@@ -268,6 +268,7 @@ int nco_create(const char * const fl_nm,const int cmode,int * const nc_id);
 int nco__create(const char * const fl_nm,const int cmode,const size_t sz_ntl,size_t * const bfr_sz_hnt,int * const nc_id);
 int nco_open(const char * const fl_nm,const int mode,int * const nc_id);
 int nco_open_flg(const char * const fl_nm,const int mode,int * const nc_id);
+int nco_open_mem(const char * const fl_nm,const int mode,const size_t sz,void * const void_ptr,int * const nc_id);
 int nco__open(const char * const fl_nm,const int mode,size_t * const bfr_sz_hnt,int * const nc_id);
 int nco_redef(const int nc_id);
 int nco_set_fill(const int nc_id,const int fill_mode,int * const old_mode);
@@ -381,6 +382,9 @@ int nco_get_att(const int nc_id,const int var_id,const char * const att_nm,void
 #ifndef NC_HAVE_RENAME_GRP
   int nc_rename_grp(int grp_id,const char * const grp_nm);
 #endif /* NC_HAVE_RENAME_GRP */
+#if NC_LIB_VERSION < 440
+  int nc_open_mem(const char * const fl_nm,const int mode,const size_t sz,void * const void_ptr,int * const nc_id);
+#endif /* 4.4.0 */
 
 /* Begin netCDF4 stubs */
 #ifndef HAVE_NETCDF4_H
diff --git a/src/nco/nco_omp.c b/src/nco/nco_omp.c
index 2dd926a..248c3af 100644
--- a/src/nco/nco_omp.c
+++ b/src/nco/nco_omp.c
@@ -117,11 +117,12 @@ nco_openmp_ini /* [fnc] Initialize OpenMP threading environment */
     switch(nco_prg_id_get()){
       /* Operators with pre-set thread limit
 	 NB: All operators currently have default restrictions
-	 Only ncwa and ncap2 have a chance to scale on non-parallel filesystems
+	 2007: Only ncwa and ncap2 have a chance to scale on non-parallel filesystems
 	 ncap2 may, one day, see a big performance boost from threading
 	 However, as of 20090327, ncap2 threading may be buggy due to ANTLR
 	 Moreover, we want to prevent hogging processes on 32-way nodes
-	 until/unless clear benefits of threading are demonstrated. */
+	 until/unless clear benefits of threading are demonstrated.
+	 2015: Threads improve ncks regridding performance by 2-3x on ACME ~1-20 GB netCDF3 files */
     case ncap: 
       /* 20090327: Restrict ncap2 to one thread until ANTLR threading resolved */
       thr_nbr_max_fsh=1;
@@ -134,16 +135,24 @@ nco_openmp_ini /* [fnc] Initialize OpenMP threading environment */
       // thr_nbr_max_fsh=2;
       thr_nbr_max_fsh=1;
       break;
+    case ncks: 
+      // 20150529: Turn-on OpenMP for regridder
+      thr_nbr_max_fsh=8;
+      break;
+    case ncwa: 
+      // 20150530: Turn-on OpenMP for debugging
+      // 20150610: 8 threads with ncwa seemed to work for a little while, but then got flaky. Turned-off for 4.5.0 release
+      // thr_nbr_max_fsh=8;
+      thr_nbr_max_fsh=1;
+      break;
       /* Operators with higher maximum pre-set thread limit (NB: not all of these are threaded!) */
     case ncbo: 
     case ncatted: 
     case ncfe:
     case ncflint: 
-    case ncks: 
     case ncpdq: 
     case ncra:
     case ncrename: 
-    case ncwa: 
     case ncge:
       // 20140219: Turn-off OpenMP until thoroughly tested
       // thr_nbr_max_fsh=4;
@@ -166,7 +175,7 @@ nco_openmp_ini /* [fnc] Initialize OpenMP threading environment */
   } /* !USR_SPC_THR_RQS */
 
 #ifdef ENABLE_NETCDF4
-  if(thr_nbr_rqs > 1){
+  if(nco_prg_id_get() != ncks && nco_prg_id_get() != ncwa && thr_nbr_rqs > 1){
     if(USR_SPC_THR_RQS && nco_dbg_lvl_get() >= nco_dbg_fl) (void)fprintf(stdout,"%s: WARNING This is TODO nco939. Requested threading with netCDF4 (HDF5) support. The NCO thread request algorithm considers user-input, environment variables, and software and hardware limitations in determining the number of threads to request, thr_nbr_rqs. At this point NCO would request result %d threads from a netCDF3-based library. However, this NCO was built with netCDF4, which relies on HDF5. netCDF4 [...]
     thr_nbr_rqs=1;
   } /* endif */
@@ -178,24 +187,29 @@ nco_openmp_ini /* [fnc] Initialize OpenMP threading environment */
     nco_exit(EXIT_FAILURE);
   }else{
     (void)omp_set_num_threads(thr_nbr_rqs); 
-    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(fp_stderr,"%s: INFO omp_set_num_threads() used to set execution environment to spawn teams of %d threads\n",nco_prg_nm_get(),thr_nbr_rqs);
+    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(fp_stderr,"%s: INFO omp_set_num_threads() used to set execution environment to spawn teams of %d thread(s)\n",nco_prg_nm_get(),thr_nbr_rqs);
   } /* end error */
 
   thr_nbr_act=omp_get_max_threads();
-  if(nco_dbg_lvl_get() >= nco_dbg_scl) (void)fprintf(fp_stderr,"%s: INFO After using omp_set_num_threads() to adjust for any user requests/NCO optimizations, omp_get_max_threads() reports that a parallel construct here/now would spawn %d threads\n",nco_prg_nm_get(),thr_nbr_act);
+  if(nco_dbg_lvl_get() >= nco_dbg_scl) (void)fprintf(fp_stderr,"%s: INFO After using omp_set_num_threads() to adjust for any user requests/NCO optimizations, omp_get_max_threads() reports that a parallel construct here/now would spawn %d thread(s)\n",nco_prg_nm_get(),thr_nbr_act);
 #ifdef _OPENMP
   if(nco_dbg_lvl_get() >= nco_dbg_scl){
-#pragma omp parallel default(none) shared(thr_nbr_act)
+# pragma omp parallel default(none) shared(thr_nbr_act)
     { /* begin OpenMP parallel */
-#pragma omp single nowait
+# pragma omp single nowait
       { /* begin OpenMP single */
 	thr_nbr_act=omp_get_num_threads(); /* [nbr] Number of threads NCO uses */
-	if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(fp_stderr,"%s: INFO Small parallel test region spawned team of %d threads\n",nco_prg_nm_get(),thr_nbr_act);
+	if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(fp_stderr,"%s: INFO Small parallel test region spawned team of %d thread(s)\n",nco_prg_nm_get(),thr_nbr_act);
       } /* end OpenMP single */
     } /* end OpenMP parallel */
   } /* end dbg */
 #endif /* !_OPENMP */
   
+  /* Issue any warnings about OpenMP credibility during debugging phase */
+  if(True)
+    if(nco_prg_id_get() == ncwa && thr_nbr_act > 1)
+      if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(fp_stderr,"%s: WARNING OpenMP threading active with %d threads but not guaranteed to work on this operator. If strange behavior (e.g., NaN results) ensues, manually turn-off multi-threading by specifying \"-t 1\" option.\n",nco_prg_nm_get(),thr_nbr_act);
+
   return thr_nbr_act; /* O [nbr] Number of threads NCO uses */
 } /* end nco_openmp_ini() */
 
diff --git a/src/nco/nco_ppc.c b/src/nco/nco_ppc.c
index d234698..7805a9f 100644
--- a/src/nco/nco_ppc.c
+++ b/src/nco/nco_ppc.c
@@ -60,14 +60,14 @@ nco_ppc_ini /* Set PPC based on user specifications */
 (const int nc_id, /* I [id] netCDF input file ID */
  int *dfl_lvl, /* O [enm] Deflate level */
  const int fl_out_fmt,  /* I [enm] Output file format */
- char * const ppc_arg[], /* I [sng] List of user-specified PPC */
+ char * const ppc_arg[], /* I [sng] List of user-specified PPCs */
  const int ppc_arg_nbr, /* I [nbr] Number of PPC specified */
  trv_tbl_sct * const trv_tbl) /* I/O [sct] Traversal table */
 {
-  int ppc_arg_idx; /* [idx] Index over ppr_arg (i.e., separate invocations of "--ppc var1[,var2]=val") */
-  int ppc_var_idx; /* [idx] Index over ppr_lst (i.e., all names explicitly specified in all "--ppc var1[,var2]=val" options) */
+  int ppc_arg_idx; /* [idx] Index over ppc_arg (i.e., separate invocations of "--ppc var1[,var2]=val") */
+  int ppc_var_idx; /* [idx] Index over ppc_lst (i.e., all names explicitly specified in all "--ppc var1[,var2]=val" options) */
   int ppc_var_nbr=0;
-  kvm_sct *ppc_lst;  /* [sct] PPC container */
+  kvm_sct *ppc_lst; /* [sct] List of all PPC specifications */
   kvm_sct kvm;
 
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC){
@@ -86,10 +86,10 @@ nco_ppc_ini /* Set PPC based on user specifications */
   for(ppc_arg_idx=0;ppc_arg_idx<ppc_arg_nbr;ppc_arg_idx++){
     if(!strstr(ppc_arg[ppc_arg_idx],"=")){
       (void)fprintf(stdout,"%s: Invalid --ppc specification: %s. Must contain \"=\" sign.\n",nco_prg_nm_get(),ppc_arg[ppc_arg_idx]);
-      if(ppc_lst) nco_kvm_free(ppc_lst);
+      if(ppc_lst) ppc_lst=(kvm_sct *)nco_free(ppc_lst);
       nco_exit(EXIT_FAILURE);
     } /* endif */
-    kvm=nco_sng2kvm(ppc_arg[ppc_arg_idx],kvm);
+    kvm=nco_sng2kvm(ppc_arg[ppc_arg_idx]);
     /* nco_sng2kvm() converts argument "--ppc one,two=3" into kvm.key="one,two" and kvm.val=3
        Then nco_lst_prs_2D() converts kvm.key into two items, "one" and "two", with the same value, 3 */
     if(kvm.key){
@@ -106,7 +106,7 @@ nco_ppc_ini /* Set PPC based on user specifications */
     } /* end if */
   } /* end for */
 
-  /* PPC default exists, set all non-coordinate variables to default first */
+  /* PPC "default" specified, set all non-coordinate variables to default first */
   for(ppc_var_idx=0;ppc_var_idx<ppc_var_nbr;ppc_var_idx++){
     if(!strcasecmp(ppc_lst[ppc_var_idx].key,"default")){
       nco_ppc_set_dflt(nc_id,ppc_lst[ppc_var_idx].val,trv_tbl);
@@ -195,7 +195,7 @@ nco_ppc_ini /* Set PPC based on user specifications */
     } /* endif */
   } /* endfor */
 
-  if(ppc_lst) nco_kvm_free(ppc_lst);
+  if(ppc_lst) ppc_lst=nco_kvm_lst_free(ppc_lst,ppc_var_nbr);
 } /* end nco_ppc_ini() */
 
 void
@@ -347,3 +347,395 @@ nco_ppc_set_var
     
   return;
 } /* end nco_ppc_set_var() */
+
+void
+nco_ppc_around /* [fnc] Replace op1 values by their values rounded to decimal precision prc */
+(const int ppc, /* I [nbr] Precision-preserving compression, i.e., number of total or decimal significant digits */
+ const nc_type type, /* I [enm] netCDF type of operand */
+ const long sz, /* I [nbr] Size (in elements) of operand */
+ const int has_mss_val, /* I [flg] Flag for missing values */
+ ptr_unn mss_val, /* I [val] Value of missing value */
+ ptr_unn op1) /* I/O [val] Values of first operand */
+{
+  /* Threads: Routine is thread safe and calls no unsafe routines */
+
+  /* Purpose: Replace op1 values by their values rounded to decimal precision ppc
+     Similar to numpy.around() function, hence the name around()
+     Based on implementation by Jeff Whitaker for netcdf4-python described here:
+     http://netcdf4-python.googlecode.com/svn/trunk/docs/netCDF4-module.html
+     which invokes the numpy.around() function documented here:
+     http://docs.scipy.org/doc/numpy/reference/generated/numpy.around.html#numpy.around
+     A practical discussion of rounding is at
+     http://stackoverflow.com/questions/20388071/what-are-the-under-the-hood-differences-between-round-and-numpy-round
+     This mentions the () NumPy source code:
+     https://github.com/numpy/numpy/blob/7b2f20b406d27364c812f7a81a9c901afbd3600c/numpy/core/src/multiarray/calculation.c#L588
+
+     Manually determine scale:
+     ncap2 -O -v -s 'ppc=2;ppc_abs=abs(ppc);bit_nbr_xct=ppc_abs*ln(10.)/ln(2.);bit_nbr_int=ceil(bit_nbr_xct);scale=pow(2.0,bit_nbr_int);' ~/nco/data/in.nc ~/foo.nc 
+     ncks -H ~/foo.nc
+
+     Test full algorithm:
+     ncks -4 -O -C -v ppc_dbl,ppc_big --ppc ppc_dbl=3 --ppc ppc_big=-2 ~/nco/data/in.nc ~/foo.nc
+
+     Compare to Jeff Whitaker's nc3tonc4 results:
+     nc3tonc4 -o --quantize=ppc_dbl=3,ppc_big=-2 ~/nco/data/in.nc ~/foo.nc
+     ncks -H -C -v ppc_dbl,ppc_big ~/foo.nc */
+  
+  /* Rounding is currently defined as op1:=around(op1,ppc) */  
+  
+  /* Use constants defined in math.h */
+  const double bit_per_dcm_dgt_prc=M_LN10/M_LN2; /* 3.32 [frc] Bits per decimal digit of precision */
+
+  double scale; /* [frc] Number by which to scale data to achieve rounding */
+  float scalef; /* [frc] Number by which to scale data to achieve rounding */
+
+  int bit_nbr; /* [nbr] Number of bits required to exceed pow(10,-ppc) */
+  int ppc_abs; /* [nbr] Absolute value of precision */
+
+  long idx;
+  
+  /* Only numeric types can be quantized */
+  if(type == NC_CHAR || type == NC_BYTE || type == NC_UBYTE || type == NC_STRING) return;
+
+  ppc_abs=abs(ppc);
+  assert(ppc_abs <= 16);
+  switch(ppc_abs){
+  case 0:
+    bit_nbr=0;
+    scale=1.0;
+    break;
+  case 1:
+    bit_nbr=4;
+    scale=16.0;
+    break;
+  case 2:
+    bit_nbr=7;
+    scale=128.0;
+    break;
+  case 3:
+    bit_nbr=10;
+    scale=1024.0;
+    break;
+  case 4:
+    bit_nbr=14;
+    scale=16384.0;
+    break;
+  case 5:
+    bit_nbr=17;
+    scale=131072.0;
+    break;
+  case 6:
+    bit_nbr=20;
+    scale=1048576.0;
+    break;
+  default:
+    bit_nbr=(int)ceil(ppc_abs*bit_per_dcm_dgt_prc);
+    scale=pow(2.0,bit_nbr);
+    break;
+  } /* end switch */   
+  if(ppc < 0) scale=1.0/scale;
+
+  if(nco_dbg_lvl_get() == nco_dbg_sbr) (void)fprintf(stdout,"%s: INFO nco_ppc_around() reports ppc = %d, bit_nbr= %d, scale = %g\n",nco_prg_nm_get(),ppc,bit_nbr,scale);
+
+  /* Typecast pointer to values before access */
+  (void)cast_void_nctype(type,&op1);
+  if(has_mss_val) (void)cast_void_nctype(type,&mss_val);
+  
+  scalef=(float)scale;
+  switch(type){
+  case NC_FLOAT: 
+    /* By default do float arithmetic in double precision before converting back to float
+       Allow --flt to override
+       NB: Use rint() not lrint()
+       If ignoring this advice, be sure to bound calls to lrint(), e.g., 
+       rint_arg=scale*op1.fp[idx];
+       if(rint_arg > LONG_MIN && rint_arg < LONG_MAX) op1.fp[idx]=(float)lrint(scale*op1.fp[idx])/scale; */
+    if(!has_mss_val){
+      if(nco_rth_cnv_get() == nco_rth_flt_flt)
+	for(idx=0L;idx<sz;idx++) op1.fp[idx]=rintf(scalef*op1.fp[idx])/scalef;
+      else
+	for(idx=0L;idx<sz;idx++) op1.fp[idx]=(float)(rint(scale*op1.fp[idx])/scale); /* Coerce to avoid implicit conversions warning */
+    }else{
+      const float mss_val_flt=*mss_val.fp;
+      if(nco_rth_cnv_get() == nco_rth_flt_flt){
+	for(idx=0;idx<sz;idx++)
+	  if(op1.fp[idx] != mss_val_flt)
+	    op1.fp[idx]=rintf(scalef*op1.fp[idx])/scalef;
+      }else{
+	for(idx=0;idx<sz;idx++)
+	  if(op1.fp[idx] != mss_val_flt)
+	    op1.fp[idx]=(float)(rint(scale*op1.fp[idx])/scale); /* Coerce to avoid implicit conversions warning */
+      } /* end else */
+    } /* end else */
+    break;
+  case NC_DOUBLE: 
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.dp[idx]=rint(scale*op1.dp[idx])/scale;
+    }else{
+      const double mss_val_dbl=*mss_val.dp;
+      for(idx=0;idx<sz;idx++)
+	if(op1.dp[idx] != mss_val_dbl) op1.dp[idx]=rint(scale*op1.dp[idx])/scale;
+    } /* end else */
+    break;
+  case NC_SHORT:
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.sp[idx]=(short int)lrint(scale*op1.sp[idx])/scale;
+    }else{
+      const nco_int mss_val_short=*mss_val.sp;
+      for(idx=0;idx<sz;idx++)
+	if(op1.sp[idx] != mss_val_short) op1.sp[idx]=(short int)lrint(scale*op1.sp[idx])/scale;
+    } /* end else */
+    break;
+  case NC_USHORT:
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.usp[idx]=(unsigned short int)lrint(scale*op1.usp[idx])/scale;
+    }else{
+      const nco_ushort mss_val_ushort=*mss_val.usp;
+      for(idx=0;idx<sz;idx++)
+	if(op1.usp[idx] != mss_val_ushort) op1.usp[idx]=(unsigned short int)lrint(scale*op1.usp[idx])/scale;
+    } /* end else */
+    break;
+  case NC_INT:
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.ip[idx]=lrint(scale*op1.ip[idx])/scale;
+    }else{
+      const nco_int mss_val_int=*mss_val.ip;
+      for(idx=0;idx<sz;idx++)
+	if(op1.ip[idx] != mss_val_int) op1.ip[idx]=lrint(scale*op1.ip[idx])/scale;
+    } /* end else */
+    break;
+  case NC_UINT:
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.uip[idx]=(unsigned int)lrint(scale*op1.uip[idx])/scale;
+    }else{
+      const nco_uint mss_val_uint=*mss_val.uip;
+      for(idx=0;idx<sz;idx++)
+	if(op1.uip[idx] != mss_val_uint) op1.uip[idx]=(unsigned int)lrint(scale*op1.uip[idx])/scale;
+    } /* end else */
+    break;
+  case NC_INT64:
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.i64p[idx]=lrint(scale*op1.i64p[idx])/scale;
+    }else{
+      const nco_int64 mss_val_int64=*mss_val.i64p;
+      for(idx=0;idx<sz;idx++)
+	if(op1.i64p[idx] != mss_val_int64) op1.i64p[idx]=lrint(scale*op1.i64p[idx])/scale;
+    } /* end else */
+    break;
+  case NC_UINT64:
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx++) op1.ui64p[idx]=(unsigned long)lrint(scale*op1.ui64p[idx])/scale;
+    }else{
+      const nco_uint64 mss_val_uint64=*mss_val.ui64p;
+      for(idx=0;idx<sz;idx++)
+	if(op1.ui64p[idx] != mss_val_uint64) op1.ui64p[idx]=(unsigned long)lrint(scale*op1.ui64p[idx])/scale;
+    } /* end else */
+    break;
+  case NC_CHAR: /* Do nothing for non-numeric types ...*/
+  case NC_BYTE:
+  case NC_UBYTE:
+  case NC_STRING: break;
+  default: 
+    nco_dfl_case_nc_type_err();
+    break;
+  } /* end switch */
+
+  /* NB: it is not neccessary to un-typecast pointers to values after access 
+     because we have only operated on local copies of them. */
+  
+} /* end nco_ppc_around() */
+
+void
+nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
+(const int nsd, /* I [nbr] Number of significant digits, i.e., arithmetic precision */
+ const nc_type type, /* I [enm] netCDF type of operand */
+ const long sz, /* I [nbr] Size (in elements) of operand */
+ const int has_mss_val, /* I [flg] Flag for missing values */
+ ptr_unn mss_val, /* I [val] Value of missing value */
+ ptr_unn op1) /* I/O [val] Values of first operand */
+{
+  /* Threads: Routine is thread safe and calls no unsafe routines */
+
+  /* Purpose: Mask-out insignificant bits of op1 values */
+  
+  /* Rounding is currently defined as op1:=bitmask(op1,ppc) */  
+  
+  /* Number of Significant Digits (NSD) algorithm
+     NSD based on absolute precision, i.e., number of digits in significand and in decimal scientific notation
+     DSD based on precision relative to decimal point, i.e., number of digits before/after decimal point
+     DSD is more often used colloquially, e.g., "thermometers measure temperature accurate to 1 degree C" 
+     NSD is more often used scientifically, e.g., "thermometers measure temperature to three significant digits"
+     These statements are both equivalent and describe the same instrument and data
+     If data are stored in C or K then optimal specifications for each algorithm would be DSD=0 and NSD=3
+     However, if data are stored in mK (milli-Kelvin) then optimal specifications would be DSD=-3 and NSD=3
+     In other words, the number of significant digits (NSD) does not depend on the units of storage, but DSD does
+     Hence NSD is more instrinsic and portable than DSD
+     NSD requires only bit-shifting and bit-masking, no floating point math
+     DSD is implemented with rounding techniques that rely on floating point math
+     This makes DSD subject to accompanying overflow and underflow problems when exponent near MAX_EXP/2
+     Thus NSD is faster, more accurate, and less ambiguous than DSD
+     Nevertheless many users think in terms of DSD not NSD
+     
+     Terminology: 
+     Decimal Precision is number of significant digits following decimal point (DSD)
+     Arithmetic Precision is number of significant digits (NSD)
+     "Arithmetic precision can also be defined with reference to a fixed number of decimal places (the number of digits following the decimal point). This second definition is useful in applications where the number of digits in the fractional part has particular importance, but it does not follow the rules of significance arithmetic." -- Wikipedia
+     "A common convention in science and engineering is to express accuracy and/or precision implicitly by means of significant figures. Here, when not explicitly stated, the margin of error is understood to be one-half the value of the last significant place. For instance, a recording of 843.6 m, or 843.0 m, or 800.0 m would imply a margin of 0.05 m (the last significant place is the tenths place), while a recording of 8,436 m would imply a margin of error of 0.5 m (the last significant [...]
+     
+     Test NSD:
+     nc3tonc4 -o --quantize=ppc_big=3,ppc_bgr=3,ppc_flt=3 --quiet=1 ~/nco/data/in.nc ~/foo_n34.nc
+     ncks -D 1 -4 -O -C -v ppc_big,ppc_bgr,ppc_flt --ppc .?=3 ~/nco/data/in.nc ~/foo.nc
+     ncks -C -v ppc_big,ppc_bgr ~/foo.nc
+     ncks -s '%16.12e\n' -C -H -v ppc_big,ppc_bgr ~/foo_n34.nc */
+  
+  /* IEEE single- and double-precision significands have 24 and 53 bits of precision (prc_bnr)
+     Decimal digits of precision (prc_dcm) obtained via prc_dcm=prc_bnr*ln(2)/ln(10) = 7.22 and 15.95, respectively
+     Binary digits of precision (prc_bnr) obtained via prc_bnr=prc_dcm*ln(10)/ln(2) */
+  
+  /* Use constants defined in math.h */
+  const double bit_per_dcm_dgt_prc=M_LN10/M_LN2; /* 3.32 [frc] Bits per decimal digit of precision */
+  
+  const int bit_xpl_nbr_sgn_flt=23; /* [nbr] Bits 0-22 of SP significands are explicit. Bit 23 is implicit. */
+  const int bit_xpl_nbr_sgn_dbl=53; /* [nbr] Bits 0-52 of DP significands are explicit. Bit 53 is implicit. */
+  
+  double prc_bnr_xct; /* [nbr] Binary digits of precision, exact */
+  
+  int bit_xpl_nbr_sgn=int_CEWI; /* [nbr] Number of explicit bits in significand */
+  int bit_xpl_nbr_zro; /* [nbr] Number of explicit bits to zero */
+
+  long idx;
+
+  unsigned int *u32_ptr;
+  unsigned int msk_f32_u32_zro;
+  unsigned int msk_f32_u32_one;
+  unsigned long int *u64_ptr;
+  unsigned long int msk_f64_u64_zro;
+  unsigned long int msk_f64_u64_one;
+  unsigned short prc_bnr_ceil; /* [nbr] Exact binary digits of precision rounded-up */
+  unsigned short prc_bnr_xpl_rqr; /* [nbr] Explicitly represented binary digits required to retain */
+  
+  /* Only floating point types can be quantized */
+  if(type != NC_FLOAT && type != NC_DOUBLE) return;
+
+  /* Disallow unreasonable quantization */
+  assert(nsd > 0);
+  assert(nsd <= 16);
+
+    /* How many bits to preserve? */
+  prc_bnr_xct=nsd*bit_per_dcm_dgt_prc;
+  /* Be conservative, round upwards */
+  prc_bnr_ceil=(unsigned short)ceil(prc_bnr_xct);
+  /* First bit is implicit not explicit but corner cases prevent our taking advantage of this */
+  //prc_bnr_xpl_rqr=prc_bnr_ceil-1;
+  //prc_bnr_xpl_rqr=prc_bnr_ceil;
+  prc_bnr_xpl_rqr=prc_bnr_ceil+1;
+  if(type == NC_DOUBLE) prc_bnr_xpl_rqr++; /* Seems necessary for double-precision ppc=array(1.234567,1.e-6,$dmn) */
+  /* 20150128: Hand-tuning shows we can sacrifice one or two more bits for almost all cases
+     20150205: However, small integers are an exception. In fact they require two more bits, at least for NSD=1.
+     Thus minimum threshold to preserve half of least significant digit (LSD) is prc_bnr_xpl_rqr=prc_bnr_ceil.
+     Decrementing prc_bnr_xpl_rqr by one or two more bits produces maximum errors that exceed half the LSD
+     ncra -4 -O -C --ppc default=1 --ppc one=1 -p ~/nco/data in.nc in.nc ~/foo.nc 
+     ncks -H -v Q.. --cdl ~/foo.nc | m */
+
+  /* 20150126: fxm casting pointers is tricky with this routine. Avoid for now. */
+  /* Typecast pointer to values before access */
+  //(void)cast_void_nctype(type,&op1);
+  //if(has_mss_val) (void)cast_void_nctype(type,&mss_val);
+
+  if(type == NC_FLOAT  && prc_bnr_xpl_rqr >= bit_xpl_nbr_sgn_flt) return;
+  if(type == NC_DOUBLE && prc_bnr_xpl_rqr >= bit_xpl_nbr_sgn_dbl) return;
+
+  switch(type){
+  case NC_FLOAT:
+    bit_xpl_nbr_sgn=bit_xpl_nbr_sgn_flt;
+    bit_xpl_nbr_zro=bit_xpl_nbr_sgn-prc_bnr_xpl_rqr;
+    assert(bit_xpl_nbr_zro <= bit_xpl_nbr_sgn-NCO_PPC_BIT_XPL_NBR_MIN);
+    u32_ptr=op1.uip;
+    /* Create mask */
+    msk_f32_u32_zro=0u; /* Zero all bits */
+    msk_f32_u32_zro=~msk_f32_u32_zro; /* Turn all bits to ones */
+    /* Left shift zeros into bits to be rounded */
+    msk_f32_u32_zro <<= bit_xpl_nbr_zro;
+    msk_f32_u32_one=~msk_f32_u32_zro;
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx+=2L) u32_ptr[idx]&=msk_f32_u32_zro;
+      for(idx=1L;idx<sz;idx+=2L)
+	if(u32_ptr[idx] != 0U) /* Never quantize upwards floating point values of zero */
+	  u32_ptr[idx]|=msk_f32_u32_one;
+    }else{
+      const float mss_val_flt=*mss_val.fp;
+      for(idx=0L;idx<sz;idx+=2L)
+	if(op1.fp[idx] != mss_val_flt) u32_ptr[idx]&=msk_f32_u32_zro;
+      for(idx=1L;idx<sz;idx+=2L)
+	if(op1.fp[idx] != mss_val_flt && u32_ptr[idx] != 0U) u32_ptr[idx]|=msk_f32_u32_one;
+    } /* end else */
+    break;
+  case NC_DOUBLE:
+    bit_xpl_nbr_sgn=bit_xpl_nbr_sgn_dbl;
+    bit_xpl_nbr_zro=bit_xpl_nbr_sgn-prc_bnr_xpl_rqr;
+    assert(bit_xpl_nbr_zro <= bit_xpl_nbr_sgn-NCO_PPC_BIT_XPL_NBR_MIN);
+    u64_ptr=(unsigned long int *)op1.ui64p;
+    /* Create mask */
+    msk_f64_u64_zro=0ul; /* Zero all bits */
+    msk_f64_u64_zro=~msk_f64_u64_zro; /* Turn all bits to ones */
+    /* Left shift zeros into bits to be rounded */
+    msk_f64_u64_zro <<= bit_xpl_nbr_zro;
+    msk_f64_u64_one=~msk_f64_u64_zro;
+    if(!has_mss_val){
+      for(idx=0L;idx<sz;idx+=2L) u64_ptr[idx]&=msk_f64_u64_zro;
+      for(idx=1L;idx<sz;idx+=2L)
+	if(u64_ptr[idx] != 0UL) /* Never quantize upwards floating point values of zero */
+	  u64_ptr[idx]|=msk_f64_u64_one;
+    }else{
+      const double mss_val_dbl=*mss_val.dp;
+      for(idx=0L;idx<sz;idx+=2L)
+	if(op1.dp[idx] != mss_val_dbl) u64_ptr[idx]&=msk_f64_u64_zro;
+      for(idx=1L;idx<sz;idx+=2L)
+	if(op1.dp[idx] != mss_val_dbl && u64_ptr[idx] != 0UL) u64_ptr[idx]|=msk_f64_u64_one;
+    } /* end else */
+    break;
+  case NC_INT: /* Do nothing for non-floating point types ...*/
+  case NC_SHORT:
+  case NC_CHAR:
+  case NC_BYTE:
+  case NC_UBYTE:
+  case NC_USHORT:
+  case NC_UINT:
+  case NC_INT64:
+  case NC_UINT64:
+  case NC_STRING: break;
+  default: 
+    nco_dfl_case_nc_type_err();
+    break;
+  } /* end switch */
+  
+  /* 20150126: fxm casting pointers is tricky with this routine. Avoid for now. */
+  /* NB: it is not neccessary to un-typecast pointers to values after access 
+     because we have only operated on local copies of them. */
+
+} /* end nco_ppc_bitmask() */
+
+double /* [frc] Rounded value */
+nco_ppc_bitmask_scl /* [fnc] Round input value significand by specified number of bits */
+(const double val_xct, /* I [frc] Exact value to round */
+ const int bit_xpl_nbr_zro) /* I [nbr] Bits to round */
+{
+  /* Purpose: Mask-out bit_xpl_nbr_zro least most significant bits of a scalar double precision value
+     Code originally from nco_ppc_bitmask() (bitmasking is my signature move)
+     Code used in nco_rgr_map() when diagnosing whether quadrature weights properly normalized */
+
+  const int bit_xpl_nbr_sgn_dbl=53; /* [nbr] Bits 0-52 of DP significands are explicit. Bit 53 is implicit. */
+  double val_rnd; /* [frc] Rounded version of exact value */
+  unsigned long int *u64_ptr;
+  unsigned long int msk_f64_u64_zro;
+  assert(bit_xpl_nbr_zro >= 0 && bit_xpl_nbr_zro <= bit_xpl_nbr_sgn_dbl-NCO_PPC_BIT_XPL_NBR_MIN);
+
+  val_rnd=val_xct;
+  msk_f64_u64_zro=0ul; /* Zero all bits */
+  msk_f64_u64_zro=~msk_f64_u64_zro; /* Turn all bits to ones */
+  msk_f64_u64_zro <<= bit_xpl_nbr_zro;
+  u64_ptr=(unsigned long int *)&val_rnd;
+  *u64_ptr&=msk_f64_u64_zro;
+
+  return val_rnd;
+} /* end nco_ppc_bitmask_scl() */
diff --git a/src/nco/nco_ppc.h b/src/nco/nco_ppc.h
index 5b41fae..3e5f0ac 100644
--- a/src/nco/nco_ppc.h
+++ b/src/nco/nco_ppc.h
@@ -28,6 +28,12 @@
 #include "nco_mmr.h" /* Memory management */
 #include "nco_sng_utl.h" /* String utilities */
 
+/* Minimum number of explicit significand bits to preserve when zeroing/bit-masking floating point values
+   Codes will preserve at least two explicit bits, IEEE significand representation contains one implicit bit
+   Thus preserve a least three bits which is approximately one sigificant decimal digit
+   Used in nco_ppc_bitmask() and nco_ppc_bitmask_scl() */
+#define NCO_PPC_BIT_XPL_NBR_MIN 2
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -58,6 +64,29 @@ extern "C" {
    const char * const ppc_arg, /* I [sng] user input for precision-preserving compression */
    trv_tbl_sct * const trv_tbl); /* I/O [sct] Traversal table */
 
+  void
+  nco_ppc_around /* [fnc] Replace op1 values by their values rounded to decimal precision prc */
+  (const int prc, /* I [nbr] Precision-preserving compression, i.e., number of total or decimal significant digits */
+   const nc_type type, /* I [enm] netCDF type of operand */
+   const long sz, /* I [nbr] Size (in elements) of operand */
+   const int has_mss_val, /* I [flg] Flag for missing values */
+   ptr_unn mss_val, /* I [val] Value of missing value */
+   ptr_unn op1); /* I/O [val] Values of first operand */
+
+  void
+  nco_ppc_bitmask /* [fnc] Mask-out insignificant bits of significand */
+  (const int nsd, /* I [nbr] Number of significant digits, i.e., arithmetic precision */
+   const nc_type type, /* I [enm] netCDF type of operand */
+   const long sz, /* I [nbr] Size (in elements) of operand */
+   const int has_mss_val, /* I [flg] Flag for missing values */
+   ptr_unn mss_val, /* I [val] Value of missing value */
+   ptr_unn op1); /* I/O [val] Values of first operand */
+  
+  double /* [frc] Rounded value */
+  nco_ppc_bitmask_scl /* [fnc] Round input value significand by specified number of bits */
+  (const double val_xct, /* I [frc] Exact value to round */
+   const int bit_xpl_nbr_zro); /* I [nbr] Bits to round */
+
 #ifdef __cplusplus
 } /* end extern "C" */
 #endif /* __cplusplus */
diff --git a/src/nco/nco_prn.c b/src/nco/nco_prn.c
index 41d80f1..e250b0f 100644
--- a/src/nco/nco_prn.c
+++ b/src/nco/nco_prn.c
@@ -1222,6 +1222,7 @@ nco_prn_var_dfn                     /* [fnc] Print variable metadata */
   if(prn_flg->xml) prn_ndn=prn_flg->sxn_fst+var_trv->grp_dpt*prn_flg->spc_per_lvl;
   if(prn_flg->trd){
     if(nco_fmt_xtn_get() != nco_fmt_xtn_hdf4 || NC_LIB_VERSION >= 433) (void)fprintf(stdout,"%*s%s: type %s, %i dimension%s, %i attribute%s, compressed? %s, chunked? %s, packed? %s\n",prn_ndn,spc_sng,var_trv->nm,nco_typ_sng(var_typ),nbr_dim,(nbr_dim == 1) ? "" : "s",nbr_att,(nbr_att == 1) ? "" : "s",(deflate) ? "yes" : "no",(srg_typ == NC_CHUNKED) ? "yes" : "no",(packing) ? "yes" : "no"); else (void)fprintf(stdout,"%*s%s: type %s, %i dimension%s, %i attribute%s, compressed? HDF4_UNKNOWN, [...]
+    if(nco_dbg_lvl_get() >= nco_dbg_var) (void)fprintf(stdout,"%*s%s id = %d\n",prn_ndn,spc_sng,var_trv->nm,var_id);
   } /* !trd */
   if(prn_flg->xml) (void)fprintf(stdout,"%*s<variable name=\"%s\" type=\"%s\"",prn_ndn,spc_sng,var_trv->nm,xml_typ_nm(var_typ));
 
@@ -2157,6 +2158,8 @@ nco_grp_prn /* [fnc] Recursively print group contents */
   dmn_nbr=0; /* [nbr] Number of dimensions defined in group */
   var_nbr_xtr=0; /* [nbr] Number of variables to be extracted in group */
 
+  if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: DEBUG qrk5 nm = %s xtr = %s\n",nco_prg_nm_get(),trv_tbl->lst[1].nm_fll,(trv_tbl->lst[1].flg_xtr) ? "Yes" : "No");
+
   /* Find group in traversal table */
   for(obj_idx=0;obj_idx<trv_tbl->nbr;obj_idx++)
     if(trv_tbl->lst[obj_idx].nco_typ == nco_obj_typ_grp)
@@ -2238,6 +2241,8 @@ nco_grp_prn /* [fnc] Recursively print group contents */
   /* Create array to hold names and indices of extracted variables in this group */
   var_lst=(nm_id_sct *)nco_malloc(nbr_var*(sizeof(nm_id_sct)));
 
+  if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: DEBUG qrk6 nm = %s xtr = %s\n",nco_prg_nm_get(),trv_tbl->lst[1].nm_fll,(trv_tbl->lst[1].flg_xtr) ? "Yes" : "No");
+
   for(var_idx=0;var_idx<nbr_var;var_idx++){
     /* Get variable name */
     rcd+=nco_inq_varname(grp_id,var_idx,var_nm);
@@ -2274,6 +2279,8 @@ nco_grp_prn /* [fnc] Recursively print group contents */
 
   } /* end loop over variables */
 
+  if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: DEBUG qrk7 nm = %s xtr = %s\n",nco_prg_nm_get(),trv_tbl->lst[1].nm_fll,(trv_tbl->lst[1].flg_xtr) ? "Yes" : "No");
+
   /* Compactify array to hold names and indices of extracted variables in this group */
   var_lst=(nm_id_sct *)nco_realloc(var_lst,var_nbr_xtr*(sizeof(nm_id_sct)));
 
diff --git a/src/nco/nco_rgr.c b/src/nco/nco_rgr.c
index f958ceb..140cda0 100644
--- a/src/nco/nco_rgr.c
+++ b/src/nco/nco_rgr.c
@@ -11,38 +11,38 @@
 
 int /* O [enm] Return code */
 nco_rgr_ctl /* [fnc] Control regridding logic */
-(rgr_sct * const rgr_nfo) /* I/O [sct] Regridding structure */
+(rgr_sct * const rgr, /* I/O [sct] Regridding structure */
+ trv_tbl_sct * const trv_tbl) /* I/O [sct] Traversal Table */
 {
   /* Purpose: Control regridding logic */
   int rcd=NCO_NOERR;
   const char fnc_nm[]="nco_rgr_ctl()";
 
+  nco_bool flg_map=False; /* [flg] Weight-based regridding */
   nco_bool flg_smf=False; /* [flg] ESMF regridding */
   nco_bool flg_tps=False; /* [flg] Tempest regridding */
-  nco_bool flg_map=False; /* [flg] Weight-based regridding */
 
   /* Main control branching occurs here
-     The branching complexity will increase as more regridding features are added */
-  if(rgr_nfo->flg_map) flg_map=True;
-  if(rgr_nfo->flg_grd_src && rgr_nfo->flg_grd_dst) flg_smf=True;
-  if(rgr_nfo->drc_tps) flg_tps=True;
+     Branching complexity and utility will increase as regridding features are added */
+  if(rgr->flg_map) flg_map=True;
+  if(rgr->flg_grd_src && rgr->flg_grd_dst) flg_smf=True;
+  if(rgr->drc_tps && !flg_map) flg_tps=True;
   assert(!(flg_smf && flg_map));
   assert(!(flg_smf && flg_tps));
   assert(!(flg_map && flg_tps));
   
   if(flg_map){
     /* Regrid using external mapping weights */
-    rcd=nco_rgr_map(rgr_nfo);
+    rcd=nco_rgr_map(rgr,trv_tbl);
   } /* !flg_map */
 
   if(flg_smf){
 #ifdef ENABLE_ESMF
     /* Regrid using ESMF library */
     (void)fprintf(stderr,"%s: %s calling nco_rgr_esmf() to generate and apply regridding map\n",nco_prg_nm_get(),fnc_nm);
-    rcd=nco_rgr_esmf(rgr_nfo);
+    rcd=nco_rgr_esmf(rgr);
     /* Close output and free dynamic memory */
-    (void)nco_fl_out_cls(rgr_nfo->fl_out,rgr_nfo->fl_out_tmp,rgr_nfo->out_id);
-    (void)nco_rgr_free(rgr_nfo);
+    (void)nco_fl_out_cls(rgr->fl_out,rgr->fl_out_tmp,rgr->out_id);
 #else /* !ENABLE_ESMF */
     (void)fprintf(stderr,"%s: ERROR %s reports attempt to use ESMF regridding without built-in support. Re-configure with --enable_esmf.\n",nco_prg_nm_get(),fnc_nm);
     nco_exit(EXIT_FAILURE);
@@ -51,45 +51,63 @@ nco_rgr_ctl /* [fnc] Control regridding logic */
   
   if(flg_tps){
     /* Regrid using Tempest regridding */
-    rcd=nco_rgr_tps(rgr_nfo);
+    rcd=nco_rgr_tps(rgr);
   } /* !flg_map */
 
   return rcd;
 } /* end nco_rgr_ctl() */
 
-void
+rgr_sct * /* O [sct] Pointer to free'd regridding structure */
 nco_rgr_free /* [fnc] Deallocate regridding structure */
-(rgr_sct * const rgr_nfo) /* I/O [sct] Regridding structure */
+(rgr_sct *rgr) /* I/O [sct] Regridding structure */
 {
-  /* [fnc] Free all dynamic memory in regridding structure */
-  if(rgr_nfo->fl_grd_src) rgr_nfo->fl_grd_src=(char *)nco_free(rgr_nfo->fl_grd_src);
-  if(rgr_nfo->fl_grd_dst) rgr_nfo->fl_grd_dst=(char *)nco_free(rgr_nfo->fl_grd_dst);
-  if(rgr_nfo->fl_in) rgr_nfo->fl_in=(char *)nco_free(rgr_nfo->fl_in);
-  if(rgr_nfo->fl_out) rgr_nfo->fl_out=(char *)nco_free(rgr_nfo->fl_out);
-  if(rgr_nfo->fl_out_tmp) rgr_nfo->fl_out_tmp=(char *)nco_free(rgr_nfo->fl_out_tmp);
-  if(rgr_nfo->fl_map) rgr_nfo->fl_map=(char *)nco_free(rgr_nfo->fl_map);
-  if(rgr_nfo->var_nm) rgr_nfo->var_nm=(char *)nco_free(rgr_nfo->var_nm);
+  /* Purpose: Free all dynamic memory in regridding structure */
+  if(rgr->fl_grd_src) rgr->fl_grd_src=(char *)nco_free(rgr->fl_grd_src);
+  if(rgr->fl_grd_dst) rgr->fl_grd_dst=(char *)nco_free(rgr->fl_grd_dst);
+  if(rgr->fl_in) rgr->fl_in=(char *)nco_free(rgr->fl_in);
+  if(rgr->fl_out) rgr->fl_out=(char *)nco_free(rgr->fl_out);
+  if(rgr->fl_out_tmp) rgr->fl_out_tmp=(char *)nco_free(rgr->fl_out_tmp);
+  if(rgr->fl_map) rgr->fl_map=(char *)nco_free(rgr->fl_map);
+  if(rgr->var_nm) rgr->var_nm=(char *)nco_free(rgr->var_nm);
 
   /* Tempest */
-  if(rgr_nfo->drc_tps) rgr_nfo->drc_tps=(char *)nco_free(rgr_nfo->drc_tps);
-
-  /* Mapfiles */
-  if(rgr_nfo->drc_tps) rgr_nfo->drc_tps=(char *)nco_free(rgr_nfo->drc_tps);
-
+  if(rgr->drc_tps) rgr->drc_tps=(char *)nco_free(rgr->drc_tps);
+
+  /* free() memory used to construct KVMs */
+  if(rgr->rgr_nbr > 0) rgr->rgr_arg=nco_sng_lst_free(rgr->rgr_arg,rgr->rgr_nbr);
+
+  /* free() memory copied from KVMs */
+  if(rgr->area_nm) rgr->area_nm=(char *)nco_free(rgr->area_nm);
+  if(rgr->bnd_nm) rgr->bnd_nm=(char *)nco_free(rgr->bnd_nm);
+  if(rgr->bnd_tm_nm) rgr->bnd_tm_nm=(char *)nco_free(rgr->bnd_tm_nm);
+  if(rgr->col_nm) rgr->col_nm=(char *)nco_free(rgr->col_nm);
+  if(rgr->lat_bnd_nm) rgr->lat_bnd_nm=(char *)nco_free(rgr->lat_bnd_nm);
+  if(rgr->lat_nm) rgr->lat_nm=(char *)nco_free(rgr->lat_nm);
+  if(rgr->lat_vrt_nm) rgr->lat_vrt_nm=(char *)nco_free(rgr->lat_vrt_nm);
+  if(rgr->lat_wgt_nm) rgr->lat_wgt_nm=(char *)nco_free(rgr->lat_wgt_nm);
+  if(rgr->lon_bnd_nm) rgr->lon_bnd_nm=(char *)nco_free(rgr->lon_bnd_nm);
+  if(rgr->lon_nm) rgr->lon_nm=(char *)nco_free(rgr->lon_nm);
+  if(rgr->lon_vrt_nm) rgr->lon_vrt_nm=(char *)nco_free(rgr->lon_vrt_nm);
+  if(rgr->vrt_nm) rgr->vrt_nm=(char *)nco_free(rgr->vrt_nm);
+
+  /* Lastly, free() regrid structure itself */
+  if(rgr) rgr=(rgr_sct *)nco_free(rgr);
+
+  return rgr;
 } /* end nco_rfr_free() */
   
-int /* O [enm] Return code */
+rgr_sct * /* O [sct] Regridding structure */
 nco_rgr_ini /* [fnc] Initialize regridding structure */
 (const int in_id, /* I [id] Input netCDF file ID */
  char **rgr_arg, /* [sng] Regridding arguments */
- const int rgr_nbr, /* [nbr] Number of regridding arguments */
+ const int rgr_arg_nbr, /* [nbr] Number of regridding arguments */
  char * const rgr_in, /* I [sng] File containing fields to be regridded */
  char * const rgr_out, /* I [sng] File containing regridded fields */
  char * const rgr_grd_src, /* I [sng] File containing input grid */
  char * const rgr_grd_dst, /* I [sng] File containing destination grid */
  char * const rgr_map, /* I [sng] File containing mapping weights from source to destination grid */
  char * const rgr_var, /* I [sng] Variable for special regridding treatment */
- rgr_sct * const rgr_nfo) /* O [sct] Regridding structure */
+ const double wgt_vld_thr) /* I [frc] Weight threshold for valid destination value */
 {
   /* Purpose: Initialize regridding structure */
      
@@ -106,62 +124,199 @@ nco_rgr_ini /* [fnc] Initialize regridding structure */
      T42->T42 from scratch:
      ncks -O --rgr=Y --rgr_grd_src=${DATA}/scrip/grids/remap_grid_T42.nc --rgr_grd_dst=${DATA}/scrip/grids/remap_grid_T42.nc --rgr_out=${DATA}/rgr/rgr_out.nc ${DATA}/rgr/essgcm14_clm.nc ~/foo.nc
      T42->POP43 from existing weights:
-     ncks -O --rgr=Y --rgr_grd_src=${DATA}/scrip/grids/remap_grid_T42.nc --rgr_grd_dst=${DATA}/scrip/grids/remap_grid_POP43.nc --rgr_map=${DATA}/scrip/rmp_T42_to_POP43_conserv.nc --rgr_out=${DATA}/rgr/rgr_out.nc ${DATA}/rgr/essgcm14_clm.nc ~/foo.nc */
+     ncks -O --rgr=Y --rgr_map=${DATA}/scrip/rmp_T42_to_POP43_conserv.nc --rgr_out=${DATA}/rgr/rgr_out.nc ${DATA}/rgr/essgcm14_clm.nc ~/foo.nc */
 
   const char fnc_nm[]="nco_rgr_ini()";
   
-  int rcd=NCO_NOERR;
+  rgr_sct *rgr;
+
+  /* Allocate */
+  rgr=(rgr_sct *)nco_malloc(sizeof(rgr_sct));
   
   /* Initialize */
-  rgr_nfo->flg_usr_rqs=False; /* [flg] User requested regridding */
-  rgr_nfo->out_id=int_CEWI; /* [id] Output netCDF file ID */
+  rgr->flg_usr_rqs=False; /* [flg] User requested regridding */
+  rgr->out_id=int_CEWI; /* [id] Output netCDF file ID */
 
-  rgr_nfo->in_id=in_id; /* [id] Input netCDF file ID */
-  rgr_nfo->rgr_arg=rgr_arg; /* [sng] Regridding arguments */
-  rgr_nfo->rgr_nbr=rgr_nbr; /* [nbr] Number of regridding arguments */
+  rgr->in_id=in_id; /* [id] Input netCDF file ID */
+  rgr->rgr_arg=rgr_arg; /* [sng] Regridding arguments */
+  rgr->rgr_nbr=rgr_arg_nbr; /* [nbr] Number of regridding arguments */
 
-  rgr_nfo->flg_grd_src= rgr_grd_src ? True : False; /* [flg] User-specified input grid */
-  rgr_nfo->fl_grd_src=rgr_grd_src; /* [sng] File containing input grid */
+  rgr->drc_tps=NULL; /* [sng] Directory where Tempest grids, meshes, and weights are stored */
 
-  rgr_nfo->flg_grd_dst= rgr_grd_dst ? True : False; /* [flg] User-specified destination grid */
-  rgr_nfo->fl_grd_dst=rgr_grd_dst; /* [sng] File containing destination grid */
+  rgr->flg_grd_src= rgr_grd_src ? True : False; /* [flg] User-specified input grid */
+  rgr->fl_grd_src=rgr_grd_src; /* [sng] File containing input grid */
 
-  rgr_nfo->fl_in=rgr_in; /* [sng] File containing fields to be regridded */
-  rgr_nfo->fl_out=rgr_out; /* [sng] File containing regridded fields */
-  rgr_nfo->fl_out_tmp=NULL_CEWI; /* [sng] Temporary file containing regridded fields */
+  rgr->flg_grd_dst= rgr_grd_dst ? True : False; /* [flg] User-specified destination grid */
+  rgr->fl_grd_dst=rgr_grd_dst; /* [sng] File containing destination grid */
 
-  rgr_nfo->flg_map= rgr_map ? True : False; /* [flg] User-specified mapping weights */
-  rgr_nfo->fl_map=rgr_map; /* [sng] File containing mapping weights from source to destination grid */
+  rgr->fl_in=rgr_in; /* [sng] File containing fields to be regridded */
+  rgr->fl_out=rgr_out; /* [sng] File containing regridded fields */
+  rgr->fl_out_tmp=NULL_CEWI; /* [sng] Temporary file containing regridded fields */
 
-  rgr_nfo->var_nm=rgr_var; /* [sng] Variable for special regridding treatment */
+  rgr->flg_map= rgr_map ? True : False; /* [flg] User-specified mapping weights */
+  rgr->fl_map=rgr_map; /* [sng] File containing mapping weights from source to destination grid */
+
+  rgr->var_nm=rgr_var; /* [sng] Variable for special regridding treatment */
   
   /* Did user explicitly request regridding? */
-  if(rgr_nbr > 0 || rgr_grd_src != NULL || rgr_grd_dst != NULL || rgr_out != NULL || rgr_map != NULL) rgr_nfo->flg_usr_rqs=True;
+  if(rgr_arg_nbr > 0 || rgr_grd_src != NULL || rgr_grd_dst != NULL || rgr_map != NULL) rgr->flg_usr_rqs=True;
 
   /* Initialize arguments after copying */
-  if(!rgr_nfo->fl_out) rgr_nfo->fl_out=(char *)strdup("/data/zender/rgr/rgr_out.nc");
-  if(!rgr_nfo->fl_grd_dst) rgr_nfo->fl_grd_dst=(char *)strdup("/data/zender/scrip/grids/remap_grid_T42.nc");
-  if(!rgr_nfo->var_nm) rgr_nfo->var_nm=(char *)strdup("ORO");
+  if(!rgr->fl_out) rgr->fl_out=(char *)strdup("/data/zender/rgr/rgr_out.nc");
+  if(!rgr->fl_grd_dst) rgr->fl_grd_dst=(char *)strdup("/data/zender/scrip/grids/remap_grid_T42.nc");
+  if(!rgr->var_nm) rgr->var_nm=(char *)strdup("ORO");
   
   if(nco_dbg_lvl_get() >= nco_dbg_crr){
     (void)fprintf(stderr,"%s: INFO %s reports ",nco_prg_nm_get(),fnc_nm);
-    (void)fprintf(stderr,"flg_usr_rqs = %d, ",rgr_nfo->flg_usr_rqs);
-    (void)fprintf(stderr,"rgr_nbr = %d, ",rgr_nfo->rgr_nbr);
-    (void)fprintf(stderr,"fl_grd_src = %s, ",rgr_nfo->fl_grd_src ? rgr_nfo->fl_grd_src : "NULL");
-    (void)fprintf(stderr,"fl_grd_dst = %s, ",rgr_nfo->fl_grd_dst ? rgr_nfo->fl_grd_dst : "NULL");
-    (void)fprintf(stderr,"fl_in = %s, ",rgr_nfo->fl_in ? rgr_nfo->fl_in : "NULL");
-    (void)fprintf(stderr,"fl_out = %s, ",rgr_nfo->fl_out ? rgr_nfo->fl_out : "NULL");
-    (void)fprintf(stderr,"fl_out_tmp = %s, ",rgr_nfo->fl_out_tmp ? rgr_nfo->fl_out_tmp : "NULL");
-    (void)fprintf(stderr,"fl_map = %s, ",rgr_nfo->fl_map ? rgr_nfo->fl_map : "NULL");
+    (void)fprintf(stderr,"flg_usr_rqs = %d, ",rgr->flg_usr_rqs);
+    (void)fprintf(stderr,"rgr_nbr = %d, ",rgr->rgr_nbr);
+    (void)fprintf(stderr,"fl_grd_src = %s, ",rgr->fl_grd_src ? rgr->fl_grd_src : "NULL");
+    (void)fprintf(stderr,"fl_grd_dst = %s, ",rgr->fl_grd_dst ? rgr->fl_grd_dst : "NULL");
+    (void)fprintf(stderr,"fl_in = %s, ",rgr->fl_in ? rgr->fl_in : "NULL");
+    (void)fprintf(stderr,"fl_out = %s, ",rgr->fl_out ? rgr->fl_out : "NULL");
+    (void)fprintf(stderr,"fl_out_tmp = %s, ",rgr->fl_out_tmp ? rgr->fl_out_tmp : "NULL");
+    (void)fprintf(stderr,"fl_map = %s, ",rgr->fl_map ? rgr->fl_map : "NULL");
     (void)fprintf(stderr,"\n");
   } /* endif dbg */
   
-  return rcd;
+  /* Flags */
+  if(wgt_vld_thr == NC_MIN_DOUBLE){
+    rgr->flg_rnr=False;
+  }else if(wgt_vld_thr >= 0.0 && wgt_vld_thr <= 1.0){
+    /* NB: Weight thresholds of 0.0 or nearly zero can lead to underflow or divide-by-zero errors */
+    // const double wgt_vld_thr_min=1.0e-10; /* [frc] Minimum weight threshold for valid destination value */
+    rgr->flg_rnr=True;
+    rgr->wgt_vld_thr=wgt_vld_thr;
+  }else{
+    (void)fprintf(stderr,"%s: ERROR weight threshold must be in [0.0,1.0] and user supplied wgt_vld_thr = %g\n",nco_prg_nm_get(),wgt_vld_thr);
+    nco_exit(EXIT_FAILURE);
+  } /* endif */
+  
+  /* Parse extended kvm options */
+  int rgr_arg_idx; /* [idx] Index over rgr_arg (i.e., separate invocations of "--rgr var1[,var2]=val") */
+  int rgr_var_idx; /* [idx] Index over rgr_lst (i.e., all names explicitly specified in all "--rgr var1[,var2]=val" options) */
+  int rgr_var_nbr=0;
+  kvm_sct *rgr_lst; /* [sct] List of all regrid specifications */
+  kvm_sct kvm;
+
+  rgr_lst=(kvm_sct *)nco_malloc(NC_MAX_VARS*sizeof(kvm_sct));
+
+  /* Parse RGRs */
+  for(rgr_arg_idx=0;rgr_arg_idx<rgr_arg_nbr;rgr_arg_idx++){
+    if(!strstr(rgr_arg[rgr_arg_idx],"=")){
+      (void)fprintf(stdout,"%s: Invalid --rgr specification: %s. Must contain \"=\" sign, e.g., \"key=value\".\n",nco_prg_nm_get(),rgr_arg[rgr_arg_idx]);
+      if(rgr_lst) rgr_lst=(kvm_sct *)nco_free(rgr_lst);
+      nco_exit(EXIT_FAILURE);
+    } /* endif */
+    kvm=nco_sng2kvm(rgr_arg[rgr_arg_idx]);
+    /* nco_sng2kvm() converts argument "--rgr one,two=3" into kvm.key="one,two" and kvm.val=3
+       Then nco_lst_prs_2D() converts kvm.key into two items, "one" and "two", with the same value, 3 */
+    if(kvm.key){
+      int var_idx; /* [idx] Index over variables in current RGR argument */
+      int var_nbr; /* [nbr] Number of variables in current RGR argument */
+      char **var_lst;
+      var_lst=nco_lst_prs_2D(kvm.key,",",&var_nbr);
+      for(var_idx=0;var_idx<var_nbr;var_idx++){ /* Expand multi-variable specification */
+        rgr_lst[rgr_var_nbr].key=strdup(var_lst[var_idx]);
+        rgr_lst[rgr_var_nbr].val=strdup(kvm.val);
+        rgr_var_nbr++;
+      } /* end for */
+      var_lst=nco_sng_lst_free(var_lst,var_nbr);
+    } /* end if */
+  } /* end for */
+
+  /* NULL-initialize */
+  rgr->area_nm=NULL; /* [sng] Name of variable containing gridcell area */
+  rgr->bnd_nm=NULL; /* [sng] Name of dimension to employ for spatial bounds */
+  rgr->bnd_tm_nm=NULL; /* [sng] Name of dimension to employ for temporal bounds */
+  rgr->col_nm=NULL; /* [sng] Name of horizontal spatial dimension on unstructured grid */
+  rgr->lat_bnd_nm=NULL; /* [sng] Name of rectangular boundary variable for latitude */
+  rgr->lat_nm=NULL; /* [sng] Name of dimension to recognize as latitude */
+  rgr->lat_vrt_nm=NULL; /* [sng] Name of non-rectangular boundary variable for latitude */
+  rgr->lat_wgt_nm=NULL; /* [sng] Name of variable containing latitude weights */
+  rgr->lon_bnd_nm=NULL; /* [sng] Name of rectangular boundary variable for longitude */
+  rgr->lon_nm=NULL; /* [sng] Name of dimension to recognize as longitude */
+  rgr->lon_vrt_nm=NULL; /* [sng] Name of non-rectangular boundary variable for longitude */
+  rgr->vrt_nm=NULL; /* [sng] Name of dimension to employ for vertices */
+
+  for(rgr_var_idx=0;rgr_var_idx<rgr_var_nbr;rgr_var_idx++){
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"area_nm")){
+      rgr->area_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"bnd_nm")){
+      rgr->bnd_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"bnd_tm_nm")){
+      rgr->bnd_tm_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"col_nm")){
+      rgr->col_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lat_bnd_nm")){
+      rgr->lat_bnd_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lat_nm")){
+      rgr->lat_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lat_vrt_nm")){
+      rgr->lat_vrt_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lat_wgt_nm")){
+      rgr->lat_wgt_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lon_bnd_nm")){
+      rgr->lon_bnd_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lon_nm")){
+      rgr->lon_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"lon_vrt_nm")){
+      rgr->lon_vrt_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    if(!strcasecmp(rgr_lst[rgr_var_idx].key,"vrt_nm")){
+      rgr->vrt_nm=(char *)strdup(rgr_lst[rgr_var_idx].val);
+      continue;
+    } /* endif */
+    (void)fprintf(stderr,"%s: ERROR %s reports unrecognized key-value option to --rgr switch: %s\n",nco_prg_nm_get(),fnc_nm,rgr_lst[rgr_var_idx].key);
+    nco_exit(EXIT_FAILURE);
+  } /* end for */
+
+  /* Revert to defaults for any not specified on command-line */
+  if(!rgr->area_nm) rgr->area_nm=(char *)strdup("area"); /* [sng] Name of variable containing gridcell area */
+  if(!rgr->bnd_nm) rgr->bnd_nm=(char *)strdup("nbnd"); /* [sng] Name of dimension to employ for spatial bounds */
+  /* NB: CESM uses nbnd for temporal bounds. NCO defaults to nbnd for all bounds with two endpoints */
+  if(!rgr->bnd_tm_nm) rgr->bnd_tm_nm=(char *)strdup("nbnd"); /* [sng] Name of dimension to employ for spatial bounds */
+  if(!rgr->col_nm) rgr->col_nm=(char *)strdup("ncol"); /* [sng] Name of horizontal spatial dimension on unstructured grid */
+  if(!rgr->lat_bnd_nm) rgr->lat_bnd_nm=(char *)strdup("lat_bnds"); /* [sng] Name of rectangular boundary variable for latitude */
+  if(!rgr->lat_nm) rgr->lat_nm=(char *)strdup("lat"); /* [sng] Name of dimension to recognize as latitude */
+  if(!rgr->lat_vrt_nm) rgr->lat_vrt_nm=(char *)strdup("lat_vertices"); /* [sng] Name of non-rectangular boundary variable for latitude */
+  if(!rgr->lat_wgt_nm) rgr->lat_wgt_nm=(char *)strdup("gw"); /* [sng] Name of variable containing latitude weights */
+  if(!rgr->lon_bnd_nm) rgr->lon_bnd_nm=(char *)strdup("lon_bnds"); /* [sng] Name of rectangular boundary variable for longitude */
+  if(!rgr->lon_nm) rgr->lon_nm=(char *)strdup("lon"); /* [sng] Name of dimension to recognize as longitude */
+  if(!rgr->lon_vrt_nm) rgr->lon_vrt_nm=(char *)strdup("lon_vertices"); /* [sng] Name of non-rectangular boundary variable for longitude */
+  if(!rgr->vrt_nm) rgr->vrt_nm=(char *)strdup("nv"); /* [sng] Name of dimension to employ for vertices */
+
+  /* Free kvms */
+  if(rgr_lst) rgr_lst=nco_kvm_lst_free(rgr_lst,rgr_var_nbr);
+
+  return rgr;
 } /* end nco_rgr_ini() */
   
 int /* O [enm] Return code */
 nco_rgr_map /* [fnc] Regrid using external weights */
-(rgr_sct * const rgr_nfo) /* I/O [sct] Regridding structure */
+(rgr_sct * const rgr, /* I/O [sct] Regridding structure */
+ trv_tbl_sct * const trv_tbl) /* I/O [sct] Traversal Table */
 {
   /* Purpose: Regrid fields using external weights (i.e., a mapping file)
 
@@ -207,55 +362,57 @@ nco_rgr_map /* [fnc] Regrid using external weights */
      in SCRIP remapping files because SCRIP stores everying in 1-D sparse matrix arrays
      Sparse matrix formulations:
 
-     for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++)
+     for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++){
        // Normalization: fractional area
        dst[ddr_dst[lnk_idx]]+=src[ddr_src[lnk_idx]]*remap_matrix[lnk_idx,0];
        // Normalization: destination area
        dst[ddr_dst[lnk_idx]]+=src[ddr_src[lnk_idx]]*remap_matrix[lnk_idx,0]/dst_area[ddr_dst[lnk_idx]];
        // Normalization: none
        dst[ddr_dst[lnk_idx]]+=src[ddr_src[lnk_idx]]*remap_matrix[lnk_idx,0]/(dst_area[ddr_dst[lnk_idx]]*dst_frc[ddr_dst[lnk_idx]);
-  */
+     } // end loop over lnk
+
+     Documentation:
+     NCL special cases described in popRemap.ncl, e.g., at
+     https://github.com/yyr/ncl/blob/master/ni/src/examples/gsun/popRemap.ncl */
 
   const char fnc_nm[]="nco_rgr_map()"; /* [sng] Function name */
 
-  char *fl_in=rgr_nfo->fl_map;
+  char *fl_in;
   char *fl_pth_lcl=NULL;
 
-  int in_id;  
+  int in_id; /* I [id] Input netCDF file ID */
+  int out_id; /* I [id] Output netCDF file ID */
   int md_open; /* [enm] Mode flag for nc_open() call */
   int rcd=NC_NOERR;
 
-  int src_grid_size_id; /* [id] Source grid size dimension ID */
-  int dst_grid_size_id; /* [id] Destination grid size dimension ID */
-  int src_grid_corners_id; /* [id] Source grid corners dimension ID */
   int dst_grid_corners_id; /* [id] Destination grid corners dimension ID */
-  int src_grid_rank_id; /* [id] Source grid rank dimension ID */
   int dst_grid_rank_id; /* [id] Destination grid rank dimension ID */
+  int dst_grid_size_id; /* [id] Destination grid size dimension ID */
   int num_links_id; /* [id] Number of links dimension ID */
   int num_wgts_id; /* [id] Number of weights dimension ID */
+  int src_grid_corners_id; /* [id] Source grid corners dimension ID */
+  int src_grid_rank_id; /* [id] Source grid rank dimension ID */
+  int src_grid_size_id; /* [id] Source grid size dimension ID */
 
   nco_bool FL_RTR_RMT_LCN;
   nco_bool RAM_OPEN=False; /* [flg] Open (netCDF3-only) file(s) in RAM */
   nco_bool RM_RMT_FL_PST_PRC=True; /* Option R */
-
+  
   nco_map_sct rgr_map;
 
   size_t bfr_sz_hnt=NC_SIZEHINT_DEFAULT; /* [B] Buffer size hint */
-  size_t lnk_nbr; /* [nbr] Number of links */
-  size_t lnk_idx; 
   
-  if(nco_dbg_lvl_get() >= nco_dbg_crr) (void)fprintf(stderr,"%s: INFO %s obtaining mapping weights from %s\n",nco_prg_nm_get(),fnc_nm,rgr_nfo->fl_map);
-
-  var_sct *wgt=NULL;
-  var_sct *wgt_out=NULL;
+  if(nco_dbg_lvl_get() >= nco_dbg_crr) (void)fprintf(stderr,"%s: INFO %s obtaining mapping weights from %s\n",nco_prg_nm_get(),fnc_nm,rgr->fl_map);
 
+  /* Duplicate (because nco_fl_mk_lcl() free()'s fl_in) */
+  fl_in=(char *)strdup(rgr->fl_map);
   /* Make sure file is on local system and is readable or die trying */
   fl_in=nco_fl_mk_lcl(fl_in,fl_pth_lcl,&FL_RTR_RMT_LCN);
   /* Open file using appropriate buffer size hints and verbosity */
   if(RAM_OPEN) md_open=NC_NOWRITE|NC_DISKLESS; else md_open=NC_NOWRITE;
   rcd+=nco_fl_open(fl_in,md_open,&bfr_sz_hnt,&in_id);
 
-  /* Identify mapping file type.
+  /* Identify mapping file type
      Generated by SCRIP: conventions = "SCRIP"
      Generated by ESMF_Regridder: conventions = "NCAR-CSM" */
   char *att_val;
@@ -269,6 +426,7 @@ nco_rgr_map /* [fnc] Regrid using external weights */
   nc_type att_typ;
 
   nco_rgr_mpf_typ_enm nco_rgr_mpf_typ=nco_rgr_mpf_nil; /* [enm] Type of remapping file */
+  nco_rgr_grd_typ_enm nco_rgr_grd_typ=nco_rgr_grd_nil; /* [enm] Type of grid conversion */
   
   /* Look for map-type signature in Conventions attribute */
   cnv_sng=cnv_sng_UC;
@@ -288,7 +446,7 @@ nco_rgr_map /* [fnc] Regrid using external weights */
     /* ESMF conventions */
     if(strstr(att_val,"NCAR-CSM")) nco_rgr_mpf_typ=nco_rgr_mpf_ESMF;
     if(strstr(att_val,"SCRIP")) nco_rgr_mpf_typ=nco_rgr_mpf_SCRIP;
-    if(nco_rgr_mpf_typ == nco_rgr_mpf_nil) (void)fprintf(stderr,"%s: ERROR %s unrecognized map type specified in attribute Conventions = %s\n",nco_prg_nm_get(),fnc_nm,att_val);
+    if(nco_rgr_mpf_typ == nco_rgr_mpf_nil) (void)fprintf(stderr,"%s: ERROR %s unrecognized map-type specified in attribute Conventions = %s\n",nco_prg_nm_get(),fnc_nm,att_val);
     if(att_val) att_val=(char *)nco_free(att_val);
   } /* end rcd && att_typ */
 
@@ -336,7 +494,7 @@ nco_rgr_map /* [fnc] Regrid using external weights */
     att_val=(char *)nco_malloc(att_sz*nco_typ_lng(att_typ)+1L);
     rcd+=nco_get_att(in_id,NC_GLOBAL,cnv_sng,att_val,att_typ);
   } /* endif */
-    /* NUL-terminate convention attribute before using strcmp() */
+  /* NUL-terminate convention attribute before using strcmp() */
   att_val[att_sz]='\0';
   if(strstr(att_val,"fracarea")) nco_rgr_nrm_typ=nco_rgr_nrm_fracarea;
   if(strstr(att_val,"destarea")) nco_rgr_nrm_typ=nco_rgr_nrm_destarea;
@@ -344,6 +502,7 @@ nco_rgr_map /* [fnc] Regrid using external weights */
   assert(nco_rgr_nrm_typ == nco_rgr_nrm_destarea);
   if(att_val) att_val=(char *)nco_free(att_val);
   if(cnv_sng) cnv_sng=(char *)nco_free(cnv_sng);
+  assert(rgr_map.src_grid_size < INT_MAX && rgr_map.dst_grid_size < INT_MAX);
 
   cnv_sng=strdup("map_method");
   nco_rgr_mth_typ_enm nco_rgr_mth_typ=nco_rgr_mth_nil;
@@ -362,142 +521,365 @@ nco_rgr_map /* [fnc] Regrid using external weights */
   if(att_val) att_val=(char *)nco_free(att_val);
   if(cnv_sng) cnv_sng=(char *)nco_free(cnv_sng);
 
-  if(nco_dbg_lvl_get() >= nco_dbg_crr){
-    (void)fprintf(stderr,"%s: INFO %s reports ",nco_prg_nm_get(),fnc_nm);
+  if(nco_dbg_lvl_get() >= nco_dbg_scl){
+    (void)fprintf(stderr,"%s: INFO %s regridding input metadata and grid sizes: ",nco_prg_nm_get(),fnc_nm);
     (void)fprintf(stderr,"map_method = %s, normalization = %s, src_grid_size = %li, dst_grid_size = %li, src_grid_corners = %li, dst_grid_corners = %li, src_grid_rank = %li, dst_grid_rank = %li, num_links = %li, num_wgts = %li\n",nco_rgr_mth_sng(nco_rgr_mth_typ),nco_rgr_nrm_sng(nco_rgr_nrm_typ),rgr_map.src_grid_size,rgr_map.dst_grid_size,rgr_map.src_grid_corners,rgr_map.dst_grid_corners,rgr_map.src_grid_rank,rgr_map.dst_grid_rank,rgr_map.num_links,rgr_map.num_wgts);
   } /* endif dbg */
 
+  /* Set type of grid conversion */
+  if(rgr_map.src_grid_rank == 1 && rgr_map.dst_grid_rank == 1) nco_rgr_grd_typ=nco_rgr_grd_1D_to_1D;
+  if(rgr_map.src_grid_rank == 1 && rgr_map.dst_grid_rank == 2) nco_rgr_grd_typ=nco_rgr_grd_1D_to_2D;
+  if(rgr_map.src_grid_rank == 2 && rgr_map.dst_grid_rank == 1) nco_rgr_grd_typ=nco_rgr_grd_2D_to_1D;
+  if(rgr_map.src_grid_rank == 2 && rgr_map.dst_grid_rank == 2) nco_rgr_grd_typ=nco_rgr_grd_2D_to_2D;
+  assert(nco_rgr_grd_typ != nco_rgr_grd_nil);
+  /* Save typing later */
+  nco_bool flg_grd_in_1D=False;
+  nco_bool flg_grd_in_2D=False;
+  nco_bool flg_grd_out_1D=False;
+  nco_bool flg_grd_out_2D=False;
+  if(nco_rgr_grd_typ == nco_rgr_grd_1D_to_1D || nco_rgr_grd_typ == nco_rgr_grd_1D_to_2D) flg_grd_in_1D=True;
+  if(nco_rgr_grd_typ == nco_rgr_grd_2D_to_1D || nco_rgr_grd_typ == nco_rgr_grd_2D_to_2D) flg_grd_in_2D=True;
+  if(nco_rgr_grd_typ == nco_rgr_grd_1D_to_1D || nco_rgr_grd_typ == nco_rgr_grd_2D_to_1D) flg_grd_out_1D=True;
+  if(nco_rgr_grd_typ == nco_rgr_grd_1D_to_2D || nco_rgr_grd_typ == nco_rgr_grd_2D_to_2D) flg_grd_out_2D=True;
+
   /* Obtain grid values necessary to compute output latitude and longitude coordinates */
-  int dst_grd_ctr_lon_id; /* [id] Destination grid center longitudes variable ID */
-  int dst_grd_ctr_lat_id; /* [id] Destination grid center latitudes  variable ID */
-  int dst_grd_crn_lon_id; /* [id] Destination grid corner longitudes variable ID */
+  int area_dst_id; /* [id] Area variable ID */
+  int col_src_adr_id; /* [id] Source address (col) variable ID */
+  int dmn_sz_in_int_id; /* [id] Source grid dimension sizes ID */
+  int dmn_sz_out_int_id; /* [id] Destination grid dimension sizes ID */
   int dst_grd_crn_lat_id; /* [id] Destination grid corner latitudes  variable ID */
-  int dmn_sz_id; /* [id] Destination grid dimension sizes ID */
-  int wgt_raw_out_id; /* [id] Remap matrix variable ID */
+  int dst_grd_crn_lon_id; /* [id] Destination grid corner longitudes variable ID */
+  int dst_grd_ctr_lat_id; /* [id] Destination grid center latitudes  variable ID */
+  int dst_grd_ctr_lon_id; /* [id] Destination grid center longitudes variable ID */
+  int row_dst_adr_id; /* [id] Destination address (row) variable ID */
+  int wgt_raw_id; /* [id] Remap matrix variable ID */
 
   switch(nco_rgr_mpf_typ){
     /* Obtain fields whose name depends on mapfile type */
   case nco_rgr_mpf_SCRIP:
-    rcd+=nco_inq_varid(in_id,"dst_grid_center_lon",&dst_grd_ctr_lon_id);
-    rcd+=nco_inq_varid(in_id,"dst_grid_center_lat",&dst_grd_ctr_lat_id);
-    rcd+=nco_inq_varid(in_id,"dst_grid_corner_lon",&dst_grd_crn_lon_id);
-    rcd+=nco_inq_varid(in_id,"dst_grid_corner_lat",&dst_grd_crn_lat_id);
-    rcd+=nco_inq_varid(in_id,"remap_matrix",&wgt_raw_out_id); /* fxm: remap_matrix[num_links,num_wgts] != S[n_s] */
-  break;
+    rcd+=nco_inq_varid(in_id,"dst_grid_area",&area_dst_id); /* ESMF: area_b */
+    rcd+=nco_inq_varid(in_id,"dst_grid_center_lon",&dst_grd_ctr_lon_id); /* ESMF: xc_b */
+    rcd+=nco_inq_varid(in_id,"dst_grid_center_lat",&dst_grd_ctr_lat_id); /* ESMF: yc_b */
+    rcd+=nco_inq_varid(in_id,"dst_grid_corner_lon",&dst_grd_crn_lon_id); /* ESMF: xv_b */
+    rcd+=nco_inq_varid(in_id,"dst_grid_corner_lat",&dst_grd_crn_lat_id); /* ESMF: yv_b */
+    rcd+=nco_inq_varid(in_id,"dst_address",&row_dst_adr_id); /* ESMF: row */
+    rcd+=nco_inq_varid(in_id,"src_address",&col_src_adr_id); /* ESMF: col */
+    rcd+=nco_inq_varid(in_id,"remap_matrix",&wgt_raw_id); /* fxm: remap_matrix[num_links,num_wgts] != S[n_s] */
+    break;
   case nco_rgr_mpf_ESMF:
-    rcd+=nco_inq_varid(in_id,"xc_b",&dst_grd_ctr_lon_id);
-    rcd+=nco_inq_varid(in_id,"yc_b",&dst_grd_ctr_lat_id);
-    rcd+=nco_inq_varid(in_id,"xv_b",&dst_grd_crn_lon_id);
-    rcd+=nco_inq_varid(in_id,"yv_b",&dst_grd_crn_lat_id);
-    rcd+=nco_inq_varid(in_id,"S",&wgt_raw_out_id); /* fxm: remap_matrix[num_links,num_wgts] != S[n_s] */
+    rcd+=nco_inq_varid(in_id,"area_b",&area_dst_id); /* SCRIP: dst_grid_area */
+    rcd+=nco_inq_varid(in_id,"xc_b",&dst_grd_ctr_lon_id); /* SCRIP: dst_grid_center_lon */
+    rcd+=nco_inq_varid(in_id,"yc_b",&dst_grd_ctr_lat_id); /* SCRIP: dst_grid_center_lat */
+    rcd+=nco_inq_varid(in_id,"xv_b",&dst_grd_crn_lon_id); /* SCRIP: dst_grid_corner_lon */
+    rcd+=nco_inq_varid(in_id,"yv_b",&dst_grd_crn_lat_id); /* SCRIP: dst_grid_corner_lat */
+    rcd+=nco_inq_varid(in_id,"row",&row_dst_adr_id); /* SCRIP: dst_address */
+    rcd+=nco_inq_varid(in_id,"col",&col_src_adr_id); /* SCRIP: src_address */
+    rcd+=nco_inq_varid(in_id,"S",&wgt_raw_id); /* fxm: remap_matrix[num_links,num_wgts] != S[n_s] */
     break;
   default:
     (void)fprintf(stderr,"%s: ERROR %s unknown map file type\n",nco_prg_nm_get(),fnc_nm);
     nco_dfl_case_generic_err(); break;
   } /* end switch */
   /* Obtain fields whose name is independent of mapfile type */
-  rcd+=nco_inq_varid(in_id,"dst_grid_dims",&dmn_sz_id);
+  rcd+=nco_inq_varid(in_id,"src_grid_dims",&dmn_sz_in_int_id);
+  rcd+=nco_inq_varid(in_id,"dst_grid_dims",&dmn_sz_out_int_id);
 
-  long dmn_cnt[2];
-  long dmn_srt[2];
-  long dmn_srd[2];
-  long idx; /* [idx] Counting index for unrolled grids */
+  const int lon_psn_dst=0; /* [idx] Ordinal position of longitude size in rectangular destination grid */
+  const int lat_psn_dst=1; /* [idx] Ordinal position of latitude  size in rectangular destination grid */
+  const int dmn_nbr_1D=1; /* [nbr] Rank of 1-D grid variables */
+  const int dmn_nbr_2D=2; /* [nbr] Rank of 2-D grid variables */
+  const int dmn_nbr_grd_max=dmn_nbr_2D; /* [nbr] Maximum rank of grid variables */
+  double *area_out; /* [sr] Area of destination grid */
   double *lon_ctr_out; /* [dgr] Longitude centers of rectangular destination grid */
   double *lat_ctr_out; /* [dgr] Latitude  centers of rectangular destination grid */
-  double *lon_crn_out; /* [dgr] Longitude corners of rectangular destination grid */
-  double *lat_crn_out; /* [dgr] Latitude  corners of rectangular destination grid */
-  double *lon_ntf_out; /* [dgr] Longitude interfaces of rectangular destination grid */
-  double *lat_ntf_out; /* [dgr] Latitude  interfaces of rectangular destination grid */
+  double *lat_wgt_out=NULL; /* [dgr] Latitude  weights of rectangular destination grid */
+  double *lon_crn_out=NULL; /* [dgr] Longitude corners of rectangular destination grid */
+  double *lat_crn_out=NULL; /* [dgr] Latitude  corners of rectangular destination grid */
+  double *lon_ntf_out=NULL; /* [dgr] Longitude interfaces of rectangular destination grid */
+  double *lat_ntf_out=NULL; /* [dgr] Latitude  interfaces of rectangular destination grid */
   double *lon_bnd_out; /* [dgr] Longitude boundaries of rectangular destination grid */
   double *lat_bnd_out; /* [dgr] Latitude  boundaries of rectangular destination grid */
-  double *wgt_raw_out; /* [frc] Remapping weights */
-  int *dmn_sz; /* [nbr] Array of dimension sizes of destination grid */
-  const int lon_psn_dst=0; /* [idx] Ordinal position of longitude size in rectangular destination grid */
-  const int lat_psn_dst=1; /* [idx] Ordinal position of latitude  size in rectangular destination grid */
-  const int bnd_rnk=2; /* [nbr] Rank of output coordinate CF boundary variables */
+  double *wgt_raw; /* [frc] Remapping weights */
+  int *col_src_adr; /* [idx] Source address (col) */
+  int *row_dst_adr; /* [idx] Destination address (row) */
+  int *dmn_sz_in_int; /* [nbr] Array of dimension sizes of source grid */
+  int *dmn_sz_out_int; /* [nbr] Array of dimension sizes of destination grid */
+  long *dmn_cnt;
+  long *dmn_srt;
+  long *dmn_srd;
+  long idx; /* [idx] Counting index for unrolled grids */
     
   /* Allocate space to hold dimension metadata for rectangular destination grid */
-  assert(rgr_map.dst_grid_rank == 2);
+  dmn_srt=(long *)nco_malloc(dmn_nbr_grd_max*sizeof(long));
+  dmn_cnt=(long *)nco_malloc(dmn_nbr_grd_max*sizeof(long));
+  dmn_srd=(long *)nco_malloc(dmn_nbr_grd_max*sizeof(long));
+
+  dmn_srt[0]=0L;
+  dmn_cnt[0]=rgr_map.src_grid_rank;
+  dmn_sz_in_int=(int *)nco_malloc(rgr_map.src_grid_rank*nco_typ_lng((nc_type)NC_INT));
+  rcd=nco_get_vara(in_id,dmn_sz_in_int_id,dmn_srt,dmn_cnt,dmn_sz_in_int,(nc_type)NC_INT);
   dmn_srt[0]=0L;
   dmn_cnt[0]=rgr_map.dst_grid_rank;
-  dmn_sz=(int *)nco_malloc(rgr_map.dst_grid_rank*nco_typ_lng((nc_type)NC_INT));
-  rcd=nco_get_vara(in_id,dmn_sz_id,dmn_srt,dmn_cnt,dmn_sz,(nc_type)NC_INT);
+  dmn_sz_out_int=(int *)nco_malloc(rgr_map.dst_grid_rank*nco_typ_lng((nc_type)NC_INT));
+  rcd=nco_get_vara(in_id,dmn_sz_out_int_id,dmn_srt,dmn_cnt,dmn_sz_out_int,(nc_type)NC_INT);
+
+  long lon_nbr_in; /* [idx] Number of longitudes in rectangular source grid */
+  long lat_nbr_in; /* [idx] Number of latitudes  in rectangular source grid */
+  long ncol_nbr_in; /* [idx] Number of columns in source grid */
+  if(flg_grd_in_1D){
+    lon_nbr_in=dmn_sz_in_int[0];
+    lat_nbr_in=dmn_sz_in_int[0];
+    ncol_nbr_in=dmn_sz_in_int[0];
+  }else if(flg_grd_in_2D){
+    lon_nbr_in=dmn_sz_in_int[lon_psn_dst];
+    lat_nbr_in=dmn_sz_in_int[lat_psn_dst];
+    ncol_nbr_in=0;
+  } /* !src_grid_rank */
+
+  const int bnd_tm_nbr_out=2; /* [nbr] Number of boundaries for output time */
+  int bnd_nbr_out; /* [nbr] Number of boundaries for output time and rectangular grid coordinates, and number of vertices for output non-rectangular grid coordinates */
+  long lon_nbr_out; /* [nbr] Number of longitudes in rectangular destination grid */
+  long lat_nbr_out; /* [nbr] Number of latitudes  in rectangular destination grid */
+  long ncol_nbr_out; /* [nbr] Number of columns in destination grid */
+  if(flg_grd_out_1D){
+    bnd_nbr_out=rgr_map.dst_grid_corners; /* NB: this assumes rectangular latitude and longitude and is invalid for other quadrilaterals */
+    lon_nbr_out=dmn_sz_out_int[0];
+    lat_nbr_out=dmn_sz_out_int[0];
+    ncol_nbr_out=dmn_sz_out_int[0];
+  }else if(flg_grd_out_2D){
+    bnd_nbr_out=2; /* NB: this assumes rectangular latitude and longitude and is invalid for other quadrilaterals */
+    lon_nbr_out=dmn_sz_out_int[lon_psn_dst];
+    lat_nbr_out=dmn_sz_out_int[lat_psn_dst];
+    ncol_nbr_out=0;
+  } /* !dst_grid_rank */
+
+  if(nco_dbg_lvl_get() >= nco_dbg_scl){
+    (void)fprintf(stderr,"%s: INFO %s grid conversion type = %s with expected input and prescribed output grid sizes: ",nco_prg_nm_get(),fnc_nm,nco_rgr_grd_sng(nco_rgr_grd_typ));
+    (void)fprintf(stderr,"lat_in = %li, lon_in  %li, ncol_in = %li, lat_out = %li, lon_out = %li, ncol_out = %li\n",lat_nbr_in,lon_nbr_in,ncol_nbr_in,lat_nbr_out,lon_nbr_out,ncol_nbr_out);
+  } /* endif dbg */
 
-  const long lon_nbr_out=dmn_sz[lon_psn_dst]; /* [idx] Number of longitudes in rectangular destination grid */
-  const long lat_nbr_out=dmn_sz[lat_psn_dst]; /* [idx] Number of latitudes  in rectangular destination grid */
-  
   /* Allocate space for and obtain coordinates and weights */
   nc_type crd_typ_out=NC_DOUBLE;
-  lon_ctr_out=(double *)nco_malloc(lon_nbr_out*nco_typ_lng(crd_typ_out));
-  lat_ctr_out=(double *)nco_malloc(lat_nbr_out*nco_typ_lng(crd_typ_out));
-  lon_crn_out=(double *)nco_malloc(rgr_map.dst_grid_corners*lon_nbr_out*nco_typ_lng(crd_typ_out));
-  lat_crn_out=(double *)nco_malloc(rgr_map.dst_grid_corners*lat_nbr_out*nco_typ_lng(crd_typ_out));
-  lon_ntf_out=(double *)nco_malloc((lon_nbr_out+1L)*nco_typ_lng(crd_typ_out));
-  lat_ntf_out=(double *)nco_malloc((lat_nbr_out+1L)*nco_typ_lng(crd_typ_out));
-  lon_bnd_out=(double *)nco_malloc(bnd_rnk*lon_nbr_out*nco_typ_lng(crd_typ_out));
-  lat_bnd_out=(double *)nco_malloc(bnd_rnk*lat_nbr_out*nco_typ_lng(crd_typ_out));
-  wgt_raw_out=(double *)nco_malloc_dbg(rgr_map.num_links*nco_typ_lng(crd_typ_out),"Unable to malloc() value buffer for remapping weights",fnc_nm);
+  area_out=(double *)nco_malloc(rgr_map.dst_grid_size*nco_typ_lng(crd_typ_out));
+
+  if(flg_grd_out_1D){
+    lon_ctr_out=(double *)nco_malloc(ncol_nbr_out*nco_typ_lng(crd_typ_out));
+    lat_ctr_out=(double *)nco_malloc(ncol_nbr_out*nco_typ_lng(crd_typ_out));
+    lon_bnd_out=(double *)nco_malloc(ncol_nbr_out*bnd_nbr_out*nco_typ_lng(crd_typ_out));
+    lat_bnd_out=(double *)nco_malloc(ncol_nbr_out*bnd_nbr_out*nco_typ_lng(crd_typ_out));
+  } /* !flg_grd_out_1D */
+  if(flg_grd_out_2D){
+    lon_ctr_out=(double *)nco_malloc(lon_nbr_out*nco_typ_lng(crd_typ_out));
+    lat_ctr_out=(double *)nco_malloc(lat_nbr_out*nco_typ_lng(crd_typ_out));
+    lat_wgt_out=(double *)nco_malloc(lat_nbr_out*nco_typ_lng(crd_typ_out));
+    lon_crn_out=(double *)nco_malloc(rgr_map.dst_grid_corners*lon_nbr_out*nco_typ_lng(crd_typ_out));
+    lat_crn_out=(double *)nco_malloc(rgr_map.dst_grid_corners*lat_nbr_out*nco_typ_lng(crd_typ_out));
+    lon_ntf_out=(double *)nco_malloc((lon_nbr_out+1L)*nco_typ_lng(crd_typ_out));
+    lat_ntf_out=(double *)nco_malloc((lat_nbr_out+1L)*nco_typ_lng(crd_typ_out));
+    lon_bnd_out=(double *)nco_malloc(lon_nbr_out*bnd_nbr_out*nco_typ_lng(crd_typ_out));
+    lat_bnd_out=(double *)nco_malloc(lat_nbr_out*bnd_nbr_out*nco_typ_lng(crd_typ_out));
+  } /* !flg_grd_out_2D */
+
+  wgt_raw=(double *)nco_malloc_dbg(rgr_map.num_links*nco_typ_lng(NC_DOUBLE),"Unable to malloc() value buffer for remapping weights",fnc_nm);
+  col_src_adr=(int *)nco_malloc_dbg(rgr_map.num_links*nco_typ_lng(NC_INT),"Unable to malloc() value buffer for remapping addresses",fnc_nm);
+  row_dst_adr=(int *)nco_malloc_dbg(rgr_map.num_links*nco_typ_lng(NC_INT),"Unable to malloc() value buffer for remapping addresses",fnc_nm);
   
   /* Arrays unroll into all longitudes for first latitude, then second latitude, ...
      Thus longitudes obtained by reading first block contiguously (unstrided)
      Latitudes obtained by reading unrolled data with stride of lon_nbr */
   dmn_srt[0]=0L;
-  dmn_cnt[0]=lon_nbr_out;
-  rcd=nco_get_vara(in_id,dst_grd_ctr_lon_id,dmn_srt,dmn_cnt,lon_ctr_out,crd_typ_out);
-  dmn_srt[0]=0L;
-  dmn_cnt[0]=lat_nbr_out;
-  dmn_srd[0]=lon_nbr_out;
-  rcd=nco_get_vars(in_id,dst_grd_ctr_lat_id,dmn_srt,dmn_cnt,dmn_srd,lat_ctr_out,crd_typ_out);
-  dmn_srt[0]=dmn_srt[1]=0L;
-  dmn_cnt[0]=lon_nbr_out;
-  dmn_cnt[1]=rgr_map.dst_grid_corners;
-  rcd=nco_get_vara(in_id,dst_grd_crn_lon_id,dmn_srt,dmn_cnt,lon_crn_out,crd_typ_out);
-  dmn_srt[0]=0L;
-  dmn_cnt[0]=lat_nbr_out;
-  dmn_cnt[1]=rgr_map.dst_grid_corners;
-  dmn_srd[0]=lon_nbr_out;
-  dmn_srd[1]=1L;
-  rcd=nco_get_vars(in_id,dst_grd_crn_lat_id,dmn_srt,dmn_cnt,dmn_srd,lat_crn_out,crd_typ_out);
-  
-  /* Derive interface boundaries from lat and lon grid-center values
+  dmn_cnt[0]=rgr_map.dst_grid_size;
+  rcd=nco_get_vara(in_id,area_dst_id,dmn_srt,dmn_cnt,area_out,crd_typ_out);
+  if(flg_grd_out_1D){
+    dmn_srt[0]=0L;
+    dmn_cnt[0]=ncol_nbr_out;
+    rcd=nco_get_vara(in_id,dst_grd_ctr_lon_id,dmn_srt,dmn_cnt,lon_ctr_out,crd_typ_out);
+    dmn_srt[0]=0L;
+    dmn_cnt[0]=ncol_nbr_out;
+    rcd=nco_get_vara(in_id,dst_grd_ctr_lat_id,dmn_srt,dmn_cnt,lat_ctr_out,crd_typ_out);
+    dmn_srt[0]=dmn_srt[1]=0L;
+    dmn_cnt[0]=ncol_nbr_out;
+    dmn_cnt[1]=bnd_nbr_out;
+    rcd=nco_get_vara(in_id,dst_grd_crn_lon_id,dmn_srt,dmn_cnt,lon_bnd_out,crd_typ_out);
+    dmn_srt[0]=dmn_srt[1]=0L;
+    dmn_cnt[0]=ncol_nbr_out;
+    dmn_cnt[1]=bnd_nbr_out;
+    rcd=nco_get_vara(in_id,dst_grd_crn_lat_id,dmn_srt,dmn_cnt,lat_bnd_out,crd_typ_out);
+    if(nco_dbg_lvl_get() >= nco_dbg_crr){
+      for(idx=0;idx<lon_nbr_out;idx++){
+	(void)fprintf(stdout,"lon[%li] = %g, vertices = ", idx,lon_ctr_out[idx]);
+	for(int bnd_idx=0;bnd_idx<bnd_nbr_out;bnd_idx++)
+	  (void)fprintf(stdout,"%s%g%s",bnd_idx == 0 ? "[" : "",lon_bnd_out[bnd_nbr_out*idx+bnd_idx],bnd_idx == bnd_nbr_out-1 ? "]\n" : ", ");
+      } /* end loop over lon */
+      for(idx=0;idx<lat_nbr_out;idx++){
+	(void)fprintf(stdout,"lat[%li] = %g, vertices = ", idx,lat_ctr_out[idx]);
+	for(int bnd_idx=0;bnd_idx<bnd_nbr_out;bnd_idx++)
+	  (void)fprintf(stdout,"%s%g%s",bnd_idx == 0 ? "[" : "",lat_bnd_out[bnd_nbr_out*idx+bnd_idx],bnd_idx == bnd_nbr_out-1 ? "]\n" : ", ");
+      } /* end loop over lat */
+    } /* endif dbg */
+  } /* !flg_grd_out_1D */
+
+  if(flg_grd_out_2D){
+    dmn_srt[0]=0L;
+    dmn_cnt[0]=lon_nbr_out;
+    rcd=nco_get_vara(in_id,dst_grd_ctr_lon_id,dmn_srt,dmn_cnt,lon_ctr_out,crd_typ_out);
+    dmn_srt[0]=0L;
+    dmn_cnt[0]=lat_nbr_out;
+    dmn_srd[0]=lon_nbr_out;
+    rcd=nco_get_vars(in_id,dst_grd_ctr_lat_id,dmn_srt,dmn_cnt,dmn_srd,lat_ctr_out,crd_typ_out);
+    dmn_srt[0]=dmn_srt[1]=0L;
+    dmn_cnt[0]=lon_nbr_out;
+    dmn_cnt[1]=rgr_map.dst_grid_corners;
+    rcd=nco_get_vara(in_id,dst_grd_crn_lon_id,dmn_srt,dmn_cnt,lon_crn_out,crd_typ_out);
+    dmn_srt[0]=0L;
+    dmn_cnt[0]=lat_nbr_out;
+    dmn_srd[0]=lon_nbr_out;
+    dmn_srt[1]=0L;
+    dmn_cnt[1]=rgr_map.dst_grid_corners;
+    dmn_srd[1]=1L;
+    rcd=nco_get_vars(in_id,dst_grd_crn_lat_id,dmn_srt,dmn_cnt,dmn_srd,lat_crn_out,crd_typ_out);
+  } /* !flg_grd_out_2D */
+    
+  /* Derive 2D interface boundaries from lat and lon grid-center values
      NB: Procedures to derive interfaces from midpoints on rectangular grids are theoretically possible 
      However, ESMF often outputs interfaces values (e.g., yv_b) for midpoint coordinates (e.g., yc_b)
      For example, ACME standard map from ne120np4 to 181x360 has yc_b[0] = yv_b[0] = -90.0
-     Hence safer to read boundary interfaces directly from grid corner/vertice arrays in map file */
-
-  /* Derivation of boundaries from correct xc_b, yc_b is: 
-     lon_ntf_out[0]=0.5*(lon_ctr_out[0]+lon_ctr_out[lon_nbr_out-1])-180.0;
-     lat_ntf_out[0]=lat_ctr_out[0]-0.5*(lat_ctr_out[1]-lat_ctr_out[0]);
+     Latitude = -90 is, by definition, not a midpoint coordinate
+     This appears to be an artifact of the non-physical representation of the FV grid, i.e.,
+     a grid center located at the pole where longitudes collapse in the model, but cannot be
+     represented as collapsed on a rectangular 2D grid with non-zero areas.
+     Unfortunately, ESMF supports this nonsense by labeling the grid center as at the pole
+     so that applications can easily diagnose an FV grid when they read-in datasets.
+     A superior application could diagnose FV just fine from actual non-polar gridcell centers
+     Maybe ESMF could introduce a flag or something to indicate/avoid this special case?
+     Safer to read boundary interfaces directly from grid corner/vertice arrays in map file
+     
+     Derivation of boundaries xv_b, yv_b from _correct_ xc_b, yc_b is follows
+     Do not implement this procedure until resolving midpoint/center issue described above:
+     lon_ntf_out[0]=0.5*(lon_ctr_out[0]+lon_ctr_out[lon_nbr_out-1])-180.0; // Extrapolation
+     lat_ntf_out[0]=lat_ctr_out[0]-0.5*(lat_ctr_out[1]-lat_ctr_out[0]); // Extrapolation
      for(idx=1;idx<lon_nbr_out;idx++) lon_ntf_out[idx]=0.5*(lon_ctr_out[idx-1]+lon_ctr_out[idx]);
      for(idx=1;idx<lat_nbr_out;idx++) lat_ntf_out[idx]=0.5*(lat_ctr_out[idx-1]+lat_ctr_out[idx]);
      lon_ntf_out[lon_nbr_out]=lon_ntf_out[0]+360.0;
      lat_ntf_out[lat_nbr_out]=lat_ctr_out[lat_nbr_out-1]+0.5*(lat_ctr_out[lat_nbr_out-1]-lat_ctr_out[lat_nbr_out-2]); */
 
-  for(idx=0;idx<lon_nbr_out;idx++) lon_ntf_out[idx]=lon_crn_out[rgr_map.dst_grid_corners*idx];
-  lon_ntf_out[lon_nbr_out]=lon_crn_out[rgr_map.dst_grid_corners*lon_nbr_out-(rgr_map.dst_grid_corners-1L)];
-  for(idx=0;idx<lat_nbr_out;idx++) lat_ntf_out[idx]=lat_crn_out[rgr_map.dst_grid_corners*idx];
-  lat_ntf_out[lat_nbr_out]=lat_crn_out[rgr_map.dst_grid_corners*lat_nbr_out-1L];
-
-  /* Place interfaces into coordinate boundaries */
-  for(idx=0;idx<lon_nbr_out;idx++){
-    lon_bnd_out[idx]=lon_ntf_out[idx];
-    lon_bnd_out[lon_nbr_out+idx]=lon_ntf_out[idx+1];
-  } /* end loop over longitude */
-  for(idx=0;idx<lat_nbr_out;idx++){
-    lat_bnd_out[idx]=lat_ntf_out[idx];
-    lat_bnd_out[lat_nbr_out+idx]=lat_ntf_out[idx+1];
-  } /* end loop over latitude */
+  if(flg_grd_out_2D){
+    /* Obtain 1-D rectangular interfaces from unrolled 1-D vertice arrays */
+    for(idx=0;idx<lon_nbr_out;idx++) lon_ntf_out[idx]=lon_crn_out[rgr_map.dst_grid_corners*idx];
+    lon_ntf_out[lon_nbr_out]=lon_crn_out[rgr_map.dst_grid_corners*lon_nbr_out-(rgr_map.dst_grid_corners-1L)];
+    for(idx=0;idx<lat_nbr_out;idx++) lat_ntf_out[idx]=lat_crn_out[rgr_map.dst_grid_corners*idx];
+    lat_ntf_out[lat_nbr_out]=lat_crn_out[rgr_map.dst_grid_corners*lat_nbr_out-1L];
+    
+    /* Place 1-D rectangular interfaces into 2-D coordinate boundaries */
+    for(idx=0;idx<lon_nbr_out;idx++){
+      lon_bnd_out[2*idx]=lon_ntf_out[idx];
+      lon_bnd_out[2*idx+1]=lon_ntf_out[idx+1];
+    } /* end loop over longitude */
+    for(idx=0;idx<lat_nbr_out;idx++){
+      lat_bnd_out[2*idx]=lat_ntf_out[idx];
+      lat_bnd_out[2*idx+1]=lat_ntf_out[idx+1];
+    } /* end loop over latitude */
+  } /* !flg_grd_out_2D */
   
-  if(nco_dbg_lvl_get() >= nco_dbg_vec){
-    (void)fprintf(stderr,"%s: INFO %s reports destination rectangular latitude grid:\n",nco_prg_nm_get(),fnc_nm);
-    for(idx=0;idx<lon_nbr_out;idx++) (void)fprintf(stderr,"lon[%li] = [%g, %g, %g]\n",idx,lon_bnd_out[idx],lon_ctr_out[idx],lon_bnd_out[lon_nbr_out+idx]);
-    for(idx=0;idx<lat_nbr_out;idx++) (void)fprintf(stderr,"lat[%li] = [%g, %g, %g]\n",idx,lat_bnd_out[idx],lat_ctr_out[idx],lat_bnd_out[lat_nbr_out+idx]);
-  } /* endif dbg */
-
-  /* Obtain weight from map file */
+  if(flg_grd_out_2D){
+
+    if(nco_dbg_lvl_get() >= nco_dbg_crr){
+      for(idx=0;idx<lon_nbr_out;idx++) (void)fprintf(stdout,"lon[%li] = [%g, %g, %g]\n",idx,lon_bnd_out[2*idx],lon_ctr_out[idx],lon_bnd_out[2*idx+1]);
+      for(idx=0;idx<lat_nbr_out;idx++) (void)fprintf(stdout,"lat[%li] = [%g, %g, %g]\n",idx,lat_bnd_out[2*idx],lat_ctr_out[idx],lat_bnd_out[2*idx+1]);
+    } /* endif dbg */
+
+    /* Diagnose type of two-dimensional output grid by testing second latitude center against formulae */
+    nco_grd_2D_typ_enm nco_grd_2D_typ=nco_grd_2D_nil; /* [enm] Two-dimensional grid-type enum */
+    const double lat_ctr_tst_ngl_eqi_pol=-90.0+180.0/(lat_nbr_out-1);
+    const double lat_ctr_tst_ngl_eqi_fst=-90.0+180.0*1.5/lat_nbr_out;
+    double lat_ctr_tst_gss;
+    /* In diagnosing grids, agreement with input to single-precision is "good enough for government work"
+       Hence some comparisons cast from double to float before comparison
+       20150526: T42 grid from SCRIP and related maps
+       20150611: map_ne120np4_to_fv801x1600_bilin.150418.nc has yc_b[1600]=-89.775000006 not expected exact value lat_ctr[1]=-89.775000000000006 */
+    if((float)lat_ctr_out[1] == (float)lat_ctr_tst_ngl_eqi_fst) nco_grd_2D_typ=nco_grd_2D_ngl_eqi_fst;
+    if((float)lat_ctr_out[1] == (float)lat_ctr_tst_ngl_eqi_pol) nco_grd_2D_typ=nco_grd_2D_ngl_eqi_pol;
+    double *wgt_Gss_out=NULL; // [frc] Gaussian weights double precision
+    if(nco_grd_2D_typ == nco_grd_2D_nil){
+      /* Check for Gaussian grid */
+      const double rdn2dgr=180.0/M_PI;
+      double *lat_sin_out; // [frc] Sine of Gaussian latitudes double precision
+      lat_sin_out=(double *)nco_malloc(lat_nbr_out*sizeof(double));
+      wgt_Gss_out=(double *)nco_malloc(lat_nbr_out*sizeof(double));
+      (void)nco_lat_wgt_gss(lat_nbr_out,lat_sin_out,wgt_Gss_out);
+      lat_ctr_tst_gss=rdn2dgr*asin(lat_sin_out[1]);
+      /* Gaussian weights on output grid will be double-precision accurate
+	 Grid itself is kept as user-specified so area diagnosed by ESMF_RegridWeightGen may be slightly inconsistent with weights */
+      if((float)lat_ctr_out[1] == (float)lat_ctr_tst_gss) nco_grd_2D_typ=nco_grd_2D_gss;
+      if(lat_sin_out) lat_sin_out=(double *)nco_free(lat_sin_out);
+    } /* !Gaussian */
+    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO %s diagnosed output latitude grid-type: %s\n",nco_prg_nm_get(),fnc_nm,nco_grd_2D_sng(nco_grd_2D_typ));
+    
+    const double dgr2rdn=M_PI/180.0;
+    switch(nco_grd_2D_typ){
+    case nco_grd_2D_ngl_eqi_fst:
+      for(idx=0;idx<lat_nbr_out;idx++) lat_wgt_out[idx]=cos(dgr2rdn*lat_ctr_out[idx]);
+      break;
+    case nco_grd_2D_ngl_eqi_pol:
+      for(idx=0;idx<lat_nbr_out;idx++) lat_wgt_out[idx]=sin(dgr2rdn*lat_bnd_out[2*idx+1])-sin(dgr2rdn*lat_bnd_out[2*idx]);
+      break;
+    case nco_grd_2D_gss:
+      for(idx=0;idx<lat_nbr_out;idx++) lat_wgt_out[idx]=wgt_Gss_out[idx];
+      break;
+      if(wgt_Gss_out) wgt_Gss_out=(double *)nco_free(wgt_Gss_out);
+    default:
+      (void)fprintf(stderr,"%s: ERROR %s unknown output latitude grid-type\n",nco_prg_nm_get(),fnc_nm);
+      nco_dfl_case_generic_err(); break;
+    } /* end nco_grd_2D_typ switch */
+    
+    /* Fuzzy test of latitude weight normalization */
+    const double eps_wgt_ttl=1.0e-14; /* [frc] Roundoff tolerance for sum of quadrature weights */
+    double lat_wgt_ttl=0.0; /* [frc] Actual sum of quadrature weights */
+    for(idx=0;idx<lat_nbr_out;idx++) lat_wgt_ttl+=lat_wgt_out[idx];
+    assert(1.0-lat_wgt_ttl/2.0 < eps_wgt_ttl);
+    
+    if(nco_dbg_lvl_get() >= nco_dbg_sbr){
+      (void)fprintf(stderr,"%s: INFO %s reports destination rectangular latitude grid:\n",nco_prg_nm_get(),fnc_nm);
+      double area_out_ttl=0.0; /* [frc] Exact sum of area */
+      lat_wgt_ttl=0.0;
+      area_out_ttl=0.0;
+      for(idx=0;idx<lat_nbr_out;idx++)
+	lat_wgt_ttl+=lat_wgt_out[idx];
+      for(long int lat_idx=0;lat_idx<lat_nbr_out;lat_idx++)
+	for(long int lon_idx=0;lon_idx<lon_nbr_out;lon_idx++)
+	  area_out_ttl+=area_out[lat_idx*lon_nbr_out+lon_idx];
+      (void)fprintf(stdout,"lat_wgt_ttl = %20.15f, area_ttl = %20.15f\n",lat_wgt_ttl,area_out_ttl);
+      for(idx=0;idx<lon_nbr_out;idx++) (void)fprintf(stdout,"lon[%li] = [%g, %g, %g]\n",idx,lon_bnd_out[2*idx],lon_ctr_out[idx],lon_bnd_out[2*idx+1]);
+      for(idx=0;idx<lat_nbr_out;idx++) (void)fprintf(stdout,"lat[%li] = [%g, %g, %g]\n",idx,lat_bnd_out[2*idx],lat_ctr_out[idx],lat_bnd_out[2*idx+1]);
+      for(idx=0;idx<lat_nbr_out;idx++) (void)fprintf(stdout,"lat[%li], wgt[%li] = %20.15f, %20.15f\n",idx,idx,lat_ctr_out[idx],lat_wgt_out[idx]);
+      if(nco_dbg_lvl_get() > nco_dbg_crr)
+	for(long int lat_idx=0;lat_idx<lat_nbr_out;lat_idx++)
+	  for(long int lon_idx=0;lon_idx<lon_nbr_out;lon_idx++)
+	    (void)fprintf(stdout,"lat[%li] = %g, lon[%li] = %g, area[%li,%li] = %g\n",lat_idx,lat_ctr_out[lat_idx],lon_idx,lon_ctr_out[lon_idx],lat_idx,lon_idx,area_out[lat_idx*lon_nbr_out+lon_idx]);
+    } /* endif dbg */
+  } /* !flg_grd_out_2D */
+
+  /* Obtain remap matrix addresses and weights from map file */
   dmn_srt[0]=0L;
   dmn_cnt[0]=rgr_map.num_links;
-  rcd=nco_get_vara(in_id,wgt_raw_out_id,dmn_srt,dmn_cnt,wgt_raw_out,crd_typ_out);
+  rcd=nco_get_vara(in_id,wgt_raw_id,dmn_srt,dmn_cnt,wgt_raw,NC_DOUBLE);
+  rcd=nco_get_vara(in_id,col_src_adr_id,dmn_srt,dmn_cnt,col_src_adr,NC_INT);
+  rcd=nco_get_vara(in_id,row_dst_adr_id,dmn_srt,dmn_cnt,row_dst_adr,NC_INT);
+  /* Optimize row/column access by pre-subtracting one to account for Fortran index offset relative to C */
+  size_t lnk_nbr; /* [nbr] Number of links */
+  size_t lnk_idx; /* [idx] Link index */
+  lnk_nbr=rgr_map.num_links;
+  for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++) row_dst_adr[lnk_idx]--;
+  for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++) col_src_adr[lnk_idx]--;
+  if(nco_dbg_lvl_get() >= nco_dbg_io){
+    (void)fprintf(stdout,"idx row_dst col_src wgt_raw\n");
+    for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++) (void)fprintf(stdout,"%li %d %d %g\n",lnk_idx,row_dst_adr[lnk_idx],col_src_adr[lnk_idx],wgt_raw[lnk_idx]);
+  } /* endif dbg */
+
+  /* Free memory associated with input file */
+  if(dmn_srt) dmn_srt=(long *)nco_free(dmn_srt);
+  if(dmn_cnt) dmn_cnt=(long *)nco_free(dmn_cnt);
+  if(dmn_srd) dmn_srd=(long *)nco_free(dmn_srd);
 
   /* Close input netCDF file */
   nco_close(in_id);
@@ -505,37 +887,993 @@ nco_rgr_map /* [fnc] Regrid using external weights */
   /* Remove local copy of file */
   if(FL_RTR_RMT_LCN && RM_RMT_FL_PST_PRC) (void)nco_fl_rm(fl_in);
 
-  /* Weight variable */
+  /* Above this line, fl_in and in_id refer to map file
+     Below this line, fl_in and in_id refer to input file to be regridded */
+
+  /* Initialize */
+  in_id=rgr->in_id;
+  out_id=rgr->out_id;
+
+  /* Do not extract extensive variables like lon, lat, and area
+     If necessary, create them from scratch from remap data
+     I decided not to include "date_written" and "time_written" in this list, this is debatable... */
+  const int var_xcl_lst_nbr=13; /* [nbr] Number of objects on exclusion list */
+  const char *var_xcl_lst[]={"/area","/gridcell_area","/gw","/lat","/latitude","/lat_bnds","/lat_vertices","/bounds_lat","/lon","/longitude","/lon_bnds","/lon_vertices","/bounds_lon"};
+  int var_cpy_nbr=0; /* [nbr] Number of copied variables */
+  int var_rgr_nbr=0; /* [nbr] Number of regridded variables */
+  int var_xcl_nbr=0; /* [nbr] Number of deleted variables */
+  int var_crt_nbr=0; /* [nbr] Number of created variables */
+  unsigned int idx_tbl; /* [idx] Counter for traversal table */
+  const unsigned int trv_nbr=trv_tbl->nbr; /* [idx] Number of traversal table entries */
+  for(idx=0;idx<var_xcl_lst_nbr;idx++){
+    for(idx_tbl=0;idx_tbl<trv_nbr;idx_tbl++)
+      if(!strcmp(trv_tbl->lst[idx_tbl].nm_fll,var_xcl_lst[idx])) break;
+    if(idx_tbl < trv_nbr){
+      if(trv_tbl->lst[idx_tbl].flg_xtr){
+	if(nco_dbg_lvl_get() >= nco_dbg_var) (void)fprintf(stdout,"%s: INFO automatically omitting (not copying or regridding from input) variable %s\n",nco_prg_nm_get(),trv_tbl->lst[idx_tbl].nm_fll);
+	var_xcl_nbr++;
+      } /* endif */
+      trv_tbl->lst[idx_tbl].flg_xtr=False;
+    } /* endif */
+  } /* end loop */
+  
+  char *col_nm=rgr->col_nm; /* [sng] Name of horizontal spatial dimension on unstructured grid */
+  char *lat_nm=rgr->lat_nm; /* [sng] Name of dimension to recognize as latitude */
+  char *lon_nm=rgr->lon_nm; /* [sng] Name of dimension to recognize as longitude */
+  char *dmn_nm_cp; /* [sng] Dimension name as char * to reduce indirection */
+  int dmn_idx; /* [idx] Dimension index */
+  int dmn_nbr_in; /* [nbr] Number of dimensions in input variable */
+  int dmn_nbr_out; /* [nbr] Number of dimensions in output variable */
+  trv_sct trv; /* [sct] Traversal table object structure to reduce indirection */
+  /* Define regridding flag for each variable */
+  for(idx_tbl=0;idx_tbl<trv_nbr;idx_tbl++){
+    trv=trv_tbl->lst[idx_tbl];
+    dmn_nbr_in=trv_tbl->lst[idx_tbl].nbr_dmn;
+    if(trv.nco_typ == nco_obj_typ_var && trv.flg_xtr){
+      for(dmn_idx=0;dmn_idx<dmn_nbr_in;dmn_idx++){
+	dmn_nm_cp=trv.var_dmn[dmn_idx].dmn_nm;
+	/* Regrid variables containing a horizontal spatial dimension */
+	/* fxm: generalize to include any variable containing a dimension in a coordinate with "standard_name" = "latitude" or "longitude" */
+	if(!strcmp(dmn_nm_cp,col_nm) || !strcmp(dmn_nm_cp,lat_nm) || !strcmp(dmn_nm_cp,lon_nm)){
+	  trv_tbl->lst[idx_tbl].flg_rgr=True;
+	  var_rgr_nbr++;
+	  break;
+	} /* endif */
+      } /* end loop over dimensions */
+      if(dmn_idx == dmn_nbr_in) var_cpy_nbr++;
+    } /* end nco_obj_typ_var */
+  } /* end idx_tbl */
+  if(!var_rgr_nbr) (void)fprintf(stdout,"%s: WARNING %s reports no variables fit regridding criteria\n",nco_prg_nm_get(),fnc_nm);
+  
+  if(nco_dbg_lvl_get() >= nco_dbg_sbr){
+    for(idx_tbl=0;idx_tbl<trv_nbr;idx_tbl++){
+      trv=trv_tbl->lst[idx_tbl];
+      if(trv.nco_typ == nco_obj_typ_var && trv.flg_xtr) (void)fprintf(stderr,"Regrid %s? %s\n",trv.nm,trv.flg_rgr ? "Yes" : "No");
+    } /* end idx_tbl */
+  } /* end dbg */
+
+  /* Layout regridded file */
+  aed_sct aed_mtd;
+  char *area_nm_out;
+  char *att_nm;
+  char *bnd_nm_out;
+  char *bnd_tm_nm_out;
+  char *col_nm_out;
+  char *lat_bnd_nm_out;
+  char *lat_nm_out;
+  char *lat_wgt_nm;
+  char *lon_bnd_nm_out;
+  char *lon_nm_out;
+  int dmn_id_lat; /* [id] Dimension ID */
+  int dmn_id_ncol; /* [id] Dimension ID */
+  int dmn_id_lon; /* [id] Dimension ID */
+  int dmn_id_bnd; /* [id] Dimension ID */
+  int dmn_id_bnd_tm; /* [id] Dimension ID */
+  int area_out_id; /* [id] Variable ID for area */
+  int lon_out_id; /* [id] Variable ID for longitude */
+  int lat_out_id; /* [id] Variable ID for latitude */
+  int lat_wgt_id; /* [id] Variable ID for latitude weight */
+  int lon_bnd_id; /* [id] Variable ID for lon_bnds/lon_vertices */
+  int lat_bnd_id; /* [id] Variable ID for lat_bnds/lat_vertices */
+  int dmn_ids_out[dmn_nbr_grd_max]; /* [id] Dimension IDs array for output variable */
+  long dmn_srt_out[dmn_nbr_grd_max];
+  long dmn_cnt_out[dmn_nbr_grd_max];
+
+  /* Name output dimensions */
+  area_nm_out=rgr->area_nm;
+  bnd_nm_out=rgr->bnd_nm;
+  bnd_tm_nm_out=rgr->bnd_tm_nm;
+  col_nm_out=rgr->col_nm;
+  lat_bnd_nm_out=rgr->lat_bnd_nm;
+  lat_nm_out=rgr->lat_nm;
+  lat_wgt_nm=rgr->lat_wgt_nm;
+  lon_bnd_nm_out=rgr->lon_bnd_nm;
+  lon_nm_out=rgr->lon_nm;
+  if(flg_grd_out_1D){
+    bnd_nm_out=rgr->vrt_nm;
+    lat_bnd_nm_out=rgr->lat_vrt_nm;
+    lon_bnd_nm_out=rgr->lon_vrt_nm;
+  } /* !flg_grd_out_1D */
+  if(flg_grd_out_2D){
+    bnd_nm_out=rgr->bnd_nm;
+    lat_bnd_nm_out=rgr->lat_bnd_nm;
+    lon_bnd_nm_out=rgr->lon_bnd_nm;
+  } /* !flg_grd_out_2D */
+
+  /* Persistent metadata */
+  aed_sct aed_mtd_crd;
+  char *att_val_crd=NULL;
+  char *att_nm_crd=NULL;
+  att_nm_crd=strdup("coordinates");
+  aed_mtd_crd.att_nm=att_nm_crd;
+  if(flg_grd_out_1D) aed_mtd_crd.mode=aed_overwrite; else aed_mtd_crd.mode=aed_delete;
+  aed_mtd_crd.type=NC_CHAR;
+  aed_mtd_crd.sz=strlen(lat_nm_out)+strlen(lon_nm_out)+1L;
+  att_val_crd=(char *)nco_malloc(aed_mtd_crd.sz*nco_typ_lng(aed_mtd_crd.type)+1L);
+  (void)sprintf(att_val_crd,"%s %s",lat_nm_out,lon_nm_out);
+  aed_mtd_crd.val.cp=att_val_crd;
+
+  /* Define new horizontal dimensions before all else */
+  if(flg_grd_out_1D){
+    rcd=nco_def_dim(out_id,col_nm_out,ncol_nbr_out,&dmn_id_ncol);
+  } /* !flg_grd_out_1D */
+  if(flg_grd_out_2D){
+    rcd=nco_def_dim(out_id,lat_nm_out,lat_nbr_out,&dmn_id_lat);
+    rcd=nco_def_dim(out_id,lon_nm_out,lon_nbr_out,&dmn_id_lon);
+  } /* !flg_grd_out_2D */
+  rcd=nco_inq_dimid_flg(out_id,bnd_tm_nm_out,&dmn_id_bnd_tm);
+  /* If dimension has not been defined, define it */
+  if(rcd != NC_NOERR) rcd=nco_def_dim(out_id,bnd_tm_nm_out,bnd_tm_nbr_out,&dmn_id_bnd_tm);
+  rcd=nco_inq_dimid_flg(out_id,bnd_nm_out,&dmn_id_bnd);
+  /* If dimension has not been defined, define it */
+  if(rcd != NC_NOERR) rcd=nco_def_dim(out_id,bnd_nm_out,bnd_nbr_out,&dmn_id_bnd);
+
+  char dmn_nm[NC_MAX_NAME]; /* [sng] Dimension name */
+  char *var_nm; /* [sng] Variable name */
+  int *dmn_id_in; /* [id] Dimension IDs */
+  int *dmn_id_out; /* [id] Dimension IDs */
+  int var_id_in; /* [id] Variable ID */
+  int var_id_out; /* [id] Variable ID */
+  nc_type var_typ; /* [enm] Variable type */
+  nco_bool PCK_ATT_CPY=True; /* [flg] Copy attributes "scale_factor", "add_offset" */
+
+  /* Define new coordinates and variables in regridded file */
+  if(flg_grd_out_1D){
+    (void)nco_def_var(out_id,lat_nm_out,crd_typ_out,dmn_nbr_1D,&dmn_id_ncol,&lat_out_id);
+    var_crt_nbr++;
+    (void)nco_def_var(out_id,lon_nm_out,crd_typ_out,dmn_nbr_1D,&dmn_id_ncol,&lon_out_id);
+    var_crt_nbr++;
+    dmn_ids_out[0]=dmn_id_ncol;
+    dmn_ids_out[1]=dmn_id_bnd;
+    (void)nco_def_var(out_id,lat_bnd_nm_out,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&lat_bnd_id);
+    var_crt_nbr++;
+    dmn_ids_out[0]=dmn_id_ncol;
+    dmn_ids_out[1]=dmn_id_bnd;
+    (void)nco_def_var(out_id,lon_bnd_nm_out,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&lon_bnd_id);
+    var_crt_nbr++;
+    (void)nco_def_var(out_id,area_nm_out,crd_typ_out,dmn_nbr_1D,&dmn_id_ncol,&area_out_id);
+    var_crt_nbr++;
+  } /* !flg_grd_out_1D */
+  if(flg_grd_out_2D){
+    (void)nco_def_var(out_id,lat_nm_out,crd_typ_out,dmn_nbr_1D,&dmn_id_lat,&lat_out_id);
+    var_crt_nbr++;
+    (void)nco_def_var(out_id,lon_nm_out,crd_typ_out,dmn_nbr_1D,&dmn_id_lon,&lon_out_id);
+    var_crt_nbr++;
+    dmn_ids_out[0]=dmn_id_lat;
+    dmn_ids_out[1]=dmn_id_bnd;
+    (void)nco_def_var(out_id,lat_bnd_nm_out,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&lat_bnd_id);
+    var_crt_nbr++;
+    dmn_ids_out[0]=dmn_id_lon;
+    dmn_ids_out[1]=dmn_id_bnd;
+    (void)nco_def_var(out_id,lon_bnd_nm_out,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&lon_bnd_id);
+    var_crt_nbr++;
+    (void)nco_def_var(out_id,lat_wgt_nm,crd_typ_out,dmn_nbr_1D,&dmn_id_lat,&lat_wgt_id);
+    var_crt_nbr++;
+    dmn_ids_out[0]=dmn_id_lat;
+    dmn_ids_out[1]=dmn_id_lon;
+    (void)nco_def_var(out_id,area_nm_out,crd_typ_out,dmn_nbr_2D,dmn_ids_out,&area_out_id);
+    var_crt_nbr++;
+  } /* !flg_grd_out_2D */
+
+  /* Define regridded variables in output file */
+  for(idx_tbl=0;idx_tbl<trv_nbr;idx_tbl++){
+    trv=trv_tbl->lst[idx_tbl];
+    if(trv.nco_typ == nco_obj_typ_var && trv.flg_xtr){
+      var_nm=trv.nm;
+      var_typ=trv.var_typ;
+      dmn_nbr_in=trv.nbr_dmn;
+      dmn_nbr_out=trv.nbr_dmn;
+      rcd=nco_inq_varid(in_id,var_nm,&var_id_in);
+      rcd=nco_inq_varid_flg(out_id,var_nm,&var_id_out);
+      /* If variable has not been defined, define it */
+      if(rcd != NC_NOERR){
+	dmn_id_in=(int *)nco_malloc((dmn_nbr_in+1)*sizeof(int)); /* Allocate an extra slot in case additional dimension in output */
+	dmn_id_out=(int *)nco_malloc((dmn_nbr_in+1)*sizeof(int));
+	dmn_srt=(long *)nco_malloc((dmn_nbr_in+1)*sizeof(long));
+	dmn_cnt=(long *)nco_malloc((dmn_nbr_in+1)*sizeof(long));
+	if(trv.flg_rgr){
+	  /* Regrid */
+	  rcd=nco_inq_vardimid(in_id,var_id_in,dmn_id_in);
+	  for(dmn_idx=0;dmn_idx<dmn_nbr_in;dmn_idx++){
+	    rcd=nco_inq_dimname(in_id,dmn_id_in[dmn_idx],dmn_nm);
+	    if(flg_grd_out_1D){
+	      if(nco_rgr_grd_typ == nco_rgr_grd_2D_to_1D && (!strcmp(dmn_nm,lat_nm) || !strcmp(dmn_nm,lon_nm))){
+		/* Replace orthogonal horizontal dimensions by unstructured horizontal dimension already defined */
+		if(!strcmp(dmn_nm,lat_nm)){
+		  dmn_id_out[dmn_idx]=dmn_id_ncol;
+		  dmn_cnt[dmn_idx]=ncol_nbr_out;
+		} /* endif lat */
+		if(!strcmp(dmn_nm,lon_nm)){
+		  dmn_id_out[dmn_idx]=-999;
+		  dmn_cnt[dmn_idx]=-999;
+		  dmn_nbr_out--;
+		} /* endif lon */
+	      }else{
+		/* Always copy existing horizontal dimensions for 1D->1D */
+		rcd=nco_inq_dimid_flg(out_id,dmn_nm,dmn_id_out+dmn_idx);
+		/* If dimension has not been defined, define it */
+		if(rcd != NC_NOERR){
+		  rcd=nco_inq_dimlen(in_id,dmn_id_in[dmn_idx],dmn_cnt+dmn_idx);
+		  rcd=nco_def_dim(out_id,dmn_nm,dmn_cnt[dmn_idx],dmn_id_out+dmn_idx);
+		} /* !rcd */
+	      } /* !lat && !lon */
+	    } /* !2D_to_1D */
+	    if(flg_grd_out_2D){
+	      if(nco_rgr_grd_typ == nco_rgr_grd_1D_to_2D && !strcmp(dmn_nm,col_nm)){
+		/* Replace unstructured horizontal dimension by orthogonal horizontal dimensions already defined */
+		dmn_id_out[dmn_idx]=dmn_id_lat;
+		dmn_id_out[dmn_idx+1]=dmn_id_lon;
+		dmn_cnt[dmn_idx]=lat_nbr_out;
+		dmn_cnt[dmn_idx+1]=lon_nbr_out;
+		dmn_idx++;
+		dmn_nbr_out++;
+	      }else{
+		/* Always copy existing horizontal dimensions for 2D->2D */
+		rcd=nco_inq_dimid_flg(out_id,dmn_nm,dmn_id_out+dmn_idx);
+		/* If dimension has not been defined, define it */
+		if(rcd != NC_NOERR){
+		  rcd=nco_inq_dimlen(in_id,dmn_id_in[dmn_idx],dmn_cnt+dmn_idx);
+		  rcd=nco_def_dim(out_id,dmn_nm,dmn_cnt[dmn_idx],dmn_id_out+dmn_idx);
+		} /* !rcd */
+	      } /* !ncol */
+	    } /* !1D_to_2D */
+	  } /* end loop over dimensions */
+	}else{ /* !flg_rgr */
+	  /* Copy as-is */
+	  rcd=nco_inq_vardimid(in_id,var_id_in,dmn_id_in);
+	  for(dmn_idx=0;dmn_idx<dmn_nbr_in;dmn_idx++){
+	    rcd=nco_inq_dimname(in_id,dmn_id_in[dmn_idx],dmn_nm);
+	    rcd=nco_inq_dimid_flg(out_id,dmn_nm,dmn_id_out+dmn_idx);
+	    /* If dimension has not been defined, define it */
+	    if(rcd != NC_NOERR){
+	      rcd=nco_inq_dimlen(in_id,dmn_id_in[dmn_idx],dmn_cnt+dmn_idx);
+	      rcd=nco_def_dim(out_id,dmn_nm,dmn_cnt[dmn_idx],dmn_id_out+dmn_idx);
+	    } /* !rcd */
+	  } /* end loop over dimensions */
+	} /* end !flg_rgr */
+	rcd=nco_def_var(out_id,var_nm,var_typ,dmn_nbr_out,dmn_id_out,&var_id_out);
+	(void)nco_att_cpy(in_id,out_id,var_id_in,var_id_out,PCK_ATT_CPY);
+	if(trv.flg_rgr){
+	  aed_mtd_crd.var_nm=var_nm;
+	  aed_mtd_crd.id=var_id_out;
+	  (void)nco_aed_prc(out_id,var_id_out,aed_mtd_crd);
+	} /* !flg_rgr */
+	if(dmn_id_in) dmn_id_in=(int *)nco_free(dmn_id_in);
+	if(dmn_id_out) dmn_id_out=(int *)nco_free(dmn_id_out);
+	if(dmn_srt) dmn_srt=(long *)nco_free(dmn_srt);
+	if(dmn_cnt) dmn_cnt=(long *)nco_free(dmn_cnt);
+      } /* !rcd */
+    } /* !var */
+  } /* end idx_tbl */
+
+  /* Define new metadata in regridded file */
+  att_nm=strdup("long_name");
+  att_val=strdup("solid angle subtended by grid cell");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=area_nm_out;
+  aed_mtd.id=area_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,area_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
 
-  /* Write variable */
+  att_nm=strdup("standard_name");
+  att_val=strdup("cell_area");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=area_nm_out;
+  aed_mtd.id=area_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,area_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
 
-  /* From this point on we parallel ncks logic for writing output files except:
-     All actions take place in sand-boxed routine and output file visible to regridding only
-     We work with a separate traversal table? 
-     Once things work with copy of traversal table, we merge back into main logic */
+  att_nm=strdup("units");
+  att_val=strdup("steradian");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=area_nm_out;
+  aed_mtd.id=area_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,area_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
 
+  att_nm=strdup("cell_methods");
+  att_val=strdup("lat, lon: sum");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=area_nm_out;
+  aed_mtd.id=area_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,area_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("long_name");
+  att_val=strdup("latitude");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lat_nm_out;
+  aed_mtd.id=lat_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lat_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("standard_name");
+  att_val=strdup("latitude");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lat_nm_out;
+  aed_mtd.id=lat_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lat_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("units");
+  att_val=strdup("degrees_north");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lat_nm_out;
+  aed_mtd.id=lat_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lat_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("axis");
+  att_val=strdup("Y");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lat_nm_out;
+  aed_mtd.id=lat_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lat_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("bounds");
+  att_val=lat_bnd_nm_out;
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lat_nm_out;
+  aed_mtd.id=lat_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lat_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+
+  att_nm=strdup("long_name");
+  if(flg_grd_out_2D) att_val=strdup("gridcell latitude interfaces"); else att_val=strdup("gridcell latitude vertices");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lat_bnd_nm_out;
+  aed_mtd.id=lat_bnd_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lat_bnd_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("long_name");
+  att_val=strdup("longitude");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lon_nm_out;
+  aed_mtd.id=lon_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lon_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("standard_name");
+  att_val=strdup("longitude");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lon_nm_out;
+  aed_mtd.id=lon_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lon_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("units");
+  att_val=strdup("degrees_east");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lon_nm_out;
+  aed_mtd.id=lon_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lon_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("axis");
+  att_val=strdup("X");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lon_nm_out;
+  aed_mtd.id=lon_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lon_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("bounds");
+  att_val=lon_bnd_nm_out;
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lon_nm_out;
+  aed_mtd.id=lon_out_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lon_out_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+
+  att_nm=strdup("long_name");
+  if(flg_grd_out_2D) att_val=strdup("gridcell longitude interfaces"); else att_val=strdup("gridcell longitude vertices");
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=lon_bnd_nm_out;
+  aed_mtd.id=lon_bnd_id;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,lon_bnd_id,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  if(flg_grd_out_2D){
+    att_nm=strdup("long_name");
+    att_val=strdup("latitude quadrature weights (normalized to sum to 2.0)");
+    aed_mtd.att_nm=att_nm;
+    aed_mtd.var_nm=lat_wgt_nm;
+    aed_mtd.id=lat_wgt_id;
+    aed_mtd.sz=strlen(att_val);
+    aed_mtd.type=NC_CHAR;
+    aed_mtd.val.cp=att_val;
+    aed_mtd.mode=aed_create;
+    (void)nco_aed_prc(out_id,lat_wgt_id,aed_mtd);
+    if(att_nm) att_nm=(char *)nco_free(att_nm);
+    if(att_val) att_val=(char *)nco_free(att_val);
+  } /* !flg_grd_out_2D */
+  
+  att_nm=strdup("mapping_file");
+  att_val=strdup(fl_in);
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=NULL;
+  aed_mtd.id=NC_GLOBAL;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,NC_GLOBAL,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  att_nm=strdup("source_file");
+  att_val=strdup(rgr->fl_in);
+  aed_mtd.att_nm=att_nm;
+  aed_mtd.var_nm=NULL;
+  aed_mtd.id=NC_GLOBAL;
+  aed_mtd.sz=strlen(att_val);
+  aed_mtd.type=NC_CHAR;
+  aed_mtd.val.cp=att_val;
+  aed_mtd.mode=aed_create;
+  (void)nco_aed_prc(out_id,NC_GLOBAL,aed_mtd);
+  if(att_nm) att_nm=(char *)nco_free(att_nm);
+  if(att_val) att_val=(char *)nco_free(att_val);
+
+  /* Annotate persistent metadata that should appear last in attribute list */
+  if(flg_grd_out_1D){
+    aed_mtd_crd.var_nm=area_nm_out;
+    aed_mtd_crd.id=area_out_id;
+    (void)nco_aed_prc(out_id,lat_out_id,aed_mtd_crd);
+    
+    aed_mtd_crd.var_nm=lat_nm_out;
+    aed_mtd_crd.id=lat_out_id;
+    (void)nco_aed_prc(out_id,lat_out_id,aed_mtd_crd);
+    
+    aed_mtd_crd.var_nm=lon_nm_out;
+    aed_mtd_crd.id=lon_out_id;
+    (void)nco_aed_prc(out_id,lon_out_id,aed_mtd_crd);
+  } /* !flg_grd_out_1D */
+  
+  /* Persistent metadata */
+  if(att_nm_crd) att_nm_crd=(char *)nco_free(att_nm_crd);
+  if(att_val_crd) att_val_crd=(char *)nco_free(att_val_crd);
+
+  /* Begin data mode */
+  (void)nco_enddef(out_id);
+
+  /* Write new coordinates and variables to regridded file */
+  if(flg_grd_out_1D){
+    dmn_srt_out[0]=0L;
+    dmn_cnt_out[0]=ncol_nbr_out;
+    (void)nco_put_vara(out_id,lat_out_id,dmn_srt_out,dmn_cnt_out,lat_ctr_out,crd_typ_out);
+    dmn_srt_out[0]=0L;
+    dmn_cnt_out[0]=ncol_nbr_out;
+    (void)nco_put_vara(out_id,lon_out_id,dmn_srt_out,dmn_cnt_out,lon_ctr_out,crd_typ_out);
+    dmn_srt_out[0]=dmn_srt_out[1]=0L;
+    dmn_cnt_out[0]=ncol_nbr_out;
+    dmn_cnt_out[1]=bnd_nbr_out;
+    (void)nco_put_vara(out_id,lat_bnd_id,dmn_srt_out,dmn_cnt_out,lat_bnd_out,crd_typ_out);
+    dmn_srt_out[0]=dmn_srt_out[1]=0L;
+    dmn_cnt_out[0]=ncol_nbr_out;
+    dmn_cnt_out[1]=bnd_nbr_out;
+    (void)nco_put_vara(out_id,lon_bnd_id,dmn_srt_out,dmn_cnt_out,lon_bnd_out,crd_typ_out);
+    dmn_srt_out[0]=0L;
+    dmn_cnt_out[0]=ncol_nbr_out;
+    (void)nco_put_vara(out_id,area_out_id,dmn_srt_out,dmn_cnt_out,area_out,crd_typ_out);
+  } /* !flg_grd_out_1D */
+  if(flg_grd_out_2D){
+    dmn_srt_out[0]=0L;
+    dmn_cnt_out[0]=lat_nbr_out;
+    (void)nco_put_vara(out_id,lat_out_id,dmn_srt_out,dmn_cnt_out,lat_ctr_out,crd_typ_out);
+    dmn_srt_out[0]=0L;
+    dmn_cnt_out[0]=lon_nbr_out;
+    (void)nco_put_vara(out_id,lon_out_id,dmn_srt_out,dmn_cnt_out,lon_ctr_out,crd_typ_out);
+    dmn_srt_out[0]=0L;
+    dmn_cnt_out[0]=lat_nbr_out;
+    (void)nco_put_vara(out_id,lat_wgt_id,dmn_srt_out,dmn_cnt_out,lat_wgt_out,crd_typ_out);
+    dmn_srt_out[0]=dmn_srt_out[1]=0L;
+    dmn_cnt_out[0]=lat_nbr_out;
+    dmn_cnt_out[1]=bnd_nbr_out;
+    (void)nco_put_vara(out_id,lat_bnd_id,dmn_srt_out,dmn_cnt_out,lat_bnd_out,crd_typ_out);
+    dmn_srt_out[0]=dmn_srt_out[1]=0L;
+    dmn_cnt_out[0]=lon_nbr_out;
+    dmn_cnt_out[1]=bnd_nbr_out;
+    (void)nco_put_vara(out_id,lon_bnd_id,dmn_srt_out,dmn_cnt_out,lon_bnd_out,crd_typ_out);
+    dmn_srt_out[0]=dmn_srt_out[1]=0L;
+    dmn_cnt_out[0]=lat_nbr_out;
+    dmn_cnt_out[1]=lon_nbr_out;
+    (void)nco_put_vara(out_id,area_out_id,dmn_srt_out,dmn_cnt_out,area_out,crd_typ_out);
+  } /* !flg_grd_out_2D */
+
+  /* Regrid or copy variable values */
+  const double wgt_vld_thr=rgr->wgt_vld_thr; /* [frc] Weight threshold for valid destination value */
+  const nco_bool flg_rnr=rgr->flg_rnr; /* [flg] Renormalize destination values by valid area */
+  const size_t grd_sz_in=rgr_map.src_grid_size; /* [nbr] Number of elements in single layer of input grid */
+  const size_t grd_sz_out=rgr_map.dst_grid_size; /* [nbr] Number of elements in single layer of output grid */
+  double *var_val_dbl_in;
+  double *var_val_dbl_out;
+  double *wgt_vld_out=NULL;
+  double mss_val_dbl;
+  double var_val_crr;
+  int *tally=NULL; /* [nbr] Number of valid (non-missing) values */
+  int idx_in; /* [idx] Input grid index */
+  int idx_out; /* [idx] Output grid index */
+  int lvl_idx; /* [idx] Level index */
+  int lvl_nbr; /* [nbr] Number of levels */
+  int thr_idx; /* [idx] Thread index */
+  nco_bool has_mss_val; /* [flg] Has numeric missing value attribute */
+  size_t dst_idx; 
+  size_t var_sz_in; /* [nbr] Number of elements in variable (will be self-multiplied) */
+  size_t var_sz_out; /* [nbr] Number of elements in variable (will be self-multiplied) */
+  size_t val_in_fst; /* [nbr] Number of elements by which current N-D slab input values are offset from origin */
+  size_t val_out_fst; /* [nbr] Number of elements by which current N-D slab output values are offset from origin */
+  
+  if(nco_dbg_lvl_get() >= nco_dbg_var) (void)fprintf(stdout,"Regridding progress: # means regridded, ~ means copied\n");
+
+  /* Using naked stdin/stdout/stderr in parallel region generates warning
+     Copy appropriate filehandle to variable scoped shared in parallel clause */
+  FILE * const fp_stdout=stdout; /* [fl] stdout filehandle CEWI */
+
+  /* OpenMP notes:
+     default(): none
+     firstprivate(): tally,wgt_vld_out (preserve NULL-initialization)
+     private(): almost everything else
+     shared(): flg_rnr,fnc_nm,wgt_vld_thr explicit shared for icc 13.1.3 (rhea), default shared for gcc 4.9.2 */
+#ifdef __INTEL_COMPILER
+# pragma omp parallel for default(none) firstprivate(tally,wgt_vld_out) private(dmn_cnt,dmn_id_in,dmn_id_out,dmn_idx,dmn_nbr_in,dmn_nbr_out,dmn_srt,dst_idx,has_mss_val,idx,idx_in,idx_out,idx_tbl,in_id,lnk_idx,lvl_idx,lvl_nbr,mss_val_dbl,rcd,thr_idx,trv,val_in_fst,val_out_fst,var_id_in,var_id_out,var_nm,var_sz_in,var_sz_out,var_typ,var_val_crr,var_val_dbl_in,var_val_dbl_out) shared(col_src_adr,flg_rnr,fnc_nm,lnk_nbr,out_id,row_dst_adr,wgt_raw,wgt_vld_thr)
+#else /* !__INTEL_COMPILER */
+# pragma omp parallel for default(none) firstprivate(tally,wgt_vld_out) private(dmn_cnt,dmn_id_in,dmn_id_out,dmn_idx,dmn_nbr_in,dmn_nbr_out,dmn_srt,dst_idx,has_mss_val,idx,idx_in,idx_out,idx_tbl,in_id,lnk_idx,lvl_idx,lvl_nbr,mss_val_dbl,rcd,thr_idx,trv,val_in_fst,val_out_fst,var_id_in,var_id_out,var_nm,var_sz_in,var_sz_out,var_typ,var_val_crr,var_val_dbl_in,var_val_dbl_out) shared(col_src_adr,lnk_nbr,out_id,row_dst_adr,wgt_raw)
+#endif /* !__INTEL_COMPILER */
+  for(idx_tbl=0;idx_tbl<trv_nbr;idx_tbl++){
+    trv=trv_tbl->lst[idx_tbl];
+    thr_idx=omp_get_thread_num();
+    in_id=trv_tbl->in_id_arr[thr_idx];
+#ifdef _OPENMP
+    if(nco_dbg_lvl_get() >= nco_dbg_var && !thr_idx && !idx_tbl) (void)fprintf(fp_stdout,"%s: %s reports regrid loop uses %d thread%s\n",nco_prg_nm_get(),fnc_nm,omp_get_num_threads(),(omp_get_num_threads() > 1) ? "s" : "");
+    if(nco_dbg_lvl_get() >= nco_dbg_io) (void)fprintf(fp_stdout,"%s: thread = %d, idx_tbl = %d, nm = %s\n",nco_prg_nm_get(),thr_idx,idx_tbl,trv.nm);
+#endif /* !_OPENMP */
+    if(trv.nco_typ == nco_obj_typ_var && trv.flg_xtr){
+      if(nco_dbg_lvl_get() >= nco_dbg_var) (void)fprintf(fp_stdout,"%s%s ",trv.flg_rgr ? "#" : "~",trv.nm);
+      if(trv.flg_rgr){
+	/* Regrid variable */
+	var_nm=trv.nm;
+	//var_typ=trv.var_typ;
+	var_typ=NC_DOUBLE; /* NB: Perform regridding in double precision */
+	var_sz_in=1L;
+	var_sz_out=1L;
+	rcd=nco_inq_varid(in_id,var_nm,&var_id_in);
+	rcd=nco_inq_varid(out_id,var_nm,&var_id_out);
+	rcd=nco_inq_varndims(out_id,var_id_out,&dmn_nbr_out);
+	rcd=nco_inq_varndims(in_id,var_id_in,&dmn_nbr_in);
+	dmn_id_in=(int *)nco_malloc(dmn_nbr_in*sizeof(int));
+	dmn_id_out=(int *)nco_malloc(dmn_nbr_out*sizeof(int));
+	dmn_srt=(long *)nco_malloc(dmn_nbr_out*sizeof(long)); /* Allocate an extra slot for new dimensions */
+	dmn_cnt=(long *)nco_malloc(dmn_nbr_out*sizeof(long));
+	rcd=nco_inq_vardimid(out_id,var_id_out,dmn_id_out);
+	rcd=nco_inq_vardimid(in_id,var_id_in,dmn_id_in);
+	for(dmn_idx=0;dmn_idx<dmn_nbr_in;dmn_idx++){
+	  rcd=nco_inq_dimlen(in_id,dmn_id_in[dmn_idx],dmn_cnt+dmn_idx);
+	  var_sz_in*=dmn_cnt[dmn_idx];
+	  dmn_srt[dmn_idx]=0L;
+	} /* end loop over dimensions */
+	var_val_dbl_in=(double *)nco_malloc_dbg(var_sz_in*nco_typ_lng(var_typ),"Unable to malloc() input value buffer",fnc_nm);
+	rcd=nco_get_vara(in_id,var_id_in,dmn_srt,dmn_cnt,var_val_dbl_in,var_typ);
+
+	for(dmn_idx=0;dmn_idx<dmn_nbr_out;dmn_idx++){
+	  rcd=nco_inq_dimlen(out_id,dmn_id_out[dmn_idx],dmn_cnt+dmn_idx);
+	  var_sz_out*=dmn_cnt[dmn_idx];
+	  dmn_srt[dmn_idx]=0L;
+	} /* end loop over dimensions */
+	var_val_dbl_out=(double *)nco_malloc_dbg(var_sz_out*nco_typ_lng(var_typ),"Unable to malloc() input value buffer",fnc_nm);
+	
+	lvl_nbr=1;
+	for(dmn_idx=0;dmn_idx<dmn_nbr_out-2;dmn_idx++) lvl_nbr*=dmn_cnt[dmn_idx];
+
+	/* Initialize output */
+	for(dst_idx=0;dst_idx<var_sz_out;dst_idx++) var_val_dbl_out[dst_idx]=0.0;
+	/* Missing value setup */
+	has_mss_val=nco_mss_val_get_dbl(in_id,var_id_in,&mss_val_dbl);
+	if(has_mss_val) tally=(int *)nco_calloc(var_sz_out,nco_typ_lng(NC_INT));
+	if(has_mss_val && flg_rnr) wgt_vld_out=(double *)nco_malloc_dbg(var_sz_out*nco_typ_lng(var_typ),"Unable to malloc() input weight buffer",fnc_nm);
+	if(has_mss_val && flg_rnr) 
+	  for(dst_idx=0;dst_idx<var_sz_out;dst_idx++) wgt_vld_out[dst_idx]=0.0;
+
+	/* Apply weights */
+	if(!has_mss_val){
+	  if(lvl_nbr == 1){
+	    for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++)
+	      var_val_dbl_out[row_dst_adr[lnk_idx]]+=var_val_dbl_in[col_src_adr[lnk_idx]]*wgt_raw[lnk_idx];
+	  }else{
+	    val_in_fst=0L;
+	    val_out_fst=0L;
+	    for(lvl_idx=0;lvl_idx<lvl_nbr;lvl_idx++){
+	      //if(nco_dbg_lvl_get() >= nco_dbg_crr) (void)fprintf(fp_stdout,"%s lvl_idx = %d val_in_fst = %li, val_out_fst = %li\n",trv.nm,lvl_idx,val_in_fst,val_out_fst);
+	      for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++)
+		var_val_dbl_out[row_dst_adr[lnk_idx]+val_out_fst]+=var_val_dbl_in[col_src_adr[lnk_idx]+val_in_fst]*wgt_raw[lnk_idx];
+	      val_in_fst+=grd_sz_in;
+	      val_out_fst+=grd_sz_out;
+	    } /* end loop over lvl */
+	  } /* lvl_nbr > 1 */
+	}else{ /* has_mss_val */
+	  if(lvl_nbr == 1){
+	    for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++){
+	      idx_in=col_src_adr[lnk_idx];
+	      idx_out=row_dst_adr[lnk_idx];
+	      if((var_val_crr=var_val_dbl_in[idx_in]) != mss_val_dbl){
+		var_val_dbl_out[idx_out]+=var_val_crr*wgt_raw[lnk_idx];
+		if(flg_rnr) wgt_vld_out[idx_out]+=wgt_raw[lnk_idx];
+		tally[idx_out]++;
+	      } /* endif */
+	    } /* end loop over link */
+	  }else{ /* lvl_nbr > 1 */
+	    val_in_fst=0L;
+	    val_out_fst=0L;
+	    for(lvl_idx=0;lvl_idx<lvl_nbr;lvl_idx++){
+	      for(lnk_idx=0;lnk_idx<lnk_nbr;lnk_idx++){
+		idx_in=col_src_adr[lnk_idx]+val_in_fst;
+		idx_out=row_dst_adr[lnk_idx]+val_out_fst;
+		if((var_val_crr=var_val_dbl_in[idx_in]) != mss_val_dbl){
+		  var_val_dbl_out[idx_out]+=var_val_crr*wgt_raw[lnk_idx];
+		  if(flg_rnr) wgt_vld_out[idx_out]+=wgt_raw[lnk_idx];
+		  tally[idx_out]++;
+		} /* endif */
+	      } /* end loop over link */
+	      val_in_fst+=grd_sz_in;
+	      val_out_fst+=grd_sz_out;
+	    } /* end loop over lvl */
+	  } /* lvl_nbr > 1 */
+	  /* NCL and ESMF treatment of weights and missing values described at
+	     https://www.ncl.ucar.edu/Applications/ESMF.shtml#WeightsAndMasking
+	     http://earthsystemmodeling.org/esmf_releases/non_public/ESMF_6_1_1/ESMF_refdoc/node5.html#SECTION05012600000000000000
+	     NCO implements one of two procedures: "conservative" or "renormalized"
+	     The "conservative" algorithm uses all valid data from the input grid on the output grid
+	     Destination cells receive the weighted valid values of the source cells
+	     This is conservative because the global integrals of the source and destination fields are equal
+	     The "renormalized" algorithm divides the destination value by the sum of the valid weights
+	     This returns "reasonable" values, i.e., the mean of the valid input values
+	     However, renormalization is equivalent to extrapolating valid data to missing regions
+	     Hence the input and output integrals are unequal and the regridding is not conservative */
+	  for(dst_idx=0;dst_idx<var_sz_out;dst_idx++)
+	    if(!tally[dst_idx]) var_val_dbl_out[dst_idx]=mss_val_dbl;
+	  if(flg_rnr){
+	    if(wgt_vld_thr == 0.0){
+	      for(dst_idx=0;dst_idx<var_sz_out;dst_idx++)
+		if(tally[dst_idx]) var_val_dbl_out[dst_idx]/=wgt_vld_out[dst_idx];
+	    }else{
+	      for(dst_idx=0;dst_idx<var_sz_out;dst_idx++)
+		if(wgt_vld_out[dst_idx] >= wgt_vld_thr){var_val_dbl_out[dst_idx]/=wgt_vld_out[dst_idx];}else{var_val_dbl_out[dst_idx]=mss_val_dbl;}
+	    } /* !wgt_vld_thr */
+	  } /* !flg_rnr */
+	} /* !has_mss_val */
+	
+#pragma omp critical
+	{ /* begin OpenMP critical */
+	  rcd=nco_put_vara(out_id,var_id_out,dmn_srt,dmn_cnt,var_val_dbl_out,var_typ);
+	} /* end OpenMP critical */
+	
+	if(dmn_id_in) dmn_id_out=(int *)nco_free(dmn_id_in);
+	if(dmn_id_out) dmn_id_out=(int *)nco_free(dmn_id_out);
+	if(dmn_srt) dmn_srt=(long *)nco_free(dmn_srt);
+	if(dmn_cnt) dmn_cnt=(long *)nco_free(dmn_cnt);
+	if(tally) tally=(int *)nco_free(tally);
+	if(var_val_dbl_out) var_val_dbl_out=(double *)nco_free(var_val_dbl_out);
+	if(var_val_dbl_in) var_val_dbl_in=(double *)nco_free(var_val_dbl_in);
+	if(wgt_vld_out) wgt_vld_out=(double *)nco_free(wgt_vld_out);
+      }else{
+	/* Use standard NCO copy routine for variables that are not regridded */
+#pragma omp critical
+	{ /* begin OpenMP critical */
+	  (void)nco_cpy_var_val(in_id,out_id,(FILE *)NULL,(md5_sct *)NULL,trv.nm,trv_tbl);
+	} /* end OpenMP critical */
+     } /* !flg_rgr */
+    } /* !xtr */
+  } /* end (OpenMP parallel for) loop over idx_tbl */
+  if(nco_dbg_lvl_get() >= nco_dbg_var) (void)fprintf(stdout,"\n");
+  if(nco_dbg_lvl_get() >= nco_dbg_fl) (void)fprintf(stdout,"%s: INFO %s completion report. Variables regridded = %d, copied unmodified = %d, omitted = %d, created = %d\n",nco_prg_nm_get(),fnc_nm,var_rgr_nbr,var_cpy_nbr,var_xcl_nbr,var_crt_nbr);
+  
   /* Free memory allocated for grid reading/writing */
-  if(dmn_sz) dmn_sz=(int *)nco_free(dmn_sz);
-  if(lon_ctr_out) lon_ctr_out=(double *)nco_free(lon_ctr_out);
-  if(lat_ctr_out) lat_ctr_out=(double *)nco_free(lat_ctr_out);
-  if(lon_crn_out) lon_crn_out=(double *)nco_free(lon_crn_out);
+  if(area_out) area_out=(double *)nco_free(area_out);
+  if(col_src_adr) col_src_adr=(int *)nco_free(col_src_adr);
+  if(dmn_sz_out_int) dmn_sz_out_int=(int *)nco_free(dmn_sz_out_int);
+  if(dmn_sz_in_int) dmn_sz_in_int=(int *)nco_free(dmn_sz_in_int);
+  if(lat_bnd_out) lat_bnd_out=(double *)nco_free(lat_bnd_out);
   if(lat_crn_out) lat_crn_out=(double *)nco_free(lat_crn_out);
-  if(lon_ntf_out) lon_ntf_out=(double *)nco_free(lon_ntf_out);
+  if(lat_ctr_out) lat_ctr_out=(double *)nco_free(lat_ctr_out);
   if(lat_ntf_out) lat_ntf_out=(double *)nco_free(lat_ntf_out);
+  if(lat_wgt_out) lat_wgt_out=(double *)nco_free(lat_wgt_out);
   if(lon_bnd_out) lon_bnd_out=(double *)nco_free(lon_bnd_out);
-  if(lat_bnd_out) lat_bnd_out=(double *)nco_free(lat_bnd_out);
-  if(wgt_raw_out) wgt_raw_out=(double *)nco_free(wgt_raw_out);
+  if(lon_crn_out) lon_crn_out=(double *)nco_free(lon_crn_out);
+  if(lon_ctr_out) lon_ctr_out=(double *)nco_free(lon_ctr_out);
+  if(lon_ntf_out) lon_ntf_out=(double *)nco_free(lon_ntf_out);
+  if(row_dst_adr) row_dst_adr=(int *)nco_free(row_dst_adr);
+  if(wgt_raw) wgt_raw=(double *)nco_free(wgt_raw);
   
   return rcd;
 } /* nco_rgr_map() */
 
+void
+nco_bsl_zro /* Return Bessel function zeros */
+(const int bsl_zro_nbr, /* O [nbr] Order of Bessel function */
+ double * const bsl_zro) /* O [frc] Bessel zero */
+{
+  /* Purpose: Return Bessel function zeros
+     Source: CCM code /fs/cgd/csm/models/atm/ccm3.5.8/src/ccmlsm_share/bsslzr.F
+     Return bsl_zro_nbr zeros (or if bsl_zro_nbr > 50, approximate zeros), of the Bessel function j0
+     First 50 zeros are given exactly, and remaining zeros are computed by extrapolation, and therefore are not exact
+     Original version:  CCM1
+     Standardized:      J. Rosinski, June 1992
+     Reviewed:          J. Hack, D. Williamson, August 1992
+     Reviewed:          J. Hack, D. Williamson, April 1996
+     Modified 19970123 by Jim Rosinski to use double precision arithmetic
+     ~2000: Converted to Fortran9X by C. Zender, changed all real*16 statements to double precision (real*8)
+     20150530: Converted to C99 by C. Zender */
+  const char fnc_nm[]="nco_bsl_zro()"; /* [sng] Function name */
+  const double pi=M_PI; // [frc] 3
+  const double bsl_zro_tbl[]={ // Zeros of Bessel functions of order 1 to 50
+    -1.e36, 2.4048255577,   5.5200781103, 
+    8.6537279129,  11.7915344391,  14.9309177086,  18.0710639679, 
+    21.2116366299,  24.3524715308,  27.4934791320,  30.6346064684, 
+    33.7758202136,  36.9170983537,  40.0584257646,  43.1997917132, 
+    46.3411883717,  49.4826098974,  52.6240518411,  55.7655107550, 
+    58.9069839261,  62.0484691902,  65.1899648002,  68.3314693299, 
+    71.4729816036,  74.6145006437,  77.7560256304,  80.8975558711, 
+    84.0390907769,  87.1806298436,  90.3221726372,  93.4637187819, 
+    96.6052679510,  99.7468198587, 102.8883742542, 106.0299309165, 
+    109.1714896498, 112.3130502805, 115.4546126537, 118.5961766309, 
+    121.7377420880, 124.8793089132, 128.0208770059, 131.1624462752, 
+    134.3040166383, 137.4455880203, 140.5871603528, 143.7287335737, 
+    146.8703076258, 150.0118824570, 153.1534580192, 156.2950342685};
+  const int bsl_zro_tbl_nbr_max=sizeof(bsl_zro_tbl)/sizeof(double); /* [nbr] */
+  int bsl_idx; /* [idx] Counting index */
+    
+  /* Main Code */
+  if(nco_dbg_lvl_get() >= nco_dbg_sbr) (void)fprintf(stdout,"%s: DEBUG Entering %s\n",nco_prg_nm_get(),fnc_nm);
+    
+  assert(bsl_zro_tbl_nbr_max == 51); /* 51 is original size of 50 plus extra value for Fortran offset */
+
+  for(bsl_idx=1;bsl_idx<=bsl_zro_nbr;bsl_idx++)
+    if(bsl_idx <= bsl_zro_tbl_nbr_max) bsl_zro[bsl_idx]=bsl_zro_tbl[bsl_idx];
+
+  if(bsl_zro_nbr > bsl_zro_tbl_nbr_max)
+    for(bsl_idx=bsl_zro_tbl_nbr_max+1;bsl_idx<=bsl_zro_nbr;bsl_idx++)
+      bsl_zro[bsl_idx]=bsl_zro[bsl_idx-1]+pi;
+    
+  if(nco_dbg_lvl_get() == nco_dbg_old){
+    (void)fprintf(stdout,"%s: DEBUG %s reports bsl_zro_nbr = %d\n",nco_prg_nm_get(),fnc_nm,bsl_zro_nbr);
+    (void)fprintf(stdout,"idx\tbsl_zro\n");
+    for(bsl_idx=1;bsl_idx<=bsl_zro_nbr;bsl_idx++)
+      (void)fprintf(stdout,"%d\t%g\n",bsl_idx,bsl_zro[bsl_idx]);
+  } /* endif dbg */
+
+  return;
+} /* end nco_bsl_zro() */
+
+void
+nco_lat_wgt_gss /* [fnc] Compute and return sine of Gaussian latitudes and their weights */
+(const int lat_nbr, /* I [nbr] Latitude number */
+ double * const lat_sin, /* O [frc] Sine of latitudes */
+ double * const wgt_Gss) /* O [frc] Gaussian weights */
+{  
+  /* Purpose: Compute and return sine of Gaussian latitudes and their weights
+     Source: CCM /fs/cgd/csm/models/atm/ccm3.5.8/src/ccmlsm_share/gauaw.F
+     Calculate sine of latitudes lat_sin(lat_nbr) and weights wgt_Gss(lat_nbr) for Gaussian quadrature
+     Algorithm described in Davis and Rabinowitz, Journal of Research of the NBS, V 56, Jan 1956
+     Zeros of Bessel function j0, obtained from nco_bsl_zro(), are first guess for abscissae
+     Original version: CCM1
+     Standardized: L. Bath, Jun 1992
+                   L. Buja, Feb 1996
+     Reviewed:     D. Williamson, J. Hack, Aug 1992
+                   D. Williamson, J. Hack, Feb 1996
+     19970123 Modified by Jim Rosinski to use real*16 arithmetic in order to 
+     achieve (nearly) identical weights and latitudes on all machines.
+     ~2000: Converted to Fortran9X by C. Zender, changed all real*16 statements to double precision (real*8)
+     20150530: Converted to C99 by C. Zender */
+  
+  const char fnc_nm[]="nco_lat_wgt_gss()"; /* [sng] Function name */
+  const double eps_rlt=1.0e-15; // Convergence criterion (NB: Threshold was 1.0d-27 in real*16, 1.0e-15 is for real*8)
+  const double pi=M_PI; // [frc] 3
+  const int itr_nbr_max=20; // [nbr] Maximum number of iterations
+  double c; // Constant combination
+  double lat_idx_dbl; // Latitude index, double precision
+  double lat_nnr_idx_dbl; // Inner latitude index, double precision
+  double lat_nbr_dbl; // [nbr] Number of latitudes, double precision
+  double pk; // Polynomial
+  double pkm1; // Polynomial
+  double pkm2; // Polynomial
+  double pkmrk; // Polynomial
+  double sp; // Current iteration latitude increment
+  double xz; // Abscissa estimate
+  int itr_cnt; // Iteration counter
+  int lat_idx; // [idx] Counting index (latitude)
+  int lat_sym_idx; // [idx] Counting index (symmetric latitude)
+  int lat_nnr_idx; // [idx] Counting index (inner latitude loop)
+  int lat_nbr_rcp2; // lat_nbr/2 (number of latitudes in hemisphere)
+  double *lat_sin_p1; // Sine of Gaussian latitudes double precision
+  double *wgt_Gss_p1; // Gaussian weights double precision
+
+  /* Main Code */
+  if(nco_dbg_lvl_get() >= nco_dbg_sbr) (void)fprintf(stdout,"%s: DEBUG Entering %s\n",nco_prg_nm_get(),fnc_nm);
+    
+  /* Create arrays with Fortran indexing to keep numerical algorithm identical */
+  lat_sin_p1=(double *)nco_malloc((lat_nbr+1)*sizeof(double)); // Sine of Gaussian latitudes double precision
+  wgt_Gss_p1=(double *)nco_malloc((lat_nbr+1)*sizeof(double)); // Gaussian weights double precision
+    
+  /* Use Newton iteration to find abscissas */
+  c=0.25*(1.0-4.0/(pi*pi));
+  lat_nbr_dbl=lat_nbr;
+  lat_nbr_rcp2=lat_nbr/2; // Integer arithmetic
+  (void)nco_bsl_zro(lat_nbr_rcp2,lat_sin_p1);
+  for(lat_idx=1;lat_idx<=lat_nbr_rcp2;lat_idx++){
+    xz=cos(lat_sin_p1[lat_idx]/sqrt((lat_nbr_dbl+0.5)*(lat_nbr_dbl+0.5)+c));
+    /* First approximation to xz */
+    itr_cnt=0;
+    /* goto label_73 */
+  label_73:
+    pkm2=1.0;
+    pkm1=xz;
+    itr_cnt=itr_cnt+1;
+    if(itr_cnt > itr_nbr_max){
+      (void)fprintf(stdout,"%s: ERROR %s reports no convergence in %d iterations for lat_idx = %d\n",nco_prg_nm_get(),fnc_nm,itr_nbr_max,lat_idx);
+      nco_exit(EXIT_FAILURE);
+    } /* endif */
+    /* Compute Legendre polynomial */
+    for(lat_nnr_idx=2;lat_nnr_idx<=lat_nbr;lat_nnr_idx++){
+      lat_nnr_idx_dbl=lat_nnr_idx;
+      pk=((2.0*lat_nnr_idx_dbl-1.0)*xz*pkm1-(lat_nnr_idx_dbl-1.0)*pkm2)/lat_nnr_idx_dbl;
+      pkm2=pkm1;
+      pkm1=pk;
+    } /* end inner loop over lat_nnr */
+    pkm1=pkm2;
+    pkmrk=(lat_nbr_dbl*(pkm1-xz*pk))/(1.0-xz*xz);
+    sp=pk/pkmrk;
+    xz=xz-sp;
+    if(fabs(sp) > eps_rlt) goto label_73;
+    lat_sin_p1[lat_idx]=xz;
+    wgt_Gss_p1[lat_idx]=(2.0*(1.0-xz*xz))/((lat_nbr_dbl*pkm1)*(lat_nbr_dbl*pkm1));
+  } /* end outer loop over lat */
+  if(lat_nbr != lat_nbr_rcp2*2){
+    /* When lat_nbr is odd, compute weight at Equator */
+    lat_sin_p1[lat_nbr_rcp2+1]=0.0;
+    pk=2.0/(lat_nbr_dbl*lat_nbr_dbl);
+    for(lat_idx=2;lat_idx<=lat_nbr;lat_idx+=2){
+      lat_idx_dbl=lat_idx;
+      pk=pk*lat_idx_dbl*lat_idx_dbl/((lat_idx_dbl-1.0)*(lat_idx_dbl-1.0));
+    } /* end loop over lat */
+    wgt_Gss_p1[lat_nbr_rcp2+1]=pk;
+  } /* endif lat_nbr is odd */
+    
+  /* Complete sets of abscissas and weights, using symmetry properties */
+  for(lat_idx=1;lat_idx<=lat_nbr_rcp2;lat_idx++){
+    lat_sym_idx=lat_nbr-lat_idx+1;
+    lat_sin_p1[lat_sym_idx]=-lat_sin_p1[lat_idx];
+    wgt_Gss_p1[lat_sym_idx]=wgt_Gss_p1[lat_idx];
+  } /* end loop over lat */
+    
+  /* Shift by one to remove Fortran offset in p1 arrays */
+  //memcpy(lat_sin,lat_sin_p1,lat_nbr*sizeof(double));
+  //memcpy(wgt_Gss,wgt_Gss_p1,lat_nbr*sizeof(double));
+  
+  /* Reverse and shift arrays because original CCM code algorithm computed latitudes from north-to-south
+     Shift by one to remove Fortran offset in p1 arrays */
+  for(lat_idx=0;lat_idx<lat_nbr;lat_idx++){
+    lat_sin[lat_idx]=lat_sin_p1[lat_nbr-lat_idx];
+    wgt_Gss[lat_idx]=wgt_Gss_p1[lat_nbr-lat_idx];
+  } /* end loop over lat */
+
+  if(nco_dbg_lvl_get() == nco_dbg_old){
+    (void)fprintf(stdout,"%s: DEBUG %s reports lat_nbr = %d\n",nco_prg_nm_get(),fnc_nm,lat_nbr);
+    (void)fprintf(stdout,"idx\tasin\tngl_rad\tngl_dgr\tgw\n");
+    for(lat_idx=0;lat_idx<lat_nbr;lat_idx++)
+      (void)fprintf(stdout,"%d\t%g\t%g\t%g%g\n",lat_idx,lat_sin[lat_idx],asin(lat_sin[lat_idx]),180.0*asin(lat_sin[lat_idx])/pi,wgt_Gss[lat_idx]);
+  } /* endif dbg */
+  
+  if(wgt_Gss_p1) wgt_Gss_p1=(double *)nco_free(wgt_Gss_p1);
+  if(lat_sin_p1) lat_sin_p1=(double *)nco_free(lat_sin_p1);
+  return;
+} /* end nco_lat_wgt_gss() */
+  
 int /* O [enm] Return code */
 nco_rgr_tps /* [fnc] Regrid using Tempest library */
-(rgr_sct * const rgr_nfo) /* I/O [sct] Regridding structure */
+(rgr_sct * const rgr) /* I/O [sct] Regridding structure */
 {
-  /* Purpose: Regrid fields using external weights (i.e., a mapping file)
+  /* Purpose: Regrid fields using Tempest remapping "library" (more precisely, executables)
 
-     Test Tempest library: fxm no way to activate yet
+     Test Tempest library: no way to activate yet
      export DATA_TEMPEST='/data/zender/rgr';ncks -O --rgr=Y ${DATA}/rgr/essgcm14_clm.nc ~/foo.nc */
 
   const char fnc_nm[]="nco_rgr_tps()";
@@ -552,11 +1890,11 @@ nco_rgr_tps /* [fnc] Regrid using Tempest library */
 
   char *nvr_DATA_TEMPEST; /* [sng] Directory where Tempest grids, meshes, and weights are stored */
   nvr_DATA_TEMPEST=getenv("DATA_TEMPEST");
-  rgr_nfo->drc_tps= (nvr_DATA_TEMPEST && strlen(nvr_DATA_TEMPEST) > 0) ? (char *)strdup(nvr_DATA_TEMPEST) : (char *)strdup("/tmp");
+  rgr->drc_tps= (nvr_DATA_TEMPEST && strlen(nvr_DATA_TEMPEST) > 0L) ? (char *)strdup(nvr_DATA_TEMPEST) : (char *)strdup("/tmp");
 
   if(nco_dbg_lvl_get() >= nco_dbg_crr){
     (void)fprintf(stderr,"%s: INFO %s reports\n",nco_prg_nm_get(),fnc_nm);
-    (void)fprintf(stderr,"drc_tps = %s, ",rgr_nfo->drc_tps ? rgr_nfo->drc_tps : "NULL");
+    (void)fprintf(stderr,"drc_tps = %s, ",rgr->drc_tps ? rgr->drc_tps : "NULL");
     (void)fprintf(stderr,"\n");
   } /* endif dbg */
 
@@ -574,7 +1912,7 @@ nco_rgr_tps /* [fnc] Regrid using Tempest library */
   (void)sprintf(cmd_rgr,cmd_rgr_fmt,lat_nbr_rqs,lon_nbr_rqs,fl_grd_dst_cdl);
   rcd_sys=system(cmd_rgr);
   if(rcd_sys == -1){
-    (void)fprintf(stdout,"%s: ERROR %s is unable to complete regridding command \"%s\"\n",nco_prg_nm_get(),fnc_nm,cmd_rgr);
+    (void)fprintf(stdout,"%s: ERROR %s unable to complete Tempest regridding command \"%s\"\n",nco_prg_nm_get(),fnc_nm,cmd_rgr);
     nco_exit(EXIT_FAILURE);
   } /* end if */
   if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"done\n");
@@ -586,6 +1924,39 @@ nco_rgr_tps /* [fnc] Regrid using Tempest library */
   return NCO_NOERR;
 } /* end nco_rgr_tps() */
 
+const char * /* O [sng] String describing two-dimensional grid-type */
+nco_grd_2D_sng /* [fnc] Convert two-dimensional grid-type enum to string */
+(const nco_grd_2D_typ_enm nco_grd_2D_typ) /* I [enm] Two-dimensional grid-type enum */
+{
+  /* Purpose: Convert two-dimensional grid-type enum to string */
+  switch(nco_grd_2D_typ){
+  case nco_grd_2D_gss: return "Gaussian latitude grid used by global spectral models: CCM 1-3, CAM 1-3, LSM, MATCH, UCICTM";
+  case nco_grd_2D_ngl_eqi_pol: return "Equi-angle latitude grid with poles at centers of first and last gridpoints (i.e., lat_ctr[0]=-90), aka FV scalar grid: CAM FV, GEOS-CHEM, UCICTM, UKMO";
+  case nco_grd_2D_ngl_eqi_fst: return "Equi-angle latitude grid with poles at edges of first and last gridpoints (i.e., lat_ctr[0]=-89.xxx), aka FV staggered velocity grid: CIESIN/SEDAC, IGBP-DIS, TOMS AAI";
+  default: nco_dfl_case_generic_err(); break;
+  } /* end switch */
+
+  /* Some compilers: e.g., SGI cc, need return statement to end non-void functions */
+  return (char *)NULL;
+} /* end nco_grd_2D_sng() */
+
+const char * /* O [sng] String describing grid conversion */
+nco_rgr_grd_sng /* [fnc] Convert grid conversion enum to string */
+(const nco_rgr_grd_typ_enm nco_rgr_grd_typ) /* I [enm] Grid conversion enum */
+{
+  /* Purpose: Convert grid conversion enum to string */
+  switch(nco_rgr_grd_typ){
+  case nco_rgr_grd_1D_to_1D: return "1D_to_1D";
+  case nco_rgr_grd_1D_to_2D: return "1D_to_2D";
+  case nco_rgr_grd_2D_to_1D: return "2D_to_1D";
+  case nco_rgr_grd_2D_to_2D: return "2D_to_2D";
+  default: nco_dfl_case_generic_err(); break;
+  } /* end switch */
+
+  /* Some compilers: e.g., SGI cc, need return statement to end non-void functions */
+  return (char *)NULL;
+} /* end nco_rgr_grd_sng() */
+
 const char * /* O [sng] String describing regridding method */
 nco_rgr_mth_sng /* [fnc] Convert regridding method enum to string */
 (const nco_rgr_mth_typ_enm nco_rgr_mth_typ) /* I [enm] Regridding method enum */
@@ -862,7 +2233,7 @@ nco_esmf_rgn_flg_sng /* [fnc] Convert ESMF region flag enum to string */
 
 int /* O [enm] Return code */
 nco_rgr_esmf /* [fnc] Regrid using ESMF library */
-(rgr_sct * const rgr_nfo) /* I/O [sct] Regridding structure */
+(rgr_sct * const rgr) /* I/O [sct] Regridding structure */
 {
   /* Purpose: Regrid fields
      ESMC is C-interface to ESMF documented at
@@ -903,6 +2274,7 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   long *dmn_srt;
   
   nc_type var_typ_in;
+  nc_type crd_typ_out=NC_DOUBLE;
   nc_type var_typ_out=NC_DOUBLE;
   
   double *lon_in;
@@ -939,8 +2311,8 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   const int crd_idx_f_1bs_lon_src=1; /* [dgr] 1-based index of longitude in Fortran representation of rank-2 source grids */
 
   /* Initialize */
-  in_id=rgr_nfo->in_id;
-  out_id=rgr_nfo->out_id;
+  in_id=rgr->in_id;
+  out_id=rgr->out_id;
   
   /* Obtain input longitude type and length */
   char lon_nm_in[]="lon";
@@ -948,7 +2320,7 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   (void)nco_inq_var(in_id,var_in_id,(char *)NULL,&var_typ_in,&dmn_nbr,(int *)NULL,(int *)NULL);
   if(var_typ_in != NC_DOUBLE){
     assert(var_typ_in == NC_FLOAT);
-    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO WARNING Cheapskate regridding input file %s stores coordinate as NC_FLOAT\n",nco_prg_nm_get(),rgr_nfo->fl_in);
+    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO WARNING Cheapskate regridding input file %s stores coordinate as NC_FLOAT\n",nco_prg_nm_get(),rgr->fl_in);
   } /* !var_typ_in */
 
   /* Allocate space to hold dimension metadata */
@@ -969,8 +2341,8 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   max_idx[crd_idx_f_0bs_lon_src]=dmn_sz; /* [nbr] Number of elements in dimensions */
   
   /* Allocate space for and obtain longitude */
-  lon_in=(double *)nco_malloc(dmn_sz*nco_typ_lng(var_typ_out));
-  rcd=nco_get_vara(in_id,var_in_id,dmn_srt,dmn_cnt,lon_in,var_typ_out);
+  lon_in=(double *)nco_malloc(dmn_sz*nco_typ_lng(crd_typ_out));
+  rcd=nco_get_vara(in_id,var_in_id,dmn_srt,dmn_cnt,lon_in,crd_typ_out);
 
   /* Obtain input latitude type and length */
   char lat_nm_in[]="lat";
@@ -978,7 +2350,7 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   (void)nco_inq_var(in_id,var_in_id,(char *)NULL,&var_typ_in,&dmn_nbr,(int *)NULL,(int *)NULL);
   if(var_typ_in != NC_DOUBLE){
     assert(var_typ_in == NC_FLOAT);
-    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO WARNING Cheapskate regridding input file %s stores coordinate as NC_FLOAT\n",nco_prg_nm_get(),rgr_nfo->fl_in);
+    if(nco_dbg_lvl_get() >= nco_dbg_std) (void)fprintf(stderr,"%s: INFO WARNING Cheapskate regridding input file %s stores coordinate as NC_FLOAT\n",nco_prg_nm_get(),rgr->fl_in);
   } /* !var_typ_in */
   (void)nco_inq_vardimid(in_id,var_in_id,dmn_id);
   dmn_sz=1L;
@@ -991,8 +2363,8 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   max_idx[crd_idx_f_0bs_lat_src]=dmn_sz; /* [nbr] Number of elements in dimensions */
 
   /* Allocate space for and obtain latitude */
-  lat_in=(double *)nco_malloc(dmn_sz*nco_typ_lng(var_typ_out));
-  rcd=nco_get_vara(in_id,var_in_id,dmn_srt,dmn_cnt,lat_in,var_typ_out);
+  lat_in=(double *)nco_malloc(dmn_sz*nco_typ_lng(crd_typ_out));
+  rcd=nco_get_vara(in_id,var_in_id,dmn_srt,dmn_cnt,lat_in,crd_typ_out);
 
   /* Initialize before any other ESMC API calls!
      ESMC_ArgLast is ALWAYS at the end to indicate the end of opt args */
@@ -1030,7 +2402,7 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   char **crd_nm=NULL; /* [sng] Iff GRIDSPEC use these lon/lat variable coordinates */
   enum ESMC_FileFormat_Flag grd_fl_typ=ESMC_FILEFORMAT_SCRIP;
   ESMC_Grid grd_dst;
-  grd_dst=ESMC_GridCreateFromFile(rgr_nfo->fl_grd_dst,grd_fl_typ,&flg_isSphere,&flg_addCornerStagger,&flg_addUserArea,&flg_addMask,var_nm,crd_nm,&rcd_esmf);
+  grd_dst=ESMC_GridCreateFromFile(rgr->fl_grd_dst,grd_fl_typ,&flg_isSphere,&flg_addCornerStagger,&flg_addUserArea,&flg_addMask,var_nm,crd_nm,&rcd_esmf);
   if(rcd_esmf != ESMF_SUCCESS) goto rgr_cln;
 
   int *msk_dst; /* [enm] Destination grid mask */
@@ -1093,7 +2465,7 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   if(nco_dbg_lvl_get() >= nco_dbg_crr){
     (void)fprintf(stderr,"%s: INFO %s reports\n",nco_prg_nm_get(),fnc_nm);
     (void)fprintf(stderr,"ESMC_VMGet(): localPet = %d, petCount = %d, peCount = %d, pthreadsEnabledFlag = %s, openMPEnabledFlag = %s\n",localPet,petCount,peCount,flg_pthreadsEnabledFlag ? "Enabled" : "Disabled",flg_openMPEnabledFlag ? "Enabled" : "Disabled");
-    (void)fprintf(stderr,"ESMC_GridCreateFromFile(): filename = %s, fileTypeFlag = %s, isSphere = %s, addCornerStagger = %s, addUserArea = %s, addMask = %s, var_nm = %s, crd_nm = %s\n",rgr_nfo->fl_grd_dst,nco_esmf_fl_fmt_sng(grd_fl_typ),flg_isSphere ? "Enabled" : "Disabled",flg_addCornerStagger ? "Enabled" : "Disabled",flg_addUserArea ? "Enabled" : "Disabled",flg_addMask ? "Enabled" : "Disabled",var_nm,crd_nm ? "non-NULL" : "NULL");
+    (void)fprintf(stderr,"ESMC_GridCreateFromFile(): filename = %s, fileTypeFlag = %s, isSphere = %s, addCornerStagger = %s, addUserArea = %s, addMask = %s, var_nm = %s, crd_nm = %s\n",rgr->fl_grd_dst,nco_esmf_fl_fmt_sng(grd_fl_typ),flg_isSphere ? "Enabled" : "Disabled",flg_addCornerStagger ? "Enabled" : "Disabled",flg_addUserArea ? "Enabled" : "Disabled",flg_addMask ? "Enabled" : "Disabled",var_nm,crd_nm ? "non-NULL" : "NULL");
     (void)fprintf(stderr,"ESMC_GridGetCoord(): bnd_lwr_dst[0..1] = %d, %d; bnd_upr_dst[0..1] = %d, %d;\n",bnd_lwr_dst[0],bnd_lwr_dst[1],bnd_upr_dst[0],bnd_upr_dst[1]);
     (void)fprintf(stderr,"ESMC_InterfaceIntCreate(): No printable information\n");
     (void)fprintf(stderr,"ESMC_GridCreateNoPeriDim(): crd_sys = %s, typ_knd = %s\n",nco_esmf_crd_sys_sng(crd_sys),nco_esmf_typ_knd_sng(typ_knd));
@@ -1136,7 +2508,7 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   if(rcd_esmf != ESMF_SUCCESS) goto rgr_cln;
 
   /* Get variables from input file */
-  (void)nco_inq_varid(in_id,rgr_nfo->var_nm,&var_in_id);
+  (void)nco_inq_varid(in_id,rgr->var_nm,&var_in_id);
   (void)nco_inq_var(in_id,var_in_id,(char *)NULL,&var_typ_in,&dmn_nbr,(int *)NULL,(int *)NULL);
   /* Get dimension IDs from input file */
   (void)nco_inq_vardimid(in_id,var_in_id,dmn_id);
@@ -1206,25 +2578,30 @@ nco_rgr_esmf /* [fnc] Regrid using ESMF library */
   int lat_out_id; /* [id] Variable ID for latitude  */
   int dmn_id_lat; /* [id] Dimension ID */
   int dmn_id_lon; /* [id] Dimension ID */
-  (void)nco_def_dim(out_id,lat_nm_in,bnd_upr_dst[crd_idx_f_0bs_lat_dst],&dmn_id_lat);
-  (void)nco_def_dim(out_id,lon_nm_in,bnd_upr_dst[crd_idx_f_0bs_lon_dst],&dmn_id_lon);
+  char *lat_nm_out=lat_nm_in;
+  char *lon_nm_out=lon_nm_in;
+  (void)nco_def_dim(out_id,lat_nm_out,bnd_upr_dst[crd_idx_f_0bs_lat_dst],&dmn_id_lat);
+  (void)nco_def_dim(out_id,lon_nm_out,bnd_upr_dst[crd_idx_f_0bs_lon_dst],&dmn_id_lon);
   int dmn_ids_out[2]; /* [id] Dimension IDs array for output variable */
   long dmn_srt_out[2];
   long dmn_cnt_out[2];
   dmn_ids_out[crd_idx_c_0bs_lat_dst]=dmn_id_lat;
   dmn_ids_out[crd_idx_c_0bs_lon_dst]=dmn_id_lon;
-  (void)nco_def_var(out_id,lon_nm_in,var_typ_out,1,&dmn_id_lon,&lon_out_id);
-  (void)nco_def_var(out_id,lat_nm_in,var_typ_out,1,&dmn_id_lat,&lat_out_id);
-  (void)nco_def_var(out_id,rgr_nfo->var_nm,var_typ_out,2,dmn_ids_out,&var_out_id);
+  (void)nco_def_var(out_id,lon_nm_out,crd_typ_out,(int)1,&dmn_id_lon,&lon_out_id);
+  (void)nco_def_var(out_id,lat_nm_out,crd_typ_out,(int)1,&dmn_id_lat,&lat_out_id);
+  (void)nco_def_var(out_id,rgr->var_nm,var_typ_out,(int)2,dmn_ids_out,&var_out_id);
   (void)nco_enddef(out_id);
   dmn_srt_out[crd_idx_c_0bs_lat_dst]=0L;
   dmn_srt_out[crd_idx_c_0bs_lon_dst]=0L;
   dmn_cnt_out[crd_idx_c_0bs_lat_dst]=bnd_upr_dst[crd_idx_f_0bs_lat_dst];
   dmn_cnt_out[crd_idx_c_0bs_lon_dst]=bnd_upr_dst[crd_idx_f_0bs_lon_dst];
-  (void)nco_put_vara(out_id,lat_out_id,dmn_srt_out,dmn_cnt_out,lat_out,var_typ_out);
-  (void)nco_put_vara(out_id,lon_out_id,dmn_srt_out,dmn_cnt_out,lon_out,var_typ_out);
+  (void)nco_put_vara(out_id,lat_out_id,dmn_srt_out,dmn_cnt_out,lat_out,crd_typ_out);
+  (void)nco_put_vara(out_id,lon_out_id,dmn_srt_out,dmn_cnt_out,lon_out,crd_typ_out);
   (void)nco_put_vara(out_id,var_out_id,dmn_srt_out,dmn_cnt_out,fld_dst_ptr,var_typ_out);
 
+  /* Close output file and move it from temporary to permanent location */
+  (void)nco_fl_out_cls(rgr->fl_out,rgr->fl_out_tmp,out_id);
+
 rgr_cln:
   if(rcd_esmf != ESMF_SUCCESS){
     /* ESMF return codes are enumerated in ESMC_ReturnCodes.h and ESMC_LogErr.h
diff --git a/src/nco/nco_rgr.h b/src/nco/nco_rgr.h
index 588cfb9..9e43236 100644
--- a/src/nco/nco_rgr.h
+++ b/src/nco/nco_rgr.h
@@ -14,6 +14,8 @@
 #define NCO_RGR_H
 
 /* Standard header files */
+#include <limits.h> /* INT_MAX, LONG_MAX */
+#include <math.h> /* sin cos cos sin 3.14159 */
 #include <stdio.h> /* stderr, FILE, NULL, printf */
 #include <stdlib.h> /* atof, atoi, malloc, getopt */
 
@@ -27,12 +29,18 @@
 /* Personal headers */
 #include "nco.h" /* netCDF Operator (NCO) definitions */
 #include "nco_mmr.h" /* Memory management */
+#include "nco_omp.h" /* OpenMP utilities */
 #include "nco_sng_utl.h" /* String utilities */
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
+/* WIN32 math.h does not define M_PI, needed for dgr2rdn and rdn2dgr */
+#ifndef M_PI
+# define M_PI		3.14159265358979323846
+#endif /* M_PI */
+
   typedef enum nco_rgr_cmd_typ_enm{ /* [enm] Tempest remap type enum */
     nco_rgr_AAA_nil=0,
     nco_rgr_ApplyOfflineMap,
@@ -52,9 +60,24 @@ extern "C" {
   typedef enum nco_rgr_mpf_typ_enm{ /* [enm] Mapfile type enum */
     nco_rgr_mpf_nil=0,
     nco_rgr_mpf_SCRIP,
-    nco_rgr_mpf_ESMF
+    nco_rgr_mpf_ESMF,
   } nco_rgr_mpf_typ_enm;
 
+  typedef enum nco_rgr_grd_typ_enm{ /* [enm] Regrid type enum */
+    nco_rgr_grd_nil=0,
+    nco_rgr_grd_1D_to_1D,
+    nco_rgr_grd_1D_to_2D,
+    nco_rgr_grd_2D_to_1D,
+    nco_rgr_grd_2D_to_2D,
+  } nco_rgr_grd_typ_enm;
+
+  typedef enum nco_grd_2D_typ_enm{ /* [enm] Two-dimensional grid-type enum */
+    nco_grd_2D_nil=0,
+    nco_grd_2D_gss, /* Gaussian latitudes used by global spectral models: CCM 1-3, CAM 1-3, LSM, MATCH, UCICTM */
+    nco_grd_2D_ngl_eqi_pol, /* Equi-angle grid including poles, the FV scalar grid (lat[0]=-90): CAM FV, GEOS-CHEM, UCICTM, UKMO */
+    nco_grd_2D_ngl_eqi_fst, /* Equi-angle offset grid, FV staggered velocity grid (lat[0]=-89.X)): CIESIN/SEDAC, IGBP-DIS, TOMS AAI */
+  } nco_grd_2D_typ_enm;
+
   /* ESMF: The normalization attribute describes how the conservative weights are calculated, currently this is always set to "destarea" because this is the only option which we currently support. The setting "destarea" means that the conservative weights are calculated by dividing the area of the intersection of the source and destination cells by the area of the destination cell. This is set even when the weights are not conservative in which case it can be ignored. */
   typedef enum nco_rgr_nrm_typ_enm{ /* [enm] Normalization type enum */
     nco_rgr_nrm_nil=0,
@@ -87,15 +110,28 @@ extern "C" {
     char *dest_grid; /* [sng] Destination grid */
   } nco_map_sct;
   
+  void
+  nco_bsl_zro /*  Return Bessel function zeros */
+  (const int bsl_zro_nbr, /* O [nbr] Order of Bessel function */
+   double * const bsl_zro); /* O [frc] Bessel zero */
+  
+  void
+  nco_lat_wgt_gss /* [fnc] Compute and return sine of Gaussian latitudes and their weights */
+  (const int lat_nbr, /* I [nbr] Latitude number */
+   double * const lat_sin, /* O [frc] Sine of latitudes */
+   double * const wgt_Gss); /* O [frc] Gaussian weights */
+
   int /* O [enm] Return code */
   nco_rgr_map /* [fnc] Regrid using external weights */
-  (rgr_sct * const rgr_nfo); /* I/O [sct] Regridding structure */
+  (rgr_sct * const rgr_nfo, /* I/O [sct] Regridding structure */
+   trv_tbl_sct * const trv_tbl); /* I/O [sct] Traversal Table */
 
   int /* O [enm] Return code */
   nco_rgr_ctl /* [fnc] Control regridding logic */
-  (rgr_sct * const rgr_nfo); /* I/O [sct] Regridding structure */
+  (rgr_sct * const rgr_nfo, /* I/O [sct] Regridding structure */
+   trv_tbl_sct * const trv_tbl); /* I/O [sct] Traversal Table */
 
-  int /* O [enm] Return code */
+  rgr_sct * /* O [sct] Regridding structure */
   nco_rgr_ini /* [fnc] Initialize regridding structure */
   (const int in_id, /* I [id] Input netCDF file ID */
    char **rgr_arg, /* [sng] Regridding arguments */
@@ -106,16 +142,24 @@ extern "C" {
    char * const rgr_grd_dst, /* I [sng] File containing destination grid */
    char * const rgr_map, /* I [sng] File containing mapping weights from source to destination grid */
    char * const rgr_var, /* I [sng] Variable for special regridding treatment */
-   rgr_sct * const rgr_nfo); /* O [sct] Regridding structure */
+   const double wgt_vld_thr); /* I [frc] Weight threshold for valid destination value */
     
-  void
+  rgr_sct * /* O [sct] Pointer to free'd regridding structure */
   nco_rgr_free /* [fnc] Deallocate regridding structure */
-  (rgr_sct * const rgr_nfo); /* I/O [sct] Regridding structure */
+  (rgr_sct *rgr_nfo); /* I/O [sct] Regridding structure */
 
   int /* O [enm] Return code */
   nco_rgr_tps /* [fnc] Regrid using Tempest library */
   (rgr_sct * const rgr_nfo); /* I/O [sct] Regridding structure */
 
+  const char * /* O [sng] String describing two-dimensional grid-type */
+  nco_grd_2D_sng /* [fnc] Convert two-dimensional grid-type enum to string */
+  (const nco_grd_2D_typ_enm nco_grd_2D_typ); /* I [enm] Two-dimensional grid-type enum */
+
+  const char * /* O [sng] String describing grid conversion */
+  nco_rgr_grd_sng /* [fnc] Convert grid conversion enum to string */
+  (const nco_rgr_grd_typ_enm nco_rgr_grd_typ); /* I [enm] Grid conversion enum */
+
   const char * /* O [sng] String describing regridding method */
   nco_rgr_mth_sng /* [fnc] Convert regridding method enum to string */
   (const nco_rgr_mth_typ_enm nco_rgr_mth_typ); /* I [enm] Regridding method enum */
diff --git a/src/nco/nco_rth_utl.c b/src/nco/nco_rth_utl.c
index 75c3b9b..87d3b2d 100644
--- a/src/nco/nco_rth_utl.c
+++ b/src/nco/nco_rth_utl.c
@@ -329,7 +329,7 @@ vec_set /* [fnc] Fill every value of first operand with value of second operand
   (void)cast_void_nctype(type,&op1);
   switch(type){
   case NC_FLOAT:
-    for(idx=0;idx<sz;idx++) op1.fp[idx]=op2;
+    for(idx=0;idx<sz;idx++) op1.fp[idx]=(float)op2;
     break;
   case NC_DOUBLE:
     for(idx=0;idx<sz;idx++) op1.dp[idx]=op2;
diff --git a/src/nco/nco_sld.c b/src/nco/nco_sld.c
index 3ddd82d..ce4c684 100644
--- a/src/nco/nco_sld.c
+++ b/src/nco/nco_sld.c
@@ -39,7 +39,7 @@ nco_scrip_read /* [fnc] Read, parse, and print contents of SCRIP file */
       fclose(fp_scrip);
       return NCO_ERR;
     } /* endif */
-    kvm_scrip[idx]=nco_sng2kvm(sng_line,kvm_scrip[idx]);
+    kvm_scrip[idx]=nco_sng2kvm(sng_line);
     if(!kvm_scrip[idx].key){
       fclose(fp_scrip);
       return NCO_ERR;
diff --git a/src/nco/nco_sng_utl.c b/src/nco/nco_sng_utl.c
index c6cdd7d..0abbdc2 100644
--- a/src/nco/nco_sng_utl.c
+++ b/src/nco/nco_sng_utl.c
@@ -603,16 +603,15 @@ sng_trm_trl_zro /* [fnc] Trim zeros trailing decimal point and preceding exponen
 
 kvm_sct /* O [sct] Key-value pair */
 nco_sng2kvm /* [fnc] Parse string into key-value pair */
-(char *sng, /* I [sng] String to parse, including "=" */
- kvm_sct kvm) /* O [sct] Key-value pair */
+(char *sng) /* I [sng] String to parse, including "=" */
 {
   /* Purpose: Convert string separated by single delimiter into two strings
      Routine converts argument "--ppc key1,key2,...,keyN=val" into kvm.key="key1,key2,...keyN" and kvm.val=val
      e.g., routine converts argument "--ppc one,two=3" into kvm.key="one,two" and kvm.val=3 */
   char *tkn_sng;
   const char dlm[]="="; /* [sng] Delimiter */
-  
   int arg_idx=0; /* [nbr] */
+  kvm_sct kvm;
 
   /* NB: Replace strtok() by strsep()? strtok() does not handle consecutive delimiters well */
   tkn_sng=strtok(sng,dlm);
@@ -653,20 +652,20 @@ nco_sng_strip /* [fnc] Strip leading and trailing white space */
   return sng;
 } /* end nco_sng_strip() */
 
-void
-nco_kvm_free /* [fnc] Relinquish dynamic memory from list of kvm structures */
-(kvm_sct *kvm) /* I/O [sct] List of kvm structures */
+kvm_sct * /* O [sct] Pointer to free'd kvm list */
+nco_kvm_lst_free /* [fnc] Relinquish dynamic memory from list of kvm structures */
+(kvm_sct *kvm, /* I/O [sct] List of kvm structures */
+ const int kvm_nbr) /* I [nbr] Number of kvm structures */
 {
   /* Purpose: Relinquish dynamic memory from list of kvm structures
      End of list is indicated by NULL in key slot */
-  int idx=0;
-  while(kvm[idx].key){
-    kvm[idx].key=(char *)nco_free(kvm[idx].key);
-    kvm[idx].val=(char *)nco_free(kvm[idx].val);
-    idx++;
-  } /* end while */
-  kvm=(kvm_sct *)nco_free(kvm);
-} /* end nco_kvm_free() */
+  for(int kvm_idx=0;kvm_idx<kvm_nbr;kvm_idx++){
+    kvm[kvm_idx].key=(char *)nco_free(kvm[kvm_idx].key);
+    kvm[kvm_idx].val=(char *)nco_free(kvm[kvm_idx].val);
+  } /* end for */
+  if(kvm) kvm=(kvm_sct *)nco_free(kvm);
+  return kvm;
+} /* end nco_kvm_lst_free() */
 
 void
 nco_kvm_prn(kvm_sct kvm)
diff --git a/src/nco/nco_sng_utl.h b/src/nco/nco_sng_utl.h
index 08e3e43..fa5fd79 100644
--- a/src/nco/nco_sng_utl.h
+++ b/src/nco/nco_sng_utl.h
@@ -127,16 +127,16 @@ extern "C" {
   
   kvm_sct /* O [sct] Key-value pair */
   nco_sng2kvm /* [fnc] Parse string into key-value pair */
-  (char *sng, /* I [sng] String to parse, including "=" */
-   kvm_sct kvm); /* O [sct] Key-value pair */
+  (char *sng); /* I [sng] String to parse, including "=" */
   
   char * /* O [sng] Stripped-string */
   nco_sng_strip /* [fnc] Strip leading and trailing white space */
   (char *sng); /* I/O [sng] String to strip */
   
-  void
-  nco_kvm_free /* [fnc] Relinquish dynamic memory from list of kvm structures */
-  (kvm_sct *kvm); /* I/O [sct] List of kvm structures */
+  kvm_sct * /* O [sct] Pointer to free'd kvm list */
+  nco_kvm_lst_free /* [fnc] Relinquish dynamic memory from list of kvm structures */
+  (kvm_sct *kvm, /* I/O [sct] List of kvm structures */
+   const int kvm_nbr); /* I [nbr] Number of kvm structures */
   
   void
   nco_kvm_prn /* [fnc] Print kvm contents */
diff --git a/src/nco/nco_var_avg.c b/src/nco/nco_var_avg.c
index 8dfb558..b8d765d 100644
--- a/src/nco/nco_var_avg.c
+++ b/src/nco/nco_var_avg.c
@@ -132,7 +132,7 @@ nco_var_avg /* [fnc] Reduce given variable over specified dimensions */
   dmn_fix=(dmn_sct **)nco_realloc(dmn_fix,dmn_rdd_nbr*sizeof(dmn_sct *));
   dmn_avg=(dmn_sct **)nco_realloc(dmn_avg,dmn_avg_nbr*sizeof(dmn_sct *));
 
-  /* Get rid of averaged dimensions */
+  /* Eliminate averaged dimensions */
   fix->nbr_dim=dmn_rdd_nbr;
 
   avg_sz=1L;
@@ -354,7 +354,7 @@ nco_var_avg /* [fnc] Reduce given variable over specified dimensions */
     /* Simplest way to retain degenerate dimensions is average over them,
        then insert degenerate dimensions back into list at end */
 
-    /* Get rid of averaged dimensions */
+    /* Eliminate averaged dimensions */
     fix->nbr_dim=dmn_rdd_nbr;
     if(var->is_rec_var) fix->is_rec_var=True;
     fix->is_crd_var=var->is_crd_var;
diff --git a/src/nco/nco_var_lst.c b/src/nco/nco_var_lst.c
index 8fbad7d..1e32852 100644
--- a/src/nco/nco_var_lst.c
+++ b/src/nco/nco_var_lst.c
@@ -886,7 +886,7 @@ nco_var_lst_dvd /* [fnc] Divide input lists into output lists */
   nco_prg_id=nco_prg_id_get(); /* Program key */
 
   /* Allocate space for too many structures first then realloc() appropriately
-  It is calling function's responsibility to free() this memory */
+     It is calling function's responsibility to free() this memory */
   var_fix=(var_sct **)nco_malloc(NC_MAX_VARS*sizeof(var_sct *));
   var_fix_out=(var_sct **)nco_malloc(NC_MAX_VARS*sizeof(var_sct *));
   var_prc=(var_sct **)nco_malloc(NC_MAX_VARS*sizeof(var_sct *));
@@ -906,7 +906,9 @@ nco_var_lst_dvd /* [fnc] Divide input lists into output lists */
 
     var_nm=var[idx]->nm;
     var_typ=var[idx]->type;
-    /* Until 20131005, NCO default was to consider NC_BYTE and NC_UBYTE as funky, too */
+    /* Until 20131005, NCO default was to consider NC_BYTE and NC_UBYTE as funky, too
+       NB: Unfortunately, ncra and ncwa must process funky variables that contain averaging dimensions
+       Otherwise, a new dummy dimension would be required to store the uncollapsed output */
     if((var_typ == NC_CHAR) || (var_typ == NC_STRING)) var_typ_fnk=True; else var_typ_fnk=False;
 
     /* Many operators should not process coordinate variables, or auxiliary coordinate variables (lat, lon, time, latixy, longxy, ...) and bounds (lat_bnds, lon_bnds, ...)
@@ -949,13 +951,12 @@ nco_var_lst_dvd /* [fnc] Divide input lists into output lists */
       if(!var[idx]->is_rec_var) var_op_typ[idx]=fix_typ;
       break;
     case ncge:
-      /* Obtain variable GTT object using full variable name */
       var_trv=trv_tbl_var_nm_fll(var[idx]->nm_fll,trv_tbl);
       /* If variable is template, mark as processed */
       if(var_trv->flg_nsm_tpl && var_trv->nco_typ == nco_obj_typ_var){
-        assert(var_trv->flg_nsm_mbr == True);
+        assert(var_trv->flg_nsm_mbr);
         var_op_typ[idx]=prc_typ;
-      }
+      } /* endif */
       break;
     case ncrcat:
       if(!var[idx]->is_rec_var) var_op_typ[idx]=fix_typ;
@@ -1010,13 +1011,9 @@ nco_var_lst_dvd /* [fnc] Divide input lists into output lists */
       if(var[idx]->sz == 0L) var_op_typ[idx]=fix_typ;
 
     if(CNV_CCM_CCSM_CF){
-
       nco_bool var_is_fix;  /* [fnc] Variable should be treated as a fixed variable */
-
       var_is_fix=nco_var_is_fix(var_nm,nco_prg_id,nco_pck_plc);  
-
-      if (var_is_fix) var_op_typ[idx]=fix_typ;
-
+      if(var_is_fix) var_op_typ[idx]=fix_typ;
     } /* end if CNV_CCM_CCSM_CF */
 
     /* Warn about any expected weird behavior */
@@ -1085,7 +1082,7 @@ nco_var_lst_dvd /* [fnc] Divide input lists into output lists */
       (void)fprintf(stdout,"%s: HINT Extraction list must contain a record variable which to concatenate. A record variable is a variable defined with a record dimension. Often the record dimension, aka unlimited dimension, refers to time. For more information on creating record dimensions within existing datasets, see http://nco.sf.net/nco.html#mk_rec_dmn\n",nco_prg_nm_get());
       break;
     case ncwa:
-      (void)fprintf(stdout,"%s: HINT Extraction list must contain a variable that contains an averaging dimension\n",nco_prg_nm_get());
+      (void)fprintf(stdout,"%s: HINT Extraction list must contain a non-character variable with an averaging dimension\n",nco_prg_nm_get());
       break;
     default: nco_dfl_case_prg_id_err(); break;
     } /* end switch */
@@ -1275,32 +1272,32 @@ nco_var_is_fix                               /* [fnc] Variable should be treated
   /* NB: all !strcmp()'s except "msk_" which uses strstr() */
   if(is_sz_rnk_prv_rth_opr && (!strcmp(var_nm,"hyam") || !strcmp(var_nm,"hybm") || !strcmp(var_nm,"hyai") || !strcmp(var_nm,"hybi") || !strcmp(var_nm,"gw") || !strcmp(var_nm,"lon_bnds") || !strcmp(var_nm,"lat_bnds") || !strcmp(var_nm,"area") || !strcmp(var_nm,"ORO") || !strcmp(var_nm,"date") || !strcmp(var_nm,"datesec") || (strstr(var_nm,"msk_") == var_nm))) var_is_fix=True;
   /* Known "multi-dimensional coordinates" in CCSM-like model output:
-  lat, lon, lev are normally 1-D coordinates
-  Known exceptions:
-  lat and lon are "2-D coordinates" in NARCCAP output
-  NARCCAP specifies lat and lon in "coordinates" attribute of 2-D fields
-  latixy and longxy are "2-D coordinates" in CLM output
-  CLM does not specify latixy and longxy in "coordinates" attribute of any fields
-  NARCCAP output gives all "coordinate-like" fields an "axis" attribute
-  This includes the record coordinate (i.e., "time") which both ncra and ncwa _should_ process
-  CLM does not give an "axis" attribute to any fields
-  One method of chasing down all "coordinate-like" fields is to look
-  for the field name in the "coordinates" attribute of any variable.
-  However, this will miss (false-negative) the case when no variables 
-  use an N-D coordinate-like variable as a coordinate. 
-  And this may hit (false-positive) the record coordinate (often "time")
-  which should be averaged by ncra, though perhaps not by nces.
-  "coordinate-like" variables that should be "fixed", and not
-  differenced, interpolated, or ensemble-averaged, include those 
-  satisfying these conditions:
-  0. Traditional coordinate (1-D variable same name as its dimension)
-  1. Present in a "coordinates" attribute (except "time" for ncra)
-  2. Present in a "bounds" attribute (except "time_bnds" for ncra)
-  3. Contain an "axis" attribute (except "time") fxm not done yet
-  4. Found in empirical list of variables
-  NB: In the above algorithm discussion, "time" is my shorthand 
-  for "the record variable, if any" */
-
+     lat, lon, lev are normally 1-D coordinates
+     Known exceptions:
+     lat and lon are "2-D coordinates" in NARCCAP output
+     NARCCAP specifies lat and lon in "coordinates" attribute of 2-D fields
+     latixy and longxy are "2-D coordinates" in CLM output
+     CLM does not specify latixy and longxy in "coordinates" attribute of any fields
+     NARCCAP output gives all "coordinate-like" fields an "axis" attribute
+     This includes the record coordinate (i.e., "time") which both ncra and ncwa _should_ process
+     CLM does not give an "axis" attribute to any fields
+     One method of chasing down all "coordinate-like" fields is to look
+     for the field name in the "coordinates" attribute of any variable.
+     However, this will miss (false-negative) the case when no variables 
+     use an N-D coordinate-like variable as a coordinate. 
+     And this may hit (false-positive) the record coordinate (often "time")
+     which should be averaged by ncra, though perhaps not by nces.
+     "coordinate-like" variables that should be "fixed", and not
+     differenced, interpolated, or ensemble-averaged, include those 
+     satisfying these conditions:
+     0. Traditional coordinate (1-D variable same name as its dimension)
+     1. Present in a "coordinates" attribute (except "time" for ncra)
+     2. Present in a "bounds" attribute (except "time_bnds" for ncra)
+     3. Contain an "axis" attribute (except "time") fxm not done yet
+     4. Found in empirical list of variables
+     NB: In the above algorithm discussion, "time" is my shorthand 
+     for "the record variable, if any" */
+  
   /* Conditions #1 and #2 are already implemented above in the case() statement */
   /* Check condition #4 above: */
   if(is_sz_rnk_prv_rth_opr && (!strcmp(var_nm,"lat") || !strcmp(var_nm,"lon") || !strcmp(var_nm,"lev") || !strcmp(var_nm,"longxy") || !strcmp(var_nm,"latixy") )) var_is_fix=True;
diff --git a/src/nco/nco_var_rth.c b/src/nco/nco_var_rth.c
index 788082c..7f0ba79 100644
--- a/src/nco/nco_var_rth.c
+++ b/src/nco/nco_var_rth.c
@@ -105,376 +105,6 @@ nco_var_abs /* [fnc] Replace op1 values by their absolute values */
 } /* end nco_var_abs() */
 
 void
-nco_var_around /* [fnc] Replace op1 values by their values rounded to decimal precision prc */
-(const int ppc, /* I [nbr] Precision-preserving compression, i.e., number of total or decimal significant digits */
- const nc_type type, /* I [enm] netCDF type of operand */
- const long sz, /* I [nbr] Size (in elements) of operand */
- const int has_mss_val, /* I [flg] Flag for missing values */
- ptr_unn mss_val, /* I [val] Value of missing value */
- ptr_unn op1) /* I/O [val] Values of first operand */
-{
-  /* Threads: Routine is thread safe and calls no unsafe routines */
-
-  /* Purpose: Replace op1 values by their values rounded to decimal precision ppc
-     Similar to numpy.around() function, hence the name around()
-     Based on implementation by Jeff Whitaker for netcdf4-python described here:
-     http://netcdf4-python.googlecode.com/svn/trunk/docs/netCDF4-module.html
-     which invokes the numpy.around() function documented here:
-     http://docs.scipy.org/doc/numpy/reference/generated/numpy.around.html#numpy.around
-     A practical discussion of rounding is at
-     http://stackoverflow.com/questions/20388071/what-are-the-under-the-hood-differences-between-round-and-numpy-round
-     This mentions the () NumPy source code:
-     https://github.com/numpy/numpy/blob/7b2f20b406d27364c812f7a81a9c901afbd3600c/numpy/core/src/multiarray/calculation.c#L588
-
-     Manually determine scale:
-     ncap2 -O -v -s 'ppc=2;ppc_abs=abs(ppc);bit_nbr_xct=ppc_abs*ln(10.)/ln(2.);bit_nbr_int=ceil(bit_nbr_xct);scale=pow(2.0,bit_nbr_int);' ~/nco/data/in.nc ~/foo.nc 
-     ncks -H ~/foo.nc
-
-     Test full algorithm:
-     ncks -4 -O -C -v ppc_dbl,ppc_big --ppc ppc_dbl=3 --ppc ppc_big=-2 ~/nco/data/in.nc ~/foo.nc
-
-     Compare to Jeff Whitaker's nc3tonc4 results:
-     nc3tonc4 -o --quantize=ppc_dbl=3,ppc_big=-2 ~/nco/data/in.nc ~/foo.nc
-     ncks -H -C -v ppc_dbl,ppc_big ~/foo.nc */
-  
-  /* Rounding is currently defined as op1:=around(op1,ppc) */  
-  
-  /* Use constants defined in math.h */
-  const double bit_per_dcm_dgt_prc=M_LN10/M_LN2; /* 3.32 [frc] Bits per decimal digit of precision */
-
-  double scale; /* [frc] Number by which to scale data to achieve rounding */
-  float scalef; /* [frc] Number by which to scale data to achieve rounding */
-
-  int bit_nbr; /* [nbr] Number of bits required to exceed pow(10,-ppc) */
-  int ppc_abs; /* [nbr] Absolute value of precision */
-
-  long idx;
-  
-  /* Only numeric types can be quantized */
-  if(type == NC_CHAR || type == NC_BYTE || type == NC_UBYTE || type == NC_STRING) return;
-
-  ppc_abs=abs(ppc);
-  assert(ppc_abs <= 16);
-  switch(ppc_abs){
-  case 0:
-    bit_nbr=0;
-    scale=1.0;
-    break;
-  case 1:
-    bit_nbr=4;
-    scale=16.0;
-    break;
-  case 2:
-    bit_nbr=7;
-    scale=128.0;
-    break;
-  case 3:
-    bit_nbr=10;
-    scale=1024.0;
-    break;
-  case 4:
-    bit_nbr=14;
-    scale=16384.0;
-    break;
-  case 5:
-    bit_nbr=17;
-    scale=131072.0;
-    break;
-  case 6:
-    bit_nbr=20;
-    scale=1048576.0;
-    break;
-  default:
-    bit_nbr=(int)ceil(ppc_abs*bit_per_dcm_dgt_prc);
-    scale=pow(2.0,bit_nbr);
-    break;
-  } /* end switch */   
-  if(ppc < 0) scale=1.0/scale;
-
-  if(nco_dbg_lvl_get() == nco_dbg_sbr) (void)fprintf(stdout,"%s: INFO nco_var_around() reports ppc = %d, bit_nbr= %d, scale = %g\n",nco_prg_nm_get(),ppc,bit_nbr,scale);
-
-  /* Typecast pointer to values before access */
-  (void)cast_void_nctype(type,&op1);
-  if(has_mss_val) (void)cast_void_nctype(type,&mss_val);
-  
-  scalef=(float)scale;
-  switch(type){
-  case NC_FLOAT: 
-    /* By default do float arithmetic in double precision before converting back to float
-       Allow --flt to override
-       NB: Use rint() not lrint()
-       If ignoring this advice, be sure to bound calls to lrint(), e.g., 
-       rint_arg=scale*op1.fp[idx];
-       if(rint_arg > LONG_MIN && rint_arg < LONG_MAX) op1.fp[idx]=(float)lrint(scale*op1.fp[idx])/scale; */
-    if(!has_mss_val){
-      if(nco_rth_cnv_get() == nco_rth_flt_flt)
-	for(idx=0L;idx<sz;idx++) op1.fp[idx]=rintf(scalef*op1.fp[idx])/scalef;
-      else
-	for(idx=0L;idx<sz;idx++) op1.fp[idx]=(float)(rint(scale*op1.fp[idx])/scale); /* Coerce to avoid implicit conversions warning */
-    }else{
-      const float mss_val_flt=*mss_val.fp;
-      if(nco_rth_cnv_get() == nco_rth_flt_flt){
-	for(idx=0;idx<sz;idx++)
-	  if(op1.fp[idx] != mss_val_flt)
-	    op1.fp[idx]=rintf(scalef*op1.fp[idx])/scalef;
-      }else{
-	for(idx=0;idx<sz;idx++)
-	  if(op1.fp[idx] != mss_val_flt)
-	    op1.fp[idx]=(float)(rint(scale*op1.fp[idx])/scale); /* Coerce to avoid implicit conversions warning */
-      } /* end else */
-    } /* end else */
-    break;
-  case NC_DOUBLE: 
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.dp[idx]=rint(scale*op1.dp[idx])/scale;
-    }else{
-      const double mss_val_dbl=*mss_val.dp;
-      for(idx=0;idx<sz;idx++)
-	if(op1.dp[idx] != mss_val_dbl) op1.dp[idx]=rint(scale*op1.dp[idx])/scale;
-    } /* end else */
-    break;
-  case NC_SHORT:
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.sp[idx]=(short int)lrint(scale*op1.sp[idx])/scale;
-    }else{
-      const nco_int mss_val_short=*mss_val.sp;
-      for(idx=0;idx<sz;idx++)
-	if(op1.sp[idx] != mss_val_short) op1.sp[idx]=(short int)lrint(scale*op1.sp[idx])/scale;
-    } /* end else */
-    break;
-  case NC_USHORT:
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.usp[idx]=(unsigned short int)lrint(scale*op1.usp[idx])/scale;
-    }else{
-      const nco_ushort mss_val_ushort=*mss_val.usp;
-      for(idx=0;idx<sz;idx++)
-	if(op1.usp[idx] != mss_val_ushort) op1.usp[idx]=(unsigned short int)lrint(scale*op1.usp[idx])/scale;
-    } /* end else */
-    break;
-  case NC_INT:
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.ip[idx]=lrint(scale*op1.ip[idx])/scale;
-    }else{
-      const nco_int mss_val_int=*mss_val.ip;
-      for(idx=0;idx<sz;idx++)
-	if(op1.ip[idx] != mss_val_int) op1.ip[idx]=lrint(scale*op1.ip[idx])/scale;
-    } /* end else */
-    break;
-  case NC_UINT:
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.uip[idx]=(unsigned int)lrint(scale*op1.uip[idx])/scale;
-    }else{
-      const nco_uint mss_val_uint=*mss_val.uip;
-      for(idx=0;idx<sz;idx++)
-	if(op1.uip[idx] != mss_val_uint) op1.uip[idx]=(unsigned int)lrint(scale*op1.uip[idx])/scale;
-    } /* end else */
-    break;
-  case NC_INT64:
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.i64p[idx]=lrint(scale*op1.i64p[idx])/scale;
-    }else{
-      const nco_int64 mss_val_int64=*mss_val.i64p;
-      for(idx=0;idx<sz;idx++)
-	if(op1.i64p[idx] != mss_val_int64) op1.i64p[idx]=lrint(scale*op1.i64p[idx])/scale;
-    } /* end else */
-    break;
-  case NC_UINT64:
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx++) op1.ui64p[idx]=(unsigned long)lrint(scale*op1.ui64p[idx])/scale;
-    }else{
-      const nco_uint64 mss_val_uint64=*mss_val.ui64p;
-      for(idx=0;idx<sz;idx++)
-	if(op1.ui64p[idx] != mss_val_uint64) op1.ui64p[idx]=(unsigned long)lrint(scale*op1.ui64p[idx])/scale;
-    } /* end else */
-    break;
-  case NC_CHAR: /* Do nothing for non-numeric types ...*/
-  case NC_BYTE:
-  case NC_UBYTE:
-  case NC_STRING: break;
-  default: 
-    nco_dfl_case_nc_type_err();
-    break;
-  } /* end switch */
-
-  /* NB: it is not neccessary to un-typecast pointers to values after access 
-     because we have only operated on local copies of them. */
-  
-} /* end nco_var_around() */
-
-void
-nco_var_bitmask /* [fnc] Mask-out insignificant bits of significand */
-(const int nsd, /* I [nbr] Number of significant digits, i.e., arithmetic precision */
- const nc_type type, /* I [enm] netCDF type of operand */
- const long sz, /* I [nbr] Size (in elements) of operand */
- const int has_mss_val, /* I [flg] Flag for missing values */
- ptr_unn mss_val, /* I [val] Value of missing value */
- ptr_unn op1) /* I/O [val] Values of first operand */
-{
-  /* Threads: Routine is thread safe and calls no unsafe routines */
-
-  /* Purpose: Mask-out insignificant bits of op1 values */
-  
-  /* Rounding is currently defined as op1:=bitmask(op1,ppc) */  
-  
-  /* Number of Significant Digits (NSD) algorithm
-     NSD based on absolute precision, i.e., number of digits in significand and in decimal scientific notation
-     DSD based on precision relative to decimal point, i.e., number of digits before/after decimal point
-     DSD is more often used colloquially, e.g., "thermometers measure temperature accurate to 1 degree C" 
-     NSD is more often used scientifically, e.g., "thermometers measure temperature to three significant digits"
-     These statements are both equivalent and describe the same instrument and data
-     If data are stored in C or K then optimal specifications for each algorithm would be DSD=0 and NSD=3
-     However, if data are stored in mK (milli-Kelvin) then optimal specifications would be DSD=-3 and NSD=3
-     In other words, the number of significant digits (NSD) does not depend on the units of storage, but DSD does
-     Hence NSD is more instrinsic and portable than DSD
-     NSD requires only bit-shifting and bit-masking, no floating point math
-     DSD is implemented with rounding techniques that rely on floating point math
-     This makes DSD subject to accompanying overflow and underflow problems when exponent near MAX_EXP/2
-     Thus NSD is faster, more accurate, and less ambiguous than DSD
-     Nevertheless many users think in terms of DSD not NSD
-     
-     Terminology: 
-     Decimal Precision is number of significant digits following decimal point (DSD)
-     Arithmetic Precision is number of significant digits (NSD)
-     "Arithmetic precision can also be defined with reference to a fixed number of decimal places (the number of digits following the decimal point). This second definition is useful in applications where the number of digits in the fractional part has particular importance, but it does not follow the rules of significance arithmetic." -- Wikipedia
-     "A common convention in science and engineering is to express accuracy and/or precision implicitly by means of significant figures. Here, when not explicitly stated, the margin of error is understood to be one-half the value of the last significant place. For instance, a recording of 843.6 m, or 843.0 m, or 800.0 m would imply a margin of 0.05 m (the last significant place is the tenths place), while a recording of 8,436 m would imply a margin of error of 0.5 m (the last significant [...]
-     
-     Test NSD:
-     nc3tonc4 -o --quantize=ppc_big=3,ppc_bgr=3,ppc_flt=3 --quiet=1 ~/nco/data/in.nc ~/foo_n34.nc
-     ncks -D 1 -4 -O -C -v ppc_big,ppc_bgr,ppc_flt --ppc .?=3 ~/nco/data/in.nc ~/foo.nc
-     ncks -C -v ppc_big,ppc_bgr ~/foo.nc
-     ncks -s '%16.12e\n' -C -H -v ppc_big,ppc_bgr ~/foo_n34.nc */
-  
-  /* IEEE single- and double-precision significands have 24 and 53 bits of precision (prc_bnr)
-     Decimal digits of precision (prc_dcm) obtained via prc_dcm=prc_bnr*ln(2)/ln(10) = 7.22 and 15.95, respectively
-     Binary digits of precision (prc_bnr) obtained via prc_bnr=prc_dcm*ln(10)/ln(2) */
-  
-  /* Use constants defined in math.h */
-  const double bit_per_dcm_dgt_prc=M_LN10/M_LN2; /* 3.32 [frc] Bits per decimal digit of precision */
-  
-  /* Preserve at least two explicit bits, plus one implicit bit means three total bits */
-  /* [nbr] Minimum number of explicit significand bits to preserve */
-#define BIT_XPL_NBR_MIN 2
-  const int bit_xpl_nbr_sgn_flt=23; /* [nbr] Bits 0-22 of SP significands are explicit. Bit 23 is implicit. */
-  const int bit_xpl_nbr_sgn_dbl=53; /* [nbr] Bits 0-52 of DP significands are explicit. Bit 53 is implicit. */
-  
-  double prc_bnr_xct; /* [nbr] Binary digits of precision, exact */
-  
-  int bit_xpl_nbr_sgn=int_CEWI; /* [nbr] Number of explicit bits in significand */
-  int bit_xpl_nbr_zro; /* [nbr] Number of explicit bits to zero */
-
-  long idx;
-
-  unsigned int *u32_ptr;
-  unsigned int msk_f32_u32_zro;
-  unsigned int msk_f32_u32_one;
-  unsigned long int *u64_ptr;
-  unsigned long int msk_f64_u64_zro;
-  unsigned long int msk_f64_u64_one;
-  unsigned short prc_bnr_ceil; /* [nbr] Exact binary digits of precision rounded-up */
-  unsigned short prc_bnr_xpl_rqr; /* [nbr] Explicitly represented binary digits required to retain */
-  
-  /* Only floating point types can be quantized */
-  if(type != NC_FLOAT && type != NC_DOUBLE) return;
-
-  /* Disallow unreasonable quantization */
-  assert(nsd > 0);
-  assert(nsd <= 16);
-
-    /* How many bits to preserve? */
-  prc_bnr_xct=nsd*bit_per_dcm_dgt_prc;
-  /* Be conservative, round upwards */
-  prc_bnr_ceil=(unsigned short)ceil(prc_bnr_xct);
-  /* First bit is implicit not explicit but corner cases prevent our taking advantage of this */
-  //prc_bnr_xpl_rqr=prc_bnr_ceil-1;
-  //prc_bnr_xpl_rqr=prc_bnr_ceil;
-  prc_bnr_xpl_rqr=prc_bnr_ceil+1;
-  if(type == NC_DOUBLE) prc_bnr_xpl_rqr++; /* Seems necessary for double-precision ppc=array(1.234567,1.e-6,$dmn) */
-  /* 20150128: Hand-tuning shows we can sacrifice one or two more bits for almost all cases
-     20150205: However, small integers are an exception. In fact they require two more bits, at least for NSD=1.
-     Thus minimum threshold to preserve half of least significant digit (LSD) is prc_bnr_xpl_rqr=prc_bnr_ceil.
-     Decrementing prc_bnr_xpl_rqr by one or two more bits produces maximum errors that exceed half the LSD
-     ncra -4 -O -C --ppc default=1 --ppc one=1 -p ~/nco/data in.nc in.nc ~/foo.nc 
-     ncks -H -v Q.. --cdl ~/foo.nc | m */
-
-  /* 20150126: fxm casting pointers is tricky with this routine. Avoid for now. */
-  /* Typecast pointer to values before access */
-  //(void)cast_void_nctype(type,&op1);
-  //if(has_mss_val) (void)cast_void_nctype(type,&mss_val);
-
-  if(type == NC_FLOAT  && prc_bnr_xpl_rqr >= bit_xpl_nbr_sgn_flt) return;
-  if(type == NC_DOUBLE && prc_bnr_xpl_rqr >= bit_xpl_nbr_sgn_dbl) return;
-
-  switch(type){
-  case NC_FLOAT:
-    bit_xpl_nbr_sgn=bit_xpl_nbr_sgn_flt;
-    bit_xpl_nbr_zro=bit_xpl_nbr_sgn-prc_bnr_xpl_rqr;
-    assert(bit_xpl_nbr_zro <= bit_xpl_nbr_sgn-BIT_XPL_NBR_MIN);
-    u32_ptr=op1.uip;
-    /* Create mask */
-    msk_f32_u32_zro=0u; /* Zero all bits */
-    msk_f32_u32_zro=~msk_f32_u32_zro; /* Turn all bits to ones */
-    /* Left shift zeros into bits to be rounded */
-    msk_f32_u32_zro <<= bit_xpl_nbr_zro;
-    msk_f32_u32_one=~msk_f32_u32_zro;
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx+=2L) u32_ptr[idx]&=msk_f32_u32_zro;
-      for(idx=1L;idx<sz;idx+=2L)
-	if(u32_ptr[idx] != 0U) /* Never quantize upwards floating point values of zero */
-	  u32_ptr[idx]|=msk_f32_u32_one;
-    }else{
-      const float mss_val_flt=*mss_val.fp;
-      for(idx=0L;idx<sz;idx+=2L)
-	if(op1.fp[idx] != mss_val_flt) u32_ptr[idx]&=msk_f32_u32_zro;
-      for(idx=1L;idx<sz;idx+=2L)
-	if(op1.fp[idx] != mss_val_flt && u32_ptr[idx] != 0U) u32_ptr[idx]|=msk_f32_u32_one;
-    } /* end else */
-    break;
-  case NC_DOUBLE:
-    bit_xpl_nbr_sgn=bit_xpl_nbr_sgn_dbl;
-    bit_xpl_nbr_zro=bit_xpl_nbr_sgn-prc_bnr_xpl_rqr;
-    assert(bit_xpl_nbr_zro <= bit_xpl_nbr_sgn-BIT_XPL_NBR_MIN);
-    u64_ptr=(unsigned long int *)op1.ui64p;
-    /* Create mask */
-    msk_f64_u64_zro=0ul; /* Zero all bits */
-    msk_f64_u64_zro=~msk_f64_u64_zro; /* Turn all bits to ones */
-    /* Left shift zeros into bits to be rounded */
-    msk_f64_u64_zro <<= bit_xpl_nbr_zro;
-    msk_f64_u64_one=~msk_f64_u64_zro;
-    if(!has_mss_val){
-      for(idx=0L;idx<sz;idx+=2L) u64_ptr[idx]&=msk_f64_u64_zro;
-      for(idx=1L;idx<sz;idx+=2L)
-	if(u64_ptr[idx] != 0UL) /* Never quantize upwards floating point values of zero */
-	  u64_ptr[idx]|=msk_f64_u64_one;
-    }else{
-      const double mss_val_dbl=*mss_val.dp;
-      for(idx=0L;idx<sz;idx+=2L)
-	if(op1.dp[idx] != mss_val_dbl) u64_ptr[idx]&=msk_f64_u64_zro;
-      for(idx=1L;idx<sz;idx+=2L)
-	if(op1.dp[idx] != mss_val_dbl && u64_ptr[idx] != 0UL) u64_ptr[idx]|=msk_f64_u64_one;
-    } /* end else */
-    break;
-  case NC_INT: /* Do nothing for non-floating point types ...*/
-  case NC_SHORT:
-  case NC_CHAR:
-  case NC_BYTE:
-  case NC_UBYTE:
-  case NC_USHORT:
-  case NC_UINT:
-  case NC_INT64:
-  case NC_UINT64:
-  case NC_STRING: break;
-  default: 
-    nco_dfl_case_nc_type_err();
-    break;
-  } /* end switch */
-  
-  /* 20150126: fxm casting pointers is tricky with this routine. Avoid for now. */
-  /* NB: it is not neccessary to un-typecast pointers to values after access 
-     because we have only operated on local copies of them. */
-
-} /* end nco_var_bitmask() */
-
-void
 nco_var_add /* [fnc] Add first operand to second operand */
 (const nc_type type, /* I [enm] netCDF type of operands */
  const long sz, /* I [nbr] Size (in elements) of operands */
diff --git a/src/nco/nco_var_rth.h b/src/nco/nco_var_rth.h
index f51ac32..7762a13 100644
--- a/src/nco/nco_var_rth.h
+++ b/src/nco/nco_var_rth.h
@@ -54,24 +54,6 @@ extern "C" {
    ptr_unn op1); /* I/O [val] Values of first operand */
   
   void
-  nco_var_around /* [fnc] Replace op1 values by their values rounded to decimal precision prc */
-  (const int prc, /* I [nbr] Precision-preserving compression, i.e., number of total or decimal significant digits */
-   const nc_type type, /* I [enm] netCDF type of operand */
-   const long sz, /* I [nbr] Size (in elements) of operand */
-   const int has_mss_val, /* I [flg] Flag for missing values */
-   ptr_unn mss_val, /* I [val] Value of missing value */
-   ptr_unn op1); /* I/O [val] Values of first operand */
-
-  void
-  nco_var_bitmask /* [fnc] Mask-out insignificant bits of significand */
-  (const int nsd, /* I [nbr] Number of significant digits, i.e., arithmetic precision */
-   const nc_type type, /* I [enm] netCDF type of operand */
-   const long sz, /* I [nbr] Size (in elements) of operand */
-   const int has_mss_val, /* I [flg] Flag for missing values */
-   ptr_unn mss_val, /* I [val] Value of missing value */
-   ptr_unn op1); /* I/O [val] Values of first operand */
-  
-  void
   nco_var_add /* [fnc] Add first operand to second operand */
   (const nc_type type, /* I [type] netCDF type of operands */
    const long sz, /* I [nbr] Size (in elements) of operands */
diff --git a/src/nco/nco_var_utl.c b/src/nco/nco_var_utl.c
index 28bd3a7..f4588af 100644
--- a/src/nco/nco_var_utl.c
+++ b/src/nco/nco_var_utl.c
@@ -112,20 +112,24 @@ nco_cpy_var_val /* [fnc] Copy variable from input to output file, no limits */
       if(var_out.nm) var_out.nm=(char *)nco_free(var_out.nm);
     } /* endif ppc */
   } /* endif True */
-    
+
+  nco_bool flg_xcp; /* [flg] Variable requires exception processing */
+  flg_xcp=nco_is_xcp(var_nm);
+
   /* Get variable */
   if(dmn_nbr == 0){
     nco_get_var1(in_id,var_in_id,0L,void_ptr,var_typ);
     if(flg_ppc){
-      if(flg_nsd) (void)nco_var_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_var_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
+      if(flg_nsd) (void)nco_ppc_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_ppc_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
     } /* !PPC */
     nco_put_var1(out_id,var_out_id,0L,void_ptr,var_typ);
   }else{ /* end if variable is scalar */
     if(var_sz > 0){ /* Allow for zero-size record variables */
       nco_get_vara(in_id,var_in_id,dmn_srt,dmn_cnt,void_ptr,var_typ);
       if(flg_ppc){
-	if(flg_nsd) (void)nco_var_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_var_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
+	if(flg_nsd) (void)nco_ppc_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_ppc_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
       } /* !PPC */
+      if(flg_xcp) nco_xcp_prc(var_nm,var_typ,var_sz,(char *)void_ptr);
       nco_put_vara(out_id,var_out_id,dmn_srt,dmn_cnt,void_ptr,var_typ);
     } /* end if var_sz */
   } /* end if variable is an array */
@@ -444,8 +448,9 @@ nco_cpy_rec_var_val /* [fnc] Copy all record variables, record-by-record, from i
       if(var_sz > 0){ /* Allow for zero-size record variables */
         nco_get_vara(var_lst[var_idx]->grp_id_in,var_in_id,dmn_srt,dmn_cnt,void_ptr,var_typ);
 	if(flg_ppc){
-	  if(flg_nsd) (void)nco_var_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_var_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
+	  if(flg_nsd) (void)nco_ppc_bitmask(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val); else (void)nco_ppc_around(ppc,var_out.type,var_out.sz,var_out.has_mss_val,var_out.mss_val,var_out.val);
 	} /* !PPC */
+	if(nco_is_xcp(var_lst[var_idx]->nm)) nco_xcp_prc(var_lst[var_idx]->nm,var_typ,var_sz,(char *)void_ptr);
         nco_put_vara(var_lst[var_idx]->grp_id_out,var_out_id,dmn_srt,dmn_cnt,void_ptr,var_typ);
       } /* end if var_sz */
 
@@ -1174,16 +1179,16 @@ nco_var_dfn /* [fnc] Define variables and write their attributes to output file
           /* Is dimension allowed in output file? */
           for(idx_ncl=0;idx_ncl<nbr_dmn_ncl;idx_ncl++){
             /* All I can say about this line, is...Yikes! 
-            No, really, it indicates poor program design
-            fxm: TODO nco374: have ncwa re-arrange output metadata prior to nco_var_dfn()
-            Then delete this branch and use straightforward branch of code */
+	       No, really, it indicates poor program design
+	       fxm: TODO nco374: have ncwa re-arrange output metadata prior to nco_var_dfn()
+	       Then delete this branch and use straightforward branch of code */
             if(var[idx]->xrf->dim[dmn_idx]->id == dmn_ncl[idx_ncl]->xrf->id){
               break;
-            }
+            } /* endif */
           } /* end loop over idx_ncl */
           if(idx_ncl != nbr_dmn_ncl){
             dmn_id_vec[dmn_nbr++]=var[idx]->dim[dmn_idx]->id;
-          }
+          } /* endif */
         } /* end loop over dmn_idx */
       }else{ /* ...operator does not change variable rank so handle normally... */
         /* More straightforward definition used by operators besides ncwa */
@@ -1195,9 +1200,9 @@ nco_var_dfn /* [fnc] Define variables and write their attributes to output file
 
       if(nco_dbg_lvl_get() > 3 && nco_prg_id != ncwa){
         /* fxm TODO nco374 diagnostic information fails for ncwa since var[idx]->dim[dmn_idx]->nm
-        contains _wrong name_ when variables will be averaged.
-        ncwa does contain write name information now if retain_degenerate_dimensions 
-        option is in effect, but this is the exception rather than the rule. */
+	   contains _wrong name_ when variables will be averaged.
+	   ncwa does contain write name information now if retain_degenerate_dimensions 
+	   option is in effect, but this is the exception rather than the rule. */
         (void)fprintf(stdout,"%s: DEBUG %s about to define variable %s with %d dimension%s%s",nco_prg_nm_get(),fnc_nm,var[idx]->nm,dmn_nbr,(dmn_nbr == 1) ? "" : "s",(dmn_nbr > 0) ? " (ordinal,output ID): " : "");
         for(dmn_idx=0;dmn_idx<dmn_nbr;dmn_idx++){
           (void)fprintf(stdout,"%s (%d,%s)%s",var[idx]->dim[dmn_idx]->nm,dmn_idx,"unknown",(dmn_idx < dmn_nbr-1) ? ", " : "");
@@ -1238,9 +1243,9 @@ nco_var_dfn /* [fnc] Define variables and write their attributes to output file
 
       if(nco_dbg_lvl_get() > 3 && nco_prg_id != ncwa){
         /* fxm TODO nco374 diagnostic information fails for ncwa since var[idx]->dim[dmn_idx]->nm
-        contains _wrong name_ when variables will be averaged.
-        ncwa does contain write name information now if retain_degenerate_dimensions 
-        option is in effect, but this is the exception rather than the rule. */
+	   contains _wrong name_ when variables will be averaged.
+	   ncwa does contain write name information now if retain_degenerate_dimensions 
+	   option is in effect, but this is the exception rather than the rule. */
         (void)fprintf(stdout,"%s: DEBUG %s defined variable %s with %d dimension%s%s",nco_prg_nm_get(),fnc_nm,var[idx]->nm,dmn_nbr,(dmn_nbr == 1) ? "" : "s",(dmn_nbr > 0) ? " (ordinal,output ID): " : "");
         for(dmn_idx=0;dmn_idx<dmn_nbr;dmn_idx++){
           (void)fprintf(stdout,"%s (%d,%d)%s",var[idx]->dim[dmn_idx]->nm,dmn_idx,dmn_id_vec[dmn_idx],(dmn_idx < dmn_nbr-1) ? ", " : "");
@@ -1256,43 +1261,43 @@ nco_var_dfn /* [fnc] Define variables and write their attributes to output file
     } /* end if variable is already in output file */
 
     /* Copy all attributes except in cases where packing/unpacking is involved
-    0. Variable is unpacked on input, unpacked on output
-    --> Copy all attributes
-    1. Variable is packed on input, is not altered, and remains packed on output
-    --> Copy all attributes
-    2. Variable is packed on input, is unpacked for some reason, and will be unpacked on output
-    --> Copy all attributes except scale_factor and add_offset
-    3. Variable is packed on input, is unpacked for some reason, and will be packed on output (possibly with new packing attributes)
-    --> Copy all attributes, but scale_factor and add_offset must be overwritten later with new values
-    4. Variable is not packed on input, packing is performed, and output is packed
-    --> Copy all attributes, define dummy values for scale_factor and add_offset now, and write those values later, when they are known */
+       0. Variable is unpacked on input, unpacked on output
+       --> Copy all attributes
+       1. Variable is packed on input, is not altered, and remains packed on output
+       --> Copy all attributes
+       2. Variable is packed on input, is unpacked for some reason, and will be unpacked on output
+       --> Copy all attributes except scale_factor and add_offset
+       3. Variable is packed on input, is unpacked for some reason, and will be packed on output (possibly with new packing attributes)
+       --> Copy all attributes, but scale_factor and add_offset must be overwritten later with new values
+       4. Variable is not packed on input, packing is performed, and output is packed
+       --> Copy all attributes, define dummy values for scale_factor and add_offset now, and write those values later, when they are known */
 
     /* Do not copy packing attributes "scale_factor" and "add_offset" 
-    if variable is packed in input file and unpacked in output file 
-    Arithmetic operators calling nco_var_dfn() with fixed variables should leave them fixed
-    Currently ncap calls nco_var_dfn() only for fixed variables, so handle exception with ncap-specific condition */
+       if variable is packed in input file and unpacked in output file 
+       Arithmetic operators calling nco_var_dfn() with fixed variables should leave them fixed
+       Currently ncap calls nco_var_dfn() only for fixed variables, so handle exception with ncap-specific condition */
     /* Copy exising packing attributes, if any, unless... */
     if(nco_is_rth_opr(nco_prg_id) && /* ...operator is arithmetic... */
-      nco_prg_id != ncap && /* ...and is not ncap (hence it must be, e.g., ncra, ncbo)... */
-      !var[idx]->is_fix_var && /* ...and variable is processed (not fixed)... */
-      var[idx]->xrf->pck_dsk) /* ...and variable is packed in input file... */
+       nco_prg_id != ncap && /* ...and is not ncap (hence it must be, e.g., ncra, ncbo)... */
+       !var[idx]->is_fix_var && /* ...and variable is processed (not fixed)... */
+       var[idx]->xrf->pck_dsk) /* ...and variable is packed in input file... */
       PCK_ATT_CPY=False;
-
+    
     /* Do not copy packing attributes when unpacking variables 
-    ncpdq is currently only operator that passes values other than nco_pck_plc_nil */
+       ncpdq is currently only operator that passes values other than nco_pck_plc_nil */
     if(nco_pck_plc == nco_pck_plc_upk) /* ...and variable will be _unpacked_ ... */
       PCK_ATT_CPY=False;
-
+    
     /* Recall that:
-    var      refers to output variable structure
-    var->xrf refers to input  variable structure 
-    ncpdq may pre-define packing attributes below regardless of PCK_ATT_CPY */ 
+       var      refers to output variable structure
+       var->xrf refers to input  variable structure 
+       ncpdq may pre-define packing attributes below regardless of PCK_ATT_CPY */ 
     (void)nco_att_cpy(in_id,out_id,var[idx]->xrf->id,var[idx]->id,PCK_ATT_CPY);
 
     /* Create dummy packing attributes for ncpdq if necessary 
-    Must apply nearly same logic at end of ncpdq when writing final attributes
-    Recall ncap calls ncap_var_write() to define newly packed LHS variables 
-    If variable is not fixed (e.g., coordinate variables)...*/
+       Must apply nearly same logic at end of ncpdq when writing final attributes
+       Recall ncap calls ncap_var_write() to define newly packed LHS variables 
+       If variable is not fixed (e.g., coordinate variables)...*/
     if(!var[idx]->is_fix_var){
       /* ...and operator will attempt to pack some variables... */
       if(nco_pck_plc != nco_pck_plc_nil && nco_pck_plc != nco_pck_plc_upk){ 
@@ -1300,30 +1305,30 @@ nco_var_dfn /* [fnc] Define variables and write their attributes to output file
         if(nco_pck_plc_typ_get(nco_pck_map,var[idx]->typ_upk,(nc_type *)NULL)){
           /* ...and operator will pack this particular variable... */
           if(
-            /* ...either because operator newly packs all variables... */
-            (nco_pck_plc == nco_pck_plc_all_new_att) ||
-            /* ...or because operator newly packs un-packed variables like this one... */
-            (nco_pck_plc == nco_pck_plc_all_xst_att && !var[idx]->pck_ram) ||
-            /* ...or because operator re-packs packed variables like this one... */
-            (nco_pck_plc == nco_pck_plc_xst_new_att && var[idx]->pck_ram)
-            ){
-
-              /* ...then add/overwrite dummy scale_factor and add_offset attributes
-              Overwrite these with correct values once known
-              Adding dummy attributes of maximum possible size (NC_DOUBLE) now 
-              reduces likelihood that netCDF layer will impose file copy 
-              penalties when final attribute values are written later
-              Either add_offset or scale_factor may be removed in nco_pck_val() 
-              if nco_var_pck() packing algorithm did not require utilizing it */ 
-              const char add_fst_sng[]="add_offset"; /* [sng] Unidata standard string for add offset */
-              const char scl_fct_sng[]="scale_factor"; /* [sng] Unidata standard string for scale factor */
-              val_unn zero_unn; /* [frc] Generic container for value 0.0 */
-              var_sct *zero_var; /* [sct] NCO variable for value 0.0 */
-              zero_unn.d=0.0; /* [frc] Generic container for value 0.0 */
-              zero_var=scl_mk_var(zero_unn,typ_out); /* [sct] NCO variable for value 0.0 */
-              (void)nco_put_att(out_id,var[idx]->id,scl_fct_sng,typ_out,1,zero_var->val.vp);
-              (void)nco_put_att(out_id,var[idx]->id,add_fst_sng,typ_out,1,zero_var->val.vp);
-              zero_var=(var_sct *)nco_var_free(zero_var);
+	     /* ...either because operator newly packs all variables... */
+	     (nco_pck_plc == nco_pck_plc_all_new_att) ||
+	     /* ...or because operator newly packs un-packed variables like this one... */
+	     (nco_pck_plc == nco_pck_plc_all_xst_att && !var[idx]->pck_ram) ||
+	     /* ...or because operator re-packs packed variables like this one... */
+	     (nco_pck_plc == nco_pck_plc_xst_new_att && var[idx]->pck_ram)
+	     ){
+	    
+	    /* ...then add/overwrite dummy scale_factor and add_offset attributes
+	       Overwrite these with correct values once known
+	       Adding dummy attributes of maximum possible size (NC_DOUBLE) now 
+	       reduces likelihood that netCDF layer will impose file copy 
+	       penalties when final attribute values are written later
+	       Either add_offset or scale_factor may be removed in nco_pck_val() 
+	       if nco_var_pck() packing algorithm did not require utilizing it */ 
+	    const char add_fst_sng[]="add_offset"; /* [sng] Unidata standard string for add offset */
+	    const char scl_fct_sng[]="scale_factor"; /* [sng] Unidata standard string for scale factor */
+	    val_unn zero_unn; /* [frc] Generic container for value 0.0 */
+	    var_sct *zero_var; /* [sct] NCO variable for value 0.0 */
+	    zero_unn.d=0.0; /* [frc] Generic container for value 0.0 */
+	    zero_var=scl_mk_var(zero_unn,typ_out); /* [sct] NCO variable for value 0.0 */
+	    (void)nco_put_att(out_id,var[idx]->id,scl_fct_sng,typ_out,1,zero_var->val.vp);
+	    (void)nco_put_att(out_id,var[idx]->id,add_fst_sng,typ_out,1,zero_var->val.vp);
+	    zero_var=(var_sct *)nco_var_free(zero_var);
           } /* endif this variable will be packed or re-packed */
         } /* !nco_pck_plc_alw */
       } /* endif nco_pck_plc involves packing */
@@ -1345,7 +1350,7 @@ nco_var_val_cpy /* [fnc] Copy variables data from input to output file */
   int idx;
   int dmn_idx;
   long srd_prd=1L; /* [nbr] Product of strides */
-
+  
   for(idx=0;idx<nbr_var;idx++){
     var[idx]->xrf->val.vp=var[idx]->val.vp=(void *)nco_malloc(var[idx]->sz*nco_typ_lng(var[idx]->type));
     if(var[idx]->nbr_dim == 0){
@@ -1353,10 +1358,10 @@ nco_var_val_cpy /* [fnc] Copy variables data from input to output file */
       nco_put_var1(out_id,var[idx]->xrf->id,var[idx]->xrf->srt,var[idx]->xrf->val.vp,var[idx]->type);
     }else{ /* end if variable is scalar */
       if(var[idx]->sz > 0){ /* Do nothing for zero-size record variables */
-
+	
         /* Is stride > 1? */
         for(dmn_idx=0;dmn_idx<var[idx]->nbr_dim;dmn_idx++) srd_prd*=var[idx]->srd[dmn_idx];
-
+	
         if(srd_prd == 1L){ 
           nco_get_vara(in_id,var[idx]->id,var[idx]->srt,var[idx]->cnt,var[idx]->val.vp,var[idx]->type);
           nco_put_vara(out_id,var[idx]->xrf->id,var[idx]->xrf->srt,var[idx]->xrf->cnt,var[idx]->xrf->val.vp,var[idx]->type);
diff --git a/src/nco/nco_var_utl.h b/src/nco/nco_var_utl.h
index 240721e..251d851 100644
--- a/src/nco/nco_var_utl.h
+++ b/src/nco/nco_var_utl.h
@@ -19,10 +19,10 @@
 
 /* Standard header files */
 #include <assert.h> /* assert() */
+#include <limits.h> /* need LONG_MAX */
 #include <stdio.h> /* stderr, FILE, NULL, printf */
 #include <stdlib.h> /* strtod, strtol, malloc, getopt, exit */
 #include <string.h> /* strcmp() */
-#include <limits.h> /* need LONG_MAX */
 
 /* 3rd party vendors */
 #include <netcdf.h> /* netCDF definitions and C library */
@@ -39,6 +39,7 @@
 #include "nco_mmr.h" /* Memory management */
 #include "nco_mss_val.h" /* Missing value utilities */
 #include "nco_pck.h" /* Packing and unpacking variables */
+#include "nco_ppc.h" /* Precision-Preserving Compression */
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/src/nco/ncpdq.c b/src/nco/ncpdq.c
index e6de8ea..b191e1f 100644
--- a/src/nco/ncpdq.c
+++ b/src/nco/ncpdq.c
@@ -700,11 +700,13 @@ main(int argc,char **argv)
   /* Open output file */
   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
 
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
 
   /* Determine and set new dimensionality in metadata of each re-ordered variable */
@@ -731,10 +733,12 @@ main(int argc,char **argv)
   } /* nco_pck_plc == nco_pck_plc_nil */
 
   /* Define dimensions, extracted groups, variables, and attributes in output file. NB: record name is NULL */
-  (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,True,True,False,nco_pck_plc,(char *)NULL,trv_tbl);
+  (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,!FORCE_APPEND,True,False,nco_pck_plc,(char *)NULL,trv_tbl);
 
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
 
   /* Turn off default filling behavior to enhance efficiency */
@@ -841,8 +845,9 @@ main(int argc,char **argv)
       } /* endif nco_pck_plc != nco_pck_plc_nil */
 
       if(var_trv->ppc != NC_MAX_INT){
-	if(var_trv->flg_nsd) (void)nco_var_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_var_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
+	if(var_trv->flg_nsd) (void)nco_ppc_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_ppc_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
       } /* endif ppc */
+      if(nco_is_xcp(var_trv->nm)) nco_xcp_prc(var_trv->nm,var_prc_out[idx]->type,var_prc_out[idx]->sz,(char *)var_prc_out[idx]->val.vp);
 	
 #ifdef _OPENMP
 #pragma omp critical
diff --git a/src/nco/ncra.c b/src/nco/ncra.c
index 9c3c7c2..75615bc 100644
--- a/src/nco/ncra.c
+++ b/src/nco/ncra.c
@@ -635,9 +635,9 @@ main(int argc,char **argv)
     case 'w': /* Per-file and per-record weights */
       if(isalpha(optarg[0])){
 	wgt_nm=(char *)strdup(optarg);
-	//	(void)fprintf(stderr,"%s: WARNING The \"-w weight_name\" feature is still buggy and this switch is intended only for developers\n",nco_prg_nm);
-	(void)fprintf(stderr,"%s: WARNING The \"-w weight_name\" feature is still buggy and this option is intended only for developers. The \"-w weight_array\" option works fine, e.g., \"-w 31,31,28\". If you are very interested in the weight_name functionality, start a thread on SourceForge and we will update the status of that option there.\n",nco_prg_nm);
-        nco_exit(EXIT_FAILURE);
+	(void)fprintf(stderr,"%s: WARNING The \"-w weight_name\" feature is still buggy and this switch is intended only for developers\n",nco_prg_nm);
+	//	(void)fprintf(stderr,"%s: WARNING The \"-w weight_name\" feature is still buggy and this option is intended only for developers. The \"-w weight_array\" option works fine, e.g., \"-w 31,31,28\". If you are very interested in the weight_name functionality, start a thread on SourceForge and we will update the status of that option there.\n",nco_prg_nm);
+        // nco_exit(EXIT_FAILURE);
       }else{ /* !wgt_nm */
 	optarg_lcl=(char *)strdup(optarg);
 	wgt_lst_in=nco_lst_prs_2D(optarg_lcl,",",&wgt_nbr);
@@ -784,17 +784,19 @@ main(int argc,char **argv)
   /* Open output file */
   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
 
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   /* Define dimensions, extracted groups, variables, and attributes in output file */
-  (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,True,True,False,nco_pck_plc_nil,(char *)NULL,trv_tbl);
+  (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,!FORCE_APPEND,True,False,nco_pck_plc_nil,(char *)NULL,trv_tbl);
 
   /* Define ensemble fixed variables (True parameter) */
   if(nco_prg_id_get() == ncge) (void)nco_nsm_dfn_wrt(in_id,out_id,&cnk,dfl_lvl,gpe,True,trv_tbl); 
 
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
 
   /* Add input file list global attribute */
@@ -995,7 +997,7 @@ main(int argc,char **argv)
           if(nco_dbg_lvl >= nco_dbg_scl) (void)fprintf(fp_stdout,"%s: INFO Record %ld of %s contributes to output record %ld\n",nco_prg_nm_get(),idx_rec_crr_in,fl_in,idx_rec_out[idx_rec]);
 
 #ifdef _OPENMP
-#pragma omp parallel for default(none) private(idx,in_id) shared(CNV_ARM,base_time_crr,base_time_srt,nco_dbg_lvl,fl_in,fl_out,idx_rec_crr_in,idx_rec_out,rec_usd_cml,in_id_arr,REC_FRS_GRP,REC_LST_DSR,md5,nbr_var_prc,nco_op_typ,FLG_BFR_NRM,FLG_MRO,out_id,nco_prg_id,rcd,var_prc,var_prc_out,nbr_dmn_fl,trv_tbl,var_trv,grp_id,gpe,grp_out_fll,grp_out_id,var_out_id,idx_rec,flg_skp1,flg_skp2,lmt_rec,nbr_rec,var_prc_typ_pre_prm)
+#pragma omp parallel for default(none) private(idx,in_id) shared(CNV_ARM,FLG_BFR_NRM,FLG_MRO,REC_FRS_GRP,REC_LST_DSR,base_time_crr,base_time_srt,fl_idx,fl_in,fl_nbr,fl_out,flg_skp1,flg_skp2,gpe,grp_id,grp_out_fll,grp_out_id,idx_rec,idx_rec_crr_in,idx_rec_out,in_id_arr,lmt_rec,md5,nbr_dmn_fl,nbr_rec,nbr_var_prc,nco_dbg_lvl,nco_op_typ,nco_prg_id,out_id,rcd,rec_usd_cml,trv_tbl,var_out_id,var_prc,var_prc_out,var_prc_typ_pre_prm,var_trv,wgt_arr,wgt_avg,wgt_nbr,wgt_nm,wgt_out,wgt_scv)
 #endif /* !_OPENMP */
           for(idx=0;idx<nbr_var_prc;idx++){
 
@@ -1076,7 +1078,7 @@ main(int argc,char **argv)
 		    wgt_scv.type=wgt_out->type;
 		  } /* !wgt_nm */
 		  nco_scv_cnf_typ(var_prc[idx]->type,&wgt_scv);
-		  if(nco_dbg_lvl > nco_dbg_std && (wgt_nm || wgt_arr)) (void)fprintf(stdout,"wgt_nm = %s, var_nm = %s, idx = %li, typ = %s, wgt_val = %g, var_val=%g\n",wgt_nm ? wgt_out->nm_fll : "NULL",var_prc[idx]->nm,idx_rec_crr_in,nco_typ_sng(wgt_scv.type),wgt_scv.val.d,var_prc[idx]->val.dp[0]);
+		  if(nco_dbg_lvl > nco_dbg_std && (wgt_nm || wgt_arr)) (void)fprintf(fp_stdout,"wgt_nm = %s, var_nm = %s, idx = %li, typ = %s, wgt_val = %g, var_val=%g\n",wgt_nm ? wgt_out->nm_fll : "NULL",var_prc[idx]->nm,idx_rec_crr_in,nco_typ_sng(wgt_scv.type),wgt_scv.val.d,var_prc[idx]->val.dp[0]);
 		  (void)nco_var_scv_mlt(var_prc[idx]->type,var_prc[idx]->sz,var_prc[idx]->has_mss_val,var_prc[idx]->mss_val,var_prc[idx]->val,&wgt_scv);
 		  /* Increment running total of weight after its application to last processed variable */
 		  if(wgt_nm){
@@ -1100,8 +1102,9 @@ main(int argc,char **argv)
               /* Replace this time_offset value with time_offset from initial file base_time */
               if(CNV_ARM && !strcmp(var_prc[idx]->nm,"time_offset")) var_prc[idx]->val.dp[0]+=(base_time_crr-base_time_srt);
 	      if(var_trv->ppc != NC_MAX_INT){
-		if(var_trv->flg_nsd) (void)nco_var_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc[idx]->val); else (void)nco_var_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc[idx]->val);
+		if(var_trv->flg_nsd) (void)nco_ppc_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc[idx]->val); else (void)nco_ppc_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc[idx]->val);
 	      } /* endif ppc */
+	      if(nco_is_xcp(var_trv->nm)) nco_xcp_prc(var_trv->nm,var_prc_out[idx]->type,var_prc_out[idx]->sz,(char *)var_prc[idx]->val.vp);
 #ifdef _OPENMP
 #pragma omp critical
 #endif /* _OPENMP */
@@ -1177,8 +1180,9 @@ main(int argc,char **argv)
               /* Packing/Unpacking */
               if(nco_pck_plc == nco_pck_plc_all_new_att) var_prc_out[idx]=nco_put_var_pck(grp_out_id,var_prc_out[idx],nco_pck_plc);
 	      if(var_trv->ppc != NC_MAX_INT){
-		if(var_trv->flg_nsd) (void)nco_var_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_var_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
+		if(var_trv->flg_nsd) (void)nco_ppc_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_ppc_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
 	      } /* endif ppc */
+	      if(nco_is_xcp(var_trv->nm)) nco_xcp_prc(var_trv->nm,var_prc_out[idx]->type,var_prc_out[idx]->sz,(char *)var_prc_out[idx]->val.vp);
               if(var_prc_out[idx]->nbr_dim == 0) (void)nco_put_var1(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->val.vp,var_prc_out[idx]->type); else (void)nco_put_vara(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_out[idx]->val.vp,var_prc_out[idx]->type);
             } /* end loop over idx */
             idx_rec_out[idx_rec]++; /* [idx] Index of current record in output file (0 is first, ...) */
@@ -1452,7 +1456,7 @@ main(int argc,char **argv)
       /* Packing/Unpacking */
       if(nco_pck_plc == nco_pck_plc_all_new_att) var_prc_out[idx]=nco_put_var_pck(grp_out_id,var_prc_out[idx],nco_pck_plc);
       if(var_trv->ppc != NC_MAX_INT){
-	if(var_trv->flg_nsd) (void)nco_var_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_var_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
+	if(var_trv->flg_nsd) (void)nco_ppc_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_ppc_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
       } /* endif ppc */
       if(var_prc_out[idx]->nbr_dim == 0) (void)nco_put_var1(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->val.vp,var_prc_out[idx]->type); else (void)nco_put_vara(grp_out_id,var_prc_out[idx]->id,var_prc_out[idx]->srt,var_prc_out[idx]->cnt,var_prc_out[idx]->val.vp,var_prc_out[idx]->type);
 
diff --git a/src/nco/ncwa.c b/src/nco/ncwa.c
index 4c4c00e..8fbd3b8 100644
--- a/src/nco/ncwa.c
+++ b/src/nco/ncwa.c
@@ -751,14 +751,16 @@ main(int argc,char **argv)
   /* Open output file */
   fl_out_tmp=nco_fl_out_open(fl_out,FORCE_APPEND,FORCE_OVERWRITE,fl_out_fmt,&bfr_sz_hnt,RAM_CREATE,RAM_OPEN,WRT_TMP_FL,&out_id);
 
-  /* Create structure with all chunking information */
+  /* Initialize chunking from user-specified inputs */
   if(fl_out_fmt == NC_FORMAT_NETCDF4 || fl_out_fmt == NC_FORMAT_NETCDF4_CLASSIC) rcd+=nco_cnk_ini(in_id,fl_out,cnk_arg,cnk_nbr,cnk_map,cnk_plc,cnk_min_byt,cnk_sz_byt,cnk_sz_scl,&cnk);
 
   /* Define dimensions, extracted groups, variables, and attributes in output file.  */
-  (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,True,True,False,nco_pck_plc_nil,(char *)NULL,trv_tbl);
+  (void)nco_xtr_dfn(in_id,out_id,&cnk,dfl_lvl,gpe,md5,!FORCE_APPEND,True,False,nco_pck_plc_nil,(char *)NULL,trv_tbl);
 
   /* Catenate time-stamped command line to "history" global attribute */
   if(HISTORY_APPEND) (void)nco_hst_att_cat(out_id,cmd_ln);
+  if(HISTORY_APPEND && FORCE_APPEND) (void)nco_prv_att_cat(fl_in,in_id,out_id);
+  if(HISTORY_APPEND) (void)nco_vrs_att_cat(out_id);
   if(thr_nbr > 0 && HISTORY_APPEND) (void)nco_thr_att_cat(out_id,thr_nbr);
 
   /* Add new missing values to output file while in define mode */
@@ -842,22 +844,18 @@ main(int argc,char **argv)
 
 #ifdef _OPENMP
     /* OpenMP notes:
-       firstprivate(): msk_out and wgt_out must be NULL on first call to nco_var_cnf_dmn()
-       shared(): msk and wgt are not altered within loop
-       private(): wgt_avg does not need initialization */
-#pragma omp parallel for default(none) firstprivate(DO_CONFORM_MSK,DO_CONFORM_WGT,ddra_info) private(idx,in_id,wgt_avg) shared(MULTIPLY_BY_TALLY,MUST_CONFORM,NRM_BY_DNM,WGT_MSK_CRD_VAR,nco_dbg_lvl,dmn_avg,dmn_avg_nbr,flg_ddra,flg_rdd,gpe,in_id_arr,msk_nm,msk_val,nbr_var_prc,nco_op_typ,op_typ_rlt,out_id,nco_prg_nm,rcd,trv_tbl,var_prc,var_prc_out,wgt_nm)
+       firstprivate(): rcd gets incremented, so keep initial value
+       lastprivate(): retain rcd value from last thread
+       private(): wgt_avg does not need initialization
+       shared(): msk and wgt are not altered within loop */
+#pragma omp parallel for default(none) firstprivate(DO_CONFORM_MSK,DO_CONFORM_WGT,ddra_info,rcd) lastprivate(rcd) private(idx,in_id,wgt_avg) shared(MULTIPLY_BY_TALLY,MUST_CONFORM,NRM_BY_DNM,WGT_MSK_CRD_VAR,dmn_avg,dmn_avg_nbr,flg_ddra,flg_rdd,gpe,in_id_arr,msk_nm,msk_val,nbr_var_prc,nco_dbg_lvl,nco_op_typ,nco_prg_nm,op_typ_rlt,out_id,trv_tbl,var_prc,var_prc_out,wgt_nm)
 #endif /* !_OPENMP */
-
     for(idx=0;idx<nbr_var_prc;idx++){ /* Process all variables in current file */
-
       char *grp_out_fll=NULL; /* [sng] Group name */
-
       int grp_id;        /* [ID] Group ID */
       int grp_out_id;    /* [ID] Group ID (output) */
       int var_out_id;    /* [ID] Variable ID (output) */
-
       trv_sct *var_trv;  /* [sct] Variable GTT object */
-
       var_sct *wgt=NULL;
       var_sct *wgt_out=NULL;
       var_sct *msk=NULL;
@@ -1129,8 +1127,9 @@ main(int argc,char **argv)
       var_prc_out[idx]->id=var_out_id;
 
       if(var_trv->ppc != NC_MAX_INT){
-	if(var_trv->flg_nsd) (void)nco_var_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_var_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
+	if(var_trv->flg_nsd) (void)nco_ppc_bitmask(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val); else (void)nco_ppc_around(var_trv->ppc,var_prc_out[idx]->type,var_prc_out[idx]->sz,var_prc_out[idx]->has_mss_val,var_prc_out[idx]->mss_val,var_prc_out[idx]->val);
       } /* endif ppc */
+      if(nco_is_xcp(var_trv->nm)) nco_xcp_prc(var_trv->nm,var_prc_out[idx]->type,var_prc_out[idx]->sz,(char *)var_prc_out[idx]->val.vp);
 	
 #ifdef _OPENMP
 #pragma omp critical

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/nco.git



More information about the Pkg-grass-devel mailing list