<p><b>cahrens@lanl.gov</b> 2010-08-16 16:07:43 -0600 (Mon, 16 Aug 2010)</p><p>Added xml/binary .vtu outputting versions: transdualbin and projlatlonbin<br>
</p><hr noshade><pre><font color="gray">Added: branches/ocean_projects/graphics/paraview/projection/EncodeBase64.cpp
===================================================================
--- branches/ocean_projects/graphics/paraview/projection/EncodeBase64.cpp                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/projection/EncodeBase64.cpp        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,169 @@
+using namespace std;
+
+#include &quot;EncodeBase64.h&quot;
+
+
+EncodeBase64::EncodeBase64(ofstream* astream)
+{
+  outstream = astream;
+  this-&gt;BufferLength = 0;
+}
+
+//----------------------------------------------------------------------------
+EncodeBase64::~EncodeBase64()
+{
+}
+
+
+
+//----------------------------------------------------------------------------
+static const unsigned char Base64EncodeTable[65] =
+&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;
+&quot;abcdefghijklmnopqrstuvwxyz&quot;
+&quot;0123456789+/&quot;;
+
+//----------------------------------------------------------------------------
+inline static unsigned char EncodeChar(unsigned char c)
+{
+  assert( c &lt; 65 );
+  return Base64EncodeTable[c];
+}
+
+//----------------------------------------------------------------------------
+void EncodeBase64::EncodePair(unsigned char i0,
+        unsigned char i1,
+        unsigned char *o0,
+        unsigned char *o1,
+        unsigned char *o2,
+        unsigned char *o3)
+{
+    *o0 = EncodeChar((i0 &gt;&gt; 2) &amp; 0x3F);
+    *o1 = EncodeChar(((i0 &lt;&lt; 4) &amp; 0x30)|((i1 &gt;&gt; 4) &amp; 0x0F));
+    *o2 = EncodeChar(((i1 &lt;&lt; 2) &amp; 0x3C));
+    *o3 = '=';
+}
+
+//----------------------------------------------------------------------------
+void EncodeBase64::EncodeSingle(unsigned char i0,
+        unsigned char *o0,
+        unsigned char *o1,
+        unsigned char *o2,
+        unsigned char *o3)
+{
+    *o0 = EncodeChar((i0 &gt;&gt; 2) &amp; 0x3F);
+    *o1 = EncodeChar(((i0 &lt;&lt; 4) &amp; 0x30));
+    *o2 = '=';
+    *o3 = '=';
+}
+
+//----------------------------------------------------------------------------
+void EncodeBase64::EncodeTriplet(unsigned char i0,
+        unsigned char i1,
+        unsigned char i2,
+        unsigned char *o0,
+        unsigned char *o1,
+        unsigned char *o2,
+        unsigned char *o3)
+{
+    *o0 = EncodeChar((i0 &gt;&gt; 2) &amp; 0x3F);
+    *o1 = EncodeChar(((i0 &lt;&lt; 4) &amp; 0x30)|((i1 &gt;&gt; 4) &amp; 0x0F));
+    *o2 = EncodeChar(((i1 &lt;&lt; 2) &amp; 0x3C)|((i2 &gt;&gt; 6) &amp; 0x03));
+    *o3 = EncodeChar(i2 &amp; 0x3F);
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::EncodeTriplet(unsigned char c0,
+                                                unsigned char c1,
+                                                unsigned char c2)
+{
+  // Encodes 3 bytes into 4 bytes and writes them to the output stream.
+  unsigned char out[4];
+  EncodeTriplet(c0, c1, c2,
+                                    &amp;out[0], &amp;out[1], &amp;out[2], &amp;out[3]);
+  return (outstream-&gt;write(reinterpret_cast&lt;char*&gt;(out), 4)? 1:0);
+}
+  
+//----------------------------------------------------------------------------
+int EncodeBase64::EncodeEnding(unsigned char c0,
+                                                unsigned char c1)
+{
+  // Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes.
+  unsigned char out[4];
+  EncodePair(c0, c1,
+                                 &amp;out[0], &amp;out[1], &amp;out[2], &amp;out[3]);
+  return (outstream-&gt;write(reinterpret_cast&lt;char*&gt;(out), 4)? 1:0);
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::EncodeEnding(unsigned char c0)
+{
+  // Encodes a 1-byte ending into 2 bytes and 2 pad bytes and writes.
+  unsigned char out[4];
+  EncodeSingle(c0, &amp;out[0], &amp;out[1], &amp;out[2], &amp;out[3]);
+  return (outstream-&gt;write(reinterpret_cast&lt;char*&gt;(out), 4)? 1:0);
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::StartWriting()
+{
+  this-&gt;BufferLength = 0;
+  this-&gt;WriteCount = 0;
+  //cout &lt;&lt; &quot;StartWriting!&quot; &lt;&lt; endl;
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::EndWriting()
+{
+  if(this-&gt;BufferLength == 1)
+    {
+    if(!this-&gt;EncodeEnding(this-&gt;Buffer[0])) { return 0; }
+    this-&gt;BufferLength = 0;
+    }
+  else if(this-&gt;BufferLength == 2)
+    {
+    if(!this-&gt;EncodeEnding(this-&gt;Buffer[0], this-&gt;Buffer[1])) { return 0; }
+    this-&gt;BufferLength = 0;
+    }
+  //cout &lt;&lt; &quot;EndWriting: WriteCount: &quot; &lt;&lt; WriteCount &lt;&lt; endl;
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::Write(const unsigned char* data,
+                                 unsigned long length)
+{ 
+  unsigned long totalLength = this-&gt;BufferLength + length;
+  const unsigned char* in = data;
+  const unsigned char* end = data+length;
+  
+  if(totalLength &gt;= 3)
+    {
+    if(this-&gt;BufferLength == 1)
+      {
+      if(!this-&gt;EncodeTriplet(this-&gt;Buffer[0], in[0], in[1])) { return 0; }
+      in += 2;
+      this-&gt;BufferLength = 0;
+      }
+    else if(this-&gt;BufferLength == 2)
+      {
+      if(!this-&gt;EncodeTriplet(this-&gt;Buffer[0], this-&gt;Buffer[1], in[0]))
+        { return 0; }
+      in += 1;
+      this-&gt;BufferLength = 0;
+      }
+    }
+  
+  while((end - in) &gt;= 3)
+    {
+    if(!this-&gt;EncodeTriplet(in[0], in[1], in[2])) { return 0; }
+    in += 3;
+    }
+  
+  while(in != end)
+    {
+    this-&gt;Buffer[this-&gt;BufferLength++] = *in++;
+    }
+  WriteCount++;
+  return 1;
+}


Property changes on: branches/ocean_projects/graphics/paraview/projection/EncodeBase64.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/x-c++src
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

Added: branches/ocean_projects/graphics/paraview/projection/EncodeBase64.h
===================================================================
--- branches/ocean_projects/graphics/paraview/projection/EncodeBase64.h                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/projection/EncodeBase64.h        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,72 @@
+using namespace std;
+
+#include &lt;iostream&gt;
+#include &lt;fstream&gt;
+#include &quot;stdlib.h&quot;
+#include &lt;assert.h&gt;
+
+class EncodeBase64 
+{
+public:
+  EncodeBase64(ofstream *outstream);
+  ~EncodeBase64();  
+
+  // Description:  
+  // Called after the stream position has been set by the caller, but
+  // before any Write calls.  The stream position should not be
+  // adjusted by the caller until after an EndWriting call.
+  int StartWriting();
+  
+  // Description:
+  // Write output data of the given length.
+  int Write(const unsigned char* data, unsigned long length);
+  
+  // Description:
+  // Called after all desired calls to Write have been made.  After
+  // this call, the caller is free to change the position of the
+  // stream.  Additional writes should not be done until after another
+  // call to StartWriting.
+  int EndWriting();
+  
+protected:
+  
+  // Methods to encode and write data.
+
+  // Number of un-encoded bytes left in Buffer from last call to Write.
+  unsigned int BufferLength;
+  unsigned int WriteCount;
+  unsigned char Buffer[2];
+  ofstream *outstream; 
+
+  // Description:  
+  // Encode 2 bytes into 4 bytes
+  static void EncodePair(unsigned char i0,
+                         unsigned char i1,
+                         unsigned char *o0,
+                         unsigned char *o1,
+                         unsigned char *o2,
+                         unsigned char *o3);
+
+  // Description:  
+  // Encode 1 byte into 4 bytes
+  static void EncodeSingle(unsigned char i0,
+                           unsigned char *o0,
+                           unsigned char *o1,
+                           unsigned char *o2,
+                           unsigned char *o3);
+  // Description:
+  // Encode 3 bytes into 4 bytes
+  static void EncodeTriplet(unsigned char i0,
+          unsigned char i1,
+          unsigned char i2,
+          unsigned char *o0,
+          unsigned char *o1,
+          unsigned char *o2,
+          unsigned char *o3);
+
+  int EncodeTriplet(unsigned char c0, unsigned char c1, unsigned char c2);
+  int EncodeEnding(unsigned char c0, unsigned char c1);
+  int EncodeEnding(unsigned char c0);
+  
+};
+


Property changes on: branches/ocean_projects/graphics/paraview/projection/EncodeBase64.h
___________________________________________________________________
Name: svn:mime-type
   + text/x-c++hdr
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

Modified: branches/ocean_projects/graphics/paraview/projection/Makefile
===================================================================
--- branches/ocean_projects/graphics/paraview/projection/Makefile        2010-08-12 22:02:03 UTC (rev 476)
+++ branches/ocean_projects/graphics/paraview/projection/Makefile        2010-08-16 22:07:43 UTC (rev 477)
@@ -1,12 +1,12 @@
-NETCDF = /usr/projects/climate/mhecht/netcdf-3.6.1
+#NETCDF = /usr/projects/climate/mhecht/netcdf-3.6.1
 CC = gcc
 INCLUDES = -I$(NETCDF)/include
 
 LIBS = -L$(NETCDF)/lib -lnetcdf_c++ -lnetcdf \
         -lstdc++ \
-        -L/opt/Intel/cce/10.0.023/lib/ -lirc
+#        -L/opt/Intel/cce/10.0.023/lib/ -lirc
+# uncomment above if on coyote/lobo
 
-#        -L/usr/lib -lstdc++ \
 #MYDEBUG = -g
 MYDEBUG =
 
@@ -25,5 +25,14 @@
 proj3dquadrect: proj3dquadrect.cpp
         $(CC) $(INCLUDES) -o $@ $&lt;  $(LIBS)
 
+.cpp.o:
+        $(CC) $(MYDEBUG) $(INCLUDES) -c $&lt;
+
+EncodeBase64.o: EncodeBase64.cpp
+        $(CC) $(INCLUDES) -c $&lt; 
+
+projlatlonbin: projlatlonbin.cpp  EncodeBase64.o convert.o
+        $(CC) $(INCLUDES) -o $@ $&lt;  EncodeBase64.o convert.o $(LIBS)
+
 clean:
-        rm *.o proj3dsphere projlatlon proj3dquadrect
+        rm *.o proj3dsphere projlatlon proj3dquadrect projlatlonbin

Added: branches/ocean_projects/graphics/paraview/projection/convert.c
===================================================================
--- branches/ocean_projects/graphics/paraview/projection/convert.c                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/projection/convert.c        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,16 @@
+#include &lt;math.h&gt;
+
+void CartesianToSpherical(float x, float y, float z, float* rho, float* phi, float* theta)
+{
+        *rho = sqrtf( (x*x) + (y*y) + (z*z));
+        *theta = atan2f(y, x);
+        *phi = acosf(z/(*rho));
+}
+
+void SphericalToCartesian(float rho, float phi, float theta, float* x, float* y, float* z)
+{
+        *x = rho* sinf(phi) * cosf(theta);
+        *y = rho* sinf(phi) * sinf(theta);
+        *z = rho* cosf(phi);
+}
+


Property changes on: branches/ocean_projects/graphics/paraview/projection/convert.c
___________________________________________________________________
Name: svn:mime-type
   + text/x-csrc
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

Added: branches/ocean_projects/graphics/paraview/projection/projlatlonbin.cpp
===================================================================
--- branches/ocean_projects/graphics/paraview/projection/projlatlonbin.cpp                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/projection/projlatlonbin.cpp        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,1600 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program translates a newpop netCDF data file to dual-grid lat/lon multilayer 
+// projection in legacy, binary .vtu format.  Assumes little-endian platform.
+//
+// Assume all variables are of interest.
+// Assume variable data type is double.
+// Assume variable dims are (Time, nCells|nVertices, nVertLevels|nVertLevelsP1)
+// Assume no more than 100 vars each for cell and point data
+// Deals with vectors.
+// Does not deal with edge data.
+// Only vis up to nVertLevels, not nVertLevelsP1.
+// Doubles converted to floats in .vtk files follow these rules:
+//        if a NaN, then become -FLT_MAX.
+//        if positive infinity, then become FLT_MAX
+//        if negative infinity, then become -FLT_MAX
+//        if smaller than a float, then become 0.
+//        if not zero, but between -FLT_MIN and FLT_MIN make -FLT_MIN or FLT_MIN
+//        if outside of -FLT_MAX and FLT_MAX make -FLT_MAX or FLT_MAX
+//
+// Version 1.3
+// Christine Ahrens
+// 7/26/2010
+////////////////////////////////////////////////////////////////////////////////
+
+
+#include &lt;iostream&gt;
+#include &lt;fstream&gt;
+#include &lt;sstream&gt;
+#include &quot;stdlib.h&quot;
+#include &quot;vtkCellType.h&quot;
+#include &quot;netcdfcpp.h&quot;
+#include &lt;string&gt;
+#include &lt;cmath&gt;
+//#include &lt;math&gt;
+#include &lt;cfloat&gt;
+#include &quot;EncodeBase64.h&quot;
+
+using namespace std;
+
+#define CHECK_MALLOC(ptr) \
+        if (ptr == NULL) { \
+                cerr &lt;&lt; &quot;malloc failed!</font>
<font color="blue">&quot;; \
+                exit(1); \
+        } 
+
+#define CHECK_DIM(ncFile, name) \
+    if (!isNcDim(ncFile, name)) { \
+        cerr &lt;&lt; &quot;Cannot find dimension: &quot; &lt;&lt; name &lt;&lt; endl; \
+        exit(1); \
+    }
+
+#define CHECK_VAR(ncFile, name) \
+    if (!isNcVar(ncFile, name)) { \
+        cerr &lt;&lt; &quot;Cannot find variable: &quot; &lt;&lt; name &lt;&lt; endl; \
+        exit(1); \
+    }
+
+#define MAX_VARS 100
+#define DEFAULT_LAYER_THICKNESS 10
+using namespace std;
+
+#define BUFF_SIZE 2048
+
+// append inFile to outFile 
+int myAppendFile(string *inFile, string *outFile)
+{
+   char buff[BUFF_SIZE];
+   int readBytes = 1;
+
+   ifstream inFileStream(inFile-&gt;c_str(), ios::in|ios::binary);
+   if(!inFileStream)
+   {
+     return -1;
+   }
+
+   ofstream outFileStream(outFile-&gt;c_str(), ios::out|ios::app|ios::binary);
+   if(!outFileStream)
+   {
+     return -1;
+   }
+
+   while(readBytes != 0)
+   {
+     inFileStream.read((char*)buff, BUFF_SIZE);
+     readBytes = inFileStream.gcount();
+     outFileStream.write((char*)buff, readBytes);
+   }
+   return 0;
+}
+
+int my_isinf_f(float x){
+        if (isinf(x)) {
+                return (x &lt; 0.0 ? -1 : 1);
+        } else return 0;
+}
+
+unsigned int padSize(unsigned int binarySize) {
+    switch ((binarySize*4)%3) {
+        case 1:
+            binarySize = binarySize + 2;
+            break;
+        case 2:
+            binarySize++;
+            break;
+        case 0:
+            break;
+    }
+    return binarySize;
+}
+
+float convertDouble2ValidFloat(double inputData) {
+
+        // check for NaN
+        if (inputData != inputData) {
+                //cerr &lt;&lt; &quot;found NaN!&quot; &lt;&lt; endl;
+                return -FLT_MAX;
+        }
+
+        // check for infinity
+        int retval = my_isinf_f((float)inputData);
+        if (retval &lt; 0) {
+                return -FLT_MAX;
+        } else if (retval &gt; 0) {
+                return FLT_MAX;
+        }
+
+        // check number too small for float
+        if (abs(inputData) &lt; 1e-126) return 0.0;
+
+        if ((float)inputData == 0) return 0.0;
+
+        if ((abs(inputData) &gt; 0) &amp;&amp; (abs(inputData) &lt; FLT_MIN)) {
+                if (inputData &lt; 0) return -FLT_MIN; else return FLT_MIN;
+        }
+
+        if (abs(inputData) &gt; FLT_MAX) {
+                if (inputData &lt; 0) return -FLT_MAX; else return FLT_MAX;
+        }
+
+        return (float)inputData;
+}
+
+double convertXY2Lon(double x, double y, double lon) {
+    return ((-x * sin(lon)) + (y*cos(lon)));
+}
+
+double convertXYZ2Lat(double x, double y, double z, double lon, double lat) {
+    return ((((x*cos(lon)) + (y*sin(lon)))*sin(lat)) + (z*cos(lat)));
+}
+
+void writeFloat(EncodeBase64 &amp;b64, ofstream &amp;file, double data, bool writeBinary) {
+    float validData = convertDouble2ValidFloat (data);
+    if (writeBinary) {
+        b64.Write((const unsigned char*)&amp;validData, sizeof(validData));
+    } else {
+        file &lt;&lt; validData &lt;&lt; &quot; &quot;;
+    }
+}
+
+void writeInt(EncodeBase64 &amp;b64, ofstream &amp;file, int data, bool writeBinary) {
+    if (writeBinary) {
+        b64.Write((const unsigned char*)&amp;data, sizeof(data));
+    } else {
+        file &lt;&lt; data &lt;&lt; &quot; &quot;;
+    }
+}
+
+void writeChar(EncodeBase64 &amp;b64, ofstream &amp;file, unsigned char data, bool writeBinary) {
+    if (writeBinary) {
+        b64.Write((const unsigned char*)&amp;data, sizeof(data));
+    } else {
+        file &lt;&lt; data &lt;&lt; &quot; &quot;;
+    }
+}
+
+void printUsage() {
+    cerr &lt;&lt; &quot;USAGE: projlatlonbin [OPTIONS] infile.nc outfile.vtu&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;Create lat/lon projection of MPAS-style data from input file infile.nc &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;and write to XML binary .vtu format for use in ParaView.&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;A series of vtu files are created, one file for each time step.&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;with time prepended to the file name (e.g. 0outfile.vtu).&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;OPTIONS:&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -l intval     &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       vertical level, in range 0 to nVertLevels-1, default is 0 &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -m            &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       multilayer view -- default is single layer view&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -t floatval   &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       layer_thickness -- use negative value for atmosphere, default is 10&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -c floatval   &quot; &lt;&lt; endl; 
+    cerr &lt;&lt; &quot;      display image with center_longitude in degrees, default is 180&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -z &quot; &lt;&lt; endl; 
+    cerr &lt;&lt; &quot;      input grid has center longitude at 0, the default is 180 degree or PI radians&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -a              &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       atmosphere data (longitude data is in range -PI to PI)  &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       The -a flag also converts the multilayer view to have the &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       vertical levels stack in the positive Z direction, rather &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       the negative Z direction, which is the default.&quot; &lt;&lt; endl;     
+    cerr &lt;&lt; &quot;   -s              &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       timestep to start on (defaults to 0) &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -f              &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       timestep to finish on (defaults to last timestep available) &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -g              &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       include topography (assumes you have maxLevelCell variable) &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;   -b              &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;       do bugfix to ensure no connections to faraway points &quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;Variables with time and vertical level are written out.&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;Tracer vars are named tracer1, tracer2, etc.&quot; &lt;&lt; endl;
+    cerr &lt;&lt; &quot;[vtk datafile Version 2.0, projlatlonbin Version 1.3]&quot; &lt;&lt; endl;
+    exit(1);
+}
+
+void getArgs(int argc, char* argv[], int &amp;outputVertLevel, 
+        float &amp;layerThickness, double &amp;centerLon, bool &amp;isMultilayer, 
+        bool &amp;isAtmosphere, int &amp;startTimeStep, int &amp;finishTimeStep,
+        bool &amp;isZeroCentered, bool &amp;includeTopography, bool &amp;doBugfix,
+        char* &amp;inputFileName, char* &amp;outputFileName) {
+
+    int c;
+    bool selectedVar = false;
+    optind = 1;
+
+    bool lflag = false;
+    bool tflag = false;
+    bool cflag = false;
+    bool mflag = false;
+    bool aflag = false;
+    bool sflag = false;
+    bool fflag = false;
+    bool zflag = false;
+    bool gflag = false;
+    bool bflag = false;
+
+    // -l vertical level (if not specified, assume multilayer)
+    // -t layer thickness (defaults to 1/10 * radius/#layers)
+    // -c center longitude in degrees for latlon projection
+    while ((c=getopt(argc, argv, &quot;l:t:c:mazgbs:f:&quot;)) != -1) {
+        switch(c) {
+            case 'l':
+                lflag = true;
+                if (tflag) {
+                    cerr &lt;&lt; &quot;Can't specify -l and -t at same time.&quot; &lt;&lt; endl;
+                    exit(1);
+                }
+                outputVertLevel = atoi(optarg);
+                isMultilayer = false;
+                break;
+            case 't':
+                tflag = true;
+                if (lflag) {
+                    cerr &lt;&lt; &quot;Can't specify -l and -t at same time.&quot; &lt;&lt; endl;
+                    exit(1);
+                }
+                layerThickness = atof(optarg);
+                isMultilayer = true;
+                break;
+            case 'c':
+                cflag = true;
+                centerLon = (double)atof(optarg);
+                break;
+            case 'm':
+                mflag = true;
+                if (lflag) {
+                    cerr &lt;&lt; &quot;Can't specify -l and -m at same time.&quot; &lt;&lt; endl;
+                    exit(1);
+                }
+                isMultilayer = true;
+                break;
+           case 'a':
+                aflag = true;
+                isAtmosphere = true;
+                break;
+            case 's':
+                sflag = true;
+                startTimeStep = atoi(optarg);
+                break;
+            case 'f':
+                sflag = true;
+                finishTimeStep = atoi(optarg);
+                break;
+            case 'z':
+                zflag = true;
+                isZeroCentered = true;
+                break;
+            case 'g':
+                gflag = true;
+                includeTopography = true;
+                break;
+            case 'b':
+                bflag = true;
+                doBugfix = true;
+                break;
+            default:
+                cerr &lt;&lt; &quot;Unrecognized option: -&quot; &lt;&lt; c &lt;&lt; endl;
+                printUsage();
+                exit(1);
+                break;
+        }
+    //argc -= optind;
+    //argv += optind;
+    }
+
+    inputFileName = argv[optind++];
+    outputFileName = argv[optind];
+
+}
+
+// Check if there is a variable by that name
+
+bool isNcVar(NcFile &amp;ncFile, NcToken name) {
+    int num_vars = ncFile.num_vars();
+    for (int i = 0; i &lt; num_vars; i++) {
+        NcVar* ncVar = ncFile.get_var(i);
+                if ((strcmp(ncVar-&gt;name(), name)) == 0) {
+            // we have a match, so return
+            return true;
+        }
+    }
+    return false;
+}
+
+// Check if there is a dimension by that name
+
+bool isNcDim(NcFile &amp;ncFile, NcToken name) {
+    int num_dims = ncFile.num_dims();
+    //cerr &lt;&lt; &quot;looking for: &quot; &lt;&lt; name &lt;&lt; endl;
+    for (int i = 0; i &lt; num_dims; i++) {
+        NcDim* ncDim = ncFile.get_dim(i);
+        //cerr &lt;&lt; &quot;checking &quot; &lt;&lt; ncDim-&gt;name() &lt;&lt; endl;
+                if ((strcmp(ncDim-&gt;name(), name)) == 0) {
+            // we have a match, so return
+            return true;
+        }
+    }
+    return false;
+}
+
+
+int main(int argc, char* argv[])
+{
+
+    bool multilayer = false;
+    bool atmosphere = false;
+    bool includeTopography = false;
+    bool doBugfix = false;
+        int outputVertLevel = 0;
+    char* inputFileName = NULL;
+    char* outputFileName =  NULL;
+        float layerThickness =  DEFAULT_LAYER_THICKNESS;
+    double centerLon = 180;
+    int startTimeStep = 0;
+    int finishTimeStep = -1;
+    bool isZeroCentered = false;
+
+    if (argc &lt; 3)   {
+        printUsage();
+        exit(1);
+    }
+
+    getArgs(argc, argv, outputVertLevel, layerThickness, centerLon, multilayer, 
+        atmosphere, startTimeStep, finishTimeStep, isZeroCentered, 
+        includeTopography, doBugfix, inputFileName, outputFileName); 
+        
+        NcFile ncFile(inputFileName);
+
+        if (!ncFile.is_valid()) 
+        {
+                cerr &lt;&lt; &quot;Couldn't open file: &quot; &lt;&lt; inputFileName &lt;&lt; endl;
+                exit(1);
+        }
+
+    CHECK_DIM(ncFile, &quot;nCells&quot;);
+    NcDim* nCells = ncFile.get_dim(&quot;nCells&quot;);
+
+    CHECK_DIM(ncFile, &quot;nVertices&quot;);
+    NcDim* nVertices = ncFile.get_dim(&quot;nVertices&quot;);
+
+    CHECK_DIM(ncFile, &quot;vertexDegree&quot;);
+    NcDim* vertexDegree = ncFile.get_dim(&quot;vertexDegree&quot;);
+
+    CHECK_DIM(ncFile, &quot;Time&quot;);
+    NcDim* Time = ncFile.get_dim(&quot;Time&quot;);
+
+    CHECK_DIM(ncFile, &quot;nVertLevels&quot;);
+    NcDim* nVertLevels = ncFile.get_dim(&quot;nVertLevels&quot;);
+    
+    int maxNVertLevels = nVertLevels-&gt;size();
+
+        if ((vertexDegree-&gt;size() != 3) &amp;&amp; (vertexDegree-&gt;size() != 4))  {
+                cerr &lt;&lt; &quot;This code is only for hexagonal or quad grid projection&quot; &lt;&lt; endl;
+                exit(1);
+        }
+
+        // what to do about nVertLevelsP1?
+        //NcDim* nVertLevelsP1 = ncFile.get_dim(&quot;nVertLevelsP1&quot;);
+
+    bool singlelayer = !multilayer;
+
+    // double-check we can do multilayer
+    if ((multilayer) &amp;&amp; (maxNVertLevels == 1)) {
+        multilayer = false;
+        singlelayer = !multilayer;
+    }
+
+    if (singlelayer &amp;&amp; (outputVertLevel &gt; (maxNVertLevels-1))) {
+        cerr &lt;&lt; &quot;There is no data for level &quot; &lt;&lt; outputVertLevel &lt;&lt; &quot;.&quot; &lt;&lt; endl;
+        exit(1);
+    }
+
+    if (singlelayer &amp;&amp; (outputVertLevel &lt; 0)) {
+        cerr &lt;&lt; &quot;Level number must be 0 or greater.&quot; &lt;&lt; endl;
+        exit(1);
+    }
+
+    if ((centerLon &lt; 0) || (centerLon &gt; 360)) {
+        cerr &lt;&lt; &quot;Center longitude must be between 0 and 360.&quot; &lt;&lt; endl;
+        exit(1);
+    }
+
+    if (singlelayer) {
+        maxNVertLevels = 1;
+    }
+
+    if (atmosphere) {
+        layerThickness = -layerThickness;
+    }
+
+    int availTimeSteps = Time-&gt;size();
+
+    if (startTimeStep &gt; (availTimeSteps-1)) {
+        cerr &lt;&lt; &quot;Start timestep is too large, last timestep is: &quot; &lt;&lt; availTimeSteps-1 &lt;&lt; endl;
+        exit(1);
+    }
+
+    if (startTimeStep &lt; 0) {
+        cerr &lt;&lt; &quot;Start timestep is too small, must be at least 0.&quot; &lt;&lt; endl;
+        exit(1);
+    }
+
+    if (finishTimeStep &gt; (availTimeSteps-1)) {
+        cerr &lt;&lt; &quot;Finish timestep is too large, last timestep is: &quot; &lt;&lt; availTimeSteps-1 &lt;&lt; endl;
+        exit(1);
+    }
+    
+    if (finishTimeStep &lt; 0) {
+        finishTimeStep = availTimeSteps-1;
+    }
+
+    cerr &lt;&lt; &quot;centerLon: &quot; &lt;&lt; centerLon &lt;&lt; &quot; singleLayer: &quot; &lt;&lt; singlelayer &lt;&lt; &quot; outputVertLevel: &quot; &lt;&lt; outputVertLevel &lt;&lt; &quot; start: &quot; &lt;&lt; startTimeStep &lt;&lt; &quot; finish: &quot; &lt;&lt; finishTimeStep &lt;&lt; &quot; atmosphere: &quot; &lt;&lt; atmosphere  &lt;&lt; &quot; includeTopography: &quot; &lt;&lt; includeTopography &lt;&lt; &quot; doBugfix: &quot; &lt;&lt; doBugfix &lt;&lt; endl;
+
+    bool writeBinary = true;
+
+        // figure out what variables to visualize
+        NcVar* dualCellVars[MAX_VARS];
+        NcVar* dualPointVars[MAX_VARS];
+    NcVar* vectorVars[3];
+        int dualCellVarIndex = -1;
+        int dualPointVarIndex = -1;
+        int numDualCells = nVertices-&gt;size();
+        int numDualPoints = nCells-&gt;size()+1;
+        
+        int numVars = ncFile.num_vars();
+
+        bool tracersExist = false;
+    bool isUVector = false;
+    bool isVVector = false;
+
+        for (int i = 0; i &lt; numVars; i++) {
+                NcVar* aVar = ncFile.get_var(i);
+
+                // must have 3 dims 
+                // (Time, nCells | nVertices, nVertLevels | nVertLevelsP1)
+
+                int numDims = aVar-&gt;num_dims();
+                //cout &lt;&lt; &quot;Num Dims of var: &quot; &lt;&lt; aVar-&gt;name() &lt;&lt; &quot; is &quot; &lt;&lt; numDims &lt;&lt; endl;
+                if ((numDims != 3) &amp;&amp; (strcmp(aVar-&gt;name(), &quot;tracers&quot;))) {
+                        continue; // try the next var
+                } else {
+                        // TODO, check if it is a double
+                        // assume a double for now
+
+                        // check for Time dim 0
+                        NcToken dim0Name = aVar-&gt;get_dim(0)-&gt;name();
+                        if (strcmp(dim0Name, &quot;Time&quot;)) 
+                                continue;
+
+                        // check for dim 1 being num vertices or cells 
+                        bool isVertexData = false;
+                        bool isCellData = false;
+                        NcToken dim1Name = aVar-&gt;get_dim(1)-&gt;name();
+                        if (!strcmp(dim1Name, &quot;nVertices&quot;)) 
+                                isVertexData = true;
+                        else if (!strcmp(dim1Name, &quot;nCells&quot;)) 
+                                isCellData = true; 
+                        else continue;
+
+                        // check if dim 2 is nVertLevels or nVertLevelsP1, too
+                        NcToken dim2Name = aVar-&gt;get_dim(2)-&gt;name();
+                        if ((strcmp(dim2Name, &quot;nVertLevels&quot;)) 
+                                        &amp;&amp; (strcmp(dim2Name, &quot;nVertLevelsP1&quot;))) {
+                                continue;
+                        }
+
+                        // Add to cell or point var array
+                        if (isVertexData) {  // means it is dual cell data
+                                dualCellVarIndex++;
+                                if (dualCellVarIndex &gt; MAX_VARS-1) {
+                                        cerr &lt;&lt; &quot;Exceeded number of cell vars.&quot; &lt;&lt; endl;
+                                        exit(1);
+                                }
+                                dualCellVars[dualCellVarIndex] = aVar;
+                                //cout &lt;&lt; &quot;Adding var &quot; &lt;&lt; aVar-&gt;name() &lt;&lt; &quot; to dualCellVars&quot; &lt;&lt; endl;
+                        } else if (isCellData) { // means it is dual vertex data
+                // check for u/v/w vectors
+
+                if (!strncmp(aVar-&gt;name(), &quot;uReconstruct&quot;, 12)) {
+                    if (!strcmp(aVar-&gt;name(), &quot;uReconstructZonal&quot;)) {
+                            vectorVars[0] = aVar;
+                            isUVector = true;
+                    } else if (!strcmp(aVar-&gt;name(), &quot;uReconstructMeridional&quot;)) {
+                            vectorVars[1] = aVar;
+                            isVVector = true;
+                    }
+                } else if (strcmp(aVar-&gt;name(), &quot;tracers&quot;)) {
+                                        dualPointVarIndex++;
+                                        if (dualPointVarIndex &gt; MAX_VARS-1) {
+                                                cerr &lt;&lt; &quot;Exceeded number of point vars.&quot; &lt;&lt; endl;
+                                                exit(1);
+                                        }
+                                        dualPointVars[dualPointVarIndex] = aVar;
+                                        //cout &lt;&lt; &quot;Adding var &quot; &lt;&lt; aVar-&gt;name() &lt;&lt; &quot; to dualPointVars&quot; &lt;&lt; endl;
+                                } else { // case of tracers, add each as &quot;tracer0&quot;, &quot;tracer1&quot;, etc.
+                                        tracersExist = true;
+                                        int numTracers = aVar-&gt;get_dim(3)-&gt;size();
+                                        for (int t = 0; t &lt; numTracers; t++) {
+                                                dualPointVarIndex++;
+                                                if (dualPointVarIndex &gt; MAX_VARS-1) {
+                                                        cerr &lt;&lt; &quot;Exceeded number of point vars.&quot; &lt;&lt; endl;
+                                                        exit(1);
+                                                }
+                                                dualPointVars[dualPointVarIndex] = aVar;
+                                                //cout &lt;&lt; &quot;Adding var &quot; &lt;&lt; aVar-&gt;name() &lt;&lt; &quot; to dualPointVars&quot; &lt;&lt; endl;
+                                        }
+                                }
+                        }
+                }
+        }
+
+        // TODO
+         // prompt the user to find out which fields are of interest?
+        // for now, assume all are of interest
+        
+        // get points  (centers of primal-mesh cells)
+
+    const float BLOATFACTOR = .5;
+        int myCellSize = (int)floor(nCells-&gt;size()*(1.0 + BLOATFACTOR));
+    CHECK_VAR(ncFile, &quot;lonCell&quot;);
+        double *xCellData = (double*)malloc(myCellSize * sizeof(double));
+        CHECK_MALLOC(xCellData);
+    NcVar*  xCellVar = ncFile.get_var(&quot;lonCell&quot;);
+        xCellVar-&gt;get(xCellData+1, nCells-&gt;size());
+    // point 0 is 0.0
+    *xCellData = 0.0;
+
+    const double PI = 3.141592;
+
+    // if atmospheric data, or zero centered, set center to 180 instead of 0
+    if (atmosphere || isZeroCentered) {
+        for (int j = 1; j &lt;= nCells-&gt;size(); j++) {
+            // need to shift over the point so center is at PI 
+            if (xCellData[j] &lt; 0) {
+                xCellData[j] += 2*PI;
+            }       
+        }       
+    }
+
+    double centerRad = centerLon * PI / 180.0;
+
+    if (centerLon != 180) {
+        for (int j = 1; j &lt;= nCells-&gt;size(); j++) {
+            // need to shift over the point if centerLon dictates
+            if (centerRad &lt; PI) {
+                if (xCellData[j] &gt; (centerRad + PI)) {
+                    xCellData[j] = -((2*PI) - xCellData[j]);
+                }
+            } else if (centerRad &gt; PI) {
+                if (xCellData[j] &lt; (centerRad - PI)) {
+                    xCellData[j] += 2*PI;
+                }
+            }
+        }
+    }
+
+    CHECK_VAR(ncFile, &quot;latCell&quot;);
+        double *yCellData = (double*)malloc(myCellSize * sizeof(double));
+        CHECK_MALLOC(yCellData);
+    NcVar*  yCellVar = ncFile.get_var(&quot;latCell&quot;);
+        yCellVar-&gt;get(yCellData+1, nCells-&gt;size());
+    // point 0 is 0.0
+    *yCellData = 0.0;
+
+        // get dual-mesh cells
+
+    CHECK_VAR(ncFile, &quot;cellsOnVertex&quot;);
+        int *cellsOnVertex = (int *) malloc((nVertices-&gt;size()) * vertexDegree-&gt;size() * 
+                sizeof(int));
+        CHECK_MALLOC(cellsOnVertex);
+        int myCOVSize = (int)floor(nVertices-&gt;size()*(1.0 + BLOATFACTOR))+1;
+        int *myCellsOnVertex = (int *) malloc(myCOVSize * vertexDegree-&gt;size() * sizeof(int));
+        CHECK_MALLOC(myCellsOnVertex);
+        NcVar *cellsOnVertexVar = ncFile.get_var(&quot;cellsOnVertex&quot;);
+        //cout &lt;&lt; &quot;getting cellsOnVertexVar</font>
<font color="gray">&quot;;
+        cellsOnVertexVar-&gt;get(cellsOnVertex, nVertices-&gt;size(), vertexDegree-&gt;size());
+
+        // allocate an array to map the extra points and cells to the original
+        // so that when obtaining data, we know where to get it
+        int *pointMap = (int*)malloc((int)floor(nCells-&gt;size()*BLOATFACTOR) * sizeof(int));
+        CHECK_MALLOC(pointMap);
+        int *cellMap = (int*)malloc((int)floor(nVertices-&gt;size()*BLOATFACTOR) * sizeof(int));
+        CHECK_MALLOC(cellMap);
+
+        
+        int *myptr = myCellsOnVertex;
+        int *myExtraX;
+        int *myExtraY;
+        int currentExtraPoint = numDualPoints;
+        int currentExtraCell = numDualCells;
+
+    // For each cell, examine vertices
+        // Add new points and cells where needed to account for wraparound.
+
+    int acell = 775;
+    int mirrorcell;
+    int apoint;
+    int mirrorpoint;
+
+
+        for (int j = 0; j &lt; numDualCells; j++ ) {
+                int *dualCells = cellsOnVertex + (j * vertexDegree-&gt;size());
+
+        // go through and make sure none of the referenced points are
+        // out of range (&lt;=0 or &gt;nCells-&gt;size())
+        // if so, set all to point 0
+        for (int k = 0; k &lt; vertexDegree-&gt;size(); k++)  {
+            if  ((dualCells[k] &lt;= 0) || (dualCells[k] &gt; nCells-&gt;size())) {
+                for (int m = 0; m &lt; vertexDegree-&gt;size(); m++)  {
+                    dualCells[m] = 0;
+                }
+                break;
+            } 
+        }
+
+        int lastk;
+
+        if (doBugfix) {
+            /////BUG FIX for problem where cells are stretching to a faraway point
+            lastk = vertexDegree-&gt;size()-1;
+            //const double thresh = .139626340159546; // 8 degrees
+            const double thresh = .06981317007977; // 8 degrees
+            for (int k = 0; k &lt; vertexDegree-&gt;size(); k++)  {
+                double xdiff = abs(xCellData[dualCells[k]]  - xCellData[dualCells[lastk]]);
+                double ydiff = abs(yCellData[dualCells[k]]  - yCellData[dualCells[lastk]]);
+                // Don't look at cells at map border
+                //if ((xdiff &lt;= 5.5) &amp;&amp; (xdiff &gt; (2*.06981317))) 
+                //if (((xdiff &lt;= 6) &amp;&amp; (xdiff &gt; 3)) || (ydiff &gt; .06981317)) 
+                if (((xdiff &gt; thresh) &amp;&amp; (ydiff &gt; thresh))
+                        //  || ((xdiff &lt;= 6) &amp;&amp; (xdiff &gt; 3))
+                        || (ydiff &gt; thresh)
+                   ) {
+                    for (int m = 0; m &lt; vertexDegree-&gt;size(); m++)  {
+                        dualCells[m] = 0;
+                    }
+                    break;
+                } 
+            }
+        }
+
+                lastk = vertexDegree-&gt;size()-1;
+                bool xWrap = false;
+                bool yWrap = false;
+                for (int k = 0; k &lt; vertexDegree-&gt;size(); k++) {
+                        if (abs(xCellData[dualCells[k]]  - xCellData[dualCells[lastk]]) &gt; 5.5) xWrap = true;
+                        //if (abs(yCellData[dualCells[k]]  - yCellData[dualCells[lastk]]) &gt; 2) yWrap = true;
+                        lastk = k;
+                }
+
+                if (xWrap || yWrap) {
+                        //cerr &lt;&lt; &quot;Cell wrap: &quot; &lt;&lt; j &lt;&lt; endl;
+                }
+
+                if (xWrap) {
+                        //cerr &lt;&lt; &quot;It wrapped in x direction&quot; &lt;&lt; endl;
+                        double anchorX = xCellData[dualCells[0]];
+                        double anchorY = yCellData[dualCells[0]];
+                        *myptr = *(dualCells);
+                        myptr++;
+
+            if (j == acell) { 
+               //cout &lt;&lt; &quot;cell &quot; &lt;&lt; acell &lt;&lt; &quot; anchor x: &quot; &lt;&lt; anchorX &lt;&lt; &quot; y: &quot; &lt;&lt; anchorY &lt;&lt; endl;
+            }
+
+                        // modify existing cell, so it doesn't wrap
+                        // move points to one side
+
+                        // first point is anchor it doesn't move
+            for (int k = 1; k &lt; vertexDegree-&gt;size(); k++) {
+                                double neighX = xCellData[dualCells[k]];
+                                double neighY = yCellData[dualCells[k]];
+
+                if (j == acell) { 
+                   //cout &lt;&lt; &quot;cell &quot; &lt;&lt; acell &lt;&lt; &quot; k: &quot; &lt;&lt; k &lt;&lt; &quot; x: &quot; &lt;&lt; neighX &lt;&lt; &quot; y: &quot; &lt;&lt; neighY &lt;&lt; endl;
+                }
+
+                                // add a new point, figure out east or west
+                                if (abs(neighX - anchorX) &gt; 5.5)  {
+                                        double neighEastX;
+                                        double neighWestX;
+
+                                        // add on east
+                                        if (neighX &lt; anchorX) {
+                        if (j == acell) { 
+                           //cout &lt;&lt; &quot;add on east&quot; &lt;&lt; endl;
+                        }
+                                                neighEastX = neighX + (2*PI);
+                                                xCellData[currentExtraPoint] = neighEastX;
+                                                yCellData[currentExtraPoint] = neighY;
+                                        } else { 
+                                                // add on west
+                        if (j == acell) { 
+                           //cout &lt;&lt; &quot;add on west&quot; &lt;&lt; endl;
+                        }
+                                                neighWestX = neighX - (2*PI);
+                                                xCellData[currentExtraPoint] = neighWestX;
+                                                yCellData[currentExtraPoint] = neighY;
+                                        }
+                        
+                    if (j == acell) {    
+                           //cout &lt;&lt; &quot;x: &quot; &lt;&lt; xCellData[currentExtraPoint] &lt;&lt; &quot; y: &quot; &lt;&lt; yCellData[currentExtraPoint] &lt;&lt; endl;
+                    }
+
+                    if (j == acell) { 
+                       //cout &lt;&lt; &quot;currentExtraPoint: &quot; &lt;&lt; currentExtraPoint &lt;&lt; endl;
+                    }
+
+                                        // add the new point to list of vertices
+                                        *myptr = currentExtraPoint;
+
+                                        // record mapping
+                                        *(pointMap + (currentExtraPoint - numDualPoints)) = dualCells[k];
+
+                    if (j == acell) { 
+                       mirrorpoint = currentExtraPoint;
+                       apoint = dualCells[k];
+                       //cout &lt;&lt; &quot;mirror point &quot; &lt;&lt; mirrorpoint &lt;&lt; &quot; has pointMap to: &quot; &lt;&lt; dualCells[k] &lt;&lt; endl;
+                    }
+
+                                        myptr++;
+                                        currentExtraPoint++;
+                                } else {
+                                        // use existing kth point 
+                    if (j == acell) {
+                        //cout &lt;&lt; &quot;use existing point&quot; &lt;&lt; endl;
+                    }
+                                        *myptr = dualCells[k];
+                                        myptr++;
+                                }
+                        }
+
+                        // add a mirror image cell on other side so there are no
+                        // gaps in the map
+
+                        // move anchor to other side
+                        if (anchorX &gt; centerRad) {
+                                anchorX = anchorX - (2*PI);
+                        } else {
+                                anchorX = anchorX + (2*PI);
+                        }
+        
+            if (j == acell) { 
+               //cout &lt;&lt; &quot;add new cell &quot; &lt;&lt; currentExtraCell &lt;&lt; &quot; to mirror &quot; &lt;&lt; acell &lt;&lt; &quot; anchorX: &quot; &lt;&lt; anchorX &lt;&lt; &quot; anchorY: &quot; &lt;&lt; anchorY &lt;&lt; endl;
+               mirrorcell = currentExtraCell;
+            }
+
+            // move addedCellsPtr to myCellsOnVertex extra cells area
+            int* addedCellsPtr = myCellsOnVertex + (currentExtraCell * vertexDegree-&gt;size());
+
+            // add point coord and add to list of cells
+                        xCellData[currentExtraPoint] = anchorX;
+                        yCellData[currentExtraPoint] = anchorY;
+                        *addedCellsPtr = currentExtraPoint;
+
+                        // record mapping
+                        *(pointMap + (currentExtraPoint - numDualPoints)) = dualCells[0];
+
+                        addedCellsPtr++;
+                        currentExtraPoint++;
+
+                        for (int k = 1; k &lt; vertexDegree-&gt;size(); k++) {
+                                double neighX = xCellData[dualCells[k]];
+                                double neighY = yCellData[dualCells[k]];
+
+                                // add a new point, figure out east or west
+                                if (abs(neighX - anchorX) &gt; 5.5)  {
+                                        double neighEastX;
+                                        double neighWestX;
+
+                                        // add on east
+                                        if (neighX &lt; anchorX) {
+                                                neighEastX = neighX + (2*PI);
+                                                xCellData[currentExtraPoint] = neighEastX;
+                                                yCellData[currentExtraPoint] = neighY;
+                                        } else { 
+                                                // add on west
+                                                neighWestX = neighX - (2*PI);
+                                                xCellData[currentExtraPoint] = neighWestX;
+                                                yCellData[currentExtraPoint] = neighY;
+                                        }
+
+                                        // add the new point to list of vertices
+                                        *addedCellsPtr = currentExtraPoint;
+
+                                        // record mapping
+                                        *(pointMap + (currentExtraPoint - numDualPoints)) = dualCells[k];
+
+                                        addedCellsPtr++;
+                                        currentExtraPoint++;
+                                } else {
+                                        // use existing kth point 
+                                        *addedCellsPtr = dualCells[k];
+                                        addedCellsPtr++;
+                                }
+                        }
+                        *(cellMap + (currentExtraCell - numDualCells)) = j;
+                        currentExtraCell++;
+                }
+                if (yWrap) {
+                        //cerr &lt;&lt; &quot;It wrapped in y direction&quot; &lt;&lt; endl;
+                }
+
+                // if cell doesn't extend past lat/lon perimeter, then add it to myCellsOnVertex
+                if (!xWrap &amp;&amp; !yWrap) {
+                        for (int k=0; k&lt; vertexDegree-&gt;size(); k++) {
+                                *myptr = *(dualCells+k);
+                                myptr++;
+                        }
+                }
+                if (currentExtraCell &gt; myCOVSize) {
+                        cerr &lt;&lt; &quot;Exceeded storage for extra cells!&quot; &lt;&lt; endl;
+                        return 1;
+                }
+                if (currentExtraPoint &gt; myCellSize) {
+                        cerr &lt;&lt; &quot;Exceeded storage for extra points!&quot; &lt;&lt; endl;
+                        return 1;
+                }
+        }        
+                                                
+
+        int varVertLevels = 0;
+        
+        // write a file with the geometry.
+
+        ostringstream geoFileName;
+        geoFileName &lt;&lt; &quot;geo_&quot; &lt;&lt; outputFileName;         
+        ofstream geoFile(geoFileName.str().c_str(), ios::out);
+        if (!geoFile)
+        {
+                cerr &lt;&lt; &quot;vtk output file could not be opened&quot; &lt;&lt;endl;
+                exit(1);
+        }
+
+    EncodeBase64 b64(&amp;geoFile);
+
+    // write header
+
+    string formatString;
+    if (writeBinary) {
+        formatString = &quot;binary&quot;;
+    } else {
+        formatString = &quot;ascii&quot;;
+    }
+
+    unsigned int binarySize = 0;
+
+        // write points  (the points are the primal-grid cell centers)
+
+
+        // write the point at each vertical level, plus one level for last layer
+
+    geoFile &lt;&lt; &quot;      &lt;Points&gt;&quot; &lt;&lt; endl;
+
+    // see if we can change to double
+
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;Points\&quot; NumberOfComponents=\&quot;3\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot; &lt;&lt; endl;
+
+    geoFile.precision(16);
+
+    float tmp = 0;
+
+    geoFile &lt;&lt; &quot;          &quot;;
+
+    if (writeBinary) {
+        b64.StartWriting();
+        if (singlelayer) {
+            binarySize = currentExtraPoint*sizeof(float)*3;
+        } else {
+            binarySize = currentExtraPoint*(maxNVertLevels+1)*sizeof(float)*3;
+        }
+        binarySize = padSize(binarySize);
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+
+        //cout &lt;&lt; &quot;Writing points at each level&quot; &lt;&lt; endl;
+
+        for (int j = 0; j &lt; currentExtraPoint; j++ )
+        {
+                if (abs(xCellData[j]) &lt; 1e-126) xCellData[j] = 0;
+                if (abs(yCellData[j]) &lt; 1e-126) yCellData[j] = 0;
+
+                float xLon = xCellData[j] * 180.0 / PI;
+                float yLat = yCellData[j] * 180.0 / PI;
+
+        if (singlelayer) {
+            if (writeBinary) {
+                tmp = 0;
+                b64.Write((const unsigned char*)&amp;xLon, sizeof(float));
+                b64.Write((const unsigned char*)&amp;yLat, sizeof(float));
+                b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+            } else {
+                geoFile &lt;&lt; &quot;          &quot; &lt;&lt; xLon &lt;&lt; &quot; &quot; &lt;&lt; yLat &lt;&lt; &quot; &quot; &lt;&lt; 0 &lt;&lt; endl;
+            }
+        } else {
+            for (int levelNum = 0; levelNum &lt; maxNVertLevels+1; levelNum++) {
+                tmp = -(((float)levelNum)*layerThickness);
+                if (writeBinary) {
+                    b64.Write((const unsigned char*)&amp;xLon, sizeof(float));
+                    b64.Write((const unsigned char*)&amp;yLat, sizeof(float));
+                    b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+                } else {
+                    geoFile &lt;&lt; &quot;          &quot; &lt;&lt; xLon &lt;&lt; &quot; &quot; &lt;&lt; yLat &lt;&lt; &quot; &quot; &lt;&lt; tmp &lt;&lt; endl;
+                }
+            }
+        }
+        }        
+
+    if (writeBinary) {
+        b64.EndWriting();
+        geoFile &lt;&lt; endl;
+    }
+
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;      &lt;/Points&gt;&quot; &lt;&lt; endl;
+
+    free (xCellData);
+    free (yCellData);
+
+    // Write dual-mesh cells
+    // Dual-mesh cells are triangles with primal-mesh cell 
+    // centers as the vertices.
+    // The number of dual-mesh cells is the number of vertices in the
+    // primal mesh.
+
+    geoFile &lt;&lt; &quot;      &lt;Cells&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Int32\&quot; Name=\&quot;connectivity\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot; &lt;&lt; endl;
+
+    // for each dual-mesh cell, write the points for each
+
+    if (writeBinary) {
+        geoFile &lt;&lt; &quot;          &quot;;
+        b64.StartWriting();
+        if (singlelayer) {
+            binarySize = currentExtraCell*vertexDegree-&gt;size()*sizeof(int);
+        } else {
+            binarySize = currentExtraCell*vertexDegree-&gt;size()*2*sizeof(int)
+                *maxNVertLevels;
+        }
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+
+    // for each dual-mesh cell, write number of points for each
+    // and then list the points by number
+
+    //cout &lt;&lt; &quot;Writing connectivity&quot; &lt;&lt; endl;
+
+    unsigned int val;
+
+    int* maxLevelCell;
+
+    if (includeTopography) {
+        CHECK_VAR(ncFile, &quot;maxLevelCell&quot;);
+        maxLevelCell = (int*)malloc((nCells-&gt;size()+1) * sizeof(int));
+        CHECK_MALLOC(maxLevelCell);
+        NcVar *maxLevelCellVar = ncFile.get_var(&quot;maxLevelCell&quot;);
+        maxLevelCellVar-&gt;get(maxLevelCell+1, nCells-&gt;size());
+    }
+
+    for (int j = 0; j &lt; currentExtraCell ; j++) {
+
+        // since primal vertex(pt) numbers  == dual cell numbers
+        // we go through the primal vertices, find the cells around
+        // them, and since those primal cell numbers are dual 
+        // point numbers,  
+        // we can write the cell numbers for the cellsOnVertex
+        // and those will be the numbers of the dual vertices (pts).
+
+        //cout &lt;&lt; &quot;j: &quot; &lt;&lt; j &lt;&lt; endl;
+
+        int* dualCells = myCellsOnVertex + (j * vertexDegree-&gt;size());
+
+        int minLevel; 
+
+        if (includeTopography) {
+            int* cells;
+            //check if it is a mirror cell, if so, get original
+            if (j &gt;= numDualCells) {
+                //cout &lt;&lt; &quot;setting origCell&quot; &lt;&lt; endl;
+                int origCell = *(cellMap + (j - numDualCells));
+                //cout &lt;&lt; &quot;mirror cell: &quot; &lt;&lt;j&lt;&lt; &quot; origCell: &quot;&lt;&lt; origCell &lt;&lt; endl;
+                cells = cellsOnVertex + (origCell*vertexDegree-&gt;size());
+            } else cells = cellsOnVertex + (j * vertexDegree-&gt;size());
+
+            //cout &lt;&lt; &quot;calc minLevel&quot; &lt;&lt; endl;
+            minLevel = maxLevelCell[cells[0]];
+            //cout &lt;&lt; &quot;initial minLevel:&quot; &lt;&lt; minLevel &lt;&lt; endl;
+            // Take the min of the maxLevelCell of each primal cell (dual point).
+            for (int k = 1; k &lt; vertexDegree-&gt;size(); k++)  {
+                //cout &lt;&lt; &quot; &quot; &lt;&lt; maxLevelCell[cells[k]];
+                minLevel = min(minLevel, maxLevelCell[cells[k]]);
+            }
+            //cout &lt;&lt; endl;
+        }
+
+        if (singlelayer) {
+            if (!writeBinary) geoFile &lt;&lt; &quot;          &quot;;
+
+            // If that min is greater than or equal to this output level,
+            // include the dual cell, otherwise set all points to zero.
+
+            if (includeTopography &amp;&amp; ((minLevel-1) &lt; outputVertLevel)) {
+                //cerr &lt;&lt; &quot;Setting all points to zero&quot; &lt;&lt; endl;
+                val = 0;
+                for (int k = 0; k &lt; vertexDegree-&gt;size(); k++)  {
+                    writeInt(b64, geoFile, val, writeBinary); 
+                }
+            } else {
+                for (int k = 0; k &lt; vertexDegree-&gt;size(); k++)  {
+                    writeInt(b64, geoFile, dualCells[k], writeBinary); 
+                }
+            }
+
+            if (!writeBinary) geoFile &lt;&lt; endl;
+        } else {
+
+            // for each level, write the cell
+            for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                if(!writeBinary) geoFile &lt;&lt; &quot;          &quot;;
+
+                if (includeTopography &amp;&amp; ((minLevel-1) &lt; levelNum)) {
+                    // setting all points to zero
+                    val = 0;
+                    for (int m = 0; m &lt; vertexDegree-&gt;size()*2; m++)  {
+                        writeInt(b64, geoFile, val, writeBinary); 
+                    }
+
+                } else {
+
+                    for (int k = 0; k &lt; vertexDegree-&gt;size(); k++) 
+                    { 
+                        val = (dualCells[k]*(maxNVertLevels+1)) + levelNum;
+                        writeInt(b64, geoFile, val, writeBinary); 
+                    }
+
+                    for (int k = 0; k &lt; vertexDegree-&gt;size(); k++) 
+                    {                
+                        val = (dualCells[k]*(maxNVertLevels+1)) + levelNum + 1;
+                        writeInt(b64, geoFile, val, writeBinary); 
+                    }
+                }
+                if (!writeBinary) geoFile &lt;&lt; endl;
+            }
+        }
+    }
+
+    if (writeBinary) {
+        b64.EndWriting();
+        geoFile &lt;&lt; endl;
+    }
+
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+
+    if (includeTopography) {
+        free (maxLevelCell);
+    }
+    free(cellsOnVertex);
+    free(myCellsOnVertex);
+
+
+    // Specify the offset into connectivity array for the end of each cell
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Int32\&quot; Name=\&quot;offsets\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot;;
+
+    int maxCells;
+    int maxPoints;
+
+    if (singlelayer) {
+        maxCells = currentExtraCell;
+    } else {
+        maxCells = currentExtraCell*maxNVertLevels;
+    }
+
+    if (writeBinary) {
+        geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        b64.StartWriting();
+        binarySize = maxCells*sizeof(int);
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+
+    int counter = 0;
+    unsigned int offset = 0;
+
+    for (int j = 0; j &lt; maxCells ; j++) {
+        if ((!writeBinary) &amp;&amp; (counter%6 == 0)) geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        if (singlelayer) {
+            offset += vertexDegree-&gt;size();
+        } else {
+            offset += 2*vertexDegree-&gt;size();
+        }
+        writeInt(b64, geoFile, offset, writeBinary); 
+        counter++;
+    }
+
+    if (writeBinary) {
+        b64.EndWriting();
+    }
+
+    geoFile &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+
+    // write cell types 
+    unsigned char cellType;
+    switch (vertexDegree-&gt;size()) {
+        case 3:
+            if (singlelayer) {
+                cellType = VTK_TRIANGLE;
+            } else {
+                cellType = VTK_WEDGE;
+            }
+            break;
+        case 4:
+            if (singlelayer) {
+                cellType = VTK_QUAD;
+            } else {
+                cellType = VTK_HEXAHEDRON;
+            }
+            break;
+        default:
+            break;
+    }
+
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;UInt8\&quot; Name=\&quot;types\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot;;
+
+    if (writeBinary) {
+        geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        b64.StartWriting();
+        binarySize = maxCells*sizeof(char);
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+
+    for (int j = 0; j &lt; maxCells ; j++) {
+        if ((!writeBinary) &amp;&amp; (j%6 == 0)) {
+            geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        }
+        writeChar(b64, geoFile, cellType, writeBinary); 
+    }
+
+    if (writeBinary) b64.EndWriting();
+
+    geoFile &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;      &lt;/Cells&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;    &lt;/Piece&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;  &lt;/UnstructuredGrid&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;&lt;/VTKFile&gt;&quot; &lt;&lt; endl;
+
+    geoFile.close();
+
+    // For each timestep, write data for each level
+
+
+        // for each timestep, copy the geometry file, since we don't want to
+        // have to recompute the points
+        for (int i = startTimeStep; i &lt;= finishTimeStep; i++) {
+
+                ostringstream vtkFileName;
+                vtkFileName &lt;&lt; i &lt;&lt; outputFileName;
+                ofstream vtkFile(vtkFileName.str().c_str(), ios::out);
+                if (!vtkFile)
+                {
+                        cerr &lt;&lt; &quot;vtk output file could not be opened&quot; &lt;&lt;endl;
+                        exit(1);
+                }
+
+                vtkFile.precision(16);
+        vtkFile &lt;&lt; &quot;&lt;VTKFile type=\&quot;UnstructuredGrid\&quot; version=\&quot;0.1\&quot; byte_order=\&quot;LittleEndian\&quot;&gt;&quot; &lt;&lt; endl;
+        vtkFile &lt;&lt; &quot;  &lt;UnstructuredGrid&gt;&quot; &lt;&lt; endl;
+
+        if (singlelayer) {
+           maxPoints = currentExtraPoint;
+        } else {
+           maxPoints = currentExtraPoint*(maxNVertLevels+1);
+        }
+
+        vtkFile &lt;&lt; &quot;    &lt;Piece NumberOfPoints=\&quot;&quot; &lt;&lt; maxPoints &lt;&lt; &quot;\&quot; NumberOfCells=\&quot;&quot; &lt;&lt; maxCells  &lt;&lt; &quot;\&quot;&gt;&quot; &lt;&lt; endl; 
+
+        int vertLevelIndex = 0;
+        if (singlelayer) vertLevelIndex = outputVertLevel;
+
+                // If by point, write out point data
+        vtkFile &lt;&lt; &quot;      &lt;PointData&gt;&quot; &lt;&lt; endl;
+
+                int printstep = -1;
+
+                if (i == printstep) cout &lt;&lt; &quot;TIME STEP: &quot; &lt;&lt; i &lt;&lt; endl;
+
+                int tracerNum = 0;
+
+        double* dualPointVarData;
+        dualPointVarData = (double*)malloc((sizeof(double)) * currentExtraPoint * maxNVertLevels);
+        CHECK_MALLOC(dualPointVarData);
+
+        EncodeBase64 vtkb64(&amp;vtkFile);
+
+                for (int v = 0; v &lt;= dualPointVarIndex; v++) {
+
+                        // Read variable number v data for that timestep
+
+                        varVertLevels = dualPointVars[v]-&gt;get_dim(2)-&gt;size();
+
+                        bool isTracer = false;
+
+                        if (!strcmp(dualPointVars[v]-&gt;name(), &quot;tracers&quot;)) {
+                                isTracer = true;
+                        // Uncomment if want to exclude tracers.  
+                        //        continue;
+                        }
+
+                        // Write variable number v data for that timestep
+
+                        if (isTracer) {
+                                dualPointVars[v]-&gt;set_cur(i, 0, vertLevelIndex, tracerNum);
+                if (singlelayer) {
+                    dualPointVars[v]-&gt;get(dualPointVarData+1, 1, nCells-&gt;size(), 1, 1);
+                } else {
+                    dualPointVars[v]-&gt;get(dualPointVarData+maxNVertLevels, 1, nCells-&gt;size(), maxNVertLevels, 1);
+                }
+                        } else {
+                                dualPointVars[v]-&gt;set_cur(i, 0, vertLevelIndex);
+                if (singlelayer) {
+                    dualPointVars[v]-&gt;get(dualPointVarData+1, 1, nCells-&gt;size(), 1);
+                } else {
+                    dualPointVars[v]-&gt;get(dualPointVarData+maxNVertLevels, 1, nCells-&gt;size(), maxNVertLevels);
+                }
+                        }
+
+            vtkFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;&quot; &lt;&lt; dualPointVars[v]-&gt;name();
+            if(isTracer) vtkFile &lt;&lt; tracerNum+1;
+            vtkFile &lt;&lt; &quot;\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt; &quot; &lt;&lt; endl;
+
+            // Write variable number v data for that timestep
+
+            vtkFile &lt;&lt; &quot;          &quot;;
+
+                        float defaultPointVal = 0.0;
+
+                        double *var_target;
+                        float validData;
+
+            if (writeBinary) {
+                vtkb64.StartWriting();
+                binarySize = maxPoints*sizeof(float);
+                binarySize = padSize(binarySize);
+                //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+                vtkb64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+            }
+
+            counter = 0;
+
+                        //write dummy
+            // 0th dualPointVarData value is a filler, zero, which is not necessarily in 
+            // the range of the other data, so we look at the 1st value instead for our dummy
+            if (singlelayer) {
+                var_target = dualPointVarData + 1;
+                writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                        } else {
+                var_target = dualPointVarData + maxNVertLevels;
+                for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                    var_target++;
+                }
+
+                // write highest level dummy point (duplicate of last level)
+                var_target--;
+                writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+
+                // Now set the var_target to the 1st data value
+                var_target = dualPointVarData + maxNVertLevels;
+            }
+
+                        for (int j = 1; j &lt; numDualPoints; j++) {
+
+                if (singlelayer) {
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                                        var_target++;
+                } else {
+
+                    // write data for one point -- lowest level to highest
+                    for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                        writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                        var_target++;
+                    }
+                
+                    // for last layer of dual points, repeat last level's values
+                    // Need Mark's input on this one
+                    var_target--;
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                    var_target++;
+                }
+                        }
+
+                        // put out data for extra points
+                        for (int j = numDualPoints; j &lt; currentExtraPoint; j++) {
+                if (j == mirrorpoint) {
+                    //cout &lt;&lt; &quot;data for mirror point &quot; &lt;&lt; mirrorpoint &lt;&lt; &quot; from point &quot; &lt;&lt; *(pointMap + j - numDualPoints) &lt;&lt; endl;
+                }
+                // use map to find out what point data we are using
+                                var_target = dualPointVarData + ((*(pointMap + j - numDualPoints))*maxNVertLevels);
+
+                if (singlelayer) {
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                                        validData = convertDouble2ValidFloat (*var_target);
+                                        var_target++;
+                } else {
+                    // write data for one point -- lowest level to highest
+                    for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                        writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                        var_target++;
+                    }
+                
+                    // for last layer of dual points, repeat last level's values
+                    // Need Mark's input on this one
+                    var_target--;
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                }
+                        }
+            if (writeBinary) vtkb64.EndWriting();
+            vtkFile &lt;&lt; endl &lt;&lt;  &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+
+            if (isTracer) tracerNum++;
+                }
+
+        free (dualPointVarData);
+
+        float validData;
+        const int maxDim = 2;  //z is always 0 for vectors in lat/lon projection
+
+        if (isUVector) {
+            vtkFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;uReconstruct\&quot; NumberOfComponents=\&quot;3\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt; &quot; &lt;&lt; endl;
+
+            double *vectorData[maxDim] = {NULL, NULL};
+            for (int d = 0; d &lt; maxDim; d++) {
+                vectorVars[d]-&gt;set_cur(i, 0, vertLevelIndex);
+                if (singlelayer) {
+                    vectorData[d] = (double*)malloc((sizeof(double)) * (nCells-&gt;size() + 1));
+                    vectorVars[d]-&gt;get(vectorData[d]+1, 1, nCells-&gt;size(), 1);
+                } else {
+                    vectorData[d] = (double*)malloc((sizeof(double)) * (nCells-&gt;size() + 1) * maxNVertLevels);
+                    vectorVars[d]-&gt;get(vectorData[d]+maxNVertLevels, 1, nCells-&gt;size(), maxNVertLevels);
+                }
+                CHECK_MALLOC(vectorData[d]);
+            }
+
+            vtkFile &lt;&lt; &quot;          &quot;;
+            if (writeBinary) {
+                vtkb64.StartWriting();
+                binarySize = maxPoints*sizeof(float)*3;
+                binarySize = padSize(binarySize);
+                //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+                vtkb64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+            }
+
+            double* var_target;
+
+            // dummy first
+            if (singlelayer) {
+                for (int d= 0; d &lt; maxDim; d++) {
+                    var_target = vectorData[d] + 1;
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                }
+                //third dim is 0
+                writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                if (!writeBinary) vtkFile &lt;&lt; endl;
+            } else {
+                for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                    for (int d= 0; d &lt; maxDim; d++) {
+                        var_target = vectorData[d]+maxNVertLevels+levelNum; 
+                        writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                    }
+                    //third dim is 0
+                    writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                    if (!writeBinary) vtkFile &lt;&lt; endl;
+                }
+            }
+            // write highest level dummy point
+            if (multilayer) {
+                for (int d= 0; d &lt; maxDim; d++) {
+                    var_target = vectorData[d]+maxNVertLevels+(maxNVertLevels-1);
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                }
+                //third dim is 0
+                writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                if (!writeBinary) vtkFile &lt;&lt; endl;
+            }
+
+            // rest of data
+            for (int j = 1; j &lt; numDualPoints; j++)
+            {
+                if (singlelayer) {
+                    for (int d= 0; d &lt; maxDim; d++) {
+                        writeFloat(vtkb64, vtkFile, *(vectorData[d] + j), writeBinary);
+                    }
+                    //third dim is 0
+                    writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                    if (!writeBinary) vtkFile &lt;&lt; endl;
+                } else {
+                    for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                        for (int d= 0; d &lt; maxDim; d++) {
+                            writeFloat(vtkb64, vtkFile, *(vectorData[d] + (j*maxNVertLevels) + levelNum), writeBinary);
+                        }
+                        //third dim is 0
+                        writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                        if (!writeBinary) vtkFile &lt;&lt; endl;
+                    }
+                    // for last layer of dual points, repeat last level's values
+                    // Need Mark's input on this one
+                    for (int d= 0; d &lt; maxDim; d++) {
+                        writeFloat(vtkb64, vtkFile, *(vectorData[d]+(j*maxNVertLevels)+maxNVertLevels-1), writeBinary);
+                    }
+                    //third dim is 0
+                    writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                    if (!writeBinary) vtkFile &lt;&lt; endl;
+                }
+            }
+
+                        // put out data for extra points
+                        for (int j = numDualPoints; j &lt; currentExtraPoint; j++) {
+
+                // use map to find out what point data we are using
+                                int var_target = ((*(pointMap + j - numDualPoints))*maxNVertLevels);
+
+                if (singlelayer) {
+                    for (int d= 0; d &lt; maxDim; d++) {
+                        writeFloat(vtkb64, vtkFile, *(vectorData[d]+var_target), writeBinary);
+                    }
+                    //third dim is 0
+                    validData = 0;
+                    writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                    if (!writeBinary) vtkFile &lt;&lt; endl;
+                } else {
+                    // write data for one point -- lowest level to highest
+                    for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++) {
+                        for (int d= 0; d &lt; maxDim; d++) {
+                            writeFloat(vtkb64, vtkFile, *(vectorData[d]+var_target+levelNum), writeBinary);
+                        }
+                        //third dim is 0
+                        writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                        if (!writeBinary) vtkFile &lt;&lt; endl;
+                    }
+                
+                    // for last layer of dual points, repeat last level's values
+                    for (int d= 0; d &lt; maxDim; d++) {
+                        writeFloat(vtkb64, vtkFile, *(vectorData[d]+var_target+maxNVertLevels-1), writeBinary);
+                    }
+                    //third dim is 0
+                    writeFloat(vtkb64, vtkFile, 0.0, writeBinary);
+                    if (!writeBinary) vtkFile &lt;&lt; endl;
+                }
+            }
+            if (writeBinary) {
+                vtkb64.EndWriting();
+                vtkFile &lt;&lt; endl;
+            }
+            vtkFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+            for (int d = 0; d &lt; maxDim; d++) {
+                free(vectorData[d]);
+            }
+        }
+
+        vtkFile &lt;&lt; &quot;      &lt;/PointData&gt;&quot; &lt;&lt; endl;
+
+                // if by cell, then write out cell data
+        double* dualCellVarData;
+        dualCellVarData = (double*)malloc((sizeof(double))  * currentExtraCell * maxNVertLevels);
+        CHECK_MALLOC(dualCellVarData);
+
+        vtkFile &lt;&lt; &quot;      &lt;CellData&gt;&quot; &lt;&lt; endl;
+
+
+                for (int v = 0; v &lt;= dualCellVarIndex; v++) {
+
+                        // Write variable number v data for that timestep
+            vtkFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;&quot; &lt;&lt; dualCellVars[v]-&gt;name() &lt;&lt; &quot;\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt; &quot; ;
+
+                        // Read variable number v data for that timestep and level
+                        dualCellVars[v]-&gt;set_cur(i, 0, vertLevelIndex);
+            if (singlelayer) {
+                dualCellVars[v]-&gt;get(dualCellVarData, 1, numDualCells, 1);
+            } else {
+                dualCellVars[v]-&gt;get(dualCellVarData, 1, numDualCells, maxNVertLevels);
+            }
+
+            if (writeBinary) {
+                vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                vtkb64.StartWriting();
+                binarySize = maxCells*sizeof(float);
+                binarySize = padSize(binarySize);
+                //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+                vtkb64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+            }
+
+            double *var_target = dualCellVarData;
+            counter = 0;
+
+                        for (int j = 0; j &lt; numDualCells; j++) {
+
+                if (singlelayer) {
+                    if ((!writeBinary) &amp;&amp; (j%6 == 0)) vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                                        var_target++;
+                } else {
+                    for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++)
+                    {
+                        if ((!writeBinary) &amp;&amp; (counter%6 == 0)) vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                        writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                        var_target++;
+                        counter++;
+                    }
+                }
+            }
+
+            counter = 0;
+                        for (int j = numDualCells; j &lt; currentExtraCell; j++) {
+                if (j == mirrorcell) { 
+                   //cout &lt;&lt; &quot;data for mirror cell &quot; &lt;&lt; mirrorcell &lt;&lt; &quot; from cell &quot; &lt;&lt; *(cellMap + j - numDualCells) &lt;&lt; endl;
+                }
+
+                
+                var_target = dualCellVarData + (*(cellMap + j - numDualCells))*maxNVertLevels;
+                if (singlelayer) {
+                    if ((!writeBinary) &amp;&amp; (j%6 == 0)) vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                    writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                } else {
+                    for (int levelNum = 0; levelNum &lt; maxNVertLevels; levelNum++)
+                    {
+                        if ((!writeBinary) &amp;&amp; (counter%6 == 0)) vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                        writeFloat(vtkb64, vtkFile, *var_target, writeBinary);
+                        var_target++;
+                        counter++;
+                    }
+                }    
+            }
+
+            if (writeBinary) {
+                vtkb64.EndWriting();
+            }
+            vtkFile &lt;&lt; endl &lt;&lt;  &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+
+        }
+
+        vtkFile &lt;&lt; &quot;      &lt;/CellData&gt;&quot; &lt;&lt; endl;
+
+        free(dualCellVarData);
+
+        vtkFile.close();
+
+        // append geoFile to vtkFile
+
+        string geoFileNameString = geoFileName.str();
+        string vtkFileNameString = vtkFileName.str();
+        int appRetVal = myAppendFile(&amp;geoFileNameString, &amp;vtkFileNameString);
+
+    }
+    
+    return(0);
+
+}
+


Property changes on: branches/ocean_projects/graphics/paraview/projection/projlatlonbin.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/x-c++src
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

Added: branches/ocean_projects/graphics/paraview/translator/EncodeBase64.cpp
===================================================================
--- branches/ocean_projects/graphics/paraview/translator/EncodeBase64.cpp                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/translator/EncodeBase64.cpp        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,169 @@
+using namespace std;
+
+#include &quot;EncodeBase64.h&quot;
+
+
+EncodeBase64::EncodeBase64(ofstream* astream)
+{
+  outstream = astream;
+  this-&gt;BufferLength = 0;
+}
+
+//----------------------------------------------------------------------------
+EncodeBase64::~EncodeBase64()
+{
+}
+
+
+
+//----------------------------------------------------------------------------
+static const unsigned char Base64EncodeTable[65] =
+&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ&quot;
+&quot;abcdefghijklmnopqrstuvwxyz&quot;
+&quot;0123456789+/&quot;;
+
+//----------------------------------------------------------------------------
+inline static unsigned char EncodeChar(unsigned char c)
+{
+  assert( c &lt; 65 );
+  return Base64EncodeTable[c];
+}
+
+//----------------------------------------------------------------------------
+void EncodeBase64::EncodePair(unsigned char i0,
+        unsigned char i1,
+        unsigned char *o0,
+        unsigned char *o1,
+        unsigned char *o2,
+        unsigned char *o3)
+{
+    *o0 = EncodeChar((i0 &gt;&gt; 2) &amp; 0x3F);
+    *o1 = EncodeChar(((i0 &lt;&lt; 4) &amp; 0x30)|((i1 &gt;&gt; 4) &amp; 0x0F));
+    *o2 = EncodeChar(((i1 &lt;&lt; 2) &amp; 0x3C));
+    *o3 = '=';
+}
+
+//----------------------------------------------------------------------------
+void EncodeBase64::EncodeSingle(unsigned char i0,
+        unsigned char *o0,
+        unsigned char *o1,
+        unsigned char *o2,
+        unsigned char *o3)
+{
+    *o0 = EncodeChar((i0 &gt;&gt; 2) &amp; 0x3F);
+    *o1 = EncodeChar(((i0 &lt;&lt; 4) &amp; 0x30));
+    *o2 = '=';
+    *o3 = '=';
+}
+
+//----------------------------------------------------------------------------
+void EncodeBase64::EncodeTriplet(unsigned char i0,
+        unsigned char i1,
+        unsigned char i2,
+        unsigned char *o0,
+        unsigned char *o1,
+        unsigned char *o2,
+        unsigned char *o3)
+{
+    *o0 = EncodeChar((i0 &gt;&gt; 2) &amp; 0x3F);
+    *o1 = EncodeChar(((i0 &lt;&lt; 4) &amp; 0x30)|((i1 &gt;&gt; 4) &amp; 0x0F));
+    *o2 = EncodeChar(((i1 &lt;&lt; 2) &amp; 0x3C)|((i2 &gt;&gt; 6) &amp; 0x03));
+    *o3 = EncodeChar(i2 &amp; 0x3F);
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::EncodeTriplet(unsigned char c0,
+                                                unsigned char c1,
+                                                unsigned char c2)
+{
+  // Encodes 3 bytes into 4 bytes and writes them to the output stream.
+  unsigned char out[4];
+  EncodeTriplet(c0, c1, c2,
+                                    &amp;out[0], &amp;out[1], &amp;out[2], &amp;out[3]);
+  return (outstream-&gt;write(reinterpret_cast&lt;char*&gt;(out), 4)? 1:0);
+}
+  
+//----------------------------------------------------------------------------
+int EncodeBase64::EncodeEnding(unsigned char c0,
+                                                unsigned char c1)
+{
+  // Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes.
+  unsigned char out[4];
+  EncodePair(c0, c1,
+                                 &amp;out[0], &amp;out[1], &amp;out[2], &amp;out[3]);
+  return (outstream-&gt;write(reinterpret_cast&lt;char*&gt;(out), 4)? 1:0);
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::EncodeEnding(unsigned char c0)
+{
+  // Encodes a 1-byte ending into 2 bytes and 2 pad bytes and writes.
+  unsigned char out[4];
+  EncodeSingle(c0, &amp;out[0], &amp;out[1], &amp;out[2], &amp;out[3]);
+  return (outstream-&gt;write(reinterpret_cast&lt;char*&gt;(out), 4)? 1:0);
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::StartWriting()
+{
+  this-&gt;BufferLength = 0;
+  this-&gt;WriteCount = 0;
+  //cout &lt;&lt; &quot;StartWriting!&quot; &lt;&lt; endl;
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::EndWriting()
+{
+  if(this-&gt;BufferLength == 1)
+    {
+    if(!this-&gt;EncodeEnding(this-&gt;Buffer[0])) { return 0; }
+    this-&gt;BufferLength = 0;
+    }
+  else if(this-&gt;BufferLength == 2)
+    {
+    if(!this-&gt;EncodeEnding(this-&gt;Buffer[0], this-&gt;Buffer[1])) { return 0; }
+    this-&gt;BufferLength = 0;
+    }
+  //cout &lt;&lt; &quot;EndWriting: WriteCount: &quot; &lt;&lt; WriteCount &lt;&lt; endl;
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int EncodeBase64::Write(const unsigned char* data,
+                                 unsigned long length)
+{ 
+  unsigned long totalLength = this-&gt;BufferLength + length;
+  const unsigned char* in = data;
+  const unsigned char* end = data+length;
+  
+  if(totalLength &gt;= 3)
+    {
+    if(this-&gt;BufferLength == 1)
+      {
+      if(!this-&gt;EncodeTriplet(this-&gt;Buffer[0], in[0], in[1])) { return 0; }
+      in += 2;
+      this-&gt;BufferLength = 0;
+      }
+    else if(this-&gt;BufferLength == 2)
+      {
+      if(!this-&gt;EncodeTriplet(this-&gt;Buffer[0], this-&gt;Buffer[1], in[0]))
+        { return 0; }
+      in += 1;
+      this-&gt;BufferLength = 0;
+      }
+    }
+  
+  while((end - in) &gt;= 3)
+    {
+    if(!this-&gt;EncodeTriplet(in[0], in[1], in[2])) { return 0; }
+    in += 3;
+    }
+  
+  while(in != end)
+    {
+    this-&gt;Buffer[this-&gt;BufferLength++] = *in++;
+    }
+  WriteCount++;
+  return 1;
+}


Property changes on: branches/ocean_projects/graphics/paraview/translator/EncodeBase64.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/x-c++src
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

Added: branches/ocean_projects/graphics/paraview/translator/EncodeBase64.h
===================================================================
--- branches/ocean_projects/graphics/paraview/translator/EncodeBase64.h                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/translator/EncodeBase64.h        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,72 @@
+using namespace std;
+
+#include &lt;iostream&gt;
+#include &lt;fstream&gt;
+#include &quot;stdlib.h&quot;
+#include &lt;assert.h&gt;
+
+class EncodeBase64 
+{
+public:
+  EncodeBase64(ofstream *outstream);
+  ~EncodeBase64();  
+
+  // Description:  
+  // Called after the stream position has been set by the caller, but
+  // before any Write calls.  The stream position should not be
+  // adjusted by the caller until after an EndWriting call.
+  int StartWriting();
+  
+  // Description:
+  // Write output data of the given length.
+  int Write(const unsigned char* data, unsigned long length);
+  
+  // Description:
+  // Called after all desired calls to Write have been made.  After
+  // this call, the caller is free to change the position of the
+  // stream.  Additional writes should not be done until after another
+  // call to StartWriting.
+  int EndWriting();
+  
+protected:
+  
+  // Methods to encode and write data.
+
+  // Number of un-encoded bytes left in Buffer from last call to Write.
+  unsigned int BufferLength;
+  unsigned int WriteCount;
+  unsigned char Buffer[2];
+  ofstream *outstream; 
+
+  // Description:  
+  // Encode 2 bytes into 4 bytes
+  static void EncodePair(unsigned char i0,
+                         unsigned char i1,
+                         unsigned char *o0,
+                         unsigned char *o1,
+                         unsigned char *o2,
+                         unsigned char *o3);
+
+  // Description:  
+  // Encode 1 byte into 4 bytes
+  static void EncodeSingle(unsigned char i0,
+                           unsigned char *o0,
+                           unsigned char *o1,
+                           unsigned char *o2,
+                           unsigned char *o3);
+  // Description:
+  // Encode 3 bytes into 4 bytes
+  static void EncodeTriplet(unsigned char i0,
+          unsigned char i1,
+          unsigned char i2,
+          unsigned char *o0,
+          unsigned char *o1,
+          unsigned char *o2,
+          unsigned char *o3);
+
+  int EncodeTriplet(unsigned char c0, unsigned char c1, unsigned char c2);
+  int EncodeEnding(unsigned char c0, unsigned char c1);
+  int EncodeEnding(unsigned char c0);
+  
+};
+


Property changes on: branches/ocean_projects/graphics/paraview/translator/EncodeBase64.h
___________________________________________________________________
Name: svn:mime-type
   + text/x-c++hdr
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

Modified: branches/ocean_projects/graphics/paraview/translator/Makefile
===================================================================
--- branches/ocean_projects/graphics/paraview/translator/Makefile        2010-08-12 22:02:03 UTC (rev 476)
+++ branches/ocean_projects/graphics/paraview/translator/Makefile        2010-08-16 22:07:43 UTC (rev 477)
@@ -1,18 +1,26 @@
 # NETCDF should point to the directory holding the netcdf lib and bin subdirs
 #NETCDF = /usr/projects/climate/bzhao/netcdf-3.6.1
-NETCDF = /usr/projects/climate/mhecht/netcdf-3.6.1
+#NETCDF = /usr/projects/climate/mhecht/netcdf-3.6.1
 #CC = gcc -m64
 CC = gcc
 INCLUDES = -I$(NETCDF)/include
-#LIBS = -L$(NETCDF)/lib -lnetcdf_c++ -lnetcdf -L/usr/lib -lstdc++
+LIBS = -L$(NETCDF)/lib -lnetcdf_c++ -lnetcdf -L/usr/lib -lstdc++
 
-LIBS = -L$(NETCDF)/lib -lnetcdf_c++ -lnetcdf \
-        -lstdc++ \
-        -L/opt/Intel/cce/10.0.023/lib/ -lirc
-#         -L/opt/Intel/cce/9.1.039/lib/ -lirc
+#LIBS = -L$(NETCDF)/lib -lnetcdf_c++ -lnetcdf \
+#        -lstdc++ \
+#        -L/opt/Intel/cce/10.0.023/lib/ -lirc
 
 transdual: nc2vtk_dual.cpp
         $(CC) $(INCLUDES) -o $@ $&lt;  $(LIBS)
 
+.cpp.o:
+        $(CC) $(MYDEBUG) $(INCLUDES) -c $&lt;
+
+EncodeBase64.o: EncodeBase64.cpp
+        $(CC) $(INCLUDES) -c $&lt; 
+
+transdualbin: nc2vtu_dualbin.cpp  EncodeBase64.o
+        $(CC) $(INCLUDES) -o $@ $&lt;  EncodeBase64.o $(LIBS)
+
 clean:
-        rm transdual
+        rm transdual transdualbin *.o

Added: branches/ocean_projects/graphics/paraview/translator/nc2vtu_dualbin.cpp
===================================================================
--- branches/ocean_projects/graphics/paraview/translator/nc2vtu_dualbin.cpp                                (rev 0)
+++ branches/ocean_projects/graphics/paraview/translator/nc2vtu_dualbin.cpp        2010-08-16 22:07:43 UTC (rev 477)
@@ -0,0 +1,853 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// This program translates a newpop netCDF data file to dual-grid binary VTU format
+// The variables that have time dim are automatically written.
+//
+// Assume all variables are of interest.
+// Assume variable data type is double.
+// Assume variable dims are (Time, nCells|nVertices, nVertLevels|nVertLevelsP1, [nTracers])
+// Assume no more than 100 vars each for cell and point data
+// Does not deal with edge data.
+// Handles vectors.
+// Doubles converted to floats in .vtu files follow these rules:
+//      if a NaN, then become -FLT_MAX.
+//      if positive infinity, then become FLT_MAX
+//      if negative infinity, then become -FLT_MAX
+//      if smaller than a float, then become 0.
+//      if not zero, but between -FLT_MIN and FLT_MIN make -FLT_MIN or FLT_MIN
+//      if outside of -FLT_MAX and FLT_MAX make -FLT_MAX or FLT_MAX
+//
+//
+// Version 1.7
+// Christine Ahrens
+// 7/23/2010 
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+#include &lt;iostream&gt;
+#include &lt;fstream&gt;
+#include &lt;sstream&gt;
+#include &quot;stdlib.h&quot;
+#include &quot;vtkCellType.h&quot;
+#include &quot;netcdfcpp.h&quot;
+#include &lt;string&gt;
+#include &lt;cmath&gt;
+#include &lt;cfloat&gt;
+#include &quot;EncodeBase64.h&quot;
+
+using namespace std;
+
+#define CHECK_MALLOC(ptr) \
+        if (ptr == NULL) { \
+                cerr &lt;&lt; &quot;malloc failed!</font>
<font color="blue">&quot;; \
+                exit(1); \
+        } 
+
+#define BUFF_SIZE 2048
+
+// append inFile to outFile
+int myAppendFile(string *inFile, string *outFile)
+{
+    char buff[BUFF_SIZE];
+    int readBytes = 1;
+
+    ifstream inFileStream(inFile-&gt;c_str(), ios::in|ios::binary);
+    if(!inFileStream)
+    {
+        return -1;
+    }
+
+    ofstream outFileStream(outFile-&gt;c_str(), ios::out|ios::app|ios::binary);
+    if(!outFileStream)
+    {
+        return -1;
+    }
+
+    while(readBytes != 0)
+    {
+        inFileStream.read((char*)buff, BUFF_SIZE);
+        readBytes = inFileStream.gcount();
+        outFileStream.write((char*)buff, readBytes);
+    }
+    return 0;
+}
+
+#define MAX_VARS 100
+
+int my_isinf_f(float x){
+              if (isinf(x)) {
+                return (x &lt; 0.0 ? -1 : 1);
+        } else return 0;
+}
+
+unsigned int padSize(unsigned int binarySize) {
+        switch ((binarySize*4)%3) {
+            case 1:
+                binarySize = binarySize + 2;
+                break;
+            case 2:
+                binarySize++;
+                break;
+            case 0:
+                break;
+        }
+        return binarySize;
+}
+
+float convertDouble2ValidFloat(double inputData) {
+
+        // check for NaN
+        if (inputData != inputData) {
+                //cerr &lt;&lt; &quot;found NaN!&quot; &lt;&lt; endl;
+                return -FLT_MAX;
+        }
+
+        // check for infinity
+        int retval = my_isinf_f((float)inputData);
+        if (retval &lt; 0) {
+                return -FLT_MAX;
+        } else if (retval &gt; 0) {
+                return FLT_MAX;
+        }
+
+        // check number too small for float
+        if (abs(inputData) &lt; 1e-126) return 0.0;
+
+        if ((float)inputData == 0) return 0.0;
+
+        if ((abs(inputData) &gt; 0) &amp;&amp; (abs(inputData) &lt; FLT_MIN)) {
+                if (inputData &lt; 0) return -FLT_MIN; else return FLT_MIN;
+        }
+
+        if (abs(inputData) &gt; FLT_MAX) {
+                if (inputData &lt; 0) return -FLT_MAX; else return FLT_MAX;
+        }
+
+        return (float)inputData;
+}
+
+int main(int argc, char* argv[])
+{
+        if ((argc &lt; 3) || (argc &gt; 4))  {
+                cerr &lt;&lt; &quot;Usage: transdualbin infile.nc outfile.vtu [verticalLevel]&quot; &lt;&lt; endl;
+                cerr &lt;&lt; &quot;Variables with time and vertical level are written out.&quot; &lt;&lt; endl;
+                cerr &lt;&lt; &quot;Tracer vars are named tracer1, tracer2, etc.&quot; &lt;&lt; endl;
+                cerr &lt;&lt; &quot;If vertical level is not specified, default is 0.&quot; &lt;&lt; endl;
+                cerr &lt;&lt; &quot;A series of vtu files will be created, one file for each time step.&quot; &lt;&lt; endl;
+                cerr &lt;&lt; &quot;with time prepended to the file name (e.g. 0outfile.vtu).&quot; &lt;&lt; endl;
+                cerr &lt;&lt; &quot;vtk datafile Version 2.0, transdualbin Version 1.7&quot; &lt;&lt; endl;
+                exit(1);
+        }
+
+                
+        NcFile ncFile(argv[1]);
+
+        if (!ncFile.is_valid()) 
+        {
+                cerr &lt;&lt; &quot;Couldn't open file: &quot; &lt;&lt; argv[1] &lt;&lt; endl;
+                exit(1);
+        }
+
+        NcDim* nCells = ncFile.get_dim(&quot;nCells&quot;);
+        NcDim* nVertices = ncFile.get_dim(&quot;nVertices&quot;);
+        NcDim* vertexDegree = ncFile.get_dim(&quot;vertexDegree&quot;);
+        NcDim* Time = ncFile.get_dim(&quot;Time&quot;);
+        NcDim* nVertLevels = ncFile.get_dim(&quot;nVertLevels&quot;);
+
+        // Can't check for this, b/c if not there it crashes program        
+        //NcDim* nVertLevelsP1 = ncFile.get_dim(&quot;nVertLevelsP1&quot;);
+        int maxNVertLevels = nVertLevels-&gt;size() + 1;
+        /*if (nVertLevelsP1 != NULL) {
+                maxNVertLevels = nVertLevelsP1-&gt;size();
+        }
+*/

+        int outputVertLevel = 0;
+
+        if (argc == 4) {
+                outputVertLevel = atoi(argv[3]);
+                if (outputVertLevel &gt; (maxNVertLevels-1)) {
+                        cerr &lt;&lt; &quot;Specified vertical level &quot; &lt;&lt; outputVertLevel;
+                        cerr &lt;&lt; &quot; doesn't exist.  The highest level is level &quot;;
+                        cerr &lt;&lt; maxNVertLevels-1 &lt;&lt; &quot;.&quot; &lt;&lt; endl;
+                        exit(1);
+                }
+        }
+
+
+        // figure out what variables to visualize
+        NcVar* dualCellVars[MAX_VARS];
+        NcVar* dualPointVars[MAX_VARS];
+    NcVar* vectorVars[3][3];
+        int dualCellVarIndex = -1;
+        int dualPointVarIndex = -1;
+        int numDualCells = nVertices-&gt;size();
+        int numDualPoints = nCells-&gt;size()+1;
+        
+        int numVars = ncFile.num_vars();
+
+        bool tracersExist = false;
+    bool isUVector = false;
+    bool isVVector = false;
+    bool isWVector = false;
+
+    bool writeBinary = true;
+
+        for (int i = 0; i &lt; numVars; i++) {
+                NcVar* aVar = ncFile.get_var(i);
+
+                // must have 3 dims 
+                // (Time, nCells | nVertices, nVertLevels | nVertLevelsP1)
+
+                int numDims = aVar-&gt;num_dims();
+                
+                if ((numDims != 3) &amp;&amp; (strcmp(aVar-&gt;name(), &quot;tracers&quot;))) {
+                        continue;
+                } else {
+                        // TODO, check if it is a double
+                        // assume a double for now
+
+                        // check for Time dim 0
+                        NcToken dim0Name = aVar-&gt;get_dim(0)-&gt;name();
+                        if (strcmp(dim0Name, &quot;Time&quot;)) 
+                                continue;
+
+                        // check for dim 1 being num vertices or cells 
+                        bool isVertexData = false;
+                        bool isCellData = false;
+                        NcToken dim1Name = aVar-&gt;get_dim(1)-&gt;name();
+                        if (!strcmp(dim1Name, &quot;nVertices&quot;)) 
+                                isVertexData = true;
+                        else if (!strcmp(dim1Name, &quot;nCells&quot;)) 
+                                isCellData = true; 
+                        else continue;
+
+                        // check if dim 2 is nVertLevels or nVertLevelsP1, too
+                        NcToken dim2Name = aVar-&gt;get_dim(2)-&gt;name();
+                        if ((strcmp(dim2Name, &quot;nVertLevels&quot;)) 
+                                &amp;&amp; (strcmp(dim2Name, &quot;nVertLevelsP1&quot;))) {
+                                continue;
+                        }
+
+                        // check if we have data for the selected level
+                        if (aVar-&gt;get_dim(2)-&gt;size()-1 &lt; outputVertLevel) {
+                                cout &lt;&lt; &quot;No data found for level &quot;;
+                                cout &lt;&lt; outputVertLevel &lt;&lt; &quot; for variable &quot;;
+                                cout &lt;&lt; aVar-&gt;name() &lt;&lt; endl;
+                                continue;
+                        }
+
+                        // Add to cell or point var array
+                        if (isVertexData) {  // means it is dual cell data
+                                dualCellVarIndex++;
+                                if (dualCellVarIndex &gt; MAX_VARS-1) {
+                                        cerr &lt;&lt; &quot;Exceeded number of cell vars.&quot; &lt;&lt; endl;
+                                        exit(1);
+                                }
+                                dualCellVars[dualCellVarIndex] = aVar;
+                        } else if (isCellData) { // means it is dual point data
+                // check for u/v/w vectors
+
+                if (!strncmp(aVar-&gt;name(), &quot;uReconstruct&quot;, 12)) {
+                    isUVector = true;
+                    switch (aVar-&gt;name()[12]) {
+                        case 'X':
+                            vectorVars[0][0] = aVar;
+                        case 'Y':
+                            vectorVars[0][1] = aVar;
+                        case 'Z':
+                            vectorVars[0][2] = aVar;
+                    }
+                } else if (!strncmp(aVar-&gt;name(), &quot;vReconstruct&quot;, 12)) {
+                    isVVector = true;
+                    switch (aVar-&gt;name()[12]) {
+                        case 'X':
+                            vectorVars[1][0] = aVar;
+                        case 'Y':
+                            vectorVars[1][1] = aVar;
+                        case 'Z':
+                            vectorVars[1][2] = aVar;
+                    }
+                } else if (!strncmp(aVar-&gt;name(), &quot;wReconstruct&quot;, 12)) {
+                    isWVector = true;
+                    switch (aVar-&gt;name()[12]) {
+                        case 'X':
+                            vectorVars[2][0] = aVar;
+                        case 'Y':
+                            vectorVars[2][1] = aVar;
+                        case 'Z':
+                            vectorVars[2][2] = aVar;
+                    }
+                } else if (strcmp(aVar-&gt;name(), &quot;tracers&quot;)) {
+                                        dualPointVarIndex++;
+                                        if (dualPointVarIndex &gt; MAX_VARS-1) {
+                                                cerr &lt;&lt; &quot;Exceeded number of point vars.&quot; &lt;&lt; endl;
+                                                exit(1);
+                                        }
+                                        dualPointVars[dualPointVarIndex] = aVar;
+                                } else { // case of tracers, add each as &quot;tracer0&quot;, &quot;tracer1&quot;, etc.
+                                        tracersExist = true;
+                                        int numTracers = aVar-&gt;get_dim(3)-&gt;size();
+                                        for (int t = 0; t &lt; numTracers; t++) {
+                                                dualPointVarIndex++;
+                                                if (dualPointVarIndex &gt; MAX_VARS-1) {
+                                                        cerr &lt;&lt; &quot;Exceeded number of point vars.&quot; &lt;&lt; endl;
+                                                        exit(1);
+                                                }
+                                                dualPointVars[dualPointVarIndex] = aVar;
+                                        }
+                                }        
+                        }
+                }
+        }
+
+        // TODO
+         // prompt the user to find out which fields are of interest?
+        // for now, assume all are of interest
+
+    // Write geometry to a geo+outputfile.vtu
+    ostringstream geoFileName;
+    geoFileName &lt;&lt; &quot;geo_&quot; &lt;&lt; argv[2];
+    ofstream geoFile(geoFileName.str().c_str(), ios::out|ios::binary);
+    if (!geoFile)
+    {
+            cerr &lt;&lt; &quot;vtu geo output file could not be opened&quot; &lt;&lt;endl;
+            exit(1);
+    }
+
+        // get points  (centers of primal-mesh cells)
+
+        // TO DO check malloc return vals.
+
+        double *xCellData = (double*)malloc(nCells-&gt;size() 
+                * sizeof(double));
+        CHECK_MALLOC(xCellData);
+        NcVar *xCellVar = ncFile.get_var(&quot;xCell&quot;);
+        xCellVar-&gt;get(xCellData, nCells-&gt;size());
+
+        double *yCellData = (double*)malloc(nCells-&gt;size() 
+                * sizeof(double));
+        CHECK_MALLOC(yCellData);
+        NcVar *yCellVar = ncFile.get_var(&quot;yCell&quot;);
+        yCellVar-&gt;get(yCellData, nCells-&gt;size());
+
+        double *zCellData = (double*)malloc(nCells-&gt;size() 
+                * sizeof(double));
+        CHECK_MALLOC(zCellData);
+        NcVar *zCellVar = ncFile.get_var(&quot;zCell&quot;);
+        zCellVar-&gt;get(zCellData, nCells-&gt;size());
+
+    // get num cells on each vertex
+    // how do I do that?
+    /*
+        int *cellsOnVertex = (int *) malloc((nVertices-&gt;size()) * vertexDegree-&gt;size() * 
+                sizeof(int));
+        //cout &lt;&lt; &quot;ptr for cellsOnVertex&quot;  &lt;&lt; cellsOnVertex &lt;&lt; endl;
+        CHECK_MALLOC(cellsOnVertex);
+        NcVar *cellsOnVertexVar = ncFile.get_var(&quot;cellsOnVertex&quot;);
+        //cout &lt;&lt; &quot;getting cellsOnVertexVar</font>
<font color="blue">&quot;;
+        cellsOnVertexVar-&gt;get(cellsOnVertex, nVertices-&gt;size(), vertexDegree-&gt;size());
+*/
+
+    EncodeBase64 b64(&amp;geoFile);
+
+    // write header
+
+    string formatString;
+    if (writeBinary) {
+        formatString = &quot;binary&quot;;
+    } else {
+        formatString = &quot;ascii&quot;;
+    }
+
+    unsigned int binarySize = 0;
+
+    // write points  (the points are the primal-grid cell centers)
+
+    geoFile &lt;&lt; &quot;      &lt;Points&gt;&quot; &lt;&lt; endl;
+
+    // see if we can change to double
+
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;Points\&quot; NumberOfComponents=\&quot;3\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot; &lt;&lt; endl;
+
+    // first write a dummy point, because the climate code
+    // starts their cell numbering at 1 and VTK starts it at
+    // 0
+    geoFile.precision(16);
+    float tmp = 0;
+
+    geoFile &lt;&lt; &quot;          &quot;;
+
+    if (writeBinary) {
+        b64.StartWriting();
+        binarySize = numDualPoints*sizeof(float)*3;
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+        b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+        b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+        b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+    } else {
+        geoFile &lt;&lt; (float)0.0 &lt;&lt; &quot; &quot; &lt;&lt; (float)0.0 &lt;&lt; &quot; &quot; &lt;&lt; (float)0.0 &lt;&lt; endl;
+    }
+
+    for (int j = 0; j &lt; nCells-&gt;size(); j++ )
+    {
+        geoFile.precision(16);
+        if (abs(xCellData[j]) &lt; 1e-126) xCellData[j] = 0;
+        if (abs(yCellData[j]) &lt; 1e-126) yCellData[j] = 0;
+        if (abs(zCellData[j]) &lt; 1e-126) zCellData[j] = 0;
+        if (writeBinary) {
+            tmp = (float)xCellData[j];
+            b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+            tmp = (float)yCellData[j];
+            b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+            tmp = (float)zCellData[j];
+            b64.Write((const unsigned char*)&amp;tmp, sizeof(float));
+        } else {
+            geoFile &lt;&lt; &quot;          &quot; &lt;&lt; (float)xCellData[j] &lt;&lt; &quot; &quot; &lt;&lt; (float)yCellData[j] &lt;&lt; &quot; &quot;
+                &lt;&lt; (float)zCellData[j] &lt;&lt; endl;
+        }
+    }        
+    if (writeBinary) {
+        b64.EndWriting();
+        geoFile &lt;&lt; endl;
+    }
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;      &lt;/Points&gt;&quot; &lt;&lt; endl;     
+
+    free (xCellData);
+    free (yCellData);
+    free (zCellData);
+
+    // Write dual-mesh cells
+    // Dual-mesh cells are triangles with primal-mesh cell 
+    // centers as the vertices.
+    // The number of dual-mesh cells is the number of vertices in the
+    // primal mesh.
+
+        // get dual-mesh cells
+
+        int *cellsOnVertex = (int *) malloc((nVertices-&gt;size()) * vertexDegree-&gt;size() * 
+                sizeof(int));
+        CHECK_MALLOC(cellsOnVertex);
+        NcVar *cellsOnVertexVar = ncFile.get_var(&quot;cellsOnVertex&quot;);
+        cellsOnVertexVar-&gt;get(cellsOnVertex, nVertices-&gt;size(), vertexDegree-&gt;size());
+
+    geoFile &lt;&lt; &quot;      &lt;Cells&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Int32\&quot; Name=\&quot;connectivity\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot; &lt;&lt; endl;
+
+    // for each dual-mesh cell, write the points for each
+
+    if (writeBinary) {
+        geoFile &lt;&lt; &quot;          &quot;;
+        b64.StartWriting();
+        binarySize = numDualCells*sizeof(int)*vertexDegree-&gt;size();
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+
+    for (int j = 0; j &lt; numDualCells ; j++) {
+
+        if (!writeBinary) geoFile &lt;&lt; &quot;          &quot;;
+
+        // since primal vertex(pt) numbers  == dual cell numbers
+        // we go through the primal vertices, find the cells around
+        // them, and since those primal cell numbers are dual 
+        // point numbers,  
+        // we can write the cell numbers for the cellsOnVertex
+        // and those will be the numbers of the dual vertices (pts).
+        
+        int* dualCells = cellsOnVertex + (j * vertexDegree-&gt;size());
+
+        // go through and make sure none of the referenced points are
+        // out of range (&lt;=0 or &gt; nCells-&gt;size())
+
+        for (int k = 0; k &lt; vertexDegree-&gt;size(); k++)  {
+            if  ((dualCells[k] &lt;= 0) || (dualCells[k] &gt; nCells-&gt;size())) {
+
+                // if any out of range exclude entire cell by setting
+                // all of its points to 0
+                for (int m = 0; m &lt; vertexDegree-&gt;size(); m++)  {
+                    dualCells[m] = 0;
+                }
+                break;
+            }
+        }
+
+        for (int k = 0; k &lt; vertexDegree-&gt;size(); k++)
+        {
+            if (writeBinary) {
+                b64.Write((const unsigned char*)&amp;dualCells[k], sizeof(int));
+            } else {
+                geoFile &lt;&lt; dualCells[k] &lt;&lt; &quot; &quot;;
+            }
+        }
+        if (!writeBinary) geoFile &lt;&lt; endl;
+    }        
+
+    if (writeBinary) {
+        b64.EndWriting();
+        geoFile &lt;&lt; endl;
+    }
+
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+
+    free(cellsOnVertex);
+
+
+    // Specify the offset into connectivity array for the end of each cell
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Int32\&quot; Name=\&quot;offsets\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot;;
+
+    if (writeBinary) {
+        geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        b64.StartWriting();
+        binarySize = numDualCells*sizeof(int);
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+    int counter = 0;
+    for (int j = 0; j &lt; numDualCells ; j++) {
+        if ((!writeBinary) &amp;&amp; (counter%6 == 0)) {
+            geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        }
+        counter += vertexDegree-&gt;size();
+        if (writeBinary) {
+            b64.Write((const unsigned char*)&amp;counter, sizeof(int));
+        } else {
+            geoFile &lt;&lt; counter &lt;&lt; &quot; &quot;;
+        }
+    }   
+    if (writeBinary) {
+        b64.EndWriting();
+    }
+    geoFile &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+
+    // write cell types 
+    int cellType;
+    if (vertexDegree-&gt;size() == 3) 
+        cellType = VTK_TRIANGLE;
+    else if (vertexDegree-&gt;size() == 4)
+        cellType = VTK_QUAD;
+    else cellType = VTK_POLYGON;
+
+    geoFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;UInt8\&quot; Name=\&quot;types\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt;&quot;;
+    if (writeBinary) {
+        geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        b64.StartWriting();
+        binarySize = numDualCells*sizeof(char);
+        binarySize = padSize(binarySize);
+        //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+        b64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+    }
+    for (int j = 0; j &lt; numDualCells ; j++) {
+        if ((!writeBinary) &amp;&amp; (j%6 == 0)) {
+            geoFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+        }
+        if (writeBinary) {
+            b64.Write((const unsigned char*)&amp;cellType, sizeof(unsigned char));
+        } else {
+            geoFile &lt;&lt; cellType &lt;&lt; &quot; &quot;;
+        }
+    }   
+    if (writeBinary) b64.EndWriting();
+    geoFile &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;      &lt;/Cells&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;    &lt;/Piece&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;  &lt;/UnstructuredGrid&gt;&quot; &lt;&lt; endl;
+    geoFile &lt;&lt; &quot;&lt;/VTKFile&gt;&quot; &lt;&lt; endl;
+
+    geoFile.close();
+
+        // decls for data storage
+        double* dualCellVarData;
+        double* dualPointVarData;
+
+        // allocate space for variables
+
+        int varVertLevels = 0;
+
+
+
+        // for each time step, write a file with the time prepended to filename
+        for (int i = 0; i &lt; Time-&gt;size(); i++) 
+        {
+        ostringstream vtkFileName;
+                vtkFileName &lt;&lt; i &lt;&lt; argv[2];         
+        ofstream vtkFile(vtkFileName.str().c_str(), ios::out|ios::binary);
+
+        vtkFile &lt;&lt; &quot;&lt;VTKFile type=\&quot;UnstructuredGrid\&quot; version=\&quot;0.1\&quot; byte_order=\&quot;LittleEndian\&quot;&gt;&quot; &lt;&lt; endl;
+        vtkFile &lt;&lt; &quot;  &lt;UnstructuredGrid&gt;&quot; &lt;&lt; endl;
+        vtkFile &lt;&lt; &quot;    &lt;Piece NumberOfPoints=\&quot;&quot; &lt;&lt; numDualPoints &lt;&lt; &quot;\&quot; NumberOfCells=\&quot;&quot; &lt;&lt; numDualCells  &lt;&lt; &quot;\&quot;&gt;&quot; &lt;&lt; endl;
+
+                if (!vtkFile)
+                {
+                        cerr &lt;&lt; &quot;vtk output file could not be opened&quot; &lt;&lt;endl;
+                        exit(1);
+                }
+
+
+
+                // Write attributes of dual-mesh cell data (attributes of primal-mesh
+                // vertex data)
+
+                vtkFile.precision(16);
+
+                // If by point, write out point data
+        vtkFile &lt;&lt; &quot;      &lt;PointData&gt;&quot; &lt;&lt; endl;
+
+        dualPointVarData = (double*)malloc((sizeof(double)) * nCells-&gt;size());
+        CHECK_MALLOC(dualPointVarData);
+
+                int tracerNum = 0;
+        EncodeBase64 vtkb64(&amp;vtkFile);
+
+                for (int v = 0; v &lt;= dualPointVarIndex; v++) {
+        
+                        // Read variable number v data for that timestep
+
+                        varVertLevels = dualPointVars[v]-&gt;get_dim(2)-&gt;size();
+
+                        bool isTracer = false;
+
+                        if (!strcmp(dualPointVars[v]-&gt;name(), &quot;tracers&quot;)) {
+                                isTracer = true;                                
+                                dualPointVars[v]-&gt;set_cur(i, 0, outputVertLevel, tracerNum);
+                                dualPointVars[v]-&gt;get(dualPointVarData, 1, nCells-&gt;size(), 1, 1);
+                        } else {        
+                                dualPointVars[v]-&gt;set_cur(i, 0, outputVertLevel);
+                                dualPointVars[v]-&gt;get(dualPointVarData, 1, nCells-&gt;size(), 1);
+                        }
+
+            vtkFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;&quot; &lt;&lt; dualPointVars[v]-&gt;name();
+            if(isTracer) vtkFile &lt;&lt; tracerNum+1;
+            vtkFile &lt;&lt; &quot;\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt; &quot; &lt;&lt; endl;
+
+                        // Write variable number v data for that timestep
+
+                        // get starting point
+                        double *var_target = dualPointVarData;
+
+                        float validData;
+                        validData = convertDouble2ValidFloat (*var_target);
+
+            vtkFile &lt;&lt; &quot;          &quot;;
+
+                        // write dummy
+                        if (writeBinary) {
+                vtkb64.StartWriting();
+                binarySize = numDualPoints*sizeof(float);
+                binarySize = padSize(binarySize);
+                //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+                vtkb64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+                vtkb64.Write((const unsigned char*)&amp;validData, sizeof(float));
+            } else {
+                vtkFile &lt;&lt; validData;
+            }
+                
+                        // write data        
+                        for (int j = 0; j &lt; nCells-&gt;size(); j++) 
+                        {
+                if ((!writeBinary) &amp;&amp; (j%6==0)) {
+                    vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                }
+                                validData = convertDouble2ValidFloat (*var_target);
+                if (writeBinary) {
+                    vtkb64.Write((const unsigned char*)&amp;validData, sizeof(float));
+                } else {
+                    vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+                }
+                                var_target++;
+                        }
+
+            if (writeBinary) vtkb64.EndWriting();
+                        if (isTracer) tracerNum++;
+            vtkFile &lt;&lt; endl &lt;&lt;  &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+                }
+
+        free (dualPointVarData);
+
+        // write out vectors
+
+        float validData;
+        if (isUVector) {
+
+            vtkFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;uReconstruct\&quot; NumberOfComponents=\&quot;3\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt; &quot; &lt;&lt; endl;
+           // cout &lt;&lt; &quot;isUVector:&quot; &lt;&lt; endl;
+
+            double *vectorData[3] = {NULL, NULL, NULL};
+
+            for (int d = 0; d &lt; 3; d++) {
+                vectorData[d] = (double*)malloc((sizeof(double)) * nCells-&gt;size());
+                CHECK_MALLOC(vectorData[d]);
+            }
+
+            for (int d = 0; d &lt; 3; d++) {
+                // read data in
+                vectorVars[0][d]-&gt;set_cur(i, 0, outputVertLevel);
+                vectorVars[0][d]-&gt;get(vectorData[d], 1, nCells-&gt;size(), 1);
+            }
+
+            vtkFile &lt;&lt; &quot;          &quot;;
+            if (writeBinary) {
+                vtkb64.StartWriting();
+                binarySize = numDualPoints*sizeof(float)*3;
+                binarySize = padSize(binarySize);
+                //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+                vtkb64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+            }
+
+            // dummy first
+
+            for (int d= 0; d &lt; 3; d++) {
+                validData = convertDouble2ValidFloat (vectorData[d][0]);
+                if (writeBinary) {
+                    vtkb64.Write((const unsigned char*)&amp;validData, sizeof(validData));
+                } else {
+                    vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+                }
+            }
+            if (!writeBinary) vtkFile &lt;&lt; endl;
+
+            // rest of data
+                        for (int j = 0; j &lt; nCells-&gt;size(); j++) 
+                        {
+                if (!writeBinary) vtkFile &lt;&lt; &quot;          &quot;;
+                for (int d= 0; d &lt; 3; d++) {
+                                    validData = convertDouble2ValidFloat (vectorData[d][j]);
+                    if (writeBinary) {
+                        vtkb64.Write((const unsigned char*)&amp;validData, sizeof(validData));
+                    } else {
+                        vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+                    }
+                }
+                if (!writeBinary) vtkFile &lt;&lt; endl;
+                        }
+            if (writeBinary) {
+                vtkb64.EndWriting();
+                vtkFile &lt;&lt; endl;
+            }
+            vtkFile &lt;&lt; &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+            for (int d = 0; d &lt; 3; d++) {
+                free(vectorData[d]);
+            }
+        } 
+       
+
+#ifdef NOT IMPLEMENTED YET 
+        if (isVVector) {
+            for (int d = 0; d &lt; 3; d++) {
+                // read data in
+                vectorVars[1][d]-&gt;set_cur(i, 0, outputVertLevel);
+                vectorVars[1][d]-&gt;get(vectorData[d], 1, nCells-&gt;size(), 1);
+            }
+            vtkFile &lt;&lt; &quot;VECTORS vReconstruct double&quot; &lt;&lt; endl;
+            for (int d= 0; d &lt; 3; d++) {
+                validData = convertDouble2ValidFloat (vectorData[d][0]);
+                vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+            }
+            vtkFile &lt;&lt; endl;
+
+                        for (int j = 0; j &lt; nCells-&gt;size(); j++) 
+                        {
+                for (int d= 0; d &lt; 3; d++) {
+                                    validData = convertDouble2ValidFloat (vectorData[d][j]);
+                    vtkFile &lt;&lt; validData &lt;&lt; endl;
+                }
+                vtkFile &lt;&lt; endl;
+                        }
+        } 
+        
+        if (isWVector) {
+            for (int d = 0; d &lt; 3; d++) {
+                // read data in
+                vectorVars[2][d]-&gt;set_cur(i, 0, outputVertLevel);
+                vectorVars[2][d]-&gt;get(vectorData[d], 1, nCells-&gt;size(), 1);
+            }
+            vtkFile &lt;&lt; &quot;VECTORS vReconstruct double&quot; &lt;&lt; endl;
+            for (int d= 0; d &lt; 3; d++) {
+                validData = convertDouble2ValidFloat (vectorData[d][0]);
+                vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+            }
+            vtkFile &lt;&lt; endl;
+
+                        for (int j = 0; j &lt; nCells-&gt;size(); j++) 
+                        {
+                for (int d= 0; d &lt; 3; d++) {
+                                    validData = convertDouble2ValidFloat (vectorData[d][j]);
+                    vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+                }
+                vtkFile &lt;&lt; endl;
+                        }
+        } 
+#endif
+
+                vtkFile &lt;&lt; &quot;      &lt;/PointData&gt;&quot; &lt;&lt; endl;
+
+                // if by cell, then write out cell data
+
+        vtkFile &lt;&lt; &quot;      &lt;CellData&gt;&quot; &lt;&lt; endl;
+
+        dualCellVarData = (double*)malloc((sizeof(double))  * numDualCells);
+        CHECK_MALLOC(dualCellVarData);
+
+                for (int v = 0; v &lt;= dualCellVarIndex; v++) {
+
+                        // Read variable number v data for that timestep
+                        varVertLevels = dualCellVars[v]-&gt;get_dim(2)-&gt;size();
+                        dualCellVars[v]-&gt;set_cur(i, 0, outputVertLevel);
+                        dualCellVars[v]-&gt;get(dualCellVarData, 1, numDualCells, 1);
+
+                        // Write variable number v data for that timestep
+            vtkFile &lt;&lt; &quot;        &lt;DataArray type=\&quot;Float32\&quot; Name=\&quot;&quot; &lt;&lt; dualCellVars[v]-&gt;name() &lt;&lt; &quot;\&quot; format=\&quot;&quot; &lt;&lt; formatString &lt;&lt; &quot;\&quot;&gt; &quot; ;
+
+                        double *var_target = dualCellVarData; 
+                        float validData;
+            if (writeBinary) {
+                vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                vtkb64.StartWriting();
+                binarySize = numDualCells*sizeof(float);
+                binarySize = padSize(binarySize);
+                //cout &lt;&lt; &quot;BinarySize: &quot; &lt;&lt; binarySize &lt;&lt; endl;
+                vtkb64.Write((const unsigned char*)&amp;binarySize, sizeof(int));
+            }
+                        for (int j = 0; j &lt; numDualCells; j++) 
+                        {
+                if ((!writeBinary) &amp;&amp; (j%6 == 0)) {
+                    vtkFile &lt;&lt; endl &lt;&lt; &quot;          &quot;;
+                }
+                                validData = convertDouble2ValidFloat (*var_target);
+                if (writeBinary) {
+                    vtkb64.Write((const unsigned char*)&amp;validData, sizeof(float));
+                } else {
+                    vtkFile &lt;&lt; validData &lt;&lt; &quot; &quot;;
+                }
+                                var_target++;
+                        }
+            if (writeBinary) {
+                vtkb64.EndWriting();
+            }
+            vtkFile &lt;&lt; endl &lt;&lt;  &quot;        &lt;/DataArray&gt;&quot; &lt;&lt; endl;
+                }
+        vtkFile &lt;&lt; &quot;      &lt;/CellData&gt;&quot; &lt;&lt; endl;
+
+        free(dualCellVarData);
+
+        vtkFile.close();
+
+        string geoFileNameString = geoFileName.str();
+        string vtkFileNameString = vtkFileName.str();
+        // append geoFile to vtkFile
+        int appRetVal = myAppendFile(&amp;geoFileNameString, &amp;vtkFileNameString);
+
+    }
+
+        return(0);
+
+}        
+


Property changes on: branches/ocean_projects/graphics/paraview/translator/nc2vtu_dualbin.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/x-c++src
Name: svn:keywords
   + Author Date ID Revision
Name: svn:eol-style
   + native

</font>
</pre>