[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