From a111cf640a02e548f51ea702780e51e87b50a6e3 Mon Sep 17 00:00:00 2001
From: Lars Pastewka <lars.pastewka@imtek.uni-freiburg.de>
Date: Sun, 26 Nov 2017 22:35:56 +0100
Subject: [PATCH] BUG: Proper handling of bigint data. Corrects behavior when
 compiled with LAMMPS_BIGBIG.

---
 src/USER-NETCDF/dump_netcdf.cpp       | 122 +++++++++++++++++++-------
 src/USER-NETCDF/dump_netcdf.h         |   2 +-
 src/USER-NETCDF/dump_netcdf_mpiio.cpp | 112 +++++++++++++++++------
 src/USER-NETCDF/dump_netcdf_mpiio.h   |   2 +-
 4 files changed, 179 insertions(+), 59 deletions(-)

diff --git a/src/USER-NETCDF/dump_netcdf.cpp b/src/USER-NETCDF/dump_netcdf.cpp
index 988a9db6c3..a88d74434b 100644
--- a/src/USER-NETCDF/dump_netcdf.cpp
+++ b/src/USER-NETCDF/dump_netcdf.cpp
@@ -43,7 +43,8 @@
 using namespace LAMMPS_NS;
 using namespace MathConst;
 
-enum{INT,FLOAT,BIGINT}; // same as in thermo.cpp
+enum{THERMO_INT,THERMO_FLOAT,THERMO_BIGINT}; // same as in thermo.cpp
+enum{DUMP_INT,DUMP_DOUBLE,DUMP_STRING,DUMP_BIGINT}; // same as in DumpCFG
 
 const char NC_FRAME_STR[]         = "frame";
 const char NC_SPATIAL_STR[]       = "spatial";
@@ -121,10 +122,6 @@ DumpNetCDF::DumpNetCDF(LAMMPS *lmp, int narg, char **arg) :
       ndims = 3;
       strcpy(mangled, "velocities");
     }
-    // extensions to the AMBER specification
-    else if (!strcmp(mangled, "type")) {
-      strcpy(mangled, "atom_types");
-    }
     else if (!strcmp(mangled, "xs") || !strcmp(mangled, "ys") ||
              !strcmp(mangled, "zs")) {
       idim = mangled[0] - 'x';
@@ -409,10 +406,11 @@ void DumpNetCDF::openfile()
         nc_type xtype;
 
         // Type mangling
-        if (vtype[perat[i].field[0]] == INT) {
+        if (vtype[perat[i].field[0]] == DUMP_INT) {
           xtype = NC_INT;
-        }
-        else {
+        } else if (vtype[perat[i].field[0]] == DUMP_BIGINT) {
+          xtype = NC_INT64;
+        } else {
           if (double_precision)
             xtype = NC_DOUBLE;
           else
@@ -476,15 +474,15 @@ void DumpNetCDF::openfile()
       if (thermo) {
         Thermo *th = output->thermo;
         for (int i = 0; i < th->nfield; i++) {
-          if (th->vtype[i] == FLOAT) {
+          if (th->vtype[i] == THERMO_FLOAT) {
             NCERRX( nc_def_var(ncid, th->keyword[i], NC_DOUBLE, 1, dims,
                                &thermovar[i]), th->keyword[i] );
           }
-          else if (th->vtype[i] == INT) {
+          else if (th->vtype[i] == THERMO_INT) {
             NCERRX( nc_def_var(ncid, th->keyword[i], NC_INT, 1, dims,
                                &thermovar[i]), th->keyword[i] );
           }
-          else if (th->vtype[i] == BIGINT) {
+          else if (th->vtype[i] == THERMO_BIGINT) {
 #if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG)
             NCERRX( nc_def_var(ncid, th->keyword[i], NC_INT64, 1, dims,
                                &thermovar[i]), th->keyword[i] );
@@ -645,6 +643,52 @@ int nc_put_var1_bigint<long long>(int ncid, int varid, const size_t index[],
   return nc_put_var1_longlong(ncid, varid, index, tp);
 }
 
+template <typename T>
+int nc_put_vara_bigint(int ncid, int varid, const size_t start[],
+                       const size_t count[], const T* tp)
+{
+  return nc_put_vara_int(ncid, varid, start, count, tp);
+}
+
+template <>
+int nc_put_vara_bigint<long>(int ncid, int varid, const size_t start[],
+                             const size_t count[], const long* tp)
+{
+  return nc_put_vara_long(ncid, varid, start, count, tp);
+}
+
+template <>
+int nc_put_vara_bigint<long long>(int ncid, int varid, const size_t start[],
+                                  const size_t count[], const long long* tp)
+{
+  return nc_put_vara_longlong(ncid, varid, start, count, tp);
+}
+
+template <typename T>
+int nc_put_vars_bigint(int ncid, int varid, const size_t start[],
+                       const size_t count[], const ptrdiff_t stride[],
+                       const T* tp)
+{
+  return nc_put_vars_int(ncid, varid, start, count, stride, tp);
+}
+
+template <>
+int nc_put_vars_bigint<long>(int ncid, int varid, const size_t start[],
+                             const size_t count[], const ptrdiff_t stride[],
+                             const long* tp)
+{
+  return nc_put_vars_long(ncid, varid, start, count, stride, tp);
+}
+
+template <>
+int nc_put_vars_bigint<long long>(int ncid, int varid, const size_t start[],
+                                  const size_t count[],
+                                  const ptrdiff_t stride[],
+                                  const long long* tp)
+{
+  return nc_put_vars_longlong(ncid, varid, start, count, stride, tp);
+}
+
 void DumpNetCDF::write()
 {
   // open file
@@ -666,16 +710,16 @@ void DumpNetCDF::write()
     for (int i = 0; i < th->nfield; i++) {
       th->call_vfunc(i);
       if (filewriter) {
-        if (th->vtype[i] == FLOAT) {
+        if (th->vtype[i] == THERMO_FLOAT) {
           NCERRX( nc_put_var1_double(ncid, thermovar[i], start,
                                      &th->dvalue),
                   th->keyword[i] );
         }
-        else if (th->vtype[i] == INT) {
+        else if (th->vtype[i] == THERMO_INT) {
           NCERRX( nc_put_var1_int(ncid, thermovar[i], start, &th->ivalue),
                   th->keyword[i] );
         }
-        else if (th->vtype[i] == BIGINT) {
+        else if (th->vtype[i] == THERMO_BIGINT) {
           NCERRX( nc_put_var1_bigint(ncid, thermovar[i], start, &th->bivalue),
                   th->keyword[i] );
         }
@@ -776,16 +820,16 @@ void DumpNetCDF::write_data(int n, double *mybuf)
 
   if (!int_buffer) {
     n_buffer = n;
-    int_buffer = (int *)
-      memory->smalloc(n*sizeof(int),"dump::int_buffer");
+    int_buffer = (bigint *)
+      memory->smalloc(n*sizeof(bigint),"dump::int_buffer");
     double_buffer = (double *)
       memory->smalloc(n*sizeof(double),"dump::double_buffer");
   }
 
   if (n > n_buffer) {
     n_buffer = n;
-    int_buffer = (int *)
-      memory->srealloc(int_buffer, n*sizeof(int),"dump::int_buffer");
+    int_buffer = (bigint *)
+      memory->srealloc(int_buffer, n*sizeof(bigint),"dump::int_buffer");
     double_buffer = (double *)
       memory->srealloc(double_buffer, n*sizeof(double),"dump::double_buffer");
   }
@@ -805,7 +849,7 @@ void DumpNetCDF::write_data(int n, double *mybuf)
   for (int i = 0; i < n_perat; i++) {
     int iaux = perat[i].field[0];
 
-    if (vtype[iaux] == INT) {
+    if (vtype[iaux] == DUMP_INT || vtype[iaux] == DUMP_BIGINT) {
       // integers
       if (perat[i].dims > 1) {
 
@@ -813,41 +857,55 @@ void DumpNetCDF::write_data(int n, double *mybuf)
           iaux = perat[i].field[idim];
 
           if (iaux >= 0) {
-            for (int j = 0; j < n; j++, iaux+=size_one) {
-              int_buffer[j] = mybuf[iaux];
+            if (vtype[iaux] == DUMP_INT) {
+              for (int j = 0; j < n; j++, iaux+=size_one) {
+                int_buffer[j] = static_cast<int>(mybuf[iaux]);
+              }
+            }
+            else { // DUMP_BIGINT
+              for (int j = 0; j < n; j++, iaux+=size_one) {
+                int_buffer[j] = static_cast<bigint>(mybuf[iaux]);
+              }
             }
 
             start[2] = idim;
 
             if (perat[i].constant) {
               if (perat[i].ndumped < ntotalgr) {
-                NCERR( nc_put_vars_int(ncid, perat[i].var,
-                                       start+1, count+1, stride+1,
-                                       int_buffer) );
+                NCERR( nc_put_vars_bigint(ncid, perat[i].var,
+                                          start+1, count+1, stride+1,
+                                          int_buffer) );
                 perat[i].ndumped += n;
               }
             }
             else
-              NCERR( nc_put_vars_int(ncid, perat[i].var, start, count, stride,
-                                     int_buffer) );
+              NCERR( nc_put_vars_bigint(ncid, perat[i].var, start, count, stride,
+                                        int_buffer) );
           }
         }
       }
       else {
-        for (int j = 0; j < n; j++, iaux+=size_one) {
-            int_buffer[j] = mybuf[iaux];
+        if (vtype[iaux] == DUMP_INT) {
+          for (int j = 0; j < n; j++, iaux+=size_one) {
+              int_buffer[j] = static_cast<int>(mybuf[iaux]);
+          }
+        }
+        else { // DUMP_BIGINT
+          for (int j = 0; j < n; j++, iaux+=size_one) {
+              int_buffer[j] = static_cast<bigint>(mybuf[iaux]);
+          }
         }
 
         if (perat[i].constant) {
           if (perat[i].ndumped < ntotalgr) {
-            NCERR( nc_put_vara_int(ncid, perat[i].var, start+1, count+1,
-                                   int_buffer) );
+            NCERR( nc_put_vara_bigint(ncid, perat[i].var, start+1, count+1,
+                                      int_buffer) );
             perat[i].ndumped += n;
           }
         }
         else
-          NCERR( nc_put_vara_int(ncid, perat[i].var, start, count,
-                                 int_buffer) );
+          NCERR( nc_put_vara_bigint(ncid, perat[i].var, start, count,
+                                    int_buffer) );
       }
     }
     else {
diff --git a/src/USER-NETCDF/dump_netcdf.h b/src/USER-NETCDF/dump_netcdf.h
index 25d64efade..f97fd58409 100644
--- a/src/USER-NETCDF/dump_netcdf.h
+++ b/src/USER-NETCDF/dump_netcdf.h
@@ -66,7 +66,7 @@ class DumpNetCDF : public DumpCustom {
   bool thermo;                 // write thermo output to netcdf file
 
   bigint n_buffer;             // size of buffer
-  int *int_buffer;             // buffer for passing data to netcdf
+  bigint *int_buffer;          // buffer for passing data to netcdf
   double *double_buffer;       // buffer for passing data to netcdf
 
   int ncid;
diff --git a/src/USER-NETCDF/dump_netcdf_mpiio.cpp b/src/USER-NETCDF/dump_netcdf_mpiio.cpp
index 168e46a6b7..5e5be1c7aa 100644
--- a/src/USER-NETCDF/dump_netcdf_mpiio.cpp
+++ b/src/USER-NETCDF/dump_netcdf_mpiio.cpp
@@ -43,7 +43,8 @@
 using namespace LAMMPS_NS;
 using namespace MathConst;
 
-enum{INT,FLOAT,BIGINT}; // same as in thermo.cpp
+enum{THERMO_INT,THERMO_FLOAT,THERMO_BIGINT}; // same as in thermo.cpp
+enum{DUMP_INT,DUMP_DOUBLE,DUMP_STRING,DUMP_BIGINT}; // same as in DumpCFG
 
 const char NC_FRAME_STR[]         = "frame";
 const char NC_SPATIAL_STR[]       = "spatial";
@@ -404,10 +405,11 @@ void DumpNetCDFMPIIO::openfile()
       nc_type xtype;
 
       // Type mangling
-      if (vtype[perat[i].field[0]] == INT) {
+      if (vtype[perat[i].field[0]] == DUMP_INT) {
         xtype = NC_INT;
-      }
-      else {
+      } else if (vtype[perat[i].field[0]] == DUMP_BIGINT) {
+        xtype = NC_INT64;
+      } else {
         if (double_precision)
           xtype = NC_DOUBLE;
         else
@@ -443,15 +445,15 @@ void DumpNetCDFMPIIO::openfile()
     if (thermo) {
       Thermo *th = output->thermo;
       for (int i = 0; i < th->nfield; i++) {
-        if (th->vtype[i] == FLOAT) {
+        if (th->vtype[i] == THERMO_FLOAT) {
           NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_DOUBLE, 1, dims,
                                 &thermovar[i]), th->keyword[i] );
         }
-        else if (th->vtype[i] == INT) {
+        else if (th->vtype[i] == THERMO_INT) {
           NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_INT, 1, dims,
                                 &thermovar[i]), th->keyword[i] );
         }
-        else if (th->vtype[i] == BIGINT) {
+        else if (th->vtype[i] == THERMO_BIGINT) {
 #if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG)
           NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_INT64, 1, dims,
                                 &thermovar[i]), th->keyword[i] );
@@ -602,25 +604,77 @@ void DumpNetCDFMPIIO::closefile()
 
 template <typename T>
 int ncmpi_put_var1_bigint(int ncid, int varid, const MPI_Offset index[],
-                     const T* tp)
+                          const T* tp)
 {
   return ncmpi_put_var1_int(ncid, varid, index, tp);
 }
 
 template <>
 int ncmpi_put_var1_bigint<long>(int ncid, int varid, const MPI_Offset index[],
-                           const long* tp)
+                                const long* tp)
 {
   return ncmpi_put_var1_long(ncid, varid, index, tp);
 }
 
 template <>
-int ncmpi_put_var1_bigint<long long>(int ncid, int varid, const MPI_Offset index[],
-                                const long long* tp)
+int ncmpi_put_var1_bigint<long long>(int ncid, int varid,
+                                     const MPI_Offset index[],
+                                     const long long* tp)
 {
   return ncmpi_put_var1_longlong(ncid, varid, index, tp);
 }
 
+template <typename T>
+int ncmpi_put_vara_bigint_all(int ncid, int varid, const MPI_Offset start[],
+                              const MPI_Offset count[], const T* tp)
+{
+  return ncmpi_put_vara_int_all(ncid, varid, start, count, tp);
+}
+
+template <>
+int ncmpi_put_vara_bigint_all<long>(int ncid, int varid,
+                                    const MPI_Offset start[],
+                                    const MPI_Offset count[], const long* tp)
+{
+  return ncmpi_put_vara_long_all(ncid, varid, start, count, tp);
+}
+
+template <>
+int ncmpi_put_vara_bigint_all<long long>(int ncid, int varid,
+                                         const MPI_Offset start[],
+                                         const MPI_Offset count[],
+                                         const long long* tp)
+{
+  return ncmpi_put_vara_longlong_all(ncid, varid, start, count, tp);
+}
+
+template <typename T>
+int ncmpi_put_vars_bigint_all(int ncid, int varid, const MPI_Offset start[],
+                              const MPI_Offset count[],
+                              const MPI_Offset stride[], const T* tp)
+{
+  return ncmpi_put_vars_int_all(ncid, varid, start, count, stride, tp);
+}
+
+template <>
+int ncmpi_put_vars_bigint_all<long>(int ncid, int varid,
+                                    const MPI_Offset start[],
+                                    const MPI_Offset count[],
+                                    const MPI_Offset stride[], const long* tp)
+{
+  return ncmpi_put_vars_long_all(ncid, varid, start, count, stride, tp);
+}
+
+template <>
+int ncmpi_put_vars_bigint_all<long long>(int ncid, int varid,
+                                         const MPI_Offset start[],
+                                         const MPI_Offset count[],
+                                         const MPI_Offset stride[],
+                                         const long long* tp)
+{
+  return ncmpi_put_vars_longlong_all(ncid, varid, start, count, stride, tp);
+}
+
 void DumpNetCDFMPIIO::write()
 {
   // open file
@@ -644,16 +698,16 @@ void DumpNetCDFMPIIO::write()
     for (int i = 0; i < th->nfield; i++) {
       th->call_vfunc(i);
       if (filewriter) {
-        if (th->vtype[i] == FLOAT) {
+        if (th->vtype[i] == THERMO_FLOAT) {
           NCERRX( ncmpi_put_var1_double(ncid, thermovar[i], start,
                                         &th->dvalue),
                   th->keyword[i] );
         }
-        else if (th->vtype[i] == INT) {
+        else if (th->vtype[i] == THERMO_INT) {
           NCERRX( ncmpi_put_var1_int(ncid, thermovar[i], start, &th->ivalue),
                   th->keyword[i] );
         }
-        else if (th->vtype[i] == BIGINT) {
+        else if (th->vtype[i] == THERMO_BIGINT) {
           NCERRX( ncmpi_put_var1_bigint(ncid, thermovar[i], start, &th->bivalue),
                   th->keyword[i] );
         }
@@ -782,16 +836,16 @@ void DumpNetCDFMPIIO::write_data(int n, double *mybuf)
 
   if (!int_buffer) {
     n_buffer = std::max(1, n);
-    int_buffer = (int *)
-      memory->smalloc(n_buffer*sizeof(int),"dump::int_buffer");
+    int_buffer = (bigint *)
+      memory->smalloc(n_buffer*sizeof(bigint),"dump::int_buffer");
     double_buffer = (double *)
       memory->smalloc(n_buffer*sizeof(double),"dump::double_buffer");
   }
 
   if (n > n_buffer) {
     n_buffer = std::max(1, n);
-    int_buffer = (int *)
-      memory->srealloc(int_buffer, n_buffer*sizeof(int),"dump::int_buffer");
+    int_buffer = (bigint *)
+      memory->srealloc(int_buffer, n_buffer*sizeof(bigint),"dump::int_buffer");
     double_buffer = (double *)
       memory->srealloc(double_buffer, n_buffer*sizeof(double),
                        "dump::double_buffer");
@@ -824,7 +878,7 @@ void DumpNetCDFMPIIO::write_data(int n, double *mybuf)
       error->one(FLERR,errmsg);
     }
 
-    if (vtype[iaux] == INT) {
+    if (vtype[iaux] == DUMP_INT || vtype[iaux] == DUMP_BIGINT) {
       // integers
       if (perat[i].dims > 1) {
 
@@ -839,13 +893,21 @@ void DumpNetCDFMPIIO::write_data(int n, double *mybuf)
               error->one(FLERR,errmsg);
             }
 
-            for (int j = 0; j < n; j++, iaux+=size_one) {
-              int_buffer[j] = mybuf[iaux];
+            if (vtype[iaux] == DUMP_INT) {
+              for (int j = 0; j < n; j++, iaux+=size_one) {
+                int_buffer[j] = static_cast<int>(mybuf[iaux]);
+              }
+            }
+            else { // DUMP_BIGINT
+              for (int j = 0; j < n; j++, iaux+=size_one) {
+                int_buffer[j] = static_cast<bigint>(mybuf[iaux]);
+              }
             }
 
             start[2] = idim;
-            NCERRX( ncmpi_put_vars_int_all(ncid, perat[i].var, start, count,
-                                           stride, int_buffer), perat[i].name );
+            NCERRX( ncmpi_put_vars_bigint_all(ncid, perat[i].var, start, count,
+                                              stride, int_buffer),
+                    perat[i].name );
           }
         }
       }
@@ -854,8 +916,8 @@ void DumpNetCDFMPIIO::write_data(int n, double *mybuf)
             int_buffer[j] = mybuf[iaux];
         }
 
-        NCERRX( ncmpi_put_vara_int_all(ncid, perat[i].var, start, count,
-                                       int_buffer), perat[i].name );
+        NCERRX( ncmpi_put_vara_bigint_all(ncid, perat[i].var, start, count,
+                                          int_buffer), perat[i].name );
       }
     }
     else {
diff --git a/src/USER-NETCDF/dump_netcdf_mpiio.h b/src/USER-NETCDF/dump_netcdf_mpiio.h
index 3ca52449a5..330fa46c04 100644
--- a/src/USER-NETCDF/dump_netcdf_mpiio.h
+++ b/src/USER-NETCDF/dump_netcdf_mpiio.h
@@ -65,7 +65,7 @@ class DumpNetCDFMPIIO : public DumpCustom {
   bool thermo;                          // write thermo output to netcdf file
 
   bigint n_buffer;                      // size of buffer
-  int *int_buffer;                      // buffer for passing data to netcdf
+  bigint *int_buffer;                   // buffer for passing data to netcdf
   double *double_buffer;                // buffer for passing data to netcdf
 
   int ncid;
-- 
GitLab