[MOAB-dev] r3701 - in MOAB/trunk: . config src/io

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Wed Mar 24 09:14:38 CDT 2010


Author: kraftche
Date: 2010-03-24 09:14:38 -0500 (Wed, 24 Mar 2010)
New Revision: 3701

Modified:
   MOAB/trunk/config/netcdf.m4
   MOAB/trunk/configure.ac
   MOAB/trunk/src/io/ReadNCDF.cpp
Log:
Fixes to Exodus reader (ReadNCDF):

o Request that NetCDF library not abort on errors
o Check early whether or DIM or VAR counts in file exceed the constant
   limits for the configured NetCDF library because the NetCDF library
   has a bug where it corrupts memory in this case.
o Add configure checks for whether or not the NetCDF library has 
   NC_MAX_DIMS and NC_MAX_VARS increased to the recommended values
   for ExodusII files
o Some minor cleanups to ReadNCDF


Modified: MOAB/trunk/config/netcdf.m4
===================================================================
--- MOAB/trunk/config/netcdf.m4	2010-03-23 22:43:48 UTC (rev 3700)
+++ MOAB/trunk/config/netcdf.m4	2010-03-24 14:14:38 UTC (rev 3701)
@@ -5,9 +5,21 @@
 #   NETCDF_CPPFLAGS
 #   NETCDF_LDFLAGS
 #   NETCDF_LIBS
+#   NETCDF_SUFFICIENT_DIMS_VARS
+#
+# This macro has two optional arguments:  a minimum value for
+# NC_MAX_DIMS and a minimum value for NC_MAX_VARS.  If either or
+# both of these are specified, NETCDF_SUFFICIENT_DIMS_VARS will
+# be set to yes if the NetCDF library is built with limits that
+# are at least the passed miminums.  It will be set to no if 
+# either limit is less than the passed minimum.
 #######################################################################################
 AC_DEFUN([FATHOM_CHECK_NETCDF],[
 
+MIN_NC_MAX_DIMS="$1"
+MIN_NC_MAX_VARS="$2"
+NETCDF_SUFFICIENT_DIMS_VARS=yes
+
 AC_MSG_CHECKING([if NetCDF support is enabled])
 AC_ARG_WITH(netcdf, 
 [AC_HELP_STRING([--with-netcdf=DIR], [Specify NetCDF library to use for ExodusII file format])
@@ -28,14 +40,13 @@
   HAVE_NETCDF=yes
 
     # Check for stream headers and set STRSTREAM_H_SPEC accordingly
-  AC_LANG_SAVE
-  AC_LANG_CPLUSPLUS
+  AC_LANG_PUSH([C++])
   AC_CHECK_HEADER( [strstream.h], [NETCDF_DEF="<strstream.h>"], [
     AC_CHECK_HEADER( [sstream.h], [NETCDF_DEF="<sstream.h>"], [
       AC_CHECK_HEADER( [strstream], [NETCDF_DEF="<strstream>"], [
         AC_CHECK_HEADER( [sstream], [NETCDF_DEF="<sstream>"] )
   ] ) ] ) ] )
-  AC_LANG_RESTORE
+  AC_LANG_POP([C++])
   
     # if a path is specified, update LIBS and INCLUDES accordingly
   if test "xyes" != "x$NETCDF_ARG" && test "x" != "x$NETCDF_ARG"; then
@@ -61,10 +72,27 @@
   LDFLAGS="$NETCDF_LDFLAGS $LDFLAGS"
   
    # Check for C library
+  AC_LANG_PUSH([C])
   AC_CHECK_HEADERS( [netcdf.h], [], [AC_MSG_WARN([[NetCDF header not found.]]); HAVE_NETCDF=no] )
+  if test "x" != "x$MIN_NC_MAX_DIMS"; then
+    AC_MSG_CHECKING([if NC_MAX_DIMS is at least ${MIN_NC_MAX_DIMS}])
+    AC_COMPILE_IFELSE(
+      [AC_LANG_PROGRAM([#include <netcdf.h>],
+                       [[int arr[1 + (int)(${MIN_NC_MAX_DIMS}) - (int)(NC_MAX_DIMS)];]])],
+      [AC_MSG_RESULT([yes])],
+      [AC_MSG_RESULT([no]); NETCDF_SUFFICIENT_DIMS_VARS=no])
+  fi
+  if test "x" != "x$MIN_NC_MAX_VARS"; then
+    AC_MSG_CHECKING([if NC_MAX_VARS is at least ${MIN_NC_MAX_VARS}])
+    AC_COMPILE_IFELSE(
+      [AC_LANG_PROGRAM([#include <netcdf.h>],
+                       [[int arr[1 + (int)(${MIN_NC_MAX_VARS}) - (int)(NC_MAX_VARS)];]])],
+      [AC_MSG_RESULT([yes])],
+      [AC_MSG_RESULT([no]); NETCDF_SUFFICIENT_DIMS_VARS=no])
+  fi
+  
   AC_MSG_CHECKING([for netcdf.hh])
-  AC_LANG_SAVE
-  AC_LANG_CPLUSPLUS
+  AC_LANG_PUSH([C++])
   HAVE_NETCDF_HH=no
   AC_TRY_COMPILE( 
 [#include "netcdf.hh"], [], [HAVE_NETCDF_HH=yes; NETCDF_DEF=], [
@@ -95,7 +123,10 @@
            [AC_MSG_RESULT([no]); HAVE_NETCDF=no] )    
      ])
   LIBS="$old_LIBS"
-  AC_LANG_RESTORE
+  AC_LANG_POP([C++])
+  
+  
+  
   CPPFLAGS="$old_CPPFLAGS"
   LDFLAGS="$old_LDFLAGS"
 

Modified: MOAB/trunk/configure.ac
===================================================================
--- MOAB/trunk/configure.ac	2010-03-23 22:43:48 UTC (rev 3700)
+++ MOAB/trunk/configure.ac	2010-03-24 14:14:38 UTC (rev 3701)
@@ -314,7 +314,7 @@
 
 old_LDFLAGS="$LDFLAGS"
 LDFLAGS="$LDFLAGS $HDF5_LDFLAGS"
-FATHOM_CHECK_NETCDF
+FATHOM_CHECK_NETCDF([65536],[524288])
 LDFLAGS="$old_LDFLAGS"
 if test "xno" = "x$HAVE_NETCDF"; then
   AC_MSG_WARN([Support for ExodusII file format disabled])
@@ -1072,6 +1072,16 @@
 *           MOAB has been configured w/out the NetCDF library.
 *     Support for ExodusII/Genesis and other file formats is disabled!
 *************************************************************************])
+elif test "xno" = "x$NETCDF_SUFFICIENT_DIMS_VARS"; then
+  AC_MSG_WARN([
+*************************************************************************
+*  The configured NetCDF library does not have sufficient cosntant limits
+*  to support reading of ExodusII with large numbers of blocks or sidesets
+*  or nodesets.  Please consider re-compiling your NetCDF library after
+*  increasing the constants NC_MAX_DIMS and NC_MAX_VARS in netcdf.h to
+*  65536 and 524288, respectively.  See: 
+*  http://cubit.sandia.gov/help-version11.1/finite_element_model/export/exporting_exodus2_file.htm
+*************************************************************************])
 fi
 
 if test "x$WARN_PARALLEL_HDF5" = "xyes"; then

Modified: MOAB/trunk/src/io/ReadNCDF.cpp
===================================================================
--- MOAB/trunk/src/io/ReadNCDF.cpp	2010-03-23 22:43:48 UTC (rev 3700)
+++ MOAB/trunk/src/io/ReadNCDF.cpp	2010-03-24 14:14:38 UTC (rev 3701)
@@ -21,13 +21,11 @@
 #include "netcdf.hh"
 
 #include <algorithm>
-#include <time.h>
 #include <string>
 #include <assert.h>
 #include <stdio.h>
 #include <string.h>
 #include <cmath>
-#include <memory>
 #include <sstream>
 #include <map>
 
@@ -49,18 +47,18 @@
           sprintf(stringvar, prefix, id)
           
 #define GET_DIM(ncdim, name, val) \
-          if (dimension_exists(name)) {\
+          if (dimension_exists(name)) { \
             ncdim = ncFile->get_dim(name); \
             if (!ncdim->is_valid()) {\
                readMeshIface->report_error("ReadNCDF:: name wasn't valid.");\
                return MB_FAILURE;\
             }\
             val = ncdim->size();\
-          } else val = 0;
+          } else val = 0; 
 
 #define GET_DIMB(ncdim, name, varname, id, val) \
           INS_ID(name, varname, id); \
-          if (dimension_exists(name)) {\
+          if (dimension_exists(name)) { \
             ncdim = ncFile->get_dim(name); \
             if (!ncdim->is_valid()) {\
                readMeshIface->report_error("ReadNCDF:: name wasn't valid.");\
@@ -195,15 +193,16 @@
     return MB_UNSUPPORTED_OPERATION;
   }
 
+  NcError ncError(NcError::verbose_nonfatal);
+
       // open netcdf/exodus file
-  ncFile = new NcFile(file_name);
-  if (NULL == ncFile || !ncFile->is_valid())
+  NcFile fileObject(file_name, NcFile::ReadOnly);
+  ncFile = &fileObject;
+  if (!ncFile->is_valid())
   {
     readMeshIface->report_error("ReadNCDF:: problem opening Netcdf/Exodus II file %s",file_name);
     return MB_FILE_DOES_NOT_EXIST;
   }
-    // delete file when we return from this function
-  std::auto_ptr<NcFile> deleter(ncFile);
 
     // 1. Read the header
   ErrorCode rval = read_exodus_header( );
@@ -229,7 +228,6 @@
     prop = sidesets;
   }
   else {  
-    delete ncFile;
     ncFile = 0;
     return MB_TAG_NOT_FOUND;
   }
@@ -238,20 +236,20 @@
     NcVar *nc_var = ncFile->get_var( prop );
     if (NULL == nc_var || !nc_var->is_valid()) {
       readMeshIface->report_error("Problem getting prop variable.");
-      rval = MB_FAILURE;
+      return MB_FAILURE;
     }
     else {
       id_array.resize( count );
       NcBool status = nc_var->get(&id_array[0], count);
       if (0 == status) {
         readMeshIface->report_error("Problem getting element id vector.");
-        rval = MB_FAILURE;
+        return MB_FAILURE;
       }
     }
   }
   
   ncFile = 0;
-  return rval;
+  return MB_SUCCESS;
 }
 
 
@@ -265,6 +263,8 @@
 {
   ErrorCode status;
 
+  NcError ncError(NcError::verbose_nonfatal);
+
   int num_blocks = 0;
   const int* blocks_to_load = 0;
   if (subset_list && subset_list_length) {
@@ -295,14 +295,13 @@
   // 0. Open the file.
 
       // open netcdf/exodus file
-  ncFile = new NcFile(exodus_file_name);
-  if (NULL == ncFile || !ncFile->is_valid())
+  NcFile fileObject(exodus_file_name, NcFile::ReadOnly);
+  ncFile = &fileObject;
+  if (!ncFile->is_valid())
   {
     readMeshIface->report_error("ReadNCDF:: problem opening Netcdf/Exodus II file %s",exodus_file_name);
     return MB_FILE_DOES_NOT_EXIST;
   }
-    // delete file when we return from this function
-  std::auto_ptr<NcFile> deleter(ncFile);
 
     // 1. Read the header
   status = read_exodus_header();
@@ -354,6 +353,20 @@
   CPU_WORD_SIZE = sizeof(double);  // With ExodusII version 2, all floats
   IO_WORD_SIZE = sizeof(double);   // should be changed to doubles
   
+    // NetCDF doesn't check its own limits on file read, so check
+    // them here so it doesn't corrupt memory any more than absolutely
+    // necessary.
+  if (ncFile->num_dims() > NC_MAX_DIMS) {
+    readMeshIface->report_error("ReadNCDF: File contains %d dims but NetCDF library supports only %d\n",
+                                (int)ncFile->num_dims(), (int)NC_MAX_DIMS);
+    return MB_FAILURE;
+  }
+  if (ncFile->num_vars() > NC_MAX_VARS) {
+    readMeshIface->report_error("ReadNCDF: File contains %d vars but NetCDF library supports only %d\n",
+                                (int)ncFile->num_vars(), (int)NC_MAX_VARS);
+    return MB_FAILURE;
+  }
+  
     // get the attributes
 
     // get the word size, scalar value
@@ -374,7 +387,6 @@
   delete temp_att;
 
     // float version = temp_att->as_float(0);
-  
 
     // read in initial variables
   NcDim *temp_dim;
@@ -621,11 +633,11 @@
 
     // allocate an array to read in connectivity data
     readMeshIface->get_element_array(
-        (*this_it).numElements,
+        this_it->numElements,
         verts_per_element,
         mb_type,
-        (*this_it).startExoId,
-        (*this_it).startMBId,
+        this_it->startExoId,
+        this_it->startMBId,
         conn);
         
         // create a range for this sequence of elements
@@ -1669,14 +1681,13 @@
 
 
       // open netcdf/exodus file
-  ncFile = new NcFile(exodus_file_name);
-  if (NULL == ncFile || !ncFile->is_valid())
+  NcFile fileObject( exodus_file_name, NcFile::ReadOnly );
+  ncFile = &fileObject;
+  if (!ncFile->is_valid())
   {
     readMeshIface->report_error("ReadNCDF:: problem opening Netcdf/Exodus II file %s",exodus_file_name);
     return MB_FILE_DOES_NOT_EXIST;
   }
-    // delete file when we return from this function
-  std::auto_ptr<NcFile> deleter(ncFile);
 
   rval = read_exodus_header();
   if (MB_SUCCESS != rval)



More information about the moab-dev mailing list