[MOAB-dev] commit/MOAB: 16 new changesets
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Mon Jul 1 17:32:18 CDT 2013
16 new commits in MOAB:
https://bitbucket.org/fathomteam/moab/commits/00e8666eaab6/
Changeset: 00e8666eaab6
Branch: None
User: danwu
Date: 2013-06-05 20:23:11
Summary: Merged fathomteam/moab into master
Affected #: 0 files
https://bitbucket.org/fathomteam/moab/commits/45d3b4be81ba/
Changeset: 45d3b4be81ba
Branch: None
User: danwu
Date: 2013-06-05 22:12:43
Summary: Merged fathomteam/moab into master
Affected #: 1 file
diff --git a/test/io/read_nc.cpp b/test/io/read_nc.cpp
index 0e5af72..558958c 100644
--- a/test/io/read_nc.cpp
+++ b/test/io/read_nc.cpp
@@ -4,74 +4,240 @@
using namespace moab;
=20
#ifdef MESHDIR
-static const char example[] =3D STRINGIFY(MESHDIR) "/io/camEul26x48x96.t3.=
nc";
+static const char example_eul[] =3D STRINGIFY(MESHDIR) "/io/camEul26x48x96=
.t3.nc";
+static const char example_fv[] =3D STRINGIFY(MESHDIR) "/io/fv26x46x72.t.3.=
nc";
#else
-static const char example[] =3D "/io/camEul26x48x96.t3.nc";
+static const char example_eul[] =3D "/io/camEul26x48x96.t3.nc";
+static const char example_fv[] =3D "/io/fv26x46x72.t.3.nc";
#endif
=20
#ifdef USE_MPI
#include "moab_mpi.h"
#endif
=20
-void read_file( Interface& moab, const char* input_file );
-void test_read_all();
-void test_read_onevar();
-void test_read_onetimestep();
-void test_read_nomesh();
-void test_read_novars();
-ErrorCode get_options(std::string &opts);
+// CAM-EUL
+void test_read_eul_all();
+void test_read_eul_onevar();
+void test_read_eul_onetimestep();
+void test_read_eul_nomesh();
+void test_read_eul_novars();
=20
-int main(int argc, char *argv[])
+// CAM-FV
+void test_read_fv_all();
+void test_read_fv_onevar();
+void test_read_fv_onetimestep();
+void test_read_fv_nomesh();
+void test_read_fv_novars();
+
+ErrorCode get_options(std::string& opts);
+
+int main(int argc, char* argv[])
{
int result =3D 0;
=20
#ifdef USE_MPI
int fail =3D MPI_Init(&argc, &argv);
- if (fail) return 1;
+ if (fail)
+ return 1;
#else
- argv[0]=3Dargv[argc-argc];// to remove the warnings in serial mode about=
unused variables
+ argv[0] =3D argv[argc - argc]; // to remove the warnings in serial mode =
about unused variables
#endif
- =20
- result +=3D RUN_TEST(test_read_all);
- result +=3D RUN_TEST(test_read_onevar);
- result +=3D RUN_TEST(test_read_onetimestep);
- result +=3D RUN_TEST(test_read_nomesh);
- result +=3D RUN_TEST(test_read_novars);
- =20
+
+ result +=3D RUN_TEST(test_read_eul_all);
+ result +=3D RUN_TEST(test_read_eul_onevar);
+ result +=3D RUN_TEST(test_read_eul_onetimestep);
+ result +=3D RUN_TEST(test_read_eul_nomesh);
+ result +=3D RUN_TEST(test_read_eul_novars);
+
+ // Exclude test_read_fv_all() since reading edge data is not implemented=
in MOAB yet
+ //result +=3D RUN_TEST(test_read_fv_all);
+ result +=3D RUN_TEST(test_read_fv_onevar);
+ result +=3D RUN_TEST(test_read_fv_onetimestep);
+ result +=3D RUN_TEST(test_read_fv_nomesh);
+ result +=3D RUN_TEST(test_read_fv_novars);
+
#ifdef USE_MPI
fail =3D MPI_Finalize();
if (fail) return 1;
#endif
- =20
+
return result;
}
=20
+void test_read_eul_all()
+{
+ Core moab;
+ Interface& mb =3D moab;
+
+ std::string opts;
+ ErrorCode rval =3D get_options(opts);
+ CHECK_ERR(rval);
+
+ rval =3D mb.load_file(example_eul, NULL, opts.c_str());
+ CHECK_ERR(rval);
=20
-void test_read_all()
+ // check for proper tags
+ Tag Ttag0, Ttag1, coordTag;
+ rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+ CHECK_ERR(rval);
+
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_ERR(rval);
+
+ rval =3D mb.tag_get_handle("COORDS", 3, MB_TYPE_DOUBLE, coordTag);
+ CHECK_ERR(rval);
+}
+
+void test_read_eul_onevar()=20
{
Core moab;
Interface& mb =3D moab;
+ std::string opts;
+ ErrorCode rval =3D get_options(opts);
+ CHECK_ERR(rval);
=20
+ opts +=3D std::string(";VARIABLE=3DT");
+ rval =3D mb.load_file(example_eul, NULL, opts.c_str());
+ CHECK_ERR(rval);
+
+ // check for proper tags
+ Tag Ttag0, Ttag1;
+ rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+ CHECK_ERR(rval);
+
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_eul_onetimestep()
+{
+ Core moab;
+ Interface& mb =3D moab;
std::string opts;
ErrorCode rval =3D get_options(opts);
CHECK_ERR(rval);
- =20
- rval =3D mb.load_file( example, NULL, opts.c_str());
+
+ opts +=3D std::string(";VARIABLE=3DT;TIMESTEP=3D1");
+ rval =3D mb.load_file(example_eul, NULL, opts.c_str());
CHECK_ERR(rval);
- =20
+
+ // check for proper tags
+ Tag Ttag0, Ttag1;
+ rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_eul_nomesh()=20
+{
+ Core moab;
+ Interface& mb =3D moab;
+
+ // need a set for nomesh to work right
+ EntityHandle set;
+ ErrorCode rval =3D mb.create_meshset(MESHSET_SET, set);
+ CHECK_ERR(rval);
+
+ std::string orig, opts;
+ rval =3D get_options(orig);
+ CHECK_ERR(rval);
+
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D0");
+ rval =3D mb.load_file(example_eul, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // check for proper tag
+ Tag Ttag0, Ttag1;
+ rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+ CHECK_ERR(rval);
+
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ // now read 2nd timestep with nomesh option
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D1;NOMESH");
+ rval =3D mb.load_file(example_eul, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // check for proper tag
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_eul_novars()=20
+{
+ Core moab;
+ Interface& mb =3D moab;
+
+ // need a set for nomesh to work right
+ EntityHandle set;
+ ErrorCode rval =3D mb.create_meshset(MESHSET_SET, set);
+ CHECK_ERR(rval);
+
+ std::string orig, opts;
+ rval =3D get_options(orig);
+ CHECK_ERR(rval);
+
+ opts =3D orig + std::string(";NOMESH;VARIABLE=3D");
+ rval =3D mb.load_file(example_eul, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ opts =3D orig + std::string(";VARIABLE=3D;TIMESTEP=3D0");
+ rval =3D mb.load_file(example_eul, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // check for proper tag
+ Tag Ttag0, Ttag1;
+ rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D0;NOMESH");
+ rval =3D mb.load_file(example_eul, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
+ CHECK_ERR(rval);
+
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ // now read 2nd timestep with nomesh option
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D1;NOMESH");
+ rval =3D mb.load_file(example_eul, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // check for proper tag
+ rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_fv_all()
+{
+ Core moab;
+ Interface& mb =3D moab;
+
+ std::string opts;
+ ErrorCode rval =3D get_options(opts);
+ CHECK_ERR(rval);
+
+ rval =3D mb.load_file(example_fv, NULL, opts.c_str());
+ CHECK_ERR(rval);
+
// check for proper tags
Tag Ttag0, Ttag1, coordTag;
rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
CHECK_ERR(rval);
- =20
+
rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
CHECK_ERR(rval);
=20
- rval=3Dmb.tag_get_handle("COORDS", 3 ,MB_TYPE_DOUBLE, coordTag);
+ rval=3Dmb.tag_get_handle("COORDS", 3, MB_TYPE_DOUBLE, coordTag);
CHECK_ERR(rval);
}
=20
-void test_read_onevar()=20
+void test_read_fv_onevar()=20
{
Core moab;
Interface& mb =3D moab;
@@ -80,19 +246,19 @@ void test_read_onevar()
CHECK_ERR(rval);
=20
opts +=3D std::string(";VARIABLE=3DT");
- rval =3D mb.load_file( example, NULL, opts.c_str());
+ rval =3D mb.load_file(example_fv, NULL, opts.c_str());
CHECK_ERR(rval);
- =20
+
// check for proper tags
Tag Ttag0, Ttag1;
rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
CHECK_ERR(rval);
- =20
+
rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
CHECK_ERR(rval);
}
=20
-void test_read_onetimestep()
+void test_read_fv_onetimestep()
{
Core moab;
Interface& mb =3D moab;
@@ -100,20 +266,20 @@ void test_read_onetimestep()
ErrorCode rval =3D get_options(opts);
CHECK_ERR(rval);
=20
- opts +=3D std::string(";TIMESTEP=3D1");
- rval =3D mb.load_file( example, NULL, opts.c_str() );
+ opts +=3D std::string(";VARIABLE=3DT;TIMESTEP=3D1");
+ rval =3D mb.load_file(example_fv, NULL, opts.c_str());
CHECK_ERR(rval);
- =20
+
// check for proper tags
Tag Ttag0, Ttag1;
rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
- =20
+
rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
CHECK_ERR(rval);
}
=20
-void test_read_nomesh()=20
+void test_read_fv_nomesh()=20
{
Core moab;
Interface& mb =3D moab;
@@ -122,34 +288,34 @@ void test_read_nomesh()
EntityHandle set;
ErrorCode rval =3D mb.create_meshset(MESHSET_SET, set);
CHECK_ERR(rval);
- =20
+
std::string orig, opts;
rval =3D get_options(orig);
CHECK_ERR(rval);
=20
- opts =3D orig + std::string(";TIMESTEP=3D0");
- rval =3D mb.load_file( example, &set, opts.c_str() );
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D0");
+ rval =3D mb.load_file(example_fv, &set, opts.c_str());
CHECK_ERR(rval);
- =20
+
// check for proper tag
Tag Ttag0, Ttag1;
rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
CHECK_ERR(rval);
- =20
+
rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
=20
// now read 2nd timestep with nomesh option
- opts =3D orig + std::string(";TIMESTEP=3D1;NOMESH");
- rval =3D mb.load_file( example, &set, opts.c_str() );
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D1;NOMESH");
+ rval =3D mb.load_file(example_fv, &set, opts.c_str());
CHECK_ERR(rval);
- =20
+
// check for proper tag
rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
CHECK_ERR(rval);
}
=20
-void test_read_novars()=20
+void test_read_fv_novars()=20
{
Core moab;
Interface& mb =3D moab;
@@ -158,28 +324,28 @@ void test_read_novars()
EntityHandle set;
ErrorCode rval =3D mb.create_meshset(MESHSET_SET, set);
CHECK_ERR(rval);
- =20
+
std::string orig, opts;
rval =3D get_options(orig);
CHECK_ERR(rval);
=20
opts =3D orig + std::string(";NOMESH;VARIABLE=3D");
- rval =3D mb.load_file( example, &set, opts.c_str() );
+ rval =3D mb.load_file(example_fv, &set, opts.c_str());
CHECK_ERR(rval);
- =20
+
opts =3D orig + std::string(";VARIABLE=3D;TIMESTEP=3D0");
- rval =3D mb.load_file( example, &set, opts.c_str() );
+ rval =3D mb.load_file(example_fv, &set, opts.c_str());
CHECK_ERR(rval);
- =20
+
// check for proper tag
Tag Ttag0, Ttag1;
rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
- =20
+
opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D0;NOMESH");
- rval =3D mb.load_file( example, &set, opts.c_str() );
+ rval =3D mb.load_file(example_fv, &set, opts.c_str());
CHECK_ERR(rval);
- =20
+
rval =3D mb.tag_get_handle("T0", 26, MB_TYPE_DOUBLE, Ttag0);
CHECK_ERR(rval);
=20
@@ -187,16 +353,16 @@ void test_read_novars()
CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
=20
// now read 2nd timestep with nomesh option
- opts =3D orig + std::string(";TIMESTEP=3D1;NOMESH");
- rval =3D mb.load_file( example, &set, opts.c_str() );
+ opts =3D orig + std::string(";VARIABLE=3DT;TIMESTEP=3D1;NOMESH");
+ rval =3D mb.load_file(example_fv, &set, opts.c_str());
CHECK_ERR(rval);
- =20
+
// check for proper tag
rval =3D mb.tag_get_handle("T1", 26, MB_TYPE_DOUBLE, Ttag1);
CHECK_ERR(rval);
}
=20
-ErrorCode get_options(std::string &opts)=20
+ErrorCode get_options(std::string& opts)=20
{
#ifdef USE_MPI
// use parallel options
https://bitbucket.org/fathomteam/moab/commits/48b6301dbdaa/
Changeset: 48b6301dbdaa
Branch: None
User: danwu
Date: 2013-06-05 22:50:20
Summary: Merged fathomteam/moab into master
Affected #: 1 file
diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 6490b24..32faa58 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -34,7 +34,7 @@ bool NCHelperHOMME::can_read_file(ReadNC* readNC, int fil=
eId)
// If global attribute "np" exists then it should be the HOMME grid
if (readNC->globalAtts.find("np") !=3D readNC->globalAtts.end()) {
// Make sure it is CAM grid
- std::map<std::string, ReadNC::AttData>::iterator attIt =3D readNC->global=
Atts.find("source");
+ std::map<std::string, ReadNC::AttData>::iterator attIt =3D readNC->glo=
balAtts.find("source");
if (attIt =3D=3D readNC->globalAtts.end()) {
readNC->readMeshIface->report_error("%s", "File does not have source=
global attribute.");
return false;
https://bitbucket.org/fathomteam/moab/commits/0146d4671191/
Changeset: 0146d4671191
Branch: None
User: danwu
Date: 2013-06-11 21:54:56
Summary: Update enum EntityLocation, and change ReadNC and the helpers =
accordingly.
Affected #: 9 files
diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 852fc61..16f2a3c 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -22,7 +22,7 @@ public:
static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOpt=
ions& opts);
=20
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set) =3D 0;
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads) =3D 0;
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces) =3D 0;
virtual std::string get_mesh_type_name() =3D 0;
virtual bool is_scd_mesh() =3D 0;
=20
diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index a01d4b8..cac789c 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -343,7 +343,7 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
ReadNC::VarData& vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D vd.va=
rDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
- vd.entLoc =3D ReadNC::ENTLOCQUAD;
+ vd.entLoc =3D ReadNC::ENTLOCFACE;
}
=20
// <coordinate_dim_name>
@@ -473,9 +473,9 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperEuler::create_verts_quads(ScdInterface* scdi, const File=
Options& opts, EntityHandle file_set, Range& quads)
+ErrorCode NCHelperEuler::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& faces)
{
- return _readNC->create_scd_verts_quads(scdi, file_set, quads);
+ return _readNC->create_scd_verts_quads(scdi, file_set, faces);
}
=20
} // namespace moab
diff --git a/src/io/NCHelperEuler.hpp b/src/io/NCHelperEuler.hpp
index b1c4c21..6bf2a51 100644
--- a/src/io/NCHelperEuler.hpp
+++ b/src/io/NCHelperEuler.hpp
@@ -24,7 +24,7 @@ public:
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
=20
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads);
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
=20
virtual std::string get_mesh_type_name() { return "CAM_EUL"; }
=20
diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 566b719..9bb5564 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -333,7 +333,7 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
ReadNC::VarData& vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D vd.va=
rDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
- vd.entLoc =3D ReadNC::ENTLOCQUAD;
+ vd.entLoc =3D ReadNC::ENTLOCFACE;
else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) !=3D v=
d.varDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), iCDim) !=3D vd.varDims.end()))
vd.entLoc =3D ReadNC::ENTLOCNSEDGE;
@@ -469,9 +469,9 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperFV::create_verts_quads(ScdInterface* scdi, const FileOpt=
ions& opts, EntityHandle file_set, Range& quads)
+ErrorCode NCHelperFV::create_mesh(ScdInterface* scdi, const FileOptions& o=
pts, EntityHandle file_set, Range& faces)
{
- return _readNC->create_scd_verts_quads(scdi, file_set, quads);
+ return _readNC->create_scd_verts_quads(scdi, file_set, faces);
}
=20
} // namespace moab
diff --git a/src/io/NCHelperFV.hpp b/src/io/NCHelperFV.hpp
index afcd9b8..0a1ba76 100644
--- a/src/io/NCHelperFV.hpp
+++ b/src/io/NCHelperFV.hpp
@@ -22,7 +22,7 @@ public:
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads);
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
virtual std::string get_mesh_type_name() { return "CAM_FV"; }
virtual bool is_scd_mesh() { return true; }
};
diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 32faa58..6f6b102 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -180,7 +180,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
ReadNC::VarData& vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), iDim) !=3D vd.var=
Dims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), kDim) !=3D vd.varDims.end()))
- vd.entLoc =3D ReadNC::ENTLOCNODE;
+ vd.entLoc =3D ReadNC::ENTLOCVERT;
}
=20
std::copy(gDims, gDims + 6, lDims);
@@ -199,7 +199,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperHOMME::create_verts_quads(ScdInterface* scdi, const File=
Options& opts, EntityHandle file_set, Range& quads)
+ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& quads)
{
Interface*& mbImpl =3D _readNC->mbImpl;
std::string& fileName =3D _readNC->fileName;
diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index feb3cad..827c39f 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -22,7 +22,7 @@ public:
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads);
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& elems);
virtual std::string get_mesh_type_name() { return "CAM_SE"; }
virtual bool is_scd_mesh() { return false; }
=20
diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index 514f724..5e7eaf2 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -205,15 +205,15 @@ ErrorCode ReadNC::load_file(const char *file_name, co=
nst EntityHandle* file_set,
rval =3D myHelper->init_mesh_vals(opts, tmp_set);
ERRORR(rval, "Trouble initializing mesh values.");
=20
- // Create mesh vertex/quads sequences
- Range quads;
+ // Create mesh vertex/edge/face sequences
+ Range faces;
if (noMesh && !noVars) {
- rval =3D check_verts_quads(tmp_set);
+ rval =3D check_verts_faces(tmp_set);
ERRORR(rval, "Mesh characteristics didn't match from last read.\n");
}
else if (!noMesh) {
- rval =3D myHelper->create_verts_quads(scdi, opts, tmp_set, quads);
- ERRORR(rval, "Trouble creating vertices and quads.");
+ rval =3D myHelper->create_mesh(scdi, opts, tmp_set, faces);
+ ERRORR(rval, "Trouble creating mesh.");
}
=20
bool scd_mesh =3D myHelper->is_scd_mesh();
@@ -244,21 +244,21 @@ ErrorCode ReadNC::load_file(const char *file_name, co=
nst EntityHandle* file_set,
rval =3D mbImpl->create_meshset(MESHSET_SET, partn_set);
ERRORR(rval, "Trouble creating partition set.");
=20
- rval =3D mbImpl->add_entities(partn_set,quads);
- ERRORR(rval, "Couldn't add new quads to partition set.");
+ rval =3D mbImpl->add_entities(partn_set, faces);
+ ERRORR(rval, "Couldn't add new faces to partition set.");
=20
Range verts;
- rval =3D mbImpl->get_connectivity(quads, verts);
- ERRORR(rval, "Couldn't get verts of quads");
+ rval =3D mbImpl->get_connectivity(faces, verts);
+ ERRORR(rval, "Couldn't get verts of faces");
=20
- rval =3D mbImpl->add_entities(partn_set,verts);
+ rval =3D mbImpl->add_entities(partn_set, verts);
ERRORR(rval, "Couldn't add new verts to partition set.");
=20
myPcomm->partition_sets().insert(partn_set);
=20
//write partition tag name on partition set
Tag part_tag;
- rval =3D mbImpl->tag_get_handle( partitionTagName.c_str(), 1, MB_TYPE_=
INTEGER, part_tag );
+ rval =3D mbImpl->tag_get_handle(partitionTagName.c_str(), 1, MB_TYPE_I=
NTEGER, part_tag);
if (MB_SUCCESS !=3D rval) {
// fall back to the partition tag
part_tag =3D myPcomm->partition_tag();
@@ -266,12 +266,13 @@ ErrorCode ReadNC::load_file(const char *file_name, co=
nst EntityHandle* file_set,
=20
int dum_rank =3D myPcomm->proc_config().proc_rank();
rval =3D mbImpl->tag_set_data(part_tag, &partn_set, 1, &dum_rank);
- if (MB_SUCCESS !=3D rval) return rval;
+ if (MB_SUCCESS !=3D rval)
+ return rval;
}
#endif
=20
mbImpl->release_interface(scdi);
- ERRORR(rval, "Trouble creating scd element sequence.");
+ ERRORR(rval, "Trouble creating element sequence.");
=20
// create nc conventional tags when loading header info only
if (noMesh && noVars) {
@@ -476,7 +477,7 @@ ErrorCode ReadNC::check_ucd_localGid(EntityHandle tmp_s=
et)
return MB_SUCCESS;
}
=20
-ErrorCode ReadNC::check_verts_quads(EntityHandle file_set) {
+ErrorCode ReadNC::check_verts_faces(EntityHandle file_set) {
// check parameters on this read against what was on the mesh from last =
read
// get the number of vertices
int num_verts;
@@ -702,10 +703,8 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle =
file_set, std::vector<VarD
=20
std::vector<EntityHandle>* ehandles =3D NULL;
Range* range =3D NULL;
- //std::vector<EntityHandle> verts_handles;
std::vector<EntityHandle> ns_edges_handles;
std::vector<EntityHandle> ew_edges_handles;
- //std::vector<EntityHandle> quads_handles;
=20
// get vertices in set
Range verts;
@@ -713,8 +712,6 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle f=
ile_set, std::vector<VarD
ERRORR(rval, "Trouble getting vertices in set.");
assert("Should only have a single vertex subrange, since they were read =
in one shot" &&
verts.psize() =3D=3D 1);
- //verts_handles.resize(verts.size());
- //std::copy(verts.begin(), verts.end(), verts_handles.begin());
=20
Range edges;
rval =3D mbImpl->get_entities_by_dimension(file_set, 1, edges);
@@ -730,25 +727,22 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle=
file_set, std::vector<VarD
// FIXME: initialize ew_edges_handles to get the right order
//std::copy(edges.begin(), edges.end(), ew_edges_handles.begin());
=20
- // get quads in set
- Range quads;
- rval =3D mbImpl->get_entities_by_dimension(file_set, 2, quads);
- ERRORR(rval, "Trouble getting quads in set.");
- assert("Should only have a single quad subrange, since they were read in=
one shot" &&
- quads.psize() =3D=3D 1);
- //quads_handles.resize(quads.size());
- //std::copy(quads.begin(), quads.end(), quads_handles.begin());
+ // get faces in set
+ Range faces;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 2, faces);
+ ERRORR(rval, "Trouble getting faces in set.");
+ assert("Should only have a single face subrange, since they were read in=
one shot" &&
+ faces.psize() =3D=3D 1);
=20
#ifdef USE_MPI
- moab::Range quads_owned;
+ moab::Range faces_owned;
if (isParallel)
{
- rval =3D myPcomm->filter_pstatus(quads, PSTATUS_NOT_OWNED, PSTATUS_NOT=
, -1,
- &quads_owned);
- ERRORR(rval, "Trouble getting owned quads in set.");
+ rval =3D myPcomm->filter_pstatus(faces, PSTATUS_NOT_OWNED, PSTATUS_NOT=
, -1, &faces_owned);
+ ERRORR(rval, "Trouble getting owned faces in set.");
}
else
- quads_owned=3Dquads;// not running in parallel, but still with MPI
+ faces_owned =3D faces; // not running in parallel, but still with MPI
#endif
=20
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
@@ -793,7 +787,7 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle f=
ile_set, std::vector<VarD
}
=20
switch (vdatas[i].entLoc) {
- case 0:
+ case ENTLOCVERT:
// vertices
if (scd_mesh) {
// only structured mesh has j parameter that multiplies i to g=
et total # vertices
@@ -806,14 +800,14 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle=
file_set, std::vector<VarD
{
// we will start from the first localGid, actually; we will re=
set that
// later on, anyway, in a loop
- vdatas[i].readDims[t].push_back(localGid[0]-1);
+ vdatas[i].readDims[t].push_back(localGid[0] - 1);
vdatas[i].readCounts[t].push_back(localGid.size());
}
=20
assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
range =3D &verts;
break;
- case 1:
+ case ENTLOCNSEDGE:
// north/south edges
/*
vdatas[i].readDims[t].push_back(lDims[1]);
@@ -826,10 +820,9 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle =
file_set, std::vector<VarD
ehandles =3D &ns_edges_handles;
range =3D &verts; // FIXME: should remove when edge handles are=
used
*/
- ERRORR(MB_FAILURE, "Reading edge data not implemented yet.")
- ;
+ ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
break;
- case 2:
+ case ENTLOCEWEDGE:
// east/west edges
/*
vdatas[i].readDims[t].push_back(lCDims[1]);
@@ -847,11 +840,10 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle=
file_set, std::vector<VarD
ehandles =3D &ew_edges_handles;
range =3D &verts; // FIXME: should remove when edge handles are=
used
*/
- ERRORR(MB_FAILURE, "Reading edge data not implemented yet.")
- ;
+ ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
break;
- case 3:
- // quads
+ case ENTLOCFACE:
+ // faces
vdatas[i].readDims[t].push_back(lCDims[1]);
vdatas[i].readDims[t].push_back(lCDims[0]);
vdatas[i].readCounts[t].push_back(lCDims[4] - lCDims[1] + 1);
@@ -859,17 +851,22 @@ ErrorCode ReadNC::read_variable_allocate(EntityHandle=
file_set, std::vector<VarD
assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
=20
#ifdef USE_MPI
- range =3D &quads_owned;
+ range =3D &faces_owned;
#else
- range =3D &quads;
+ range =3D &faces;
#endif
break;
- case 4:
- // set
+ case ENTLOCSET:
+ // sets
+ break;
+ case ENTLOCEDGE:
+ // edges
+ break;
+ case ENTLOCREGION:
+ // regions
break;
default:
- ERRORR(MB_FAILURE, "Unrecoganized entity location type.")
- ;
+ ERRORR(MB_FAILURE, "Unrecoganized entity location type.");
break;
}
=20
@@ -925,7 +922,7 @@ ErrorCode ReadNC::read_variables(EntityHandle file_set,=
std::vector<std::string>
#endif
rval =3D read_variable_to_nonset(file_set, vdatas, tstep_nums, scd_m=
esh);
=20
- ERRORR(rval, "Trouble read variables to entities verts/edges/quads.");
+ ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
}
=20
return MB_SUCCESS;
@@ -1029,14 +1026,12 @@ ErrorCode ReadNC::read_variable_to_set(EntityHandle=
file_set, std::vector<VarDat
case NC_CHAR:
success =3D NCFUNCAG(_vara_text)(fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
(char*) data NCREQ);
- ERRORS(success, "Failed to read char data.")
- ;
+ ERRORS(success, "Failed to read char data.");
break;
case NC_DOUBLE:
success =3D NCFUNCAG(_vara_double)(fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
(double*) data NCREQ);
- ERRORS(success, "Failed to read double data.")
- ;
+ ERRORS(success, "Failed to read double data.");
break;
case NC_FLOAT: {
success =3D NCFUNCAG(_vara_float)(fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
@@ -1047,14 +1042,12 @@ ErrorCode ReadNC::read_variable_to_set(EntityHandle=
file_set, std::vector<VarDat
case NC_INT:
success =3D NCFUNCAG(_vara_int)(fileId, vdatas[i].varId, &vdatas=
[i].readDims[t][0], &vdatas[i].readCounts[t][0],
(int*) data NCREQ);
- ERRORS(success, "Failed to read int data.")
- ;
+ ERRORS(success, "Failed to read int data.");
break;
case NC_SHORT:
success =3D NCFUNCAG(_vara_short)(fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
(short*) data NCREQ);
- ERRORS(success, "Failed to read short data.")
- ;
+ ERRORS(success, "Failed to read short data.");
break;
default:
success =3D 1;
@@ -1122,7 +1115,7 @@ ErrorCode ReadNC::read_variable_to_nonset(EntityHandl=
e file_set, std::vector<Var
}
else {
sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
- nj =3D 1; // for ucdMesh, nj holds # quads, so here should reset t=
o 1
+ nj =3D 1; // for ucdMesh, nj holds # faces, so here should reset t=
o 1
}
=20
switch (vdatas[i].varDataType) {
@@ -1174,12 +1167,11 @@ ErrorCode ReadNC::read_variable_to_nonset(EntityHan=
dle file_set, std::vector<Var
// assume that the last dimension is for the ncol,
// node varying variable
=20
- size_t indexInFloatArray=3D 0;
- size_t ic=3D0;
- for (
- Range::pair_iterator pair_iter =3D localGid.pair_begin();
- pair_iter!=3DlocalGid.pair_end();
- pair_iter++, ic++)
+ size_t indexInFloatArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter!=3DlocalGid.pair_end();
+ pair_iter++, ic++)
{
EntityHandle starth =3D pair_iter->first;
EntityHandle endh =3D pair_iter->second;// inclusive
@@ -1192,9 +1184,9 @@ ErrorCode ReadNC::read_variable_to_nonset(EntityHandl=
e file_set, std::vector<Var
ERRORS(success, "Failed to read float data in loop");
// we need to increment the index in float array for the
// next subrange
- indexInFloatArray+=3D (endh-starth+1)*1*vdatas[i].numLev; //
+ indexInFloatArray +=3D (endh - starth + 1) * 1 * vdatas[i].n=
umLev;
}
- assert(ic=3D=3DlocalGid.psize());
+ assert(ic =3D=3D localGid.psize());
//
}
if (vdatas[i].numLev !=3D 1)
@@ -1293,10 +1285,10 @@ ErrorCode ReadNC::read_variable_to_nonset_async(Ent=
ityHandle file_set, std::vect
size_t nk =3D vdatas[i].readCounts[t][1];
=20
sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
- size_t nj =3D 1; // for ucdMesh, nj holds # quads, so here should re=
set to 1
+ size_t nj =3D 1; // for ucdMesh, nj holds # faces, so here should re=
set to 1
=20
- if (sz<=3D0)
- continue;// nothing to read, why worry?
+ if (sz <=3D 0)
+ continue; // nothing to read, why worry?
=20
switch (vdatas[i].varDataType) {
case NC_BYTE:
@@ -1317,17 +1309,16 @@ ErrorCode ReadNC::read_variable_to_nonset_async(Ent=
ityHandle file_set, std::vect
// assume that the last dimension is for the ncol,
// node varying variable
=20
- size_t indexInDoubleArray=3D 0;
- size_t ic=3D0;
- for (
- Range::pair_iterator pair_iter =3D localGid.pair_begin();
- pair_iter!=3DlocalGid.pair_end();
- pair_iter++, ic++)
+ size_t indexInDoubleArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter!=3DlocalGid.pair_end();
+ pair_iter++, ic++)
{
EntityHandle starth =3D pair_iter->first;
- EntityHandle endh =3D pair_iter->second;// inclusive
- vdatas[i].readDims[t][nbDims-1] =3D (NCDF_SIZE) (starth-1);
- vdatas[i].readCounts[t][nbDims-1] =3D (NCDF_SIZE) (endh-starth=
+1);
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
=20
// do a partial read, in each subrange
// wait outside this loop
@@ -1337,7 +1328,7 @@ ErrorCode ReadNC::read_variable_to_nonset_async(Entit=
yHandle file_set, std::vect
ERRORS(success, "Failed to read double data in loop");
// we need to increment the index in float array for the
// next subrange
- indexInDoubleArray+=3D (endh-starth+1)*1*vdatas[i].numLev; //
+ indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
}
assert(ic=3D=3DlocalGid.psize());
//
@@ -1525,7 +1516,7 @@ ErrorCode ReadNC::convert_variable(VarData &var_data,=
int tstep_num, bool scd_me
=20
ErrorCode ReadNC::get_tag_to_set(VarData &var_data, int tstep_num, Tag &ta=
gh) {
std::ostringstream tag_name;
- if ((!var_data.has_t)||( var_data.varDims.size()<=3D1))
+ if ((!var_data.has_t) || (var_data.varDims.size() <=3D 1))
tag_name << var_data.varName;
else if (!tstep_num) {
std::string tmp_name =3D var_data.varName + "0";
@@ -1597,10 +1588,10 @@ void ReadNC::init_dims_with_no_cvars_info() {
// hack: look at all dimensions, and see if we have one that does not ap=
pear in the list of varInfo names
// right now, candidates are ncol and nbnd
// for them, create dummy tags
- for (unsigned int i=3D0; i<dimNames.size(); i++)
+ for (unsigned int i =3D 0; i < dimNames.size(); i++)
{
// if there is a var with this name, skip, we are fine; if not, create=
a varInfo...
- if ( varInfo.find(dimNames[i])!=3DvarInfo.end())
+ if (varInfo.find(dimNames[i]) !=3D varInfo.end())
continue; // we already have a variable with this dimension name
=20
int sizeTotalVar =3D varInfo.size();
@@ -1677,7 +1668,6 @@ ErrorCode ReadNC::read_header() {
}
=20
ErrorCode ReadNC::get_attributes(int var_id, int num_atts, std::map<std::s=
tring, AttData> &atts, const char *prefix) {
-
char dum_name[120];
=20
for (int i =3D 0; i < num_atts; i++) {
@@ -1783,7 +1773,6 @@ ErrorCode ReadNC::get_variables() {
=20
ErrorCode rval =3D get_attributes(i, data.numAtts, data.varAtts, " "=
);
ERRORR(rval, "Trouble getting attributes for a variable.");
-
}
=20
return MB_SUCCESS;
@@ -1840,7 +1829,6 @@ ErrorCode ReadNC::create_tags(ScdInterface *scdi, Ent=
ityHandle file_set, const s
// <__DIM_VALUES>
Tag dimValsTag =3D 0;
tag_name =3D "__DIM_VALUES";
- //std::vector<int> dim;
int dimValsSz =3D (int)dimVals.size();
=20
rval =3D mbImpl->tag_get_handle(tag_name.c_str(), 0, MB_TYPE_INTEGER, di=
mValsTag, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN);
@@ -2051,40 +2039,35 @@ ErrorCode ReadNC::create_attrib_string(const std::m=
ap<std::string, AttData>& att
sz =3D attIt->second.attLen;
attData =3D (char *) malloc(sz);
success =3D NCFUNC(get_att_text)(fileId, attIt->second.attVarId, a=
ttIt->second.attName.c_str(), (char*) attData);
- ERRORS(success, "Failed to read attribute char data.")
- ;
+ ERRORS(success, "Failed to read attribute char data.");
ssAtt << "char;";
break;
case NC_DOUBLE:
sz =3D attIt->second.attLen * sizeof(double);
attData =3D (double *) malloc(sz);
success =3D NCFUNC(get_att_double)(fileId, attIt->second.attVarId,=
attIt->second.attName.c_str(), (double*) attData);
- ERRORS(success, "Failed to read attribute double data.")
- ;
+ ERRORS(success, "Failed to read attribute double data.");
ssAtt << "double;";
break;
case NC_FLOAT:
sz =3D attIt->second.attLen * sizeof(float);
attData =3D (float *) malloc(sz);
success =3D NCFUNC(get_att_float)(fileId, attIt->second.attVarId, =
attIt->second.attName.c_str(), (float*) attData);
- ERRORS(success, "Failed to read attribute float data.")
- ;
+ ERRORS(success, "Failed to read attribute float data.");
ssAtt << "float;";
break;
case NC_INT:
sz =3D attIt->second.attLen * sizeof(int);
attData =3D (int *) malloc(sz);
success =3D NCFUNC(get_att_int)(fileId, attIt->second.attVarId, at=
tIt->second.attName.c_str(), (int*) attData);
- ERRORS(success, "Failed to read attribute int data.")
- ;
+ ERRORS(success, "Failed to read attribute int data.");
ssAtt << "int;";
break;
case NC_SHORT:
sz =3D attIt->second.attLen * sizeof(short);
attData =3D (short *) malloc(sz);
success =3D NCFUNC(get_att_short)(fileId, attIt->second.attVarId, =
attIt->second.attName.c_str(), (short*) attData);
- ERRORS(success, "Failed to read attribute short data.")
- ;
+ ERRORS(success, "Failed to read attribute short data.");
ssAtt << "short;";
break;
default:
diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index cd1ca6b..7e16215 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -74,14 +74,14 @@ class ReadNC : public ReaderIface
=20
public:
=20
- static ReaderIface* factory( Interface* );
+ static ReaderIface* factory(Interface*);
=20
//! load an NC file
- ErrorCode load_file( const char* file_name,
+ ErrorCode load_file(const char* file_name,
const EntityHandle* file_set,
const FileOptions& opts,
const SubsetList* subset_list =3D 0,
- const Tag* file_id_tag =3D 0 );
+ const Tag* file_id_tag =3D 0);
=20
//! Constructor
ReadNC(Interface* impl =3D NULL);
@@ -89,15 +89,15 @@ public:
//! Destructor
virtual ~ReadNC();
=20
- virtual ErrorCode read_tag_values( const char* file_name,
- const char* tag_name,
- const FileOptions& opts,
- std::vector<int>& tag_values_out,
- const SubsetList* subset_list =3D 0 );
+ virtual ErrorCode read_tag_values(const char* file_name,
+ const char* tag_name,
+ const FileOptions& opts,
+ std::vector<int>& tag_values_out,
+ const SubsetList* subset_list =3D 0);
=20
// ENTLOCNSEDGE for north/south edge
// ENTLOCWEEDGE for west/east edge
- enum EntityLocation {ENTLOCNODE=3D0, ENTLOCNSEDGE, ENTLOCEWEDGE, ENTLOCQ=
UAD, ENTLOCSET};
+ enum EntityLocation {ENTLOCVERT =3D 0, ENTLOCNSEDGE, ENTLOCEWEDGE, ENTLO=
CFACE, ENTLOCSET, ENTLOCEDGE, ENTLOCREGION};
=20
private:
=20
@@ -143,7 +143,7 @@ private:
ErrorCode read_header();
=20
//! get all global attributes in the file
- ErrorCode get_attributes(int var_id, int num_atts, std::map<std::string,=
AttData> &atts,
+ ErrorCode get_attributes(int var_id, int num_atts, std::map<std::string,=
AttData> &atts,
const char *prefix=3D"");
=20
//! get all dimensions in the file
@@ -158,14 +158,14 @@ private:
//! number of dimensions in this nc file
unsigned int number_dimensions();
=20
- //! create vertices for scd mesh
- ErrorCode create_scd_verts_quads(ScdInterface *scdi, EntityHandle file_s=
et, Range &quads);
+ //! create vertices and faces for scd mesh
+ ErrorCode create_scd_verts_quads(ScdInterface *scdi, EntityHandle file_s=
et, Range &faces);
=20
//! make sure that localGid is properly initialized for ucd mesh
ErrorCode check_ucd_localGid(EntityHandle file_set);
=20
- //! check number of vertices and elements against what's already in fi=
le_set
- ErrorCode check_verts_quads(EntityHandle file_set);
+ //! check number of vertices and faces against what's already in file_=
set
+ ErrorCode check_verts_faces(EntityHandle file_set);
=20
ErrorCode parse_options(const FileOptions &opts,
std::vector<std::string> &var_names,=20
@@ -240,7 +240,7 @@ private:
for (std::size_t j =3D 0; j !=3D nj; ++j)
for (std::size_t i =3D 0; i !=3D ni; ++i)
for (std::size_t k =3D 0; k !=3D nk; ++k)=20
- tmp_data[j*nik+i*nk+k] =3D source[k*nij+j*ni+i]; =20
+ tmp_data[j*nik + i*nk + k] =3D source[k*nij + j*ni + i];
return MB_SUCCESS;
}
=20
@@ -249,22 +249,22 @@ private:
// we read one time step, one variable at a time, usually, so we will
template <typename T> ErrorCode kji_to_jik_stride(size_t , size_t nj, si=
ze_t nk, void *dest, T *source)
{
- std::size_t idxInSource=3D0;// position of the start of the stride
+ std::size_t idxInSource =3D 0;// position of the start of the stri=
de
// for each subrange, we will transpose a matrix of size subrange*=
nj*nk (subrange takes
// =
the role of ni)
T *tmp_data =3D reinterpret_cast<T*>(dest);
for (
Range::pair_iterator pair_iter =3D localGid.pair_begin();
- pair_iter!=3DlocalGid.pair_end();
+ pair_iter !=3D localGid.pair_end();
pair_iter++)
{
- std::size_t size_range=3D pair_iter->second - pair_iter->first+1;
+ std::size_t size_range =3D pair_iter->second - pair_iter->first =
+ 1;
std::size_t nik =3D size_range * nk, nij =3D size_range * nj;
for (std::size_t j =3D 0; j !=3D nj; ++j)
for (std::size_t i =3D 0; i !=3D size_range; ++i)
for (std::size_t k =3D 0; k !=3D nk; ++k)
- tmp_data[idxInSource + j*nik+i*nk+k] =3D source[idxInSourc=
e + k*nij+j*size_range+i];
- idxInSource+=3D(size_range*nj*nk);
+ tmp_data[idxInSource + j*nik + i*nk + k] =3D source[idxInS=
ource + k*nij + j*size_range + i];
+ idxInSource +=3D (size_range * nj * nk);
}
return MB_SUCCESS;
}
@@ -287,7 +287,7 @@ private:
// these should be taken out when we fix the dummy var info things
std::set<std::string> dummyVarNames;
std::vector<int> dimVals;
- std::string iName, jName, kName,tName;
+ std::string iName, jName, kName, tName;
std::string iCName, jCName;
=20
//! global attribs
@@ -314,7 +314,7 @@ private:
//! center values for i/j
std::vector<double> ilCVals, jlCVals;
=20
- //! dimension numbers for i, j, t
+ //! dimension numbers for i, j, k, t
int iDim, jDim, kDim, tDim;
=20
//! center dimension numbers for i, j
https://bitbucket.org/fathomteam/moab/commits/04a1a74a19f2/
Changeset: 04a1a74a19f2
Branch: None
User: danwu
Date: 2013-06-11 22:50:45
Summary: Support reading MPAS file type in ReadNC (initial submission).
Affected #: 8 files
diff --git a/src/io/Makefile.am b/src/io/Makefile.am
index b7eae6a..bb5b7cb 100644
--- a/src/io/Makefile.am
+++ b/src/io/Makefile.am
@@ -21,6 +21,7 @@ if NETCDF_FILE
NCHelperEuler.cpp NCHelperEuler.hpp \
NCHelperFV.cpp NCHelperFV.hpp \
NCHelperHOMME.cpp NCHelperHOMME.hpp \
+ NCHelperMPAS.cpp NCHelperMPAS.hpp \
ReadGCRM.cpp ReadGCRM.hpp
else
MOAB_NETCDF_SRCS =3D
@@ -33,6 +34,7 @@ if !NETCDF_FILE
NCHelperEuler.cpp NCHelperEuler.hpp \
NCHelperFV.cpp NCHelperFV.hpp \
NCHelperHOMME.cpp NCHelperHOMME.hpp \
+ NCHelperMPAS.cpp NCHelperMPAS.hpp \
ReadGCRM.cpp ReadGCRM.hpp
endif
endif
diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index e0f021e..731e3af 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -2,20 +2,45 @@
#include "NCHelperEuler.hpp"
#include "NCHelperFV.hpp"
#include "NCHelperHOMME.hpp"
-#include "moab/ReadUtilIface.hpp"
+#include "NCHelperMPAS.hpp"
=20
namespace moab {
=20
NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOp=
tions& opts)
{
- if (NCHelperEuler::can_read_file(readNC, fileId))
- return new (std::nothrow) NCHelperEuler(readNC, fileId);
- else if (NCHelperFV::can_read_file(readNC, fileId))
- return new (std::nothrow) NCHelperFV(readNC, fileId);
- else if (NCHelperHOMME::can_read_file(readNC, fileId))
- return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts);
- else // Unknown NetCDF grid (will fill this in later for POP, CICE and C=
LM)
- return NULL;
+ // Check if CF convention is being followed
+ bool is_CF =3D false;
+
+ std::map<std::string, ReadNC::AttData>& globalAtts =3D readNC->globalAtt=
s;
+ std::map<std::string, ReadNC::AttData>::iterator attIt =3D globalAtts.fi=
nd("conventions");
+ if (attIt =3D=3D globalAtts.end())
+ attIt =3D globalAtts.find("Conventions");
+
+ if (attIt !=3D globalAtts.end()) {
+ unsigned int sz =3D attIt->second.attLen;
+ std::string att_data;
+ att_data.resize(sz + 1);
+ att_data[sz] =3D '\000';
+ int success =3D NCFUNC(get_att_text)(fileId, attIt->second.attVarId, a=
ttIt->second.attName.c_str(), &att_data[0]);
+ if (0 =3D=3D success && att_data.find("CF") !=3D std::string::npos)
+ is_CF =3D true;
+ }
+
+ if (is_CF) {
+ if (NCHelperEuler::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperEuler(readNC, fileId);
+ else if (NCHelperFV::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperFV(readNC, fileId);
+ else if (NCHelperHOMME::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts);
+ }
+ else {
+ if (NCHelperMPAS::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperMPAS(readNC, fileId, opts);
+ }
+
+ // Unknown NetCDF grid (will fill this in later for POP, CICE and CLM)
+ return NULL;
}
=20
} // namespace moab
diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index cac789c..1fd5673 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -473,9 +473,9 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperEuler::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& faces)
+ErrorCode NCHelperEuler::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& quads)
{
- return _readNC->create_scd_verts_quads(scdi, file_set, faces);
+ return _readNC->create_scd_verts_quads(scdi, file_set, quads);
}
=20
} // namespace moab
diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 9bb5564..8e23542 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -469,9 +469,9 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperFV::create_mesh(ScdInterface* scdi, const FileOptions& o=
pts, EntityHandle file_set, Range& faces)
+ErrorCode NCHelperFV::create_mesh(ScdInterface* scdi, const FileOptions& o=
pts, EntityHandle file_set, Range& quads)
{
- return _readNC->create_scd_verts_quads(scdi, file_set, faces);
+ return _readNC->create_scd_verts_quads(scdi, file_set, quads);
}
=20
} // namespace moab
diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index 827c39f..3deebd3 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -22,7 +22,7 @@ public:
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& elems);
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
virtual std::string get_mesh_type_name() { return "CAM_SE"; }
virtual bool is_scd_mesh() { return false; }
=20
diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
new file mode 100644
index 0000000..b2ae8bc
--- /dev/null
+++ b/src/io/NCHelperMPAS.cpp
@@ -0,0 +1,46 @@
+#include "NCHelperMPAS.hpp"
+#include "moab/ReadUtilIface.hpp"
+#include "FileOptions.hpp"
+#include "moab/SpectralMeshTool.hpp"
+
+#include <cmath>
+
+#define ERRORR(rval, str) \
+ if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", =
str); return rval;}
+
+#define ERRORS(err, str) \
+ if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_F=
AILURE;}
+
+namespace moab {
+
+NCHelperMPAS::NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& =
opts) : NCHelper(readNC, fileId)
+{
+ if (MB_SUCCESS =3D=3D opts.match_option("PARTITION_METHOD", "NODAL_PARTI=
TION"))
+ readNC->partMethod =3D -1;
+}
+
+bool NCHelperMPAS::can_read_file(ReadNC* readNC, int fileId)
+{
+ std::vector<std::string>& dimNames =3D readNC->dimNames;
+
+ // If dimension name "vertexDegree" exists then it should be the MPAS gr=
id
+ if (std::find(dimNames.begin(), dimNames.end(), std::string("vertexDegre=
e")) !=3D dimNames.end()) {
+ return true;
+ }
+
+ return false;
+}
+
+ErrorCode NCHelperMPAS::init_mesh_vals(const FileOptions& opts, EntityHand=
le file_set)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+
+ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi, const FileOptions&=
opts, EntityHandle file_set, Range& faces)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+
+} // namespace moab
diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
new file mode 100644
index 0000000..54c7146
--- /dev/null
+++ b/src/io/NCHelperMPAS.hpp
@@ -0,0 +1,32 @@
+//-------------------------------------------------------------------------
+// Filename : NCHelperMPAS.hpp
+//
+// Purpose : Climate NC file helper for MPAS grid
+//
+// Creator : Danqing Wu
+//-------------------------------------------------------------------------
+
+#ifndef NCHELPERMPAS_HPP
+#define NCHELPERMPAS_HPP
+
+#include "NCHelper.hpp"
+
+namespace moab {
+
+//! Child helper class for MPAS grid
+class NCHelperMPAS : public NCHelper
+{
+public:
+ NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& opts);
+ static bool can_read_file(ReadNC* readNC, int fileId);
+
+private:
+ virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
+ virtual std::string get_mesh_type_name() { return "MPAS"; }
+ virtual bool is_scd_mesh() { return false; }
+};
+
+} // namespace moab
+
+#endif
diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index 7e16215..c2af40e 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -71,6 +71,7 @@ class ReadNC : public ReaderIface
friend class NCHelperEuler;
friend class NCHelperFV;
friend class NCHelperHOMME;
+ friend class NCHelperMPAS;
=20
public:
=20
@@ -158,8 +159,8 @@ private:
//! number of dimensions in this nc file
unsigned int number_dimensions();
=20
- //! create vertices and faces for scd mesh
- ErrorCode create_scd_verts_quads(ScdInterface *scdi, EntityHandle file_s=
et, Range &faces);
+ //! create vertices and quads for scd mesh
+ ErrorCode create_scd_verts_quads(ScdInterface *scdi, EntityHandle file_s=
et, Range &quads);
=20
//! make sure that localGid is properly initialized for ucd mesh
ErrorCode check_ucd_localGid(EntityHandle file_set);
https://bitbucket.org/fathomteam/moab/commits/8be23c31aa55/
Changeset: 8be23c31aa55
Branch: None
User: danwu
Date: 2013-06-12 15:51:49
Summary: ReadNC no longer returns an error when CF convention is not be=
ing followed (MPAS format does not follow CF convention)
Affected #: 1 file
diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index 5e7eaf2..87cd6dd 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -175,25 +175,6 @@ ErrorCode ReadNC::load_file(const char *file_name, con=
st EntityHandle* file_set,
if (!scdi)
return MB_FAILURE;
=20
- // Check if CF convention is being followed
- std::map<std::string, AttData>::iterator attIt =3D globalAtts.find("conv=
entions");
- if (attIt =3D=3D globalAtts.end())
- attIt =3D globalAtts.find("Conventions");
-
- if (attIt =3D=3D globalAtts.end()) {
- ERRORR(MB_FAILURE, "File does not have conventions global attribute.");
- }
-
- unsigned int sz =3D attIt->second.attLen;
- std::string att_data;
- att_data.resize(sz + 1);
- att_data[sz] =3D '\000';
- success =3D NCFUNC(get_att_text)(fileId, attIt->second.attVarId, attIt->=
second.attName.c_str(), &att_data[0]);
- ERRORS(success, "Failed to read conventions global attribute char data."=
);
- if (att_data.find("CF") =3D=3D std::string::npos) {
- ERRORR(MB_FAILURE, "File not following known conventions.");
- }
-
if (myHelper !=3D NULL)
delete myHelper;
=20
https://bitbucket.org/fathomteam/moab/commits/f374962f486b/
Changeset: f374962f486b
Branch: None
User: danwu
Date: 2013-06-18 19:59:57
Summary: Introduced ScdNCHelper and UcdNCHelper classes to further refa=
ctor ReadNC code, especially read_variables(). This will make things easier=
to read MPAS file type later.
Affected #: 12 files
diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index 731e3af..350e6ae 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -4,6 +4,15 @@
#include "NCHelperHOMME.hpp"
#include "NCHelperMPAS.hpp"
=20
+#include "moab/ReadUtilIface.hpp"
+#include "MBTagConventions.hpp"
+
+#define ERRORR(rval, str) \
+ if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", =
str); return rval;}
+
+#define ERRORS(err, str) \
+ if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_F=
AILURE;}
+
namespace moab {
=20
NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOp=
tions& opts)
@@ -43,4 +52,945 @@ NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int f=
ileId, const FileOptions&
return NULL;
}
=20
+ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& =
opts, EntityHandle file_set, Range& faces)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ int (&gDims)[6] =3D _readNC->gDims;
+ int (&lDims)[6] =3D _readNC->lDims;
+ std::vector<double>& ilVals =3D _readNC->ilVals;
+ std::vector<double>& jlVals =3D _readNC->jlVals;
+ std::vector<double>& klVals =3D _readNC->klVals;
+ Tag& mGlobalIdTag =3D _readNC->mGlobalIdTag;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ int (&locallyPeriodic)[2] =3D _readNC->locallyPeriodic;
+ int (&globallyPeriodic)[2] =3D _readNC->globallyPeriodic;
+ ScdParData& parData =3D _readNC->parData;
+
+ Range tmp_range;
+ ScdBox *scd_box;
+
+ ErrorCode rval =3D scdi->construct_box(HomCoord(lDims[0], lDims[1], lDim=
s[2], 1), HomCoord(lDims[3], lDims[4], lDims[5], 1), NULL,
+ 0, scd_box, locallyPeriodic, &parData);
+ ERRORR(rval, "Trouble creating scd vertex sequence.");
+
+ // add box set and new vertices, elements to the file set
+ tmp_range.insert(scd_box->start_vertex(), scd_box->start_vertex() + scd_=
box->num_vertices() - 1);
+ tmp_range.insert(scd_box->start_element(), scd_box->start_element() + sc=
d_box->num_elements() - 1);
+ tmp_range.insert(scd_box->box_set());
+ rval =3D mbImpl->add_entities(file_set, tmp_range);
+ ERRORR(rval, "Couldn't add new vertices to file set.");
+
+ dbgOut.tprintf(1, "scdbox %d quads, %d vertices\n", scd_box->num_element=
s(), scd_box->num_vertices());
+
+ // get a ptr to global id memory
+ void* data;
+ int count;
+ const Range::iterator topv =3D tmp_range.upper_bound(tmp_range.begin(), =
tmp_range.end(), scd_box->start_vertex()
+ + scd_box->num_vertices());
+ rval =3D mbImpl->tag_iterate(mGlobalIdTag, tmp_range.begin(), topv, coun=
t, data);
+ ERRORR(rval, "Failed to get tag iterator.");
+ assert(count =3D=3D scd_box->num_vertices());
+ int* gid_data =3D (int*) data;
+
+ // set the vertex coordinates
+ double *xc, *yc, *zc;
+ rval =3D scd_box->get_coordinate_arrays(xc, yc, zc);
+ ERRORR(rval, "Couldn't get vertex coordinate arrays.");
+
+ int i, j, k, il, jl, kl, itmp;
+ int dil =3D lDims[3] - lDims[0] + 1;
+ int djl =3D lDims[4] - lDims[1] + 1;
+ int di =3D gDims[3] - gDims[0] + 1;
+ int dj =3D gDims[4] - gDims[1] + 1;
+ assert(dil =3D=3D (int)ilVals.size() && djl =3D=3D (int)jlVals.size() &&
+ (-1 =3D=3D lDims[2] || lDims[5]-lDims[2]+1 =3D=3D (int)klVals.size()=
));
+#define INDEX(i, j, k) ()
+ for (kl =3D lDims[2]; kl <=3D lDims[5]; kl++) {
+ k =3D kl - lDims[2];
+ for (jl =3D lDims[1]; jl <=3D lDims[4]; jl++) {
+ j =3D jl - lDims[1];
+ for (il =3D lDims[0]; il <=3D lDims[3]; il++) {
+ i =3D il - lDims[0];
+ unsigned int pos =3D i + j * dil + k * dil * djl;
+ xc[pos] =3D ilVals[i];
+ yc[pos] =3D jlVals[j];
+ zc[pos] =3D (-1 =3D=3D lDims[2] ? 0.0 : klVals[k]);
+ itmp =3D (!locallyPeriodic[0] && globallyPeriodic[0] && il =3D=3D =
gDims[3] ? gDims[0] : il);
+ *gid_data =3D (-1 !=3D kl ? kl * di * dj : 0) + jl * di + itmp + 1;
+ gid_data++;
+ }
+ }
+ }
+#undef INDEX
+
+#ifndef NDEBUG
+ int num_verts =3D (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1) =
* (-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
+ std::vector<int> gids(num_verts);
+ Range verts(scd_box->start_vertex(), scd_box->start_vertex() + scd_box->=
num_vertices() - 1);
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, verts, &gids[0]);
+ ERRORR(rval, "Trouble getting gid values.");
+ int vmin =3D *(std::min_element(gids.begin(), gids.end())), vmax =3D *(s=
td::max_element(gids.begin(), gids.end()));
+ dbgOut.tprintf(1, "Vertex gids %d-%d\n", vmin, vmax);
+#endif
+
+ // add elements to the range passed in
+ faces.insert(scd_box->start_element(), scd_box->start_element() + scd_bo=
x->num_elements() - 1);
+
+ if (2 <=3D dbgOut.get_verbosity()) {
+ assert(scd_box->boundary_complete());
+ EntityHandle dum_ent =3D scd_box->start_element();
+ rval =3D mbImpl->list_entities(&dum_ent, 1);
+ ERRORR(rval, "Trouble listing first hex.");
+
+ std::vector<EntityHandle> connect;
+ rval =3D mbImpl->get_connectivity(&dum_ent, 1, connect);
+ ERRORR(rval, "Trouble getting connectivity.");
+
+ rval =3D mbImpl->list_entities(&connect[0], connect.size());
+ ERRORR(rval, "Trouble listing element connectivity.");
+ }
+
+ Range edges;
+ mbImpl->get_adjacencies(faces, 1, true, edges, Interface::UNION);
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::read_variables(EntityHandle file_set, std::vector<s=
td::string>& var_names, std::vector<int>& tstep_nums)
+{
+ std::vector<ReadNC::VarData> vdatas;
+ std::vector<ReadNC::VarData> vsetdatas;
+
+ ErrorCode rval =3D read_scd_variable_setup(var_names, tstep_nums, vdatas=
, vsetdatas);
+ ERRORR(rval, "Trouble setting up read variable.");
+
+ // create COORDS tag for quads
+ rval =3D _readNC->create_quad_coordinate_tag(file_set);
+ ERRORR(rval, "Trouble creating coordinate tags to entities quads");
+
+ if (!vsetdatas.empty()) {
+ rval =3D read_scd_variable_to_set(file_set, vsetdatas, tstep_nums);
+ ERRORR(rval, "Trouble read variables to set.");
+ }
+
+ if (!vdatas.empty()) {
+ rval =3D read_scd_variable_to_nonset(file_set, vdatas, tstep_nums);
+ ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& v=
ar_names, std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData=
>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
+{
+ std::map<std::string, ReadNC::VarData>& varInfo =3D _readNC->varInfo;
+ int& tMin =3D _readNC->tMin;
+ int& tMax =3D _readNC->tMax;
+ int& iDim =3D _readNC->iDim;
+ int& jDim =3D _readNC->jDim;
+ int& tDim =3D _readNC->tDim;
+ int& iCDim =3D _readNC->iCDim;
+ int& jCDim =3D _readNC->jCDim;
+
+ std::map<std::string, ReadNC::VarData>::iterator mit;
+
+ // if empty read them all
+ if (var_names.empty()) {
+ for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D vd.=
varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) !=3D=
vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) !=
=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else
+ vsetdatas.push_back(vd);
+ }
+ }
+ else {
+ for (unsigned int i =3D 0; i < var_names.size(); i++) {
+ mit =3D varInfo.find(var_names[i]);
+ if (mit !=3D varInfo.end()) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D v=
d.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) !=
=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) !=
=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else
+ vsetdatas.push_back(vd);
+ }
+ else ERRORR(MB_FAILURE, "Couldn't find variable.");
+ }
+ }
+
+ if (tstep_nums.empty() && -1 !=3D tMin) {
+ // no timesteps input, get them all
+ for (int i =3D tMin; i <=3D tMax; i++)
+ tstep_nums.push_back(i);
+ }
+ if (!tstep_nums.empty()) {
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ vdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vdatas[i].varDatas.resize(tstep_nums.size());
+ vdatas[i].readDims.resize(tstep_nums.size());
+ vdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ for (unsigned int i =3D 0; i < vsetdatas.size(); i++) {
+ if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.en=
d(), tDim) !=3D vsetdatas[i].varDims.end())
+ && (vsetdatas[i].varDims.size() !=3D 1)) {
+ vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vsetdatas[i].varDatas.resize(tstep_nums.size());
+ vsetdatas[i].readDims.resize(tstep_nums.size());
+ vsetdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ else {
+ vsetdatas[i].varTags.resize(1, 0);
+ vsetdatas[i].varDatas.resize(1);
+ vsetdatas[i].readDims.resize(1);
+ vsetdatas[i].readCounts.resize(1);
+ }
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_to_set_allocate(std::vector<ReadN=
C::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDi=
m) !=3D vdatas[i].varDims.end()))
+ vdatas[i].has_t =3D true;
+
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ // get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[=
i].varTags[t]);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t)
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+
+ // set up the dimensions and counts
+ // first variable dimension is time, if it exists
+ if (vdatas[i].has_t)
+ {
+ if (vdatas[i].varDims.size() !=3D 1)
+ {
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else
+ {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(tstep_nums.size());
+ }
+ }
+
+ // set up other dimensions and counts
+ if (vdatas[i].varDims.empty()) {
+ // scalar variable
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else {
+ for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
+ if (tDim !=3D vdatas[i].varDims[idx]){
+ // push other variable dimensions, except time, which was alre=
ady pushed
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
+ }
+ }
+ }
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
+ sz *=3D vdatas[i].readCounts[t][idx];
+ vdatas[i].sz =3D sz;
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ vdatas[i].varDatas[t] =3D new char[sz];
+ break;
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ vdatas[i].varDatas[t] =3D new double[sz];
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ vdatas[i].varDatas[t] =3D new int[sz];
+ break;
+ default:
+ std::cerr << "Unrecognized data type for tag " << std::endl;
+ rval =3D MB_FAILURE;
+ }
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_to_set(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::set<std::string>& dummyVarNames =3D _readNC->dummyVarNames;;
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_scd_variable_to_set_allocate(vdatas, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables to set.");
+
+ // finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if (dummyVarNames.find(vdatas[i].varName)!=3D dummyVarNames.end() )
+ continue;// this is a dummy one, we don't have it; we created it fo=
r the dummy tag
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ void* data =3D vdatas[i].varDatas[t];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (char*) data NCREQ);
+ ERRORS(success, "Failed to read char data.");
+ break;
+ case NC_DOUBLE:
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (double*) data NCREQ);
+ ERRORS(success, "Failed to read double data.");
+ break;
+ case NC_FLOAT: {
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (float*) data NCREQ);
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT:
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (int*) data NCREQ);
+ ERRORS(success, "Failed to read int data.");
+ break;
+ case NC_SHORT:
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (short*) data NCREQ);
+ ERRORS(success, "Failed to read short data.");
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_scd_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vd=
atas[i].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], =
&file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle f=
ile_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ std::vector<std::string>& dimNames =3D _readNC->dimNames;
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int (&lDims)[6] =3D _readNC->lDims;
+ int (&lCDims)[6] =3D _readNC->lCDims;
+ int& tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ bool& isParallel =3D _readNC->isParallel;
+ #ifdef USE_MPI
+ ParallelComm*& myPcomm =3D _readNC->myPcomm;
+#endif
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ Range* range =3D NULL;
+
+ // get vertices in set
+ Range verts;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 0, verts);
+ ERRORR(rval, "Trouble getting vertices in set.");
+ assert("Should only have a single vertex subrange, since they were read =
in one shot" &&
+ verts.psize() =3D=3D 1);
+
+ Range edges;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 1, edges);
+ ERRORR(rval, "Trouble getting edges in set.");
+
+ // get faces in set
+ Range faces;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 2, faces);
+ ERRORR(rval, "Trouble getting faces in set.");
+ assert("Should only have a single face subrange, since they were read in=
one shot" &&
+ faces.psize() =3D=3D 1);
+
+#ifdef USE_MPI
+ moab::Range faces_owned;
+ if (isParallel)
+ {
+ rval =3D myPcomm->filter_pstatus(faces, PSTATUS_NOT_OWNED, PSTATUS_NOT=
, -1, &faces_owned);
+ ERRORR(rval, "Trouble getting owned faces in set.");
+ }
+ else
+ faces_owned =3D faces; // not running in parallel, but still with MPI
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ std::vector<std::string>::iterator vit;
+ int idx_lev =3D 0;
+ int idx_ilev =3D 0;
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "lev")) !=
=3D dimNames.end())
+ idx_lev =3D vit - dimNames.begin();
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ilev")) !=
=3D dimNames.end())
+ idx_ilev =3D vit - dimNames.begin();
+ if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), id=
x_lev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_lev];
+ else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(=
), idx_ilev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_ilev];
+
+ // get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+ }
+ else if (vdatas[i].varDims[0] !=3D tDim) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given f=
or time-independent variable.");
+ }
+
+ // set up the dimensions and counts
+ // first time
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+
+ // then z/y/x
+ if (vdatas[i].numLev !=3D 1) {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
+ }
+
+ switch (vdatas[i].entLoc) {
+ case ReadNC::ENTLOCVERT:
+ // vertices
+ // only structured mesh has j parameter that multiplies i to get=
total # vertices
+ vdatas[i].readDims[t].push_back(lDims[1]);
+ vdatas[i].readCounts[t].push_back(lDims[4] - lDims[1] + 1);
+ vdatas[i].readDims[t].push_back(lDims[0]);
+ vdatas[i].readCounts[t].push_back(lDims[3] - lDims[0] + 1);
+ assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
+ range =3D &verts;
+ break;
+ case ReadNC::ENTLOCNSEDGE:
+ ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
+ break;
+ case ReadNC::ENTLOCEWEDGE:
+ ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
+ break;
+ case ReadNC::ENTLOCFACE:
+ // faces
+ vdatas[i].readDims[t].push_back(lCDims[1]);
+ vdatas[i].readDims[t].push_back(lCDims[0]);
+ vdatas[i].readCounts[t].push_back(lCDims[4] - lCDims[1] + 1);
+ vdatas[i].readCounts[t].push_back(lCDims[3] - lCDims[0] + 1);
+ assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
+#ifdef USE_MPI
+ range =3D &faces_owned;
+#else
+ range =3D &faces;
+#endif
+ break;
+ case ReadNC::ENTLOCSET:
+ // set
+ break;
+ default:
+ ERRORR(MB_FAILURE, "Unrecognized entity location type.");
+ break;
+ }
+
+ // get ptr to tag space
+ void* data;
+ int count;
+ rval =3D mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), r=
ange->end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator.");
+ assert((unsigned)count =3D=3D range->size());
+ vdatas[i].varDatas[t] =3D data;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, =
std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_scd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables.");
+
+ // finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
+ sz *=3D vdatas[i].readCounts[t][idx];
+ void* data =3D vdatas[i].varDatas[t];
+ size_t ni =3D vdatas[i].readCounts[t][2];
+ size_t nj =3D vdatas[i].readCounts[t][3];
+ size_t nk =3D vdatas[i].readCounts[t][1];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR: {
+ std::vector<char> tmpchardata(sz);
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpchardata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpchardata=
[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpchardata.size(); idx++)
+ ((char*) data)[idx] =3D tmpchardata[idx];
+ }
+ ERRORS(success, "Failed to read char data.");
+ break;
+ }
+ case NC_DOUBLE: {
+ std::vector<double> tmpdoubledata(sz);
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpdoubledata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpdoubleda=
ta[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
+ ((double*) data)[idx] =3D tmpdoubledata[idx];
+ }
+ ERRORS(success, "Failed to read double data.");
+ break;
+ }
+ case NC_FLOAT: {
+ std::vector<float> tmpfloatdata(sz);
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpfloatdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
+ ((float*) data)[idx] =3D tmpfloatdata[idx];
+ }
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT: {
+ std::vector<int> tmpintdata(sz);
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpintdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[=
0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpintdata.size(); idx++)
+ ((int*) data)[idx] =3D tmpintdata[idx];
+ }
+ ERRORS(success, "Failed to read int data.");
+ break;
+ }
+ case NC_SHORT: {
+ std::vector<short> tmpshortdata(sz);
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpshortdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpshortdata.size(); idx+=
+)
+ ((short*) data)[idx] =3D tmpshortdata[idx];
+ }
+ ERRORS(success, "Failed to read short data.");
+ break;
+ }
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_scd_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ return rval;
+}
+
+ErrorCode ScdNCHelper::convert_scd_variable(ReadNC::VarData& var_data, int=
tstep_num)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ // get ptr to tag space
+ void* data =3D var_data.varDatas[tstep_num];
+
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D var_data.readCounts[tstep_num].size=
(); idx++)
+ sz *=3D var_data.readCounts[tstep_num][idx];
+
+ // finally, read into that space
+ int success =3D 0;
+ int* idata;
+ double* ddata;
+ float* fdata;
+ short* sdata;
+
+ switch (var_data.varDataType) {
+ case NC_FLOAT:
+ ddata =3D (double*) var_data.varDatas[tstep_num];
+ fdata =3D (float*) var_data.varDatas[tstep_num];
+ // convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ ddata[i] =3D fdata[i];
+ break;
+ case NC_SHORT:
+ idata =3D (int*) var_data.varDatas[tstep_num];
+ sdata =3D (short*) var_data.varDatas[tstep_num];
+ // convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ idata[i] =3D sdata[i];
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (2 <=3D dbgOut.get_verbosity() && !success) {
+ double dmin, dmax;
+ int imin, imax;
+ switch (var_data.varDataType) {
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ ddata =3D (double*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ dmin =3D dmax =3D ddata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (ddata[i] < dmin)
+ dmin =3D ddata[i];
+ if (ddata[i] > dmax)
+ dmax =3D ddata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (double): min =3D %f, max =3D %f\n"=
, var_data.varName.c_str(), dmin, dmax);
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ idata =3D (int*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ imin =3D imax =3D idata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (idata[i] < imin)
+ imin =3D idata[i];
+ if (idata[i] > imax)
+ imax =3D idata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (int): min =3D %d, max =3D %d\n", v=
ar_data.varName.c_str(), imin, imax);
+ break;
+ case NC_NAT:
+ case NC_BYTE:
+ case NC_CHAR:
+ break;
+ default: //default case added to remove compiler warnings
+ success =3D 1;
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode UcdNCHelper::read_variables(EntityHandle file_set, std::vector<s=
td::string>& var_names, std::vector<int>& tstep_nums)
+{
+ std::vector<ReadNC::VarData> vdatas;
+ std::vector<ReadNC::VarData> vsetdatas;
+
+ ErrorCode rval =3D read_ucd_variable_setup(var_names, tstep_nums, vdatas=
, vsetdatas);
+ ERRORR(rval, "Trouble setting up read variable.");
+
+ if (!vdatas.empty()) {
+#ifdef PNETCDF_FILE
+ // in serial, we will use the old read, everything is contiguous
+ // in parallel, we will use async read in pnetcdf
+ // the other mechanism is not working, forget about it
+ rval =3D read_ucd_variable_to_nonset_async(file_set, vdatas, tstep_num=
s);
+#else
+ rval =3D read_ucd_variable_to_nonset(file_set, vdatas, tstep_nums);
+#endif
+ ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode UcdNCHelper::read_ucd_variable_to_set_allocate(std::vector<ReadN=
C::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDi=
m) !=3D vdatas[i].varDims.end()))
+ vdatas[i].has_t =3D true;
+
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ // get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[=
i].varTags[t]);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t)
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+
+ // set up the dimensions and counts
+ // first variable dimension is time, if it exists
+ if (vdatas[i].has_t)
+ {
+ if (vdatas[i].varDims.size() !=3D 1)
+ {
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else
+ {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(tstep_nums.size());
+ }
+ }
+
+ // set up other dimensions and counts
+ if (vdatas[i].varDims.empty()) {
+ // scalar variable
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else {
+ for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
+ if (tDim !=3D vdatas[i].varDims[idx]){
+ // push other variable dimensions, except time, which was alre=
ady pushed
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
+ }
+ }
+ }
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
+ sz *=3D vdatas[i].readCounts[t][idx];
+ vdatas[i].sz =3D sz;
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ vdatas[i].varDatas[t] =3D new char[sz];
+ break;
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ vdatas[i].varDatas[t] =3D new double[sz];
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ vdatas[i].varDatas[t] =3D new int[sz];
+ break;
+ default:
+ std::cerr << "Unrecognized data type for tag " << std::endl;
+ rval =3D MB_FAILURE;
+ }
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode UcdNCHelper::read_ucd_variable_to_set(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas, std::vector<int> &tstep_nums)
+{
+ std::set<std::string>& dummyVarNames =3D _readNC->dummyVarNames;;
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_ucd_variable_to_set_allocate(vdatas, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables to set.");
+
+ // finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if (dummyVarNames.find(vdatas[i].varName) !=3D dummyVarNames.end() )
+ continue; // this is a dummy one, we don't have it; we created it f=
or the dummy tag
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ void* data =3D vdatas[i].varDatas[t];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (char*) data NCREQ);
+ ERRORS(success, "Failed to read char data.");
+ break;
+ case NC_DOUBLE:
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (double*) data NCREQ);
+ ERRORS(success, "Failed to read double data.");
+ break;
+ case NC_FLOAT: {
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (float*) data NCREQ);
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT:
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (int*) data NCREQ);
+ ERRORS(success, "Failed to read int data.");
+ break;
+ case NC_SHORT:
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (short*) data NCREQ);
+ ERRORS(success, "Failed to read short data.");
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_ucd_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vd=
atas[i].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], =
&file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
} // namespace moab
diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 16f2a3c..6aac571 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -18,19 +18,83 @@ class NCHelper
{
public:
NCHelper(ReadNC* readNC, int fileId) : _readNC(readNC), _fileId(fileId) =
{}
+ virtual ~NCHelper() {}
=20
static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOpt=
ions& opts);
=20
+ //! Interfaces to be implemented by child classes
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set) =3D 0;
virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces) =3D 0;
+ virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums) =3D 0;
virtual std::string get_mesh_type_name() =3D 0;
- virtual bool is_scd_mesh() =3D 0;
=20
protected:
ReadNC* _readNC;
int _fileId;
};
=20
+//! Child helper class for structured mesh, e.g. CAM_EL or CAM_FV
+class ScdNCHelper : public NCHelper
+{
+public:
+ ScdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ virtual ~ScdNCHelper() {}
+
+private:
+ //! Implementation of NCHelper::create_mesh()
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
+ //! Implementation of NCHelper::read_variables()
+ virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums);
+
+ //! These functions are used by read_variables(), fully implemented
+ ErrorCode read_scd_variable_setup(std::vector<std::string>& var_names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& vdatas,
+ std::vector<ReadNC::VarData>& vsetdata=
s);
+ ErrorCode read_scd_variable_to_set_allocate(std::vector<ReadNC::VarData>=
& vdatas,
+ std::vector<int>& tstep_nums=
);
+ ErrorCode read_scd_variable_to_set(EntityHandle file_set, std::vector<Re=
adNC::VarData>& vdatas,
+ std::vector<int>& tstep_nums);
+ ErrorCode read_scd_variable_to_nonset_allocate(EntityHandle file_set, st=
d::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_n=
ums);
+ ErrorCode read_scd_variable_to_nonset(EntityHandle file_set, std::vector=
<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nums);
+ ErrorCode convert_scd_variable(ReadNC::VarData& var_data, int tstep_num);
+};
+
+//! Child helper class for unstructured mesh, e.g. CAM_SE (HOMME) or MPAS
+class UcdNCHelper : public NCHelper
+{
+public:
+ UcdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ virtual ~UcdNCHelper() {}
+
+private:
+ //! Implementation of NCHelper::read_variables()
+ virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names,
+ std::vector<int> &tstep_nums);
+
+ //! These functions are used by read_variables(), partially implemented
+ virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_=
names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& =
vdatas,
+ std::vector<ReadNC::VarData>& =
vsetdatas) =3D 0;
+ ErrorCode read_ucd_variable_to_set_allocate(std::vector<ReadNC::VarData>=
& vdatas,
+ std::vector<int>& tstep_nums=
);
+ ErrorCode read_ucd_variable_to_set(EntityHandle file_set, std::vector<Re=
adNC::VarData>& vdatas,
+ std::vector<int>& tstep_nums);
+ virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file=
_set, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>&=
tstep_nums) =3D 0;
+#ifdef PNETCDF_FILE
+ virtual ErrorCode read_ucd_variable_to_nonset_async(EntityHandle file_se=
t, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& ts=
tep_nums) =3D 0;
+#else
+ virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nu=
ms) =3D 0;
+#endif
+ virtual ErrorCode convert_ucd_variable(ReadNC::VarData& var_data, int ts=
tep_num) =3D 0;
+};
+
} // namespace moab
=20
#endif
diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index 1fd5673..c225841 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -473,9 +473,4 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperEuler::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& quads)
-{
- return _readNC->create_scd_verts_quads(scdi, file_set, quads);
-}
-
} // namespace moab
diff --git a/src/io/NCHelperEuler.hpp b/src/io/NCHelperEuler.hpp
index 6bf2a51..a0d6aef 100644
--- a/src/io/NCHelperEuler.hpp
+++ b/src/io/NCHelperEuler.hpp
@@ -14,21 +14,16 @@
namespace moab {
=20
//! Child helper class for Eulerian Spectral grid (CAM_EUL)
-class NCHelperEuler : public NCHelper
+class NCHelperEuler : public ScdNCHelper
{
public:
- NCHelperEuler(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ NCHelperEuler(ReadNC* readNC, int fileId) : ScdNCHelper(readNC, fileId) =
{}
=20
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
-
- virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
-
virtual std::string get_mesh_type_name() { return "CAM_EUL"; }
-
- virtual bool is_scd_mesh() { return true; }
};
=20
} // namespace moab
diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 8e23542..cdc4392 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -469,9 +469,4 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperFV::create_mesh(ScdInterface* scdi, const FileOptions& o=
pts, EntityHandle file_set, Range& quads)
-{
- return _readNC->create_scd_verts_quads(scdi, file_set, quads);
-}
-
} // namespace moab
diff --git a/src/io/NCHelperFV.hpp b/src/io/NCHelperFV.hpp
index 0a1ba76..7dde6dc 100644
--- a/src/io/NCHelperFV.hpp
+++ b/src/io/NCHelperFV.hpp
@@ -14,17 +14,15 @@
namespace moab {
=20
//! Child helper class for Finite Volume grid (CAM_FV)
-class NCHelperFV : public NCHelper
+class NCHelperFV : public ScdNCHelper
{
public:
- NCHelperFV(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ NCHelperFV(ReadNC* readNC, int fileId) : ScdNCHelper(readNC, fileId) {}
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
virtual std::string get_mesh_type_name() { return "CAM_FV"; }
- virtual bool is_scd_mesh() { return true; }
};
=20
} // namespace moab
diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 6f6b102..6694abb 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -2,6 +2,7 @@
#include "moab/ReadUtilIface.hpp"
#include "FileOptions.hpp"
#include "moab/SpectralMeshTool.hpp"
+#include "MBTagConventions.hpp"
=20
#include <cmath>
=20
@@ -13,7 +14,7 @@
=20
namespace moab {
=20
-NCHelperHOMME::NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions=
& opts) : NCHelper(readNC, fileId), _spectralOrder(-1)
+NCHelperHOMME::NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions=
& opts) : UcdNCHelper(readNC, fileId), _spectralOrder(-1)
{
// Calculate spectral order
std::map<std::string, ReadNC::AttData>::iterator attIt =3D readNC->globa=
lAtts.find("np");
@@ -199,7 +200,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& quads)
+ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& faces)
{
Interface*& mbImpl =3D _readNC->mbImpl;
std::string& fileName =3D _readNC->fileName;
@@ -381,12 +382,12 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* sc=
di, const FileOptions& opts
=20
// get ptr to gid memory for vertices
Range vert_range(start_vertex, start_vertex + num_local_verts - 1);
- void *data;
+ void* data;
int count;
rval =3D mbImpl->tag_iterate(mGlobalIdTag, vert_range.begin(), vert_rang=
e.end(), count, data);
ERRORR(rval, "Failed to get tag iterator.");
assert(count =3D=3D (int) num_local_verts);
- int *gid_data =3D (int*) data;
+ int* gid_data =3D (int*) data;
std::copy(localGid.begin(), localGid.end(), gid_data);
// duplicate global id data, which will be used to resolve sharing
if (mpFileIdTag) {
@@ -417,7 +418,7 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi=
, const FileOptions& opts
}
=20
// add new vertices and elements to the set
- quads.merge(tmp_range);
+ faces.merge(tmp_range);
tmp_range.insert(start_vertex, start_vertex + num_local_verts - 1);
rval =3D mbImpl->add_entities(file_set, tmp_range);
ERRORR(rval, "Couldn't add new vertices and quads/hexes to file set.");
@@ -503,4 +504,596 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* sc=
di, const FileOptions& opts
return MB_SUCCESS;
}
=20
+ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>&=
var_names, std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarDa=
ta>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
+{
+ std::map<std::string, ReadNC::VarData>& varInfo =3D _readNC->varInfo;
+ int& tMin =3D _readNC->tMin;
+ int& tMax =3D _readNC->tMax;
+ int& iDim =3D _readNC->iDim;
+ int& kDim =3D _readNC->kDim;
+ int& tDim =3D _readNC->tDim;
+
+ std::map<std::string, ReadNC::VarData>::iterator mit;
+
+ if (var_names.empty()) {
+ for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd.v=
arDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), kDim) !=3D vd.varDims.end()) && (std::find(vd.=
varDims.begin(), vd.varDims.end(), iDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); //3d data (time, ncol, ilev) read here
+ else
+ vsetdatas.push_back(vd);
+ }
+ }
+ else {
+ for (unsigned int i =3D 0; i < var_names.size(); i++) {
+
+ mit =3D varInfo.find(var_names[i]);
+ if (mit !=3D varInfo.end()) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd=
.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), kDim) !=3D vd.varDims.end()) && (std::find(v=
d.varDims.begin(), vd.varDims.end(), iDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); //3d data
+ else
+ vsetdatas.push_back(vd);
+ }
+ else ERRORR(MB_FAILURE, "Couldn't find variable.");
+ }
+ }
+
+ if (tstep_nums.empty() && -1 !=3D tMin) {
+ // no timesteps input, get them all
+ for (int i =3D tMin; i <=3D tMax; i++)
+ tstep_nums.push_back(i);
+ }
+ if (!tstep_nums.empty()) {
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ vdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vdatas[i].varDatas.resize(tstep_nums.size());
+ vdatas[i].readDims.resize(tstep_nums.size());
+ vdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ for (unsigned int i =3D 0; i < vsetdatas.size(); i++) {
+ if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.en=
d(), tDim) !=3D vsetdatas[i].varDims.end())
+ && (vsetdatas[i].varDims.size() !=3D 1)) {
+ vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vsetdatas[i].varDatas.resize(tstep_nums.size());
+ vsetdatas[i].readDims.resize(tstep_nums.size());
+ vsetdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ else {
+ vsetdatas[i].varTags.resize(1, 0);
+ vsetdatas[i].varDatas.resize(1);
+ vsetdatas[i].readDims.resize(1);
+ vsetdatas[i].readCounts.resize(1);
+ }
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(EntityHandle=
file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nu=
ms)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ std::vector<std::string>& dimNames =3D _readNC->dimNames;
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int& tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ Range* range =3D NULL;
+
+ // get vertices in set
+ Range verts;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 0, verts);
+ ERRORR(rval, "Trouble getting vertices in set.");
+ assert("Should only have a single vertex subrange, since they were read =
in one shot" &&
+ verts.psize() =3D=3D 1);
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ std::vector<std::string>::iterator vit;
+ int idx_lev =3D 0;
+ int idx_ilev =3D 0;
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "lev")) !=
=3D dimNames.end())
+ idx_lev =3D vit - dimNames.begin();
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ilev")) !=
=3D dimNames.end())
+ idx_ilev =3D vit - dimNames.begin();
+ if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), id=
x_lev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_lev];
+ else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(=
), idx_ilev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_ilev];
+
+ // get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+ }
+ else if (vdatas[i].varDims[0] !=3D tDim) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given f=
or time-independent variable.");
+ }
+
+ // set up the dimensions and counts
+ // first time
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+
+ // then numLev/numVertices
+ if (vdatas[i].numLev !=3D 1) {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
+ }
+
+ switch (vdatas[i].entLoc) {
+ case ReadNC::ENTLOCVERT:
+ // vertices
+ // we will start from the first localGid, actually; we will rese=
t that
+ // later on, anyway, in a loop
+ vdatas[i].readDims[t].push_back(localGid[0]-1);
+ vdatas[i].readCounts[t].push_back(localGid.size());
+ assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
+ range =3D &verts;
+ break;
+ case ReadNC::ENTLOCSET:
+ // set
+ break;
+ default:
+ ERRORR(MB_FAILURE, "Unrecognized entity location type.");
+ break;
+ }
+
+ // get ptr to tag space
+ void* data;
+ int count;
+ rval =3D mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), r=
ange->end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator.");
+ assert((unsigned)count =3D=3D range->size());
+ vdatas[i].varDatas[t] =3D data;
+ }
+ }
+
+ return rval;
+}
+
+#ifdef PNETCDF_FILE
+ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(EntityHandle fi=
le_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
+
+ ErrorCode rval =3D read_ucd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables.");
+
+ // finally, read into that space
+ int success;
+ // MPI_offset or size_t?
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ std::size_t sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
+ if (sz <=3D 0)
+ continue; // nothing to read, why worry?
+
+ // we will synchronize all these reads with the other processors,
+ // so the wait will be inside this double loop; is it too much?
+ size_t nb_reads =3D localGid.psize();
+ std::vector<int> requests(nb_reads), statuss(nb_reads);
+ size_t idxReq =3D 0;
+ void* data =3D vdatas[i].varDatas[t];
+ size_t ni =3D vdatas[i].readCounts[t][2];
+ size_t nj =3D 1; // for HOMME, nj holds # quads, so here should set =
to 1
+ size_t nk =3D vdatas[i].readCounts[t][1];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR: {
+ ERRORR(MB_FAILURE, "not implemented");
+ break;
+ }
+ case NC_DOUBLE: {
+ // copy from float case
+ std::vector<double> tmpdoubledata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+ // assume that the last dimension is for the ncol,
+ // node varying variable
+
+ size_t indexInDoubleArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
+
+ // do a partial read, in each subrange
+ // wait outside this loop
+ success =3D NCFUNCAG2(_vara_double)(_fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpdoubledata[indexInDoubleArray]) NCREQ2);
+ ERRORS(success, "Failed to read double data in loop");
+ // we need to increment the index in float array for the
+ // next subrange
+ indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ success =3D ncmpi_wait_all(_fileId, requests.size(), &requests[0=
], &statuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik_stride(ni, nj, nk, data, &tmpd=
oubledata[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
+ ((double*) data)[idx] =3D tmpdoubledata[idx];
+ }
+ ERRORS(success, "Failed to read double data.");
+ break;
+ }
+ case NC_FLOAT: {
+ std::vector<float> tmpfloatdata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+ // assume that the last dimension is for the ncol,
+ // node varying variable
+
+ size_t indexInFloatArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
+
+ // do a partial read, in each subrange
+ // wait outside this loop
+ success =3D NCFUNCAG2(_vara_float)(_fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpfloatdata[indexInFloatArray]) NCREQ2);
+ ERRORS(success, "Failed to read float data in loop");
+ // we need to increment the index in float array for the
+ // next subrange
+ indexInFloatArray +=3D (endh - starth + 1) * 1 * vdatas[i].num=
Lev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ success =3D ncmpi_wait_all(_fileId, requests.size(), &requests[0=
], &statuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik_stride(ni, nj, nk, data, &tmpf=
loatdata[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
+ ((float*) data)[idx] =3D tmpfloatdata[idx];
+ }
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT: {
+ ERRORR(MB_FAILURE, "not implemented");
+ break;
+ }
+ case NC_SHORT: {
+ ERRORR(MB_FAILURE, "not implemented");
+ break;
+ }
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ }
+ }
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_ucd_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ return rval;
+}
+#else
+ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set=
, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_ucd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables.");
+
+ // finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ std::size_t sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
+ void* data =3D vdatas[i].varDatas[t];
+ size_t ni =3D vdatas[i].readCounts[t][2];
+ size_t nj =3D 1; // for HOMME, nj holds # quads, so here should set =
to 1
+ size_t nk =3D vdatas[i].readCounts[t][1];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR: {
+ std::vector<char> tmpchardata(sz);
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpchardata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpchardata=
[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpchardata.size(); idx++)
+ ((char*) data)[idx] =3D tmpchardata[idx];
+ }
+ ERRORS(success, "Failed to read char data.");
+ break;
+ }
+ case NC_DOUBLE: {
+ // copy from float case
+ std::vector<double> tmpdoubledata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+ // assume that the last dimension is for the ncol,
+ // node varying variable
+
+ size_t indexInDoubleArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims-1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims-1] =3D (NCDF_SIZE) (endh - star=
th + 1);
+
+ success =3D NCFUNCAG(_vara_double)(fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpdoubledata[indexInDoubleArray]) NCREQ);
+ ERRORS(success, "Failed to read float data in loop");
+ // we need to increment the index in float array for the
+ // next subrange
+ indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpdoubleda=
ta[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
+ ((double*) data)[idx] =3D tmpdoubledata[idx];
+ }
+ ERRORS(success, "Failed to read double data.");
+ break;
+ }
+ case NC_FLOAT: {
+ std::vector<float> tmpfloatdata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+ // assume that the last dimension is for the ncol,
+ // node varying variable
+
+ size_t indexInFloatArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims-1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims-1] =3D (NCDF_SIZE) (endh - star=
th + 1);
+
+ success =3D NCFUNCAG(_vara_float)(fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpfloatdata[indexInFloatArray]) NCREQ);
+ ERRORS(success, "Failed to read float data in loop");
+ // we need to increment the index in float array for the
+ // next subrange
+ indexInFloatArray +=3D (endh - starth + 1) * 1 * vdatas[i].num=
Lev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
+ ((float*) data)[idx] =3D tmpfloatdata[idx];
+ }
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT: {
+ std::vector<int> tmpintdata(sz);
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpintdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[=
0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpintdata.size(); idx++)
+ ((int*) data)[idx] =3D tmpintdata[idx];
+ }
+ ERRORS(success, "Failed to read int data.");
+ break;
+ }
+ case NC_SHORT: {
+ std::vector<short> tmpshortdata(sz);
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpshortdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpshortdata.size(); idx+=
+)
+ ((short*) data)[idx] =3D tmpshortdata[idx];
+ }
+ ERRORS(success, "Failed to read short data.");
+ break;
+ }
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_ucd_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ return rval;
+}
+#endif
+
+ErrorCode NCHelperHOMME::convert_ucd_variable(ReadNC::VarData& var_data, i=
nt tstep_num)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
+
+ // get ptr to tag space
+ void* data =3D var_data.varDatas[tstep_num];
+
+ std::size_t sz =3D var_data.numLev * localGid.size(); // how many nodes =
are we reading?
+
+ // finally, read into that space
+ int success =3D 0;
+ int* idata;
+ double* ddata;
+ float* fdata;
+ short* sdata;
+
+ switch (var_data.varDataType) {
+ case NC_FLOAT:
+ ddata =3D (double*) var_data.varDatas[tstep_num];
+ fdata =3D (float*) var_data.varDatas[tstep_num];
+ // convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ ddata[i] =3D fdata[i];
+ break;
+ case NC_SHORT:
+ idata =3D (int*) var_data.varDatas[tstep_num];
+ sdata =3D (short*) var_data.varDatas[tstep_num];
+ // convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ idata[i] =3D sdata[i];
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (2 <=3D dbgOut.get_verbosity() && !success) {
+ double dmin, dmax;
+ int imin, imax;
+ switch (var_data.varDataType) {
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ ddata =3D (double*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ dmin =3D dmax =3D ddata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (ddata[i] < dmin)
+ dmin =3D ddata[i];
+ if (ddata[i] > dmax)
+ dmax =3D ddata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (double): min =3D %f, max =3D %f\n"=
, var_data.varName.c_str(), dmin, dmax);
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ idata =3D (int*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ imin =3D imax =3D idata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (idata[i] < imin)
+ imin =3D idata[i];
+ if (idata[i] > imax)
+ imax =3D idata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (int): min =3D %d, max =3D %d\n", v=
ar_data.varName.c_str(), imin, imax);
+ break;
+ case NC_NAT:
+ case NC_BYTE:
+ case NC_CHAR:
+ break;
+ default: //default case added to remove compiler warnings
+ success =3D 1;
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
} // namespace moab
diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index 3deebd3..3fc3724 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -14,20 +14,42 @@
namespace moab {
=20
//! Child helper class for HOMME grid (CAM_SE)
-class NCHelperHOMME : public NCHelper
+class NCHelperHOMME : public UcdNCHelper
{
public:
NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions& opts);
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
+ //! Implementation of NCHelper::init_mesh_vals()
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
+ //! Implementation of NCHelper::create_mesh()
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
+ //! Implementation of NCHelper::get_mesh_type_name()
virtual std::string get_mesh_type_name() { return "CAM_SE"; }
- virtual bool is_scd_mesh() { return false; }
+
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_allocate()
+ virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file=
_set, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>&=
tstep_nums);
+ //! Implementation of UcdNCHelper::read_ucd_variable_setup()
+ virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_=
names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& =
vdatas,
+ std::vector<ReadNC::VarData>& =
vsetdatas);
+#ifdef PNETCDF_FILE
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_async()
+ virtual ErrorCode read_ucd_variable_to_nonset_async(EntityHandle file_se=
t, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& ts=
tep_nums);
+#else
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset()
+ virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nu=
ms);
+#endif
+ //! Implementation of UcdNCHelper::convert_ucd_variable()
+ virtual ErrorCode convert_ucd_variable(ReadNC::VarData& var_data, int ts=
tep_num);
=20
private:
- int _spectralOrder; // read from variable 'np'
+ int _spectralOrder; // Read from variable 'np'
};
=20
} // namespace moab
diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index b2ae8bc..1793585 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -13,7 +13,7 @@
=20
namespace moab {
=20
-NCHelperMPAS::NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& =
opts) : NCHelper(readNC, fileId)
+NCHelperMPAS::NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& =
opts) : UcdNCHelper(readNC, fileId)
{
if (MB_SUCCESS =3D=3D opts.match_option("PARTITION_METHOD", "NODAL_PARTI=
TION"))
readNC->partMethod =3D -1;
@@ -24,9 +24,8 @@ bool NCHelperMPAS::can_read_file(ReadNC* readNC, int file=
Id)
std::vector<std::string>& dimNames =3D readNC->dimNames;
=20
// If dimension name "vertexDegree" exists then it should be the MPAS gr=
id
- if (std::find(dimNames.begin(), dimNames.end(), std::string("vertexDegre=
e")) !=3D dimNames.end()) {
+ if (std::find(dimNames.begin(), dimNames.end(), std::string("vertexDegre=
e")) !=3D dimNames.end())
return true;
- }
=20
return false;
}
@@ -43,4 +42,37 @@ ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi, =
const FileOptions& opts,
return MB_SUCCESS;
}
=20
+ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::vector<std::string>& =
var_names, std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarDa=
ta>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+
+ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_allocate(EntityHandle =
file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_num=
s)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+
+#ifdef PNETCDF_FILE
+ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_async(EntityHandle fil=
e_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+#else
+ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(EntityHandle file_set,=
std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+#endif
+
+ErrorCode NCHelperMPAS::convert_ucd_variable(ReadNC::VarData& var_data, in=
t tstep_num)
+{
+ // TBD
+ return MB_SUCCESS;
+}
+
} // namespace moab
diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
index 54c7146..1426e62 100644
--- a/src/io/NCHelperMPAS.hpp
+++ b/src/io/NCHelperMPAS.hpp
@@ -14,17 +14,39 @@
namespace moab {
=20
//! Child helper class for MPAS grid
-class NCHelperMPAS : public NCHelper
+class NCHelperMPAS : public UcdNCHelper
{
public:
NCHelperMPAS(ReadNC* readNC, int fileId, const FileOptions& opts);
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
+ //! Implementation of NCHelper::init_mesh_vals()
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
+ //! Implementation of NCHelper::create_mesh()
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
+ //! Implementation of NCHelper::get_mesh_type_name()
virtual std::string get_mesh_type_name() { return "MPAS"; }
- virtual bool is_scd_mesh() { return false; }
+
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_allocate()
+ virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file=
_set, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>&=
tstep_nums);
+ //! Implementation of UcdNCHelper::read_ucd_variable_setup()
+ virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_=
names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& =
vdatas,
+ std::vector<ReadNC::VarData>& =
vsetdatas);
+#ifdef PNETCDF_FILE
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_async()
+ virtual ErrorCode read_ucd_variable_to_nonset_async(EntityHandle file_se=
t, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& ts=
tep_nums);
+#else
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset()
+ virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nu=
ms);
+#endif
+ //! Implementation of UcdNCHelper::convert_ucd_variable()
+ virtual ErrorCode convert_ucd_variable(ReadNC::VarData& var_data, int ts=
tep_num);
};
=20
} // namespace moab
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/fathomteam/moab/commits/baace931a9a9/
Changeset: baace931a9a9
Branch: None
User: danwu
Date: 2013-06-25 16:18:53
Summary: Merged fathomteam/moab into master
Affected #: 29 files
diff --git a/MeshFiles/unittest/io/Makefile.am b/MeshFiles/unittest/io/Make=
file.am
index ece20cf..8257e5f 100644
--- a/MeshFiles/unittest/io/Makefile.am
+++ b/MeshFiles/unittest/io/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST =3D HommeMapping.nc \
brick_cubit10.2.cub \
brick_cubit10.cub \
camEul26x48x96.t3.nc \
+ fv26x46x72.t.3.nc \
cubtest12.cub \
cubtest.jou \
dum.sat \
diff --git a/MeshFiles/unittest/mpas_p8.h5m b/MeshFiles/unittest/mpas_p8.h5m
new file mode 100644
index 0000000..75662d2
Binary files /dev/null and b/MeshFiles/unittest/mpas_p8.h5m differ
diff --git a/doc/DG/moabDG.h b/doc/DG/moabDG.h
new file mode 100644
index 0000000..d2e14f0
--- /dev/null
+++ b/doc/DG/moabDG.h
@@ -0,0 +1,259 @@
+/*! \page developerguide Developer's Guide (MOAB 4.6)
+=20
+ \subpage dg-contents
+=20
+ \subpage dg-figures
+
+ \page dg-contents Table of Contents
+
+ \ref sequence
+
+ \ref manager
+
+ \ref s-mesh
+
+ \ref sets
+
+ \section sequence 1. EntitySequence & SequenceData
+
+ \subsection figure1 Figure 1: EntitySequences For One SequenceData
+
+The <I>SequenceData</I> class manages as set of arrays of per-entity value=
s. Each
+<I>SequenceData</I> has a start and end handle denoting the block of entit=
ies for which
+the arrays contain data. The arrays managed by a <I>SequenceData</I> insta=
nce are
+divided into three groups:
+
+- Type-specific data (connectivity, coordinates, etc.): zero or more array=
s.
+- Adjacency data: zero or one array.
+- Dense tag data: zero or more arrays.
+.
+
+The abstract <I>EntitySequence</I> class is a non-strict subset of a <I>Se=
quenceData</I>.
+It contains a pointer to a <I>SequenceData</I> and the start and end handl=
es to indi-
+cate the subset of the referenced <I>SequenceData</I>. The <I>EntitySequen=
ce</I> class is
+used to represent the regions of valid (or allocated) handles in a <I>Sequ=
enceData</I>.
+A <I>SequenceData</I> is expected to be referenced by one or more <I>Entit=
ySequence</I>
+instances.
+
+Initial <I>EntitySequence</I> and <I>SequenceData</I> pairs are typically =
created in one
+of two configurations. When reading from a file, a <I>SequenceData</I> wil=
l be created
+to represent all of a single type of entity contained in a file. As all en=
tries in the <I>SequenceData</I> correspond to valid handles (entities read=
from the file) a single
+<I>EntitySequence</I> instance corresponding to the entire <I>SequenceData=
</I> is initially
+created. The second configuration arises when allocating a single entity. =
If no
+entities have been allocated yet, a new <I>SequenceData</I> must be create=
d to store
+the entity data. It is created with a constant size (e.g. 4k entities). Th=
e new
+<I>EntitySequence</I> corresponds to only the first entity in the <I>Seque=
nceData</I>: the
+one allocated entity. As subsequent entities are allocated, the <I>EntityS=
equence</I>
+is extended to cover more of the corresponding <I>SequenceData</I>.
+
+Concrete subclasses of the <I>EntitySequence</I> class are responsible for=
rep-
+resenting specific types of entities using the array storage provided by t=
he
+<I>SequenceData</I> class. They also handle allocating <I>SequenceData</I>=
instances with
+appropriate arrays for storing a particular type of entity. Each concrete =
subclass
+typically provides two constructors corresponding to the two initial alloc=
ation
+configurations described in the previous paragraph. <I>EntitySequence</I> =
imple-
+mentations also provide a split method, which is a type of factory method.=
It
+modifies the called sequence and creates a new sequence such that the rang=
e of
+entities represented by the original sequence is split.
+
+The <I>VertexSequence</I> class provides an <I>EntitySequence</I> for stor=
ing ver-
+tex data. It references a SequenceData containing three arrays of doubles
+for storing the blocked vertex coordinate data. The <I>ElementSequence</I>=
class
+extends the <I>EntitySequence</I> interface with element-specific function=
ality. The
+<I>UnstructuredElemSeq</I> class is the concrete implementation of <I>Elem=
entSequence</I>
+used to represent unstructured elements, polygons, and polyhedra. <I>MeshS=
etSequence</I>
+is the <I>EntitySequence</I> used for storing entity sets.
+
+Each <I>EntitySequence</I> implementation also provides an implementation =
of
+the values per entity method. This value is used to determine if an exist-
+ing <I>SequenceData</I> that has available entities is suitable for storin=
g a particular
+entity. For example, <I>UnstructuredElemSeq</I> returns the number of node=
s per el-
+ement from values per entity. When allocating a new element with a specific
+number of nodes, this value is used to determine if that element may be st=
ored
+in a specific <I>SequenceData</I>. For vertices, this value is always zero=
. This could
+be changed to the number of coordinates per vertex, allowing representatio=
n of
+mixed-dimension data. However, API changes would be required to utilize su=
ch
+a feature. Sequences for which the corresponding data cannot be used to st=
ore
+new entities (e.g. structured mesh discussed in a later section) will retu=
rn -1 or
+some other invalid value.
+
+ \ref dg-contents
+
+ \section manager 2. TypeSequenceManager & SequenceManager=20
+
+The <I>TypeSequenceManager</I> class maintains an organized set of <I>Enti=
tySequence</I>
+instances and corresponding <I>SequenceData</I> instances. It is used to m=
anage
+all such instances for entities of a single <I>EntityType</I>. <I>TypeSequ=
enceManager</I>
+enforces the following four rules on its contained data:
+
+-# No two <I>SequenceData</I> instances may overlap. =20
+-# No two <I>EntitySequence</I> instances may overlap.
+-# Every <I>EntitySequence</I> must be a subset of a <I>SequenceData</I>.
+-# Any pair of <I>EntitySequence</I> instances referencing the same <I>Seq=
uenceData</I> must be separated by at least one unallocated handle.
+.
+
+ \subsection figure2 Figure 2: SequenceManager and Related Classes
+
+The first three rules are required for the validity of the data model. The
+fourth rule avoids unnecessary inefficiency. It is implemented by merging =
such
+adjacent sequences. In some cases, other classes (e.g. <I>SequenceManager<=
/I>) can
+modify an <I>EntitySequence</I> such that the fourth rule is violated. In =
such cases,
+the <I>TypeSequenceManager::notify</I> prepended or <I>TypeSequenceManager=
::notify</I> appended
+method must be called to maintain the integrity of the data<sup>1</sup>. T=
he above rules
+(including the fourth) are assumed in many other methods of the <I>TypeSeq=
uenceManager</I>
+class, such that those methods will fail or behave unexpectedly if the man=
aged
+data does not conform to the rules.
+
+<I>TypeSequenceManager</I> contains three principal data structures. The f=
irst is
+a <I>std::set</I> of <I>EntitySequence</I> pointers sorted using a custom =
comparison op-
+erator that queries the start and end handles of the referenced sequences.=
The
+comparison operation is defined as: <I>a->end_handle() < b->start_handle()=
</I>.
+This method of comparison has the advantage that a sequence corresponding =
to
+a specific handle can be located by searching the set for a =E2=80=9Cseque=
nce=E2=80=9D beginning
+and ending with the search value. The lower bound and find methods pro-
+vided by the library are guaranteed to return the sequence, if it exists. =
Using
+such a comparison operator will result in undefined behavior if the set co=
ntains
+overlapping sequences. This is acceptable, as rule two above prohibits such
+a configuration. However, some care must be taken in writing and modifying
+methods in <I>TypeSequenceManager</I> so as to avoid having overlapping se=
quences
+as a transitory state of some operation.
+
+The second important data member of <I>TypeSequenceManager</I> is a pointer
+to the last referenced <I>EntitySequence</I>. This =E2=80=9Ccached=E2=80=
=9D value is used to speed up
+searches by entity handle. This pointer is never null unless the sequence =
is empty.
+This rule is maintained to avoid unnecessary branches in fast query paths.=
In
+cases where the last referenced sequence is deleted, <I>TypeSequenceManage=
r</I> will
+typically assign an arbitrary sequence (e.g. the first one) to the last re=
ferenced
+pointer.
+
+The third data member of <I>TypeSequenceManager</I> is a <I>std::set</I> o=
f <I>SequenceData</I>
+instances that are not completely covered by a <I>EntitySequence</I> insta=
nce<sup>2</sup>.
+This list is searched when allocating new handles. <I>TypeSequenceManager<=
/I> also
+embeds in each <I>SequenceData</I> instance a reference to the first corre=
sponding
+<I>EntitySequence</I> so that it may be located quickly from only the <I>S=
equenceData</I>
+pointer.
+
+The <I>SequenceManager</I> class contains an array of <I>TypeSequenceManag=
er</I> in-
+stances, one for each <I>EntityType</I>. It also provides all type-specifi=
c operations
+such as allocating the correct <I>EntitySequence</I> subtype for a given <=
I>EntityType</I>.
+
+<sup>1</sup>This source of potential error can be eliminated with changes =
to the entity set representation. This is discussed in a later section.
+
+<sup>2</sup>Given rule four for the data managed by a <I>TypeSequenceManag=
er</I>, any <I>SequenceData</I> for which all handles are allocated will be=
referenced by exactly one <I>EntitySequence</I>.
+
+ \ref dg-contents
+
+ \section s-mesh 3. Structured Mesh
+
+Structured mesh storage is implemented using subclasses of <I>SequenceData=
</I>:
+<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSe=
q</I> class is
+used to access the structured element connectivity. A standard <I>VertexSe=
quence</I>
+instance is used to access the ScdVertexData because the vertex data stora=
ge
+is the same as for unstructured mesh.
+
+ \ref dg-contents
+
+ \section sets 4. Entity Sets
+
+- MeshSetSequence
+
+The <I>MeshSetSequence</I> class is the same as most other subclasses of <=
I>EntitySequence</I>
+in that it utilizes SequenceData to store its data. A single array in the =
<I>SequenceData</I>
+is used to store instances of the MeshSet class, one per allocated <I>Enti=
tyHandle</I>.
+<I>SequenceData</I> allocates all of its managed arrays using malloc and f=
ree as
+simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction =
and de-
+struction of <I>MeshSet</I> instances within that array. This is similar t=
o what is
+done by <I>std::vector</I> and other container classes that may own more s=
torage
+than is required at a given time for contained objects.
+
+- MeshSet
+
+ \subsection figure3 Figure 3: SequenceManager and Related Classes
+
+The <I>MeshSet</I> class is used to represent a single entity set instance=
in MOAB.
+The class is optimized to minimize storage (further possible improvements =
in
+storage size are discussed later.)
+
+Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> clas=
s.
+The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER<=
/I>,
+<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MES=
HSET_TRACK_OWNER</I>
+indicates that reverse links from the contained entities back to the ownin=
g set
+should be maintained in the adjacency list of each entity. The <I>MESHSET_=
SET</I>
+and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most c=
ode only
+tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESH=
SET_SET</I> bit is
+ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplica=
te handles
+and that the order that the handles are added to the set should be preserv=
ed.
+In practice, such sets are stored as a simple list of handles. <I>MESHSET_=
SET</I> (or in
+practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of =
the handles
+need not be preserved and that the set may not contain duplicate handles. =
Such
+sets are stored in a sorted range-compacted format similar to that of the =
Range
+class.
+
+The memory for storing contents, parents, and children are each handled in
+the same way. The data in the class is composed of a 2-bit =E2=80=98size=
=E2=80=99 field and two
+values, where the two values may either be two handles or two pointers. Th=
e size
+bit-fields are grouped together to reduce the required amount of memory. I=
f the
+numerical value of the 2-bit size field is 0 then the corresponding list i=
s empty.
+If the 2-bit size field is either 1 or 2, then the contents of the corresp=
onding list
+are stored directly in the corresponding two data fields of the MeshSet ob=
ject.
+If the 2-bit size field has a value of 3 (11 binary), then the correspondi=
ng two
+data fields store the begin and end pointers of an external array of handl=
es.
+The number of handles in the external array can be obtained by taking the
+difference of the start and end pointers. Note that unlike <I>std::vector<=
/I>, we
+do not store both an allocated and used size. We store only the =E2=80=98u=
sed=E2=80=99 size
+and call std::realloc whenever the used size is modified, thus we rely on =
the
+std::malloc implementation in the standard C library to track =E2=80=98all=
ocated=E2=80=99 size
+for us. In practice this performs well but does not return memory to the =
=E2=80=98system=E2=80=99
+when lists shrink (unless they shrink to zero). This overall scheme could =
exhibit
+poor performance if the size of one of the data lists in the set frequentl=
y changes
+between less than two and more than two handles, as this will result in fr=
equent
+releasing and re-allocating of the memory for the corresponding array.
+
+If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents l=
ist (parent
+and child lists are unaffected) is stored in a range-compacted format. In =
this
+format the number of handles stored in the array is always a multiple of t=
wo.
+Each consecutive pair of handles indicate the start and end, inclusive, of=
a range
+of handles contained in the set. All such handle range pairs are stored in=
sorted
+order and do not overlap. Nor is the end handle of one range ever one less=
than
+the start handle of the next. All such =E2=80=98adjacent=E2=80=99 range pa=
irs are merged into a
+single pair. The code for insertion and removal of handles from range-form=
atted
+set content lists is fairly complex. The implementation will guarantee tha=
t a
+given call to insert entities into a range or remove entities from a range=
is never
+worse than O(ln n) + O(m + n), where =E2=80=98n=E2=80=99 is the number of =
handles to insert
+and =E2=80=98m=E2=80=99 is the number of handles already contained in the =
set. So it is generally
+much more efficient to build Ranges of handles to insert (and remove) and =
call
+MOAB to insert (or remove) the entire list at once rather than making may
+calls to insert (or remove) one or a few handles from the contents of a se=
t.
+The set storage could probably be further minimized by allowing up to six
+handles in one of the lists to be elided. That is, as there are six potent=
ial =E2=80=98slots=E2=80=99
+in the MeshSet object then if two of the lists are empty it should be poss=
ible to store up to six values of the remaining list directly in the MeshSe=
t object.
+However, the additional runtime cost of such complexity could easily outwe=
igh
+any storage advantage. Further investigation into this has not been done b=
ecause
+the primary motivation for the storage optimization was to support binary =
trees.
+
+Another possible optimization of storage would be to remove the <I>MeshSet=
</I>
+object entirely and instead store the data in a =E2=80=98blocked=E2=80=99 =
format. The corre-
+sponding <I>SequenceData</I> would contain four arrays: flags, parents, ch=
ildren, and
+contents instead of a single array of <I>MeshSet</I> objects. If this were=
done then
+no storage need ever be allocated for parent or child links if none of the=
sets
+in a <I>SequenceData</I> has parent or child links. The effectiveness of t=
he storage
+reduction would depend greatly on how sets get grouped into <I>SequenceDat=
as</I>.
+This alternate storage scheme might also allow for better cache utilizatio=
n as it
+would group like data together. It is often the case that application code=
that
+is querying the contents of one set will query the contents of many but ne=
ver
+query the parents or children of any set. Or that an application will quer=
y only
+parent or child links of a set without every querying other set properties=
. The
+downside of this solution is that it makes the implementation a little les=
s mod-
+ular and maintainable because the existing logic contained in the <I>MeshS=
et</I> class
+would need to be spread throughout the <I>MeshSetSequence</I> class.
+
+ \ref dg-contents
+
+ \page dg-figures List of Figures
+
+ \ref figure1
+
+ \ref figure2
+
+ \ref figure3
+*/
diff --git a/doc/UG/moabUG.h b/doc/UG/moabUG.h
new file mode 100644
index 0000000..cea942d
--- /dev/null
+++ b/doc/UG/moabUG.h
@@ -0,0 +1,1064 @@
+/*! \page userguide User's Guide (MOAB 4.6)
+=20
+ \subpage team=20
+=20
+ \subpage contents
+=20
+ \subpage figures
+=20
+ \subpage tables
+=20
+ \subpage differences
+
+ \subpage building
+
+ \page team MOAB team members
+ <h2>The MOAB Team, including: </h2>
+=20
+ - Timothy J. Tautges (Argonne National Lab, Univ Wisconsin-Madison)=20
+ - Iulian Grindeanu (Argonne National Lab)=20
+ - Rajeev Jain (Argonne National Lab)
+ - Xiabing Xu (Argonne National Lab)
+
+
+ <h2>Emeritus members:</h2>
+=20
+ - Jason A. Kraftcheck
+ - Brandon M. Smith
+ - Hong-Jun Kim
+ - Jim Porter
+=20
+ \page contents Table of Contents
+=20
+ \ref introduction =20
+
+ \ref interface =20
+
+ \ref twoone =20
+
+ \ref twotwo =20
+
+ \ref twothree =20
+
+ \ref twofour =20
+
+ \ref api =20
+
+ \ref services =20
+
+ \ref fourone =20
+
+ \ref fourtwo =20
+
+ \ref fourthree =20
+
+ \ref fourfour =20
+
+ \ref fourfive =20
+
+ \ref foursix =20
+
+ \ref parallel =20
+
+ \ref fiveone =20
+
+ \ref fivetwo =20
+
+ \ref fivethree =20
+
+ \ref fivefour =20
+
+ \ref applications =20
+
+ \ref implementation =20
+
+ \ref representation =20
+
+ \ref element =20
+
+ \ref nineone =20
+
+ \ref ninetwo =20
+
+ \ref ninethree =20
+
+ \ref performance =20
+
+ \ref conclusions =20
+
+ \ref references=20
+
+ \section introduction 1. Introduction
+
+In scientific computing, systems of partial differential equations (PDEs) =
are solved on computers. One of the most widely used methods to solve PDEs=
numerically is to solve over discrete neighborhoods or =E2=80=9Celements=
=E2=80=9D of the domain. Popular discretization methods include Finite Dif=
ference (FD), Finite Element (FE), and Finite Volume (FV). These methods r=
equire the decomposition of the domain into a discretized representation, w=
hich is referred to as a =E2=80=9Cmesh=E2=80=9D. The mesh is one of the fu=
ndamental types of data linking the various tools in the analysis process (=
mesh generation, analysis, visualization, etc.). Thus, the representation =
of mesh data and operations on those data play a very important role in PDE=
-based simulations.
+=20
+MOAB is a component for representing and evaluating mesh data. MOAB can s=
tore structured and unstructured mesh, consisting of elements in the finite=
element =E2=80=9Czoo=E2=80=9D, along with polygons and polyhedra. The fun=
ctional interface to MOAB is simple, consisting of only four fundamental da=
ta types. This data is quite powerful, allowing the representation of most=
types of metadata commonly found on the mesh. Internally MOAB uses array-=
based storage for fine-grained data, which in many cases provides more effi=
cient access, especially for large portions of mesh and associated data. M=
OAB is optimized for efficiency in space and time, based on access to mesh =
in chunks rather than through individual entities, while also versatile eno=
ugh to support individual entity access.
+
+The MOAB data model consists of the following four fundamental types: mesh=
interface instance, mesh entities (vertex, edge, tri, etc.), sets, and tag=
s. Entities are addressed through handles rather than pointers, to allow t=
he underlying representation of an entity to change without changing the ha=
ndle to that entity. Sets are arbitrary groupings of mesh entities and oth=
er sets. Sets also support parent/child relationships as a relation distin=
ct from sets containing other sets. The directed graph provided by set par=
ent/child relationships is useful for embedding graphs whose nodes include =
collections of mesh entities; this approach has been used to represent a wi=
de variety of application-specific data, including geometric model topology=
, processor partitions, and various types of search trees. Tags are named =
data which can be assigned to the mesh as a whole, individual entities, or =
sets. Tags are a mechanism for attaching data to individual entities, and =
sets are a mechanism for describing relations between entities; the combina=
tion of these two mechanisms is a powerful yet simple interface for represe=
nting metadata or application-specific data.
+
+Various mesh-related tools are provided with MOAB or can be used directly =
with MOAB. These tools can be used for mesh format translation (mbconvert)=
, mesh skinning (Skinner class), solution transfer between meshes (MBCouple=
r tool), ray tracing and other geometric searches (OrientedBoxTreeTool, Ada=
ptiveKDTree), visualization (vtkMOABReader tool), and relation between mesh=
and geometric models (the separately-packed Lasso tool). These tools are =
described later in this document.
+
+MOAB is written in the C++ programming language, with applications interac=
ting with MOAB mostly through its moab::Interface class. All of the MOAB f=
unctions and classes are isolated in and accessed through the moab namespac=
e<sup>1</sup>. The remainder of this report gives class and function names =
without the =E2=80=9Cmoab::=E2=80=9D namespace qualification; unless otherw=
ise noted, the namespace qualifier should be added to all class and functio=
n names referenced here. MOAB also implements the iMesh interface, which i=
s specified in C but can be called directly from other languages. Almost a=
ll of the functionality in MOAB can be accessed through the iMesh interface=
. MOAB is developed and supported on the Linux and MacOS operating systems=
, as well as various HPC operating systems. MOAB can be used on parallel c=
omputing systems as well, including both clusters and high-end parallel sys=
tems like IBM BG/P and Cray systems. MOAB is released under a standard LGP=
L open source software license.
+
+MOAB is used in several ways in various applications. MOAB serves as the =
underlying mesh data representation in several scientific computing applica=
tions [1]. MOAB can also be used as a mesh format translator, using reader=
s and writers included in MOAB. MOAB has also been used as a bridge to cou=
ple results in multi-physics analysis and to link these applications with o=
ther mesh services [2].
+
+The remainder of this report is organized as follows. Section 2, =E2=80=
=9CGetting Started=E2=80=9D, provides a few simple examples of using MOAB t=
o perform simple tasks on a mesh. Section 3 discusses the MOAB data model =
in more detail, including some aspects of the implementation. Section 4 su=
mmarizes the MOAB function API. Section 5 describes some of the tools incl=
uded with MOAB, and the implementation of mesh readers/writers for MOAB. S=
ection 6 describes how to build MOAB-based applications. Section 7 contain=
s a brief description of MOAB=E2=80=99s relation to the iMesh mesh interfac=
e. Sections 8 and 9 discuss MOAB's representations of structured and spect=
ral element meshes, respectively. Section 10 gives helpful hints for acces=
sing MOAB in an efficient manner from applications. Section 11 gives a con=
clusion and future plans for MOAB development. Section 12 gives references=
cited in this report.
+
+Several other sources of information about MOAB may also be of interest to=
readers. Meta-data conventions define how sets and /or tags are used toge=
ther to represent various commonly-used simulation constructs; conventions =
used by MOAB are described in Ref [4], which is also included in the MOAB s=
ource distribution. This document is maintained separately from this docum=
ent, since it is expected to change over time. The MOAB project maintains =
a wiki [5], which links to most MOAB-related information. MOAB also uses s=
everal mailing lists [6],[7] for MOAB-related discussions. Potential users=
are encouraged to interact with the MOAB team using these mailing lists.
+
+<sup>1</sup> Non-namespaced names are also provided for backward compatibi=
lity, with the =E2=80=9CMB=E2=80=9D prefix added to the class or variable n=
ame.
+
+ \ref contents
+
+ \section interface 2. MOAB Data Model
+The MOAB data model describes the basic types used in MOAB and the languag=
e used to communicate that data to applications. This chapter describes th=
at data model, along with some of the reasons for some of the design choice=
s in MOAB.
+
+ \ref contents
+
+ \subsection twoone 2.1. MOAB Interface
+MOAB is written in C++. The primary interface with applications is throug=
h member functions of the abstract base class Interface. The MOAB library =
is created by instantiating Core, which implements the Interface API. Mult=
iple instances of MOAB can exist concurrently in the same application; mesh=
entities are not shared between these instancesi<sup>2</sup>. MOAB is mos=
t easily viewed as a database of mesh objects accessed through the instance=
. No other assumptions explicitly made about the nature of the mesh stored=
there; for example, there is no fundamental requirement that elements fill=
space or do not overlap each other geometrically.
+=20
+<sup>2</sup> One exception to this statement is when the parallel interfac=
e to MOAB is used; in this case, entity sharing between instances is handle=
d explicitly using message passing. This is described in more detail in Se=
ction 5 of this document.
+
+ \ref contents
+
+ \subsection twotwo 2.2. Mesh Entities
+MOAB represents the following topological mesh entities: vertex, edge, tri=
angle, quadrilateral, polygon, tetrahedron, pyramid, prism, knife, hexahedr=
on, polyhedron. MOAB uses the EntityType enumeration to refer to these ent=
ity types (see Table 1). This enumeration has several special characterist=
ics, chosen intentionally: the types begin with vertex, entity types are gr=
ouped by topological dimension, with lower-dimensional entities appearing b=
efore higher dimensions; the enumeration includes an entity type for sets (=
described in the next section); and MBMAXTYPE is included at the end of thi=
s enumeration, and can be used to terminate loops over type. In addition t=
o these defined values, the an increment operator (++) is defined such that=
variables of type EntityType can be used as iterators in loops.
+MOAB refers to entities using =E2=80=9Chandles=E2=80=9D. Handles are impl=
emented as long integer data types, with the four highest-order bits used t=
o store the entity type (mesh vertex, edge, tri, etc.) and the remaining bi=
ts storing the entity id. This scheme is convenient for applications becau=
se:
+- Handles sort lexicographically by type and dimension; this can be useful=
for grouping and iterating over entities by type.
+- The type of an entity is indicated by the handle itself, without needing=
to call a function.
+- Entities allocated in sequence will typically have contiguous handles; t=
his characteristic can be used to efficiently store and operate on large li=
sts of handles.
+.
+
+This handle implementation is exposed to applications intentionally, becau=
se of optimizations that it enables, and is unlikely to change in future ve=
rsions.
+
+ \subsection tableone Table 1: Values defined for the EntityType enumerat=
ed type.
+<table border=3D"1">
+<tr>
+<td>MBVERTEX =3D 0</td>
+<td>MBPRISM</td>
+</tr>
+<tr>
+<td>MBEDGE</td>
+<td>MBKNIFE</td>
+</tr>
+<tr>
+<td>MBTRI</td>
+<td>MBHEX</td>
+</tr>
+<tr>
+<td>MBQUAD</td>
+<td>MBPOLYHEDRON</td>
+</tr>
+<tr>
+<td>MBPOLYGON</td>
+<td>MBENTITYSET</td>
+</tr>
+<tr>
+<td>MBTET</td>
+<td>MBMAXTYPE</td>
+</tr>
+<tr>
+<td>MBPYRAMID</td>
+<td></td>
+</tr>
+</table>
+
+MOAB defines a special class for storing lists of entity handles, named Ra=
nge. This class stores handles as a series of (start_handle, end_handle) s=
ubrange tuples. If a list of handles has large contiguous ranges, it can b=
e represented in almost constant size using Range. Since entities are typi=
cally created in groups, e.g. during mesh generation or file import, a high=
degree of contiguity in handle space is typical. Range provides an interf=
ace similar to C++ STL containers like std::vector, containing iterator dat=
a types and functions for initializing and iterating over entity handles st=
ored in the range. Range also provides functions for efficient Boolean ope=
rations like subtraction and intersection. Most API functions in MOAB come=
in both range-based and vector-based variants. By definition, a list of e=
ntities stored in an Range is always sorted, and can contain a given entity=
handle only once. Range cannot store the handle 0 (zero).
+
+Typical usage of an Range object would look like:
+
+\code
+using namespace moab;
+ int my_function(Range &from_range) {
+ int num_in_range =3D from_range.size();
+ Range to_range;
+ Range::iterator rit;
+ for (rit =3D from_range.begin(); rit !=3D from_range.end(); rit++) {
+ EntityHandle this_ent =3D *rit;
+ to_range.insert(this_ent);
+ }
+ }
+\endcode
+
+Here, the range is iterated similar to how std::vector is iterated.
+
+ \ref contents
+
+ \subsection adjacencies 2.2.1. Adjacencies & AEntities=20
+
+The term adjacencies is used to refer to those entities topologically conn=
ected to a given entity, e.g. the faces bounded by a given edge or the vert=
ices bounding a given region. The same term is used for both higher-dimens=
ional (or bounded) and lower-dimensional (or bounding) adjacent entities. =
MOAB provides functions for querying adjacent entities by target dimension,=
using the same functions for higher- and lower-dimension adjacencies. By =
default, MOAB stores the minimum data necessary to recover adjacencies betw=
een entities. When a mesh is initially loaded into MOAB, only entity-verte=
x (i.e. =E2=80=9Cdownward=E2=80=9D) adjacencies are stored, in the form of =
entity connectivity. When =E2=80=9Cupward=E2=80=9D adjacencies are request=
ed for the first time, e.g. from vertices to regions, MOAB stores all verte=
x-entity adjacencies explicitly, for all entities in the mesh. Non-vertex =
entity to entity adjacencies are never stored, unless explicitly requested =
by the application.
+
+In its most fundamental form, a mesh need only be represented by its verti=
ces and the entities of maximal topological dimension. For example, a hexa=
hedral mesh can be represented as the connectivity of the hex elements and =
the vertices forming the hexes. Edges and faces in a 3D mesh need not be e=
xplicitly represented. We refer to such entities as =E2=80=9CAEntities=E2=
=80=9D, where =E2=80=98A=E2=80=99 refers to =E2=80=9CAuxiliary=E2=80=9D, =
=E2=80=9CAncillary=E2=80=9D, and a number of other words mostly beginning w=
ith =E2=80=98A=E2=80=99. Individual AEntities are created only when reques=
ted by applications, either using mesh modification functions or by request=
ing adjacencies with a special =E2=80=9Ccreate if missing=E2=80=9D flag pas=
sed as =E2=80=9Ctrue=E2=80=9D. This reduces the overall memory usage when =
representing large meshes. Note entities must be explicitly represented be=
fore they can be assigned tag values or added to entity sets (described in =
following Sections).
+
+\ref contents
+
+ \subsection twothree 2.3. Entity Sets
+Entity sets are used to store arbitrary collections of entities and other =
sets. Sets are used for a variety of things in mesh-based applications, fr=
om the set of entities discretizing a given geometric model entity to the e=
ntities partitioned to a specific processor in a parallel finite element ap=
plication. MOAB entity sets can also store parent/child relations with oth=
er entity sets, with these relations distinct from contains relations. Par=
ent/child relations are useful for building directed graphs with graph node=
s representing collections of mesh entities; this construct can be used, fo=
r example, to represent an interface of mesh faces shared by two distinct c=
ollections of mesh regions. MOAB also defines one special set, the =E2=80=
=9Croot set=E2=80=9D or the interface itself; all entities are part of this=
set by definition. Defining a root set allows the use of a single set of =
MOAB API functions to query entities in the overall mesh as well as its sub=
sets.
+
+MOAB entity sets can be one of two distinct types: list-type entity sets p=
reserve the order in which entities are added to the set, and can store a g=
iven entity handle multiple times in the same set; set-type sets are always=
ordered by handle, regardless of the order of addition to the set, and can=
store a given entity handle only once. This characteristic is assigned wh=
en the set is created, and cannot be changed during the set=E2=80=99s lifet=
ime.
+
+MOAB provides the option to track or not track entities in a set. When en=
tities (and sets) are deleted by other operations in MOAB, they will also b=
e removed from containing sets for which tracking has been enabled. This b=
ehavior is assigned when the set is created, and cannot be changed during t=
he set=E2=80=99s lifetime. The cost of turning tracking on for a given set=
is sizeof(EntityHandle) for each entity added to the set; MOAB stores cont=
aining sets in the same list which stores adjacencies to other entities.
+
+Using an entity set looks like the following:
+\code
+using namespace moab;
+// load a file using MOAB, putting the loaded mesh into a file set
+EntityHandle file_set;
+ErrorCode rval =3D moab->create_meshset(MESHSET_SET, file_set);
+rval =3D moab->load_file(=E2=80=9Cfname.vtk=E2=80=9D, &file_set);
+Range set_ents;
+// get all the 3D entities in the set
+rval =3D moab->get_entities_by_dimension(file_set, 3, set_ents);
+\endcode
+
+Entity sets are often used in conjunction with tags (described in the next=
section), and provide a powerful mechanism to store a variety of meta-data=
with meshes.
+
+\ref contents
+
+ \subsection twofour 2.4. Tags=20
+
+Applications of a mesh database often need to attach data to mesh entities=
. The types of attached data are often not known at compile time, and can =
vary across individual entities and entity types. MOAB refers to this atta=
ched data as a =E2=80=9Ctag=E2=80=9D. Tags can be thought of loosely as a =
variable, which can be given a distinct value for individual entities, enti=
ty sets, or for the interface itself. A tag is referenced using a handle, =
similarly to how entities are referenced in MOAB. Each MOAB tag has the fo=
llowing characteristics, which can be queried through the MOAB interface:
+- Name
+- Size (in bytes)
+- Storage type
+- Data type (integer, double, opaque, entity handle)
+- Handle
+.
+
+The storage type determines how tag values are stored on entities. =20
+
+- Dense: Dense tag values are stored in arrays which match arrays of conti=
guous entity handles. Dense tags are more efficient in both storage and me=
mory if large numbers of entities are assigned the same tag. Storage for a=
given dense tag is not allocated until a tag value is set on an entity; me=
mory for a given dense tag is allocated for all entities in a given sequenc=
e at the same time.
+- Sparse: Sparse tags are stored as a list of (entity handle, tag value) t=
uples, one list per sparse tag, sorted by entity handle.
+- Bit: Bit tags are stored similarly to dense tags, but with special handl=
ing to allow allocation in bit-size amounts per entity.
+.
+
+MOAB also supports variable-length tags, which can have a different length=
for each entity they are assigned to. Variable length tags are stored sim=
ilarly to sparse tags.
+
+The data type of a tag can either be one understood at compile time (integ=
er, double, entity handle), in which case the tag value can be saved and re=
stored properly to/from files and between computers of different architectu=
re (MOAB provides a native HDF5-based save/restore format for this purpose;=
see Section 4.6). The opaque data type is used for character strings, or =
for allocating =E2=80=9Craw memory=E2=80=9D for use by applications (e.g. f=
or storage application-defined structures or other abstract data types). T=
hese tags are saved and restored as raw memory, with no special handling fo=
r endian or precision differences.
+
+An application would use the following code to attach a double-precision t=
ag to vertices in a mesh, e.g. to assign a temperature field to those verti=
ces:
+
+\code
+using namespace moab;
+// load a file using MOAB and get the vertices
+ErrorCode rval =3D moab->load_file(=E2=80=9Cfname.vtk=E2=80=9D);
+Range verts;
+rval =3D moab->get_entities_by_dimension(0, 0, verts);
+// create a tag called =E2=80=9CTEMPERATURE=E2=80=9D
+Tag temperature;
+double def_val =3D -1.0d-300, new_val =3D 273.0;
+rval =3D moab->tag_create(=E2=80=9CTEMPERATURE=E2=80=9D, sizeof(double), M=
B_TAG_DENSE,=20
+ MB_TYPE_DOUBLE, temperature, &def_val);
+// assign a value to vertices
+for (Range::iterator vit =3D verts.begin();=20
+ vit !=3D verts.end(); vit++)=20
+ rval =3D moab->tag_set_data(temperature, &(*rit), 1, &new_val);
+
+\endcode
+
+The semantic meaning of a tag is determined by applications using it. How=
ever, to promote interoperability between applications, there are a number =
of tag names reserved by MOAB which are intended to be used by convention. =
Mesh readers and writers in MOAB use these tag conventions, and applicatio=
ns can use them as well to access the same data. Ref. [4] maintains an up-t=
o-date list of conventions for meta-data usage in MOAB.
+
+ \ref contents
+
+ \section api 3. MOAB API Design Philosophy and Summary
+
+This section describes the design philosophy behind MOAB, and summarizes t=
he functions, data types and enumerated variables in the MOAB API. A compl=
ete description of the MOAB API is available in online documentation in the=
MOAB distribution [8].
+
+MOAB is designed to operate efficiently on collections of entities. Entit=
ies are often created or referenced in groups (e.g. the mesh faces discreti=
zing a given geometric face, the 3D elements read from a file), with those =
groups having some form of temporal or spatial locality. The interface pro=
vides special mechanisms for reading data directly into the native storage =
used in MOAB, and for writing large collections of entities directly from t=
hat storage, to avoid data copies. MOAB applications structured to take ad=
vantage of that locality will typically operate more efficiently.
+
+MOAB has been designed to maximize the flexibility of mesh data which can =
be represented. There is no explicit constraint on the geometric structure=
of meshes represented in MOAB, or on the connectivity between elements. I=
n particular, MOAB allows the representation of multiple entities with the =
same exact connectivity; however, in these cases, explicit adjacencies must=
be used to distinguish adjacencies with AEntities bounding such entities.
+
+The number of vertices used to represent a given topological entity can va=
ry, depending on analysis needs; this is often the case in FEA. For exampl=
e, applications often use =E2=80=9Cquadratic=E2=80=9D or 10-vertex tetrahed=
ral, with vertices at edge midpoints as well as corners. MOAB does not dis=
tinguish these variants by entity type, referring to all variants as =E2=80=
=9Ctetrahedra=E2=80=9D. The number of vertices for a given entity is used =
to distinguish the variants, with canonical numbering conventions used to d=
etermine placement of the vertices [9]. This is similar to how such variat=
ions are represented in the Exodus [10] and Patran [11] file formats. In p=
ractice, we find that this simplifies coding in applications, since in many=
cases the handling of entities depends only on the number of corner vertic=
es in the element. Some MOAB API functions provide a flag which determines=
whether corner or all vertices are requested.
+
+The MOAB API is designed to balance complexity and ease of use. This bala=
nce is evident in the following general design characteristics:
+
+- Entity lists: Lists of entities are passed to and from MOAB in a variety=
of forms. Lists output from MOAB are passed as either STL vector or Range=
data types. Either of these constructs may be more efficient in both time=
and memory, depending on the semantics of the data being requested. Input=
lists are passed as either Range=E2=80=99s, or as a pointer to EntityHandl=
e and a size. The latter allows the same function to be used when passing =
individual entities, without requiring construction of an otherwise unneede=
d STL vector.
+- Entity sets: Most query functions accept an entity set as input. Applic=
ations can pass zero to indicate a request for the whole interface. Note t=
hat this convention applies only to query functions; attempts to add or sub=
tract entities to/from the interface using set-based modification functions=
, or to add parents or children to the interface set, will fail. Allowing =
specification of the interface set in this manner avoids the need for a sep=
arate set of API functions to query the database as a whole.
+- Implicit Booleans in output lists: A number of query functions in MOAB a=
llow specification of a Boolean operation (Interface::INTERSECT or Interfac=
e::UNION). This operation is applied to the results of the query, often el=
iminating the need for code the application would need to otherwise impleme=
nt. For example, to find the set of vertices shared by a collection of qua=
drilaterals, the application would pass that list of quadrilaterals to a re=
quest for vertex adjacencies, with Interface::INTERSECT passed for the Bool=
ean flag. The list of vertices returned would be the same as if the applic=
ation called that function for each individual entity, and computed the int=
ersection of the results over all the quadrilaterals. Applications may als=
o input non-empty lists to store the results, in which case the intersectio=
n is also performed with entities already in the list. In many cases, this=
allows optimizations in both time and memory inside the MOAB implementatio=
n.=20
+.
+
+Since these objectives are at odds with each other, tradeoffs had to be ma=
de between them. Some specific issues that came up are:
+
+- Using ranges: Where possible, entities can be referenced using either ra=
nges (which allow efficient storage of long lists) or STL vectors (which al=
low list order to be preserved), in both input and output arguments.
+- Entities in sets: Accessing the entities in a set is done using the same=
functions which access entities in the entire mesh. The whole mesh is ref=
erenced by specifying a set handle of zero<sup>3</sup>.
+- Entity vectors on input: Functions which could normally take a single en=
tity as input are specified to take a vector of handles instead. Single en=
tities are specified by taking the address of that entity handle and specif=
ying a list length of one. This minimizes the number of functions, while p=
reserving the ability to input single entities.<sup>4</sup>
+.
+
+Table 2 lists basic data types and enumerated variables defined and used b=
y MOAB. Values of the ErrorCode enumeration are returned from most MOAB fu=
nctions, and can be compared to those listed in Appendix [ref-appendix].
+
+MOAB uses several pre-defined tag names to define data commonly found in v=
arious mesh-based analyses. Ref. [4] describes these meta-data conventions=
in more detail. These conventions will be added to as new conventions eme=
rge for using sets and tags in MOAB applications.
+
+ \subsection tabletwo Table 2: Basic data types and enums defined in MOAB.
+
+<table border=3D"1">
+<tr>
+<th>Enum / Type</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>ErrorCode</td>
+<td>Specific error codes returned from MOAB</td>
+</tr>
+<tr>
+<td>EntityHandle</td>
+<td>Type used to represent entity handles</td>
+</tr>
+<tr>
+<td>Tag</td>
+<td>Type used to represent tag handles</td>
+</tr>
+<tr>
+<td>TagType</td>
+<td>Type used to represent tag storage type</td>
+</tr>
+<tr>
+<td>DataType</td>
+<td>Type used to represent tag data type</td>
+</tr>
+</table>
+
+Table 3 lists the various groups of functions that comprise the MOAB API. =
This is listed here strictly as a reference to the various types of functi=
onality supported by MOAB; for a more detailed description of the scope and=
syntax of the MOAB API, see the online documentation [8].
+
+ \subsection tablethree Table 3: Groups of functions in MOAB API. See Re=
f. [8] for more details.
+
+<table border=3D"1">
+<tr>
+<th>Function group</th>
+<th>Examples</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>Constructor, destructor, interface</td>
+<td>Interface, ~Core, query_interface</td>
+<td>Construct/destroy interface; get pointer to read/write interface</td>
+</tr>
+<tr>
+<td>Entity query</td>
+<td>get_entities_by_dimension, get_entities_by_handle</td>
+<td>Get entities by dimension, type, etc.</td>
+</tr>
+<tr>
+<td>Adjacencies</td>
+<td>get_adjacencies, set_adjacencies, add_adjacencies</td>
+<td>Get topologically adjacent entities; set or add explicit adjacencies</=
td>
+</tr>
+<tr>
+<td>Vertex coordinates</td>
+<td>get_coords, set_coords</td>
+<td>Get/set vertex coordinates</td>
+</tr>
+<tr>
+<td>Connectivity</td>
+<td>get_connectivity, set_connectivity</td>
+<td>Get/set connectivity of non-vertex entities</td>
+</tr>
+<tr>
+<td>Sets</td>
+<td>create_meshset, add_entities, add_parent_child</td>
+<td>Create and work with entity sets</td>
+</tr>
+<tr>
+<td>Tags</td>
+<td>tag_get_data, tag_create</td>
+<td>Create, read, write tag data</td>
+</tr>
+<tr>
+<td>Handles</td>
+<td>type_from_handle, id_from_handle</td>
+<td>Go between handles and types/ids</td>
+</tr>
+<tr>
+<td>File handling</td>
+<td>load_mesh, save_mesh</td>
+<td>Read/write mesh files</td>
+</tr>
+<tr>
+<td>Geometric dimension</td>
+<td>get_dimension, set_dimension</td>
+<td>Get/set geometric dimension of mesh</td>
+</tr>
+<tr>
+<td>Mesh modification</td>
+<td>create_vertex, delete_entity</td>
+<td>Create or delete mesh entities</td>
+</tr>
+<tr>
+<td>Information</td>
+<td>list_entities, get_last_error</td>
+<td>Get or print certain information</td>
+</tr>
+<tr>
+<td>High-order nodes</td>
+<td>high_order_node</td>
+<td>Get information on high-order nodes</td>
+</tr>
+<tr>
+<td>Canonical numbering</td>
+<td>side_number</td>
+<td>Get canonical numbering information</td>
+</tr>
+</table>
+
+<sup>3</sup>In iMesh, the whole mesh is specified by a special entity set =
handle, referred to as the =E2=80=9Croot set=E2=80=9D.
+
+<sup>4</sup>Note that STL vectors of entity handles can be input in this m=
anner by using &vector[0] and vector.size() for the 1d vector address and s=
ize, respectively.
+
+ \ref contents
+
+ \section services 4. Related Mesh Services
+
+A number of mesh-based services are often used in conjunction with a mesh =
library. For example, parallel applications often need to visualize the me=
sh and associated data. Other services, like spatial interpolation or find=
ing the faces on the =E2=80=9Cskin=E2=80=9D of a 3D mesh, can be implemente=
d more efficiently using knowledge of specific data structures in MOAB. Se=
veral of these services provided with MOAB are described in this chapter.
+
+ \ref contents
+
+ \subsection fourone 4.1. Visualization
+
+Visualization is one of the most common needs associated with meshes. The=
primary tool used to visualize MOAB meshes is VisIt [12]. Users can speci=
fy that VisIt read mesh directly out of the MOAB instance, by specifying th=
e ITAPS-MOABC mesh format and a file readable by MOAB (see xxx).
+
+There are some initial capabilities in VisIt for limited viewing and manip=
ulation of tag data and some types of entity sets. Tag data is visualized =
using the same mechanisms used to view other field data in VisIt, e.g. usin=
g a pseudocolor plot; sets are viewed using VisIt=E2=80=99s SIL window, acc=
essed by selecting the SIL icon in the data selection window. xxx shows a =
vertex-based radiation temperature field computed by the Cooper rad-hydro c=
ode [1] for a subset of geometric volumes in a mesh. =20
+
+Reorganization of VisIt=E2=80=99s set handling is also underway, to increa=
se versatility and flexibility of this important mechanism.
+
+ \ref contents
+
+ \subsection fourtwo 4.2. Parallel Decomposition
+
+To support parallel simulation, applications often need to partition a mes=
h into parts, designed to balance the load and minimize communication betwe=
en sets. MOAB includes the MBZoltan tool for this purpose, constructed on =
the well-known Zoltan partitioning library [13]. After computing the parti=
tion using Zoltan, MBZoltan stores the partition as either tags on individu=
al entities in the partition, or as tagged sets, one set per part. Since a=
partition often exhibits locality similar to how the entities were created=
, storing it as sets (based on Range=E2=80=99s) is often more memory-effici=
ent than an entity tag-based representation. Xxx shows a partition compute=
d with MBZoltan (and visualized in VisIt).=20
+
+ \ref contents
+
+ \subsection fourthree 4.3. Skinner
+
+An operation commonly applied to mesh is to compute the outermost =E2=80=
=9Cskin=E2=80=9D bounding a contiguous block of elements. This skin consis=
ts of elements of one fewer topological dimension, arranged in one or more =
topological balls on the boundary of the elements. The Skinner tool comput=
es the skin of a mesh in a memory-efficient manner. Skinner uses knowledge=
about whether vertex-entity adjacencies and AEntities exist to minimize me=
mory requirements and searching time required during the skinning process. =
This skin can be provided as a single collection of entities, or as sets o=
f entities distinguished by forward and reverse orientation with respect to=
higher-dimensional entities in the set being skinned.
+
+The following code fragment shows how Skinner can be used to compute the s=
kin of a range of hex elements:
+
+ \code
+using namespace moab;
+Range hexes, faces;
+ErrorCode rval =3D moab->get_entities_by_dimension(0, 3, hexes);
+Skinner myskinner(moab);
+bool verts_too =3D false;
+ErrorCode rval =3D myskinner.find_skin(hexes, verts_too, faces);
+\endcode
+
+Skinner can also skin a mesh based on geometric topology groupings importe=
d with the mesh. The geometric topology groupings contain information abou=
t the mesh =E2=80=9Cowned=E2=80=9D by each of the entities in the geometric=
model, e.g. the model vertices, edges, etc. Links between the mesh sets c=
orresponding to those entities can be inferred directly from the mesh. Ski=
nning a mesh this way will typically be much faster than doing so on the ac=
tual mesh elements, because there is no need to create and destroy interior=
faces on the mesh.
+
+ \ref contents
+
+ \subsection fourfour 4.4. Tree Decompositions
+
+MOAB provides several mechanisms for spatial decomposition and searching i=
n a mesh:
+
+- AdaptiveKDTree: Adaptive KD tree, a space-filling decomposition with axi=
s-aligned splitting planes, enabling fast searching.
+- BSPTree: Binary Space Partition tree, with non-axis-aligned partitions, =
for fast spatial searches with slightly better memory efficiency than KD tr=
ees.
+- OrientedBoxTreeTool: Oriented Bounding Box tree hierarchy, useful for fa=
st ray-tracing on collections of mesh facets.
+.
+
+These trees have various space and time searching efficiencies. All are i=
mplemented based on entity sets and parent/child relations between those se=
ts, allowing storage of a tree decomposition using MOAB=E2=80=99s native fi=
le storage mechanism (see Section 4.6.1). MOAB=E2=80=99s entity set implem=
entation is specialized for memory efficiency when representing binary tree=
s. Tree decompositions in MOAB have been used to implement fast ray tracin=
g to support radiation transport [14], solution coupling between meshes [2]=
, and embedded boundary mesh generation [15]. MOAB also includes the DAGMC=
tool, supporting Monte Carlo radiation transport.
+
+The following code fragment shows very basic use of AdaptiveKDTree. A ran=
ge of entities is put in the tree; the leaf containing a given point is fou=
nd, and the entities in that leaf are returned.
+\code
+using namespace moab;
+// create the adaptive kd tree from a range of tets
+EntityHandle tree_root
+AdaptiveKDTree myTree(moab);
+ErrorCode rval =3D myTree.build_tree(tets, tree_root);
+
+// get the overall bounding box corners
+double boxmax[3], boxmin;
+rval =3D myTree.get_tree_box(tree_root, boxmax, boxmin);
+
+// get the tree leaf containing point xyz, and the tets in that leaf
+AdaptiveKDTreeIter treeiter;
+rval =3D myTree.leaf_containing_point(tree_root, xyz, treeiter);
+Range leaf_tets;
+rval =3D moab->get_entities_by_dimension(treeiter.handle(), 3,=20
+ leaf_tets, false);
+\endcode
+
+More detailed examples of using the various tree decompositions in MOAB ca=
n be found in [ref-treeexamples].
+
+ \ref contents
+
+ \subsection fourfive 4.5. File Reader/Writer Interfaces
+
+Mesh readers and writers communicate mesh into/out of MOAB from/to disk fi=
les. Reading a mesh often involves importing large sets of data, for examp=
le coordinates of all the nodes in the mesh. Normally, this process would =
involve reading data from the file into a temporary data buffer, then copyi=
ng data from there into its destination in MOAB. To avoid the expense of c=
opying data, MOAB has implemented a reader/writer interface that provides d=
irect access to blocks of memory used to represent mesh.
+
+The reader interface, declared in ReadUtilIface, is used to request blocks=
of memory for storing coordinate positions and element connectivity. The =
pointers returned from these functions point to the actual memory used to r=
epresent those data in MOAB. Once data is written to that memory, no furth=
er copying is done. This not only saves time, but it also eliminates the n=
eed to allocate a large memory buffer for intermediate storage of these dat=
a.=20
+
+MOAB allocates memory for nodes and elements (and their corresponding dens=
e tags) in chunks, to avoid frequent allocation/de-allocation of small chun=
ks of memory. The chunk size used depends on from where the mesh is being =
created, and can strongly affect the performance (and memory layout) of MOA=
B. Since dense tags are allocated at the chunk size, this can also affect =
overall memory usage in cases where the mesh size is small but the number o=
f dense tags or dense tag size is large. When creating vertices and elemen=
ts through the normal MOAB API, default chunk sizes defined in the Sequence=
Manager class are used. However, most of the file readers in MOAB allocate=
the exact amount of space necessary to represent the mesh being read. The=
re are also a few exceptions to this:
+
+- When compiled in parallel, this space is increased by a factor of 1.5, t=
o allow subsequent creation of ghost vertices/elements in the same chunk as=
the original mesh.
+- The .cub file reader, which creates nodes and elements for individual ge=
ometric entities in separate calls, allocates using the default vertex/elem=
ent sequence sizes, which are defined in the SequenceManager class in MOAB.
+.
+
+Applications calling the reader interface functions directly can specify t=
he allocation chunk size as an optional parameter.
+
+The reader interface consists of the following functions:
+
+- get_node_arrays: Given the number of vertices requested, the number of g=
eometric dimensions, and a requested start id, allocates a block of vertex =
handles and returns pointers to coordinate arrays in memory, along with the=
actual start handle for that block of vertices.
+- get_element_array: Given the number of elements requested, the number of=
vertices per element, the element type and the requested start id, allocat=
es the block of elements, and returns a pointer to the connectivity array f=
or those elements and the actual start handle for that block. The number o=
f vertices per element is necessary because those elements may include high=
er-order nodes, and MOAB stores these as part of the normal connectivity ar=
ray.
+- update_adjacencies: This function takes the start handle for a block of =
elements and the connectivity of those elements, and updates adjacencies fo=
r those elements. Which adjacencies are updated depends on the options set=
in AEntityFactory.
+.
+
+The following code fragment illustrates the use of ReadUtilIface to read a=
mesh directly into MOAB=E2=80=99s native representation. This code assume=
s that connectivity is specified in terms of vertex indices, with vertex in=
dices starting from 1.
+
+\code
+// get the read iface from moab
+ReadUtilIface *iface;
+ErrorCode rval =3D moab->get_interface("ReadUtilIface", &iface);
+
+// allocate a block of vertex handles and read xyz=E2=80=99s into them
+std::vector<double*> arrays;
+EntityHandle startv, *starth;
+rval =3D iface->get_node_arrays(3, num_nodes, 0, startv, arrays);
+for (int i =3D 0; i < num_nodes; i++)
+ infile >> arrays[0][i] >> arrays[1][i] >> arrays[2][i];
+
+// allocate block of hex handles and read connectivity into them
+rval =3D iface->get_element_array(num_hexes, 8, MBHEX, 0, starth);
+for (int i =3D 0; i < 8*num_hexes; i++)
+ infile >> starth[i];
+
+// change connectivity indices to vertex handles
+for (int i =3D 0; i < 8*num_hexes; i++)
+ starth[i] +=3D startv-1;
+\endcode
+
+The writer interface, declared in WriteUtilIface, provides functions that =
support writing vertex coordinates and element connectivity to storage loca=
tions input by the application. Assembling these data is a common task for=
writing mesh, and can be non-trivial when exporting only subsets of a mesh=
. The writer interface declares the following functions:
+
+- get_node_arrays: Given already-allocated memory and the number of vertic=
es and dimensions, and a range of vertices, this function writes vertex coo=
rdinates to that memory. If a tag is input, that tag is also written with =
integer vertex ids, starting with 1, corresponding to the order the vertice=
s appear in that sequence (these ids are used to write the connectivity arr=
ay in the form of vertex indices).
+- get_element_array: Given a range of elements and the tag holding vertex =
ids, and a pointer to memory, the connectivity of the specified elements ar=
e written to that memory, in terms of the indices referenced by the specifi=
ed tag. Again, the number of vertices per element is input, to allow the d=
irect output of higher-order vertices.
+- gather_nodes_from_elements: Given a range of elements, this function ret=
urns the range of vertices used by those elements. If a bit-type tag is in=
put, vertices returned are also marked with 0x1 using that tag. If no tag =
is input, the implementation of this function uses its own bit tag for mark=
ing, to avoid using an n2 algorithm for gathering vertices.
+- reorder: Given a permutation vector, this function reorders the connecti=
vity for entities with specified type and number of vertices per entity to =
match that permutation. This function is needed for writing connectivity i=
nto numbering systems other than that used internally in MOAB.
+.
+
+The following code fragment shows how to use WriteUtilIface to write the v=
ertex coordinates and connectivity indices for a subset of entities.
+
+\code
+using namespace moab;
+// get the write iface from moab
+WriteUtilIface *iface;
+ErrorCode rval =3D moab->get_interface("WriteUtilIface", &iface);
+
+// get all hexes the model, and choose the first 10 of those
+Range tmp_hexes, hexes, verts;
+rval =3D moab->get_entities_by_type(0, MBHEX, tmp_hexes);
+for (int i =3D 0; i < 10; i++) hexes.insert(tmp_hexes[i]);
+rval =3D iface->gather_nodes_from_elements(hexes, 0, verts);
+
+// assign vertex ids
+iface->assign_ids(verts, 0, 1);
+
+// allocate space for coordinates & write them
+std::vector<double*> arrays(3);
+for (int i =3D 0; i < 3; i++) arrays[i] =3D new double[verts.size()];
+iface->get_node_arrays(3, verts.size(), verts, 0, 1, arrays);
+
+// put connect=E2=80=99y in array, in the form of indices into vertex array
+std::vector<int> conn(8*hexes.size());
+iface->get_element_array(hexes.size(), 8, 0, hexes, 0, 1, &conn[0]);
+\endcode
+
+ \ref contents
+
+ \subsection foursix 4.6. File Readers/Writers Packaged With MOAB
+
+MOAB has been designed to efficiently represent data and metadata commonly=
found in finite element mesh files. Readers and writers are included with=
MOAB which import/export specific types of metadata in terms of MOAB sets =
and tags, as described earlier in this document. The number of readers and=
writers in MOAB will probably grow over time, and so they are not enumerat=
ed here. See the src/io/README file in the MOAB source distribution for a =
current list of supported formats.
+
+Because of its generic support for readers and writers, described in the p=
revious section, MOAB is also a good environment for constructing new mesh =
readers and writers. The ReadTemplate and WriteTemplate classes in src/io =
are useful starting points for constructing new file readers/writers; appli=
cations are encouraged to submit their own readers/writers for inclusion in=
MOAB=E2=80=99s contrib/io directory in the MOAB source.=20
+
+The usefulness of a file reader/writer is determined not only by its abili=
ty to read and write nodes and elements, but also in its ability to store t=
he various types of meta-data included with the typical mesh. MOAB readers=
and writers are distinguished by their ability to preserve meta-data in me=
shes that they read and write. For example, MOAB=E2=80=99s CUB reader impo=
rts not only the mesh saved from CUBIT, but also the grouping of mesh entit=
ies into sets which reflect the geometric topology of the model used to gen=
erate the mesh. See [4] for a more detailed description of meta-data conve=
ntions used in MOAB=E2=80=99s file readers and writers, and the individual =
file reader/writer header files in src/io for details about the specific re=
aders and writers.
+
+Three specific file readers in MOAB bear further discussion: MOAB=E2=80=99=
s native HDF5-based file reader/writer; the CUB reader, used to import mesh=
and meta-data represented in CUBIT; and the CGM reader, which imports geom=
etric models. These are described next.
+
+ \ref contents
+
+ \subsection native 4.6.1. Native HD5-Based Reader/Writer
+
+A mesh database must be able to save and restore the data stored in its da=
ta model, at least to the extent to which it understands the semantics of t=
hat data. MOAB defines an HDF5-based file format that can store data embed=
ded in MOAB. By convention, these files are given an =E2=80=9C.h5m=E2=80=
=9D file extension. When reading or writing large amounts of data, it is r=
ecommended to use this file format, as it is the most complete and also the=
most efficient of the file readers/writers in MOAB.=20
+
+ \subsection cub 4.6.2. CUB Reader
+
+CUBIT is a toolkit for generating tetrahedral and hexahedral finite elemen=
t meshes from solid model geometry [16]. This tool saves and restores data=
in a custom =E2=80=9C.cub=E2=80=9D file, which stores both mesh and geomet=
ry (and data relating the two). The CUB reader in MOAB can import and inte=
rpret much of the meta-data information saved in .cub files. Ref. [4] desc=
ribes the conventions used to store this meta-data in the MOAB data model. =
The information read from .cub files, and stored in the MOAB data model, i=
ncludes:
+
+- Geometric model entities and topology
+- Model entity names and ids
+- Groups, element blocks, nodesets, and sidesets, including model entities=
stored in them
+- Mesh scheme and interval size information assigned to model entities
+.
+
+Note that although information about model entities is recovered, MOAB by =
default does not depend on a solid modeling engine; this information is sto=
red in the form of entity sets and parent/child relations between them. Se=
e Ref. [4] for more information.
+
+ \ref contents
+
+ \subsection cgm 4.6.3. CGM Reader
+
+The Common Geometry Module (CGM) [17] is a library for representing solid =
model and other types of solid geometry data. The CUBIT mesh generation to=
olkit uses CGM for its geometric modeling support, and CGM can restore geom=
etric models in the exact state in which they were represented in CUBIT. M=
OAB contains a CGM reader, which can be enabled with a configure option. U=
sing this reader, MOAB can read geometric models, and represent their model=
topology using entity sets linked by parent/child relations. The mesh in =
these models comes directly from the modeling engine faceting routines; the=
se are the same facets used to visualize solid models in other graphics eng=
ines. When used in conjunction with the VisIt visualization tool (see Sect=
ion ), this provides a solution for visualizing geometric models. Xxx sho=
ws a model imported using MOAB=E2=80=99s CGM reader and visualized with Vis=
It.=20
+
+ \ref contents
+
+ \section parallel 5. Parallel Mesh Representation and Query
+
+A parallel mesh representation must strike a careful balance between provi=
ding an interface to mesh similar to that of a serial mesh, while also allo=
wing the discovery of parallel aspects of the mesh and performance of paral=
lel mesh-based operations efficiently. MOAB supports a spatial domain-deco=
mposed view of a parallel mesh, where each subdomain is assigned to a proce=
ssor, lower-dimensional entities on interfaces between subdomains are share=
d between processors, and ghost entities can be exchanged with neighboring =
processors. Locally, each subdomain, along with any locally-represented gh=
ost entities, are accessed through a local MOAB instance. Parallel aspects=
of the mesh, e.g. whether entities are shared, on an interface, or ghost e=
ntities, are embedded in the same data model (entities, sets, tags, interfa=
ce) used in the rest of MOAB. MOAB provides a suite of parallel functions =
for initializing and communicating with a parallel mesh, along with functio=
ns to query the parallel aspects of the mesh.
+
+ \ref contents
+
+ \subsection fiveone 5.1. Nomenclature & Representation
+
+Before discussing how to access parallel aspects of a mesh, several terms =
need to be defined: =20
+
+<B>Shared entity:</B> An entity shared by one or several other processors.
+
+<B>Multi-shared entity:</B> An entity shared by more than two processors.
+
+<B>Owning Processor:</B> Each shared entity is owned by exactly one proces=
sor. This processor has the right to set tag values on the entity and have=
those values propagated to any sharing processors. =20
+
+<B>Part:</B> The collection of entities assigned to a given processor. Wh=
en reading mesh in parallel, the entities in a Part, along with any lower-d=
imensional entities adjacent to those, will be read onto the assigned proce=
ssor.
+
+<B>Partition:</B> A collection of Parts which take part in parallel collec=
tive communication, usually associated with an MPI communicator.
+
+<B>Interface:</B> A collection of mesh entities bounding entities in multi=
ple parts. Interface entities are owned by a single processor, but are rep=
resented on all parts/processors they bound.
+
+<B>Ghost entity:</B> A shared, non-interface, non-owned entity.
+
+<B>Parallel status:</B> A characteristic of entities and sets represented =
in parallel. The parallel status, or =E2=80=9Cpstatus=E2=80=9D, is represen=
ted by a bit field stored in an unsigned character, with bit values as desc=
ribed in Table 4.
+
+ \subsection tablefour Table 4: Bits representing various parallel charac=
teristics of a mesh. Also listed are enumerated values that can be used in=
bitmask expressions; these enumerated variables are declared in MBParallel=
Conventions.h.
+
+<table border=3D"1">
+<tr>
+<th>Bit</th>
+<th>Name</th>
+<th>Represents</th>
+</tr>
+<tr>
+<td>0x1</td>
+<td>PSTATUS_NOT_OWNED</td>
+<td>Not owned by the local processor</td>
+</tr>
+<tr>
+<td>0x2</td>
+<td>PSTATUS_SHARED</td>
+<td>Shared by exactly two processorstd>
+</tr>
+<tr>
+<td>0x4</td>
+<td>PSTATUS_MULTISHARED</td>
+<td>Shared by three or more processors</td>
+</tr>
+<tr>
+<td>0x8</td>
+<td>PSTATUS_INTERFACE</td>
+<td>Part of lower-dimensional interface shared by multiple processors</td>
+</tr>
+<tr>
+<td>0x10</td>
+<td>PSTATUS_GHOST</td>
+<td>Non-owned, non-interface entities represented locally</td>
+</tr>
+</table>
+
+Parallel functionality is described in the following sections. First, met=
hods to load a mesh into a parallel representation are described; next, fun=
ctions for accessing parallel aspects of a mesh are described; functions fo=
r communicating mesh and tag data are described.
+
+ \ref contents
+
+ \subsection fivetwo 5.2. Parallel Mesh Initialization
+
+Parallel mesh is initialized in MOAB in several steps:
+
+-# Establish a local mesh on each processor, either by reading the mesh i=
nto that representation from disk, or by creating mesh locally through the =
normal MOAB interface. =20
+-# Find vertices, then other entities, shared between processors, based o=
n a globally-consistent vertex numbering stored on the GLOBAL_ID tag. =20
+-# Exchange ghost or halo elements within a certain depth of processor in=
terfaces with neighboring processors. =20
+.
+
+These steps can be executed by a single call to MOAB=E2=80=99s load_file f=
unction, using the procedure described in Section 5.2.1. Or, they can be e=
xecuted in smaller increments calling specific functions in MOAB=E2=80=99s =
ParallelComm class, as described in Section 5.2.2. Closely related to the =
latter method is the handling of communicators, described in more detail in=
Section.
+
+ \ref contents
+
+ \subsection initialization 5.2.1. Parallel Mesh Initialization by Loadin=
g a File
+
+In the file reading approach, a mesh must contain some definition of the p=
artition (the assignment of mesh, usually regions, to processors). Partiti=
ons can be derived from other set structures already on the mesh, or can be=
computed explicitly for that purpose by tools like mbzoltan (see Section 4=
.2). For example, geometric volumes used to generate the mesh, and region-=
based material type assignments, are both acceptable partitions (see Ref. [=
4] for information about this and other meta-data often accompanying mesh).=
In addition to defining the groupings of regions into parts, the assignme=
nt of specific parts to processors can be done implicitly or using addition=
al data stored with the partition.
+
+MOAB implements several specific methods for loading mesh into a parallel =
representation:
+
+- READ_PART: each processor reads only the mesh used by its part(s).
+
+- READ_DELETE: each processor reads the entire mesh, then deletes the mesh=
not used by its part(s).
+
+- BCAST_DELETE: the root processor reads and broadcasts the mesh; each pro=
cessor then deletes the mesh not used by its part(s).
+
+The READ_DELETE and BCAST_DELETE methods are supported for all file types =
MOAB is able to read, while READ_PART is only implemented for MOAB=E2=80=99=
s native HDF5-based file format.
+
+Various other options control the selection of part sets or other details =
of the parallel read process. For example, the application can specify the=
tags, and optionally tag values, which identify parts, and whether those p=
arts should be distributed according to tag value or using round-robin assi=
gnment.
+
+The options used to specify loading method, the data used to identify part=
s, and other parameters controlling the parallel read process, are shown in=
Table 5. =20
+ \subsection tablefive Table 5: Options passed to MOAB=E2=80=99s load_fil=
e function identifying the partition and other parameters controlling the p=
arallel read of mesh data. Options and values should appear in option stri=
ng as =E2=80=9Coption=3Dval=E2=80=9D, with a delimiter (usually =E2=80=9C;=
=E2=80=9D) between options.
+
+<table border=3D"1">
+<tr>
+<th>Option</th>
+<th>Value</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>PARTITION</td>
+<td><tag_name></td>
+<td>Sets with the specified tag name should be used as part sets</td>
+</tr>
+<tr>
+<td>PARTITION_VAL</td>
+<td><val1, val2-val3, ...></td>
+<td>Integer values to be combined with tag name, with ranges input using v=
al1, val2-val3. Not meaningful unless PARTITION option is also given.</td>
+</tr>
+<tr>
+<td>PARTITION_DISTRIBUTE</td>
+<td>(none)</td>
+<td>If present, or values are not input using PARTITION_VAL, sets with tag=
indicated in PARTITION option are partitioned across processors in round-r=
obin fashion.</td>
+</tr>
+<tr>
+<td>PARALLEL_RESOLVE_SHARED_ENTS</td>
+<td><pd.sd></td>
+<td>Resolve entities shared between processors, where partition is made up=
of pd- dimensional entities, and entities of dimension sd and lower should=
be resolved.</td>
+</tr>
+<tr>
+<td>PARALLEL_GHOSTS</td>
+<td><gd.bd.nl[.ad]></td>
+<td>Exchange ghost elements at shared inter-processor interfaces. Ghost e=
lements of dimension gd will be exchanged. Ghost elements are chosen going=
through bd-dimensional interface entities. Number of layers of ghost elem=
ents is specified in nl. If ad is present, lower-dimensional entities boun=
ding exchanged ghost entities will also be exchanged; allowed values for ad=
are 1 (exchange bounding edges), 2 (faces), or 3 (edges and faces).</td>
+</tr>
+<tr>
+<td>CPUTIME</td>
+<td>(none)</td>
+<td>Print cpu time required for each step of parallel read & initializatio=
n.</td>
+</tr>
+<tr>
+<td>MPI_IO_RANK</td>
+<td><r></td>
+<td>If read method requires reading mesh onto a single processor, processo=
r with rank r is used to do that read.</td>
+</tr>
+</table>
+
+Several example option strings controlling parallel reading and initializa=
tion are:
+
+<B>=E2=80=9CPARALLEL=3DREAD_DELETE; PARTITION=3DMATERIAL_SET; PARTITION_VA=
L=3D100, 200, 600-700=E2=80=9D:</B> The whole mesh is read by every process=
or; this processor keeps mesh in sets assigned the tag whose name is =E2=80=
=9CMATERIAL_SET=E2=80=9D and whose value is any one of 100, 200, and 600-70=
0 inclusive.
+
+<B>=E2=80=9CPARALLEL=3DREAD_PART; PARTITION=3DPARALLEL_PARTITION, PARTITIO=
N_VAL=3D2=E2=80=9D:</B> Each processor reads only its mesh; this processor,=
whose rank is 2, is responsible for elements in a set with the PARALLEL_PA=
RTITION tag whose value is 2. This would by typical input for a mesh which=
had already been partitioned with e.g. Zoltan or Parmetis.
+
+<B>=E2=80=9CPARALLEL=3DBCAST_DELETE; PARTITION=3DGEOM_DIMENSION, PARTITION=
_VAL=3D3, PARTITION_DISTRIBUTE=E2=80=9D:</B> The root processor reads the f=
ile and broadcasts the whole mesh to all processors. If a list is construc=
ted with entity sets whose GEOM_DIMENSION tag is 3, i.e. sets corresponding=
to geometric volumes in the original geometric model, this processor is re=
sponsible for all elements with index R+iP, i >=3D 0 (i.e. a round-robin di=
stribution).
+
+ \ref contents
+
+ \subsection functions 5.2.2. Parallel Mesh Initialization Using Functions
+
+After creating the local mesh on each processor, an application can call t=
he following functions in ParallelComm to establish information on shared m=
esh entities. See the [ref-directparmesh example] in the MOAB source tree =
for a complete example of how this is done from an application.
+
+- ParallelComm::resolve_shared_entities (collective): Resolves shared enti=
ties between processors, based on GLOBAL_ID tag values of vertices. Variou=
s forms are available, based on entities to be evaluated and maximum dimens=
ion for which entity sharing should be found.
+
+- ParallelComm::exchange_ghost_cells (collective): Exchange ghost entities=
with processors sharing an interface with this processor, based on specifi=
ed ghost dimension (dimension of ghost entities exchanged), bridge dimensio=
n, number of layers, and type of adjacencies to ghost entities. An entity =
is sent as a ghost if it is within that number of layers, across entities o=
f the bridge dimension, with entities owned by the receiving processor, or =
if it is a lower-dimensional entity adjacent to a ghost entity and that opt=
ion is requested.
+.
+
+ \ref contents
+
+ \subsection communicator 5.2.3. Communicator Handling
+
+The ParallelComm constructor takes arguments for an MPI communicator and a=
MOAB instance. The ParallelComm instance stores the MPI communicator, and=
registers itself with the MOAB instance. Applications can specify the Par=
allelComm index to be used for a given file operation, thereby specifying t=
he MPI communicator for that parallel operation. For example:
+
+\code
+using namespace moab;
+// pass a communicator to the constructor, getting back the index
+MPI_Comm my_mpicomm;
+int pcomm_index;
+ParallelComm my_pcomm(moab, my_mpicomm, &pcomm_index);
+
+// write the pcomm index into a string option
+char load_opt[32];
+sprintf(load_opt, "PARALLEL=3DBCAST_DELETE;PARALLEL_COMM=3D%d",=20
+ pcomm_index);
+
+// specify that option in a parallel read operation
+ErrorCode rval =3D moab->load_file(load_opt, fname, ...)
+\endcode
+
+In the above code fragment, the ParallelComm instance with index pcomm_ind=
ex will be used in the parallel file read, so that the operation executes o=
ver the specified MPI communicator. If no ParallelComm instance is specifi=
ed for a parallel file operation, a default instance will be defined, using=
MPI_COMM_WORLD.
+
+Applications needing to retrieve a ParallelComm instance created previousl=
y and stored with the MOAB instance, e.g. by a different code component, ca=
n do so using a static function on ParallelComm:
+
+\code
+ParallelComm *my_pcomm =3D ParallelComm::get_pcomm(moab, pcomm_index);
+\endcode
+
+ParallelComm also provides the ParallelComm::get_all_pcomm function, for r=
etrieving all ParallelComm instances stored with a MOAB instance. For synt=
ax and usage of this function, see the MOAB online documentation for Parall=
elComm.hpp [8].
+
+ \ref contents
+
+ \subsection fivethree 5.3. Parallel Mesh Query Functions
+
+Various functions are commonly used in parallel mesh-based applications. =
Functions marked as being collective must be called collectively for all pr=
ocessors that are members of the communicator associated with the ParallelC=
omm instance used for the call.
+
+<B>ParallelComm::get_pstatus:</B> Get the parallel status for the entity.
+
+<B>ParallelComm::get_pstatus_entities:</B> Get all entities whose pstatus =
satisfies (pstatus & val).
+
+<B>ParallelComm::get_owner:</B> Get the rank of the owning processor for t=
he specified entity.
+
+<B>ParallelComm::get_owner_handle:</B> Get the rank of the owning processo=
r for the specified entity, and the entity's handle on the owning processor.
+
+<B>ParallelComm::get_sharing_data:</B> Get the sharing processor(s) and ha=
ndle(s) for an entity or entities. Various overloaded versions are availab=
le, some with an optional =E2=80=9Coperation=E2=80=9D argument, where Inter=
face::INTERSECT or Interface::UNION can be specified. This is similar to t=
he operation arguments to Interface::get_adjacencies.
+
+<B>ParallelComm::get_shared_entities:</B> Get entities shared with the giv=
en processor, or with all processors. This function has optional arguments=
for specifying dimension, whether interface entities are requested, and wh=
ether to return just owned entities.
+
+<B>ParallelComm::get_interface_procs:</B> Return all processors with whom =
this processor shares an interface.
+
+<B>ParallelComm::get_comm_procs:</B> Return all processors with whom this =
processor communicates.
+
+ \ref contents
+
+ \subsection fivefour 5.4. Parallel Mesh Communication
+
+Once a parallel mesh has been initialized, applications can call the Paral=
lelComm::exchange_tags function for exchanging tag values between processor=
s. This function causes the owning processor to send the specified tag val=
ues for all shared, owned entities to other processors sharing those entiti=
es. Asynchronous communication is used to hide latency, and only point-to-=
point communication is used in these calls.
+
+ \ref contents
+
+ \section applications 6. Building MOAB-Based Applications
+
+There are two primary mechanisms supported by MOAB for building applicatio=
ns, one based on MOAB-defined make variables, and the other based on the us=
e of libtool and autoconf. Both assume the use of a =E2=80=9Cmake=E2=80=9D=
-based build system. =20
+
+The easiest way to incorporate MOAB into an application=E2=80=99s build pr=
ocess is to include the =E2=80=9Cmoab.make=E2=80=9D file into the applicati=
on=E2=80=99s Makefile, adding the make variables MOAB_INCLUDES and MOAB_LIB=
S_LINK to application=E2=80=99s compile and link commands, respectively. M=
OAB_INCLUDES contains compiler options specifying the location of MOAB incl=
ude files, and any preprocessor definitions required by MOAB. MOAB_LIBS_LI=
NK contains both the options telling where libraries can be found, and the =
link options which incorporate those libraries into the application. Any l=
ibraries depended on by the particular configuration of MOAB are included i=
n that definition, e.g. the HDF5 library. Using this method to incorporate=
MOAB is the most straightforward; for example, the following Makefile is u=
sed to build one of the example problems packaged with the MOAB source:
+\code
+include ${MOAB_LIB_DIR}/moab.make
+
+GetEntities : GetEntities.o
+ ${CXX} $< ${MOAB_LIBS_LINK} -o $@
+
+.cpp.o :=20
+ ${CXX} ${MOAB_INCLUDES} -c $<
+\endcode
+
+Here, the MOAB_LIB_DIR environment variable or make argument definition sp=
ecifies where the MOAB library is installed; this is also the location of t=
he moab.make file. Once that file has been included, MOAB_INCLUDES and MOA=
B_LIBS_LINK can be used, as shown.
+
+Other make variables are defined in the moab.make file which simplify buil=
ding applications:
+
+- MOAB_LIBDIR, MOAB_INCLUDEDIR: the directories into which MOAB libraries =
and include files will be installed, respectively. Note that some include =
files are put in a subdirectory named =E2=80=9Cmoab=E2=80=9D below that dir=
ectory, to reflect namespace naming conventions used in MOAB.
+
+- MOAB_CXXFLAGS, MOAB_CFLAGS, MOAB_LDFLAGS: Options passed to the C++ and =
C compilers and the linker, respectively.
+
+- MOAB_CXX, MOAB_CC, MOAB_FC: C++, C, and Fortran compilers specified to M=
OAB at configure time, respectively.
+.
+
+The second method for incorporating MOAB into an application=E2=80=99s bui=
ld system is to use autoconf and libtool. MOAB is configured using these t=
ools, and generates the =E2=80=9C.la=E2=80=9D files that hold information o=
n library dependencies that can be used in application build systems also b=
ased on autoconf and libtool. Further information on this subject is beyon=
d the scope of this User=E2=80=99s Guide; see the =E2=80=9C.la=E2=80=9D fil=
es as installed by MOAB, and contact the MOAB developer=E2=80=99s mailing l=
ist [6] for more details.
+
+ \ref contents
+
+ \section implementation 7. iMesh (ITAPS Mesh Interface) Implementation =
in MOAB
+
+iMesh is a common API to mesh data developed as part of the Interoperable =
Tools for Advanced Petascale Simulations (ITAPS) project [18]. Application=
s using the iMesh interface can operate on any implementation of that inter=
face, including MOAB. MOAB-based applications can take advantage of other =
services implemented on top of iMesh, including the MESQUITE mesh improveme=
nt toolkit [19] and the GRUMMP mesh improvement library [20].
+
+MOAB=E2=80=99s native interface is accessed through the Interface abstract=
C++ base class. Wrappers are not provided in other languages; rather, app=
lications wanting to access MOAB from those languages should do so through =
iMesh. In most cases, the data models and functionality available through =
MOAB and iMesh are identical. However, there are a few differences, subtle=
and not-so-subtle, between the two:
+
+<B>SPARSE tags used by default:</B> MOAB=E2=80=99s iMesh implementation cr=
eates SPARSE tags by default, because of semantic requirements of other tag=
-related functions in iMesh. To create DENSE tags through iMesh, use the i=
Mesh_createTagWithOptions extension function (see below).
+
+<B>Higher-order elements:</B> ITAPS currently handles higher-order element=
s (e.g. a 10-node tetrahedron) usi[21]<sup>5</sup>. As described in [sec-e=
ntities], MOAB supports higher-order entities by allowing various numbers o=
f vertices to define topological entities like quadrilateral or tetrahedron=
. Applications can specify flags to the connectivity and adjacency functio=
ns specifying whether corner or all vertices are requested.
+
+<B>Self-adjacencies:</B> In MOAB=E2=80=99s native interface, entities are =
always self-adjacent<sup>6</sup>; that is, adjacencies of equal dimension r=
equested from an entity will always include that entity, while from iMesh w=
ill not include that entity.
+
+<B>Option strings:</B> The iMesh specification requires that options in th=
e options string passed to various functions (e.g. iMesh_load) be prepended=
with the implementation name required to parse them, and delimited with sp=
aces. Thus, a MOAB-targeted option would appear as =E2=80=9Cmoab:PARALLEL=
=3DREAD_PART moab:PARTITION=3DMATERIAL_SET=E2=80=9D.
+
+To provide complete MOAB support from other languages through iMesh, a col=
lection of iMesh extension functions are also available. A general descrip=
tion of these extensions appears below; for a complete description, see the=
online documentation for iMesh-extensions.h [8].
+
+- Recursive get_entities functions: There are many cases where sets includ=
e other sets (see [4] for more information). MOAB provides iMesh_getEntiti=
esRec, and other recursive-supporting functions, to get all non-set entitie=
s of a given type or topology accessible from input set(s). Similar functi=
ons are available for number of entities of a given type/topology.
+
+- Get entities by tag, and optionally tag value: It is common to search fo=
r entities with a given tag, and possibly tag value(s); functions like iMes=
h_getEntitiesByTag are provided for this purpose.
+
+- Options to createTag: To provide more control over the tag type, the iMe=
sh_createTagWithOptions is provided. The storage type is controlled with t=
he =E2=80=9C
+
+- MBCNType: Canonical numbering evaluations are commonly needed by applica=
tions, e.g. to apply boundary conditions locally. The MBCN package provide=
s these evaluations in terms of entity types defined in MOAB [9]; the getMB=
CNType is required to translate between iMesh_Topology and MBCN type.
+
+- Iterator step: Step an iterator a specified number of entities; allows a=
dvancement of an iterator without needing to allocate memory to hold the en=
tity handles stepped over.
+
+- Direct access to tag storage: The Interface::tag_iterate function allows=
an application get a pointer to the memory used to store a given tag. For=
dense tags on contiguous ranges of entities, this provides more efficient =
access to tags. The iMesh functionn iMesh_tagIterate provides access to th=
is functionlity. See examples/TagIterateC.c and examples/TagIterateF.F for=
examples of how to use this from C and Fortran, respectively.=20
+.
+
+As required by the iMesh specification, MOAB generates the =E2=80=9CiMesh-=
Defs.inc=E2=80=9D file and installs it with the iMesh and MOAB libraries. =
This file defines make variables which can be used to build iMesh-based app=
lications. The method used here is quite similar to that used for MOAB its=
elf (see Section 6). In particular, the IMESH_INCLUDES and IMESH_LIBS make=
variables can be used with application compile and link commands, respecti=
vely, with other make variables similar to those provided in moab.make also=
available.
+
+Note that using the iMesh interface from Fortran-based applications requir=
es a compiler that supports Cray pointers, along with the pass-by-value (%V=
AL) extension. Almost all compilers support those extensions; however, if =
using the gcc series of compilers, you must use gfortran 4.3 or later.
+
+<sup>5</sup>There are currently no implementations of this interface.
+
+<sup>6</sup>iMesh and MOAB both define adjacencies using the topological c=
oncept of closure. Since the closure of an entity includes the entity itse=
lf, the d-dimensional entities on the closure of a given entity should incl=
ude the entity itself.
+
+ \ref contents
+
+ \section representation 8. Structured Mesh Representation
+
+A structured mesh is defined as a D-dimensional mesh whose interior vertic=
es have 2D connected edges. Structured mesh can be stored without connect=
ivity, if certain information is kept about the parametric space of each st=
ructured block of mesh. MOAB can represent structured mesh with implicit c=
onnectivity, saving approximately 57% of the storage cost compared to an un=
structured representation<sup>7</sup>. Since connectivity must be computed=
on the fly, these queries execute a bit slower than those for unstructured=
mesh. More information on the theory behind MOAB's structured mesh repres=
entation can be found in=20
+
+Currently, MOAB's structured mesh representation can only be used by creat=
ing structured mesh at runtime; that is, structured mesh is saved/restored =
in an unstructured format in MOAB's HDF5-based native save format. For mor=
e details on how to use MOAB's structured mesh representation, see the scds=
eq_test.cpp source file in the test/ directory.
+
+<sup>7</sup> This assumes vertex coordinates are represented explicitly, a=
nd that there are approximately the same number of vertices and hexahedra i=
n a structured hex mesh.
+
+ \ref contents
+
+ \section element 9. Spectral Element Meshes
+
+The Spectral Element Method (SEM) is a high-order method, using a polynomi=
al Legendre interpolation basis with Gauss-Lobatto quadrature points, in co=
ntrast to the Lagrange basis used in (linear) finite elements [20]. SEM ob=
tains exponential convergence with decreasing mesh characteristic sizes, an=
d codes implementing this method typically have high floating-point intensi=
ty, making the method highly efficient on modern CPUs. Most Nth-order SEM =
codes require tensor product cuboid (quad/hex) meshes, with each d-dimensio=
nal element containing (N+1)d degrees of freedom (DOFs). There are various=
methods for representing SEM meshes and solution fields on them; this docu=
ment discusses these methods and the tradeoffs between them. The mesh part=
s of this discussion are given in terms of the iMesh mesh interface and its=
implementation by the MOAB mesh library [21].
+
+The figure above shows a two-dimensional 3rd-order SEM mesh consisting of =
four quadrilaterals. For this mesh, each quadrilateral has (N+1)^2=3D16 DO=
Fs, with corner and edge degrees of freedom shared between neighboring quad=
rilaterals.
+
+ \ref contents
+
+ \subsection nineone 9.1. Representations
+
+There are various representations of this mesh in a mesh database like MOA=
B, depending on how DOFs are related to mesh entities and tags on those ent=
ities. We mention several possible representations:
+
+-# Corner vertices, element-based DOFs: Each quadrilateral is defined by f=
our vertices, ordered in CCW order typical of FE meshes. DOFs are stored a=
s tags on quadrilaterals, with size (N+1)^2 values, ordered lexicographical=
ly (i.e. as a 2D array tag(i,j) with i varying faster than j.) In the figu=
re above, the connectivity for face 1 would be (1, 4, 16, 13), and DOFs wou=
ld be ordered (1..16). Note that in this representation, tag values for DO=
Fs shared by neighboring elements must be set multiple times, since there a=
re as many copies of these DOFs as elements sharing them.
+-# High-order FE-like elements: Each DOF is represented by a mesh vertex. =
Quadrilaterals each have (N+1)^2 vertices, ordered as they would be for hig=
h-order finite elements (corner vertices first, then mid-edge and mid-face =
elements; see [22]). Mid -face, -edge, and -region vertices for a given ed=
ge/face/region would be ordered lexicographically, according to positive di=
rection in a corresponding reference element. In the figure above, the con=
nectivity array for face 1 would be (1, 4, 16, 13, 2, 3, 8, 12, 14, 15, 5, =
9, 6, 7, 10, 11). DOF values are stored as tags on vertices. Since DOFs a=
re uniquely associated with vertices and vertices are shared by neighboring=
elements, tag values only need to be set once. Full vertex-quadrilateral =
adjacencies are available, for all vertices.
+-# Linear FE-like elements, one vertex per DOF, array with DOF vertices: E=
ach quadrilateral is defined by four (corner) vertices, with additional ver=
tices representing mid-edge and mid-face DOFs. An additional =E2=80=9CDOF =
array=E2=80=9D tag is assigned to each quadrilateral, storing the array of =
vertices representing the (N+1)^2 DOFs for the quadrilateral, ordered lexic=
ographically. For the figure above, the connectivity array for face 1 woul=
d be (1, 4, 16, 13), and the DOF array would be (1..16), assuming that vert=
ex handles are integers as shown in the figure. DOF values are stored as t=
ags on vertices, and lexicographically-ordered arrays of DOFs can be retrie=
ved using the DOF array tag as input to the tag_get_data function in MOAB. =
Adjacency functions would only be meaningful for corner vertices, but tag =
values would only need to be set once per DOF.
+-# High-order FE-like elements, array with DOF vertices: This is a combina=
tion of options 2 and 3. The advantage would be full vertex-quad adjacency=
support and direct availability of lexicographically-ordered vertex arrays=
, at the expense of more memory.
+-# Convert to linear mesh: Since a spectral element is a cuboid with highe=
r-order vertices, it can always be converted to N^2 linear cuboids using th=
e high-order vertices as corners of the finer quads/hexes. This is how rea=
ders in ParaView and VisIt typically import spectral meshes (CAM-SE also ex=
ports connectivity in this form).
+
+As a convenience for applications, functions could also be provided for im=
portant tasks, like assembling the vertex handles for an entity in lexograp=
hic order (useful for option 2 above), and getting an array of tag values i=
n lexicographic order (for option 3 above).
+
+ \ref contents
+
+ \subsection ninetwo 9.2. Tradeoffs
+
+There are various competing tradeoffs in the various representation types.=
These include:
+
+- Adjacencies: being able to retrieve the element(s) using a given (corner=
or higher-order) vertex.
+- Connectivity list: being able to retrieve the connectivity of a given el=
ement, consisting of all (corner + higher-order) vertices in the element, u=
sually in lexicographical order. This is closely linked with being able to=
access the connectivity list as a const*, i.e. using the list straight fro=
m memory without needing to copy it.
+- Memory vs. time: There is a memory vs. execution time tradeoff between d=
uplicating interface vertex solution/tag variables in neighboring elements =
(more memory but more time-efficient and allows direct access to tag storag=
e by applications) versus using vertex-based tags (less memory but requires=
assembly of variables into lexicographically-ordered arrays, and prevents =
direct access from applications).
+.
+
+The lower-memory option (storing variables on vertices and assembling into=
lexicographically-ordered arrays for application use) usually ends up cost=
ing more in memory anyway, since applications must allocate their own stora=
ge for these arrays. On the other hand, certain applications will always c=
hoose to do that, instead of sharing storage with MOAB for these variables.=
In the case where applications do share memory with MOAB, other tools wou=
ld need to interpret the lexicographically-ordered field arrays specially, =
instead of simply treating the vertex tags as a point-based field.
+
+ \ref contents
+
+ \subsection ninethree 9.3. MOAB Representation
+In choosing the right MOAB representation for spectral meshes, we are tryi=
ng to balance a) minimal memory usage, b) access to properly-ordered and -a=
ligned tag storage, and c) maximal compatibility with tools likely to use M=
OAB. The solution we propose is to use a representation most like option 2=
) above, with a few optional behaviors based on application requirements. =20
+
+In brief, we propose to represent elements using the linear, FE-ordered co=
nnectivity list (containing only corner vertices from the spectral element)=
, with field variables written to either vertices, lexicographically-ordere=
d arrays on elements, or both, and with a lexicographically-ordered array (=
stored on tag SPECTRAL_VERTICES) of all (corner+higher-order) vertices stor=
ed on elements. In the either/or case, the choice will be evident from the=
tag size and the entities on which the tag is set. In the both case, the =
tag name will have a =E2=80=9C-LEX=E2=80=9D suffix for the element tags, an=
d the size of the element tag will be (N+1)^2 times that of the vertex-base=
d tag. Finally, the file set containing the spectral elements (or the root=
set, if no file set was input to the read) will contain a =E2=80=9CSPECTRA=
L_ORDER=E2=80=9D tag whose value is N. These conventions are described in =
the =E2=80=9CMetadata Information=E2=80=9D document distributed with the MO=
AB source code.
+
+ \ref contents
+
+ \section performance 10. Performance and Using MOAB Efficiently from App=
lications
+
+MOAB is designed to operate efficiently on groups of entities and for larg=
e meshes. Applications will be most efficient when they operate on entitie=
s in groups, especially groups which are close in their order of creation. =
The MOAB API is structured to encourage operations on groups of entities. =
Conversely, MOAB will not perform as well as other libraries if there are =
frequent deletion and creation of entities. For those types of application=
s, a mesh library using a C++ object-based representation is more appropria=
te. In this section, performance of MOAB when executing a variety of tasks=
is described, and compared to that of other representations. Of course, t=
hese metrics are based on the particular models and environments where they=
are run, and may or may not be representative of other application types.
+
+One useful measure of MOAB performance is in the representation and query =
of a large mesh. MOAB includes a performance test, located in the test/per=
f directory, in which a single rectangular region of hexahedral elements is=
created then queried; the following steps are performed:
+
+- Create the vertices and hexes in the mesh
+- For each vertex, get the set of connected hexahedra
+- For each hex, get the connected vertices, their coordinates, average the=
m, and assign them as a tag on the hexes
+.
+
+This test can be run on your system to determine the runtime and memory pe=
rformance for these queries in MOAB.
+
+ \ref contents
+
+ \section conclusions 11. Conclusions and Future Plans
+
+MOAB, a Mesh-Oriented datABase, provides a simple but powerful data abstra=
ction to structured and unstructured mesh, and makes that abstraction avail=
able through a function API. MOAB provides the mesh representation for the=
VERDE mesh verification tool, which demonstrates some of the powerful mesh=
metadata representation capabilities in MOAB. MOAB includes modules that =
import mesh in the ExodusII, CUBIT .cub and Vtk file formats, as well as th=
e capability to write mesh to ExodusII, all without licensing restrictions =
normally found in ExodusII-based applications. MOAB also has the capabilit=
y to represent and query structured mesh in a way that optimizes storage sp=
ace using the parametric space of a structured mesh; see Ref. [17] for deta=
ils.
+
+Initial results have demonstrated that the data abstraction provided by MO=
AB is powerful enough to represent many different kinds of mesh data found =
in real applications, including geometric topology groupings and relations,=
boundary condition groupings, and inter-processor interface representation=
. Our future plans are to further explore how these abstractions can be us=
ed in the design through analysis process.
+
+ \ref contents
+
+ \section references 12. References
+
+[1] M. Fatenejad and G.A. Moses, =E2=80=9CCooper radiation hydrodynamics c=
ode..=E2=80=9D
+
+[2] T.J. Tautges and A. Caceres, =E2=80=9CScalable parallel solution coupl=
ing for multiphysics reactor simulation,=E2=80=9D Journal of Physics: Confe=
rence Series, vol. 180, 2009.
+
+[3] T.J. Tautges, MOAB Meta-Data Information, 2010.
+
+[4] T.J. Tautges, =E2=80=9CMOAB - ITAPS =E2=80=93 Trac.=E2=80=9D, http://t=
rac.mcs.anl.gov/projects/ITAPS/wiki/MOAB
+
+[5] =E2=80=9CMOAB Developers Email List.=E2=80=9D, moab-dev at mcs.anl.gov.
+
+[6] =E2=80=9CMOAB Users Email List.=E2=80=9D, moab at mcs.anl.gov.
+
+[7] =E2=80=9CMOAB online documentation.=E2=80=9D, http://gnep.mcs.anl.gov:=
8010/moab-docs/
+
+[8] T.J. Tautges, =E2=80=9CCanonical numbering systems for finite-element =
codes,=E2=80=9D Communications in Numerical Methods in Engineering, vol. O=
nline, Mar. 2009.
+
+[9] L.A. Schoof and V.R. Yarberry, EXODUS II: A Finite Element Data Model,=
Albuquerque, NM: Sandia National Laboratories, 1994.
+
+[10] M. PATRAN, =E2=80=9CPATRAN User=E2=80=99s Manual,=E2=80=9D 2005.
+
+[11] VisIt User's Guide.
+
+[12] K. Devine, E. Boman, R. Heaphy, B. Hendrickson, and C. Vaughan, =E2=
=80=9CZoltan Data Management Services for Parallel Dynamic Applications,=E2=
=80=9D Computing in Science and Engineering, vol. 4, 2002, pp. 90=E2=80=93=
97.
+
+[13] T.J. Tautges, P.P.H. Wilson, J. Kraftcheck, B.F. Smith, and D.L. Hend=
erson, =E2=80=9CAcceleration Techniques for Direct Use of CAD-Based Geomet=
ries in Monte Carlo Radiation Transport,=E2=80=9D International Conference =
on Mathematics, Computational Methods & Reactor Physics (M&C 2009), Sarato=
ga Springs, NY: American Nuclear Society, 2009.
+
+[14] H. Kim and T. Tautges, =E2=80=9CEBMesh: An Embedded Boundary Meshing =
Tool,=E2=80=9D in preparation.
+
+[15] G.D. Sjaardema, T.J. Tautges, T.J. Wilson, S.J. Owen, T.D. Blacker, W=
.J. Bohnhoff, T.L. Edwards, J.R. Hipp, R.R. Lober, and S.A. Mitchell, CUBIT=
mesh generation environment Volume 1: Users manual, Sandia National Labora=
tories, May 1994, 1994.
+
+[16] T.J. Tautges, =E2=80=9CCGM: A geometry interface for mesh generation,=
analysis and other applications,=E2=80=9D Engineering with Computers, vol=
. 17, 2001, pp. 299-314.
+
+[17] T. J. Tautges, MOAB-SD: Integrated structured and unstructured mesh r=
epresentation, Engineering with Computers, vol. 20, no. 3, pp. 286-293, 200=
4.
+
+[18] =E2=80=9CInteroperable Technologies for Advanced Petascale Simulation=
s (ITAPS),=E2=80=9D Interoperable Technologies for Advanced Petascale Simul=
ations (ITAPS).
+
+[19] P. Knupp, =E2=80=9CMesh quality improvement for SciDAC applications,=
=E2=80=9D Journal of Physics: Conference Series, vol. 46, 2006, pp. 458-46=
2.
+
+[20] M. O. Deville, P. F. Fischer, and E. H. Mund, High-order methods for =
incompressible fluid flow. Cambridge, UK; New York: Cambridge University Pr=
ess, 2002.
+
+[21] T. J. Tautges, =E2=80=9CMOAB Wiki.=E2=80=9D [Online]. Available: http=
://trac.mcs.anl.gov/projects/ITAPS/wiki/MOAB. [Accessed: 30-Oct-2012].
+
+[22] T. J. Tautges, =E2=80=9CCanonical numbering systems for finite-elemen=
t codes,=E2=80=9D International Journal for Numerical Methods in Biomedical=
Engineering, vol. 26, no. 12, pp. 1559=E2=80=931572, 2010.
+
+
+ \ref contents
+
+ \page differences Differences Between iMesh and MOAB
+
+ The data models used in MOAB and iMesh are quite similar, but not identi=
cal.The most significant differences are the following:
+
+- Tags: MOAB differentiates between DENSE, SPARSE, and BIT tags, using dif=
ferent storage models for each, while iMesh uses a single tag concept. iMe=
sh allows application to query whether an entity has been given a tag of a =
specified type; this query is incompatible with the concept of a DENSE tag =
with a default value. Thus, MOAB=E2=80=99s iMesh implementation creates SP=
ARSE tags by default, and tags created and accessed through this interface =
will use more memory than DENSE tags created through MOAB=E2=80=99s native =
interface. To mitigate this problem, MOAB implements an extension of the i=
Mesh_createTag function which allows specification of the tag type (DENSE, =
SPARSE, etc.) to be created. See later in this section for more informatio=
n.
+
+- Higher-order nodes: ITAPS currently handles higher-order elements (e.g. =
a 10-node tetrahedron) using a special =E2=80=9CShape=E2=80=9D interface. =
In this interface, higher-order nodes are only accessible through the AEnti=
ties which they resolve. MOAB=E2=80=99s iMesh implementation provides acce=
ss to higher-order nodes in the same manner described in Section , by vary=
ing the number of vertices defining each entity. As a result, if higher-or=
der entities are used in a model, the functions returning connectivity and =
vertex adjacencies always return all vertices, rather than providing an opt=
ion to return just corner vertices.
+
+- Self-adjacencies: iMesh specifies that entities are not self-adjacent; t=
hat is, requesting adjacencies of the same dimension/type results in an err=
or. MOAB does not consider this an error, returning the entity itself.
+
+- Adjacency table and AEntities: iMesh uses the concept of an =E2=80=9Cadj=
acency table=E2=80=9D to determine which AEntities are available and create=
d by default. MOAB uses input arguments to the get_adjacencies functions t=
o control whether AEntities are created. These flags provide finer-grained=
control over AEntities, but make it slightly less convenient to ensure tha=
t AEntities of a given dimension are always created.
+.
+
+ \page figures List of Figures
+=20
+ This page is intended to be empty.
+=20
+ \page tables List of Tables
+=20
+ \ref tableone
+
+ \ref tabletwo
+
+ \ref tablethree
+
+ \ref tablefour
+
+ \ref tablefive
+=20
+ \page building Building & Installing
+=20
+ MOAB uses an autoconf and libtool-based build process by default. The p=
rocedure used to build MOAB from scratch depends on whether the source code=
was obtained from a =E2=80=9Ctarball=E2=80=9D or directly from the Subvers=
ion repository. Assuming the latter, the following steps should be execute=
d for building and installing MOAB:
+ - Locate and build any required dependencies. MOAB can be built with no=
dependencies on other libraries; this may be useful for applications only =
needing basic mesh representation and not needing to export mesh to formats=
implemented in other libraries. MOAB=E2=80=99s native save/restore capabi=
lity is built on HDF5-based files; applications needing to save and restore=
files from MOAB reliably should use this library. MOAB also uses ExodusII=
, a netCDF-based file format developed at Sandia National Laboratories [10]=
. Applications needing to execute these tests should also build netCDF. N=
ote that MOAB uses netCDF=E2=80=99s C++ interface, which is not enabled by =
default in netCDF but can be enabled using the =E2=80=9C=E2=80=93enable-cxx=
=E2=80=9D option to netCDF=E2=80=99s configure script.
+ - Unpack source code into <moab>, and change current working directory t=
o that location.
+ - Execute =E2=80=9Cautoreconf =E2=80=93fi=E2=80=9D.
+ - Run configure script, by executing =E2=80=9C./configure <options>=E2=
=80=9D. Recommended options:
+ -# =E2=80=93prefix=3D<install_dir>: directory below which MOAB libr=
ary and include files will be installed; can either be the directory used f=
or MOAB source (<moab> from step 1), or a different directory.
+ -# =E2=80=93hdf5-dir=3D<hdf5_dir>: directory whose =E2=80=9Cinclude=
=E2=80=9D and =E2=80=9Clib=E2=80=9D subdirectories hold HDF5 include and li=
brary, respectively. MOAB uses HDF5 for its native save/restore format (se=
e Section 4.6.1).
+ -# =E2=80=93netcdf-dir=3D: directory whose =E2=80=9Cinclude=E2=80=
=9D and =E2=80=9Clib=E2=80=9D subdirectories hold netCDF include and librar=
y, respectively. MOAB uses netCDF-based files for many of its build tests.=
If the location of netCDF cannot be found, MOAB=E2=80=99s build tests wil=
l not function properly, but MOAB will still be usable.
+ .
+ - Run =E2=80=9Cmake check=E2=80=9D; this runs a series of build tests, t=
o verify that the MOAB build was successful. Note this check will fail if =
netCDF is not used, but MOAB itself will still be usable from applications.
+ - Run =E2=80=9Cmake install=E2=80=9D; this copies include files and libr=
aries to subdirectories of the directory specified in the =E2=80=9Cprefix=
=E2=80=9D option.
+ .
+
+These steps are sufficient for building MOAB against HDF5 and netCDF. By =
default, a small number of standard MOAB-based applications are also built,=
including mbconvert (a utility for reading and writing files), mbsize (for=
querying basic information about a mesh), and the iMesh interface (see Sec=
tion 7). Other utilities can be enabled using various other options to the=
configure script; for a complete list of build options, execute =E2=80=9C.=
/configure =E2=80=93help=E2=80=9D.
+=20
+ */
+
diff --git a/doc/user.dox.in b/doc/user.dox.in
index 4fed19e..ed65208 100644
--- a/doc/user.dox.in
+++ b/doc/user.dox.in
@@ -305,7 +305,9 @@ WARN_LOGFILE =3D
# with spaces.
=20
INPUT =3D @top_srcdir@/src @top_srcdir@/src/moab \
- @top_srcdir@/src/parallel/moab \
+ @top_srcdir@/doc/UG/moabUG.h \
+ @top_srcdir@/doc/DG \
+ @top_srcdir@/src/parallel/moab \
@top_srcdir@/src/MBTagConventions.hpp \
@top_srcdir@/src/MBCN.h \
@top_srcdir@/src/MBEntityType.h \
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dc89d66..38b4130 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -38,6 +38,7 @@
ScdVertexData.cpp
SequenceData.cpp
SequenceManager.cpp
+ SetIterator.cpp
Skinner.cpp
SparseTag.cpp
StructuredElementSeq.cpp
@@ -46,6 +47,7 @@
SweptVertexData.cpp
SysUtil.cpp
TagInfo.cpp
+ Types.cpp
TypeSequenceManager.cpp
UnstructuredElemSeq.cpp
Util.cpp
@@ -53,7 +55,6 @@
VarLenSparseTag.cpp
VertexSequence.cpp
WriteUtil.cpp
- moab_mpe.c
)
include_directories(
${MOAB_SOURCE_DIR}/src
diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
index e2b18bb..8084640 100644
--- a/src/ScdInterface.cpp
+++ b/src/ScdInterface.cpp
@@ -7,12 +7,12 @@
#include "ScdVertexData.hpp"
#ifdef USE_MPI
# include "moab/ParallelComm.hpp"
+# include "moab/TupleList.hpp"
+# include "moab/gs.hpp"
#endif
#include "assert.h"
#include <iostream>
#include <functional>
-#include "moab/TupleList.hpp"
-#include "moab/gs.hpp"
=20
#define ERRORR(rval, str) {if (MB_SUCCESS !=3D rval) \
{std::cerr << str; return rval; }}
diff --git a/src/Skinner.cpp b/src/Skinner.cpp
index fb80e58..1d284b7 100644
--- a/src/Skinner.cpp
+++ b/src/Skinner.cpp
@@ -1510,6 +1510,34 @@ ErrorCode Skinner::create_side( EntityHandle elem,
rval =3D thisMB->get_connectivity( elem, conn, len, false, &storage );
if (MB_SUCCESS !=3D rval) return rval;
=20
+ // treat separately MBPOLYGON; we want to create the edge in the
+ // forward sense always ; so figure out the sense first, then get out
+ if (MBPOLYGON=3D=3Dtype && 1=3D=3Dd && MBEDGE=3D=3Dside_type)
+ {
+ // first find the first vertex in the conn list
+ int i=3D0;
+ for (i=3D0; i<len; i++)
+ {
+ if (conn[i]=3D=3Dside_conn[0])
+ break;
+ }
+ if (len =3D=3D i)
+ return MB_FAILURE; // not found, big error
+ int prevIndex =3D (i+len-1)%len;
+ int nextIndex =3D (i+1)%len;
+ EntityHandle conn2[2] =3D {side_conn[0], side_conn[1]};
+ if (conn[prevIndex]=3D=3Dside_conn[1])
+ {
+ // reverse, so the edge will be forward
+ conn2[0]=3Dside_conn[1];
+ conn2[1]=3Dside_conn[0];
+ }
+ else if ( conn[nextIndex]!=3Dside_conn[1])
+ return MB_FAILURE; // it is not adjacent to the polygon
+
+ return thisMB->create_element( MBEDGE, conn2, 2, side_elem );
+
+ }
// Find which side we are creating and get indices of all nodes
// (including higher-order, if any.)
CN::SideNumber( type, conn, side_conn, ncorner, d, side, sense, offset );
diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt
index f83eb4f..d6c3e44 100644
--- a/src/io/CMakeLists.txt
+++ b/src/io/CMakeLists.txt
@@ -12,7 +12,9 @@
ReadSmf.cpp
ReadSms.cpp
ReadSTL.cpp
+ ReadTemplate.cpp
ReadTetGen.cpp
+ ReadTxt.cpp
ReadVtk.cpp
SMF_State.cpp
Tqdcfr.cpp
diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index c225841..146227c 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -147,7 +147,7 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
#ifdef USE_MPI
for (int i =3D 0; i < 6; i++)
parData.gDims[i] =3D gDims[i];
- for (int i =3D 0; i < 3; i++)
+ for (int i =3D 0; i < 2; i++)
parData.gPeriodic[i] =3D globallyPeriodic[i];
parData.partMethod =3D partMethod;
int pdims[3];
diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index cdc4392..9141938 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -158,7 +158,7 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
#ifdef USE_MPI
for (int i =3D 0; i < 6; i++)
parData.gDims[i] =3D gDims[i];
- for (int i =3D 0; i < 3; i++)
+ for (int i =3D 0; i < 2; i++)
parData.gPeriodic[i] =3D globallyPeriodic[i];
parData.partMethod =3D partMethod;
int pdims[3];
diff --git a/src/moab/Interface.hpp b/src/moab/Interface.hpp
index 030b9d1..d7ad8aa 100644
--- a/src/moab/Interface.hpp
+++ b/src/moab/Interface.hpp
@@ -22,8 +22,8 @@
* together to describe geometric topology, boundary condition, and inter-=
processor interface=20
* groupings in a mesh.
*
- * MOAB's API is documented in the moab::Interface class. The User's Guid=
e is located in
- * doc/MOABv4-UG.doc in MOAB's source tree. Questions and comments should=
be sent to moab-dev=20
+ * MOAB's API is documented in the moab::Interface class. The User's Guid=
e and Developer's Guide are located in
+ * <a href=3D"pages.html">related pages</a>. Questions and comments shoul=
d be sent to moab-dev=20
* _at_ mcs.anl.gov.
*/
=20
diff --git a/test/parallel/par_intx_sph.cpp b/test/parallel/par_intx_sph.cpp
index de30f8b..bf5cbb8 100644
--- a/test/parallel/par_intx_sph.cpp
+++ b/test/parallel/par_intx_sph.cpp
@@ -42,9 +42,12 @@ using namespace moab;
// some input data
double EPS1=3D0.2; // this is for box error
std::string input_mesh_file("Homme_2pt.h5m"); // input file, partitioned c=
orrectly
+std::string mpas_file("mpas_p8.h5m");
double CubeSide =3D 6.; // the above file starts with cube side 6; radius =
depends on cube side
+double radius;
void test_intx_in_parallel();
void test_intx_in_parallel_elem_based();
+void test_intx_mpas();
=20
int main(int argc, char **argv)
{
@@ -73,7 +76,10 @@ int main(int argc, char **argv)
}
}
//result +=3D RUN_TEST(test_intx_in_parallel);
+ radius =3D CubeSide/2*sqrt(3.);
result +=3D RUN_TEST(test_intx_in_parallel_elem_based);
+ radius =3D1.;
+ result +=3D RUN_TEST(test_intx_mpas);
=20
MPI_Finalize();
return result;
@@ -92,9 +98,9 @@ ErrorCode manufacture_lagrange_mesh_on_sphere(Interface =
* mb, EntityHandle eule
* circumscribed sphere radius
* radius =3D length * math.sqrt(3) /2
*/
- double radius =3D CubeSide/2*sqrt(3.);// our value depends on cube side
+ //radius =3D CubeSide/2*sqrt(3.);// our value depends on cube side
Range quads;
- rval =3D mb->get_entities_by_type(euler_set, MBQUAD, quads);
+ rval =3D mb->get_entities_by_dimension(euler_set, 2, quads);
CHECK_ERR(rval);
=20
Range connecVerts;
@@ -177,10 +183,10 @@ void test_intx_in_parallel()
=20
Intx2MeshOnSphere worker(&mb);
=20
- double radius=3D CubeSide/2 * sqrt(3.) ; // input
+ //double radius=3D CubeSide/2 * sqrt(3.) ; // input
worker.SetRadius(radius);
worker.set_box_error(EPS1);//
- worker.SetEntityType(MBQUAD);
+ //worker.SetEntityType(MBQUAD);
=20
worker.SetErrorTolerance(radius*1.e-8);
worker.locate_departure_points(euler_set);
@@ -244,10 +250,10 @@ void test_intx_in_parallel_elem_based()
=20
Intx2MeshOnSphere worker(&mb);
=20
- double radius=3D CubeSide/2 * sqrt(3.) ; // input
+ //double radius=3D CubeSide/2 * sqrt(3.) ; // input
worker.SetRadius(radius);
worker.set_box_error(EPS1);//
- worker.SetEntityType(MBQUAD);
+ //worker.SetEntityType(MBQUAD);
=20
worker.SetErrorTolerance(radius*1.e-8);
std::cout << "error tolerance epsilon_1=3D"<< radius*1.e-8 << "\n";
@@ -282,3 +288,79 @@ void test_intx_in_parallel_elem_based()
" intersection area:" << intx_area << " rel error: " << fabs((intx_=
area-arrival_area)/arrival_area) << "\n";
CHECK_ERR(rval);
}
+
+void test_intx_mpas()
+{
+ std::string opts =3D std::string("PARALLEL=3DREAD_PART;PARTITION=3DPARAL=
LEL_PARTITION")+
+ std::string(";PARALLEL_RESOLVE_SHARED_ENTS");
+ Core moab;
+ Interface & mb =3D moab;
+ EntityHandle euler_set;
+ ErrorCode rval;
+ rval =3D mb.create_meshset(MESHSET_SET, euler_set);
+ CHECK_ERR(rval);
+ std::string example(TestDir + "/" + mpas_file);
+
+ rval =3D mb.load_file(example.c_str(), &euler_set, opts.c_str());
+
+ ParallelComm* pcomm =3D ParallelComm::get_pcomm(&mb, 0);
+ CHECK_ERR(rval);
+
+ rval =3D pcomm->check_all_shared_handles();
+ CHECK_ERR(rval);
+
+ // everybody will get a DP tag, including the non owned entities; so exc=
hange tags is not required for LOC (here)
+ rval =3D manufacture_lagrange_mesh_on_sphere(&mb, euler_set);
+ CHECK_ERR(rval);
+
+ int rank =3D pcomm->proc_config().proc_rank();
+
+ std::stringstream ste;
+ ste<<"initial" << rank<<".vtk";
+ mb.write_file(ste.str().c_str(), 0, 0, &euler_set, 1);
+
+ Intx2MeshOnSphere worker(&mb);
+
+ //double radius=3D CubeSide/2 * sqrt(3.) ; // input
+ worker.SetRadius(radius);
+ worker.set_box_error(EPS1);//
+ //worker.SetEntityType(MBQUAD);
+
+ worker.SetErrorTolerance(radius*1.e-8);
+ std::cout << "error tolerance epsilon_1=3D"<< radius*1.e-8 << "\n";
+ // worker.locate_departure_points(euler_set);
+
+ // we need to make sure the covering set is bigger than the euler mesh
+ EntityHandle covering_lagr_set;
+ rval =3D mb.create_meshset(MESHSET_SET, covering_lagr_set);
+ CHECK_ERR(rval);
+
+ rval =3D worker.create_departure_mesh_2nd_alg(euler_set, covering_lagr_s=
et);
+ CHECK_ERR(rval);
+
+ std::stringstream ss;
+ ss<<"partial" << rank<<".vtk";
+ mb.write_file(ss.str().c_str(), 0, 0, &covering_lagr_set, 1);
+ rval =3D enforce_convexity(&mb, covering_lagr_set);
+ CHECK_ERR(rval);
+ std::stringstream ss2;
+ ss2<<"partialConvex" << rank<<".vtk";
+ mb.write_file(ss2.str().c_str(), 0, 0, &covering_lagr_set, 1);
+ EntityHandle outputSet;
+ rval =3D mb.create_meshset(MESHSET_SET, outputSet);
+ CHECK_ERR(rval);
+ rval =3D worker.intersect_meshes(covering_lagr_set, euler_set, outputSet=
);
+ CHECK_ERR(rval);
+
+ //std::string opts_write("PARALLEL=3DWRITE_PART");
+ //rval =3D mb.write_file("manuf.h5m", 0, opts_write.c_str(), &outputSet,=
1);
+ std::string opts_write("");
+ std::stringstream outf;
+ outf<<"intersect" << rank<<".h5m";
+ rval =3D mb.write_file(outf.str().c_str(), 0, 0, &outputSet, 1);
+ double intx_area =3D area_on_sphere(&mb, outputSet, radius);
+ double arrival_area =3D area_on_sphere(&mb, euler_set, radius) ;
+ std::cout<< "On rank : " << rank << " arrival area: " << arrival_area<<
+ " intersection area:" << intx_area << " rel error: " << fabs((intx_=
area-arrival_area)/arrival_area) << "\n";
+ CHECK_ERR(rval);
+}
diff --git a/tools/mbcslam/CslamUtils.cpp b/tools/mbcslam/CslamUtils.cpp
index 61d1bf0..1166a7a 100644
--- a/tools/mbcslam/CslamUtils.cpp
+++ b/tools/mbcslam/CslamUtils.cpp
@@ -12,6 +12,11 @@
#include "ElemUtil.hpp"
#include "moab/MergeMesh.hpp"
=20
+// this is for sstream
+#include <sstream>
+
+#include <queue>
+
namespace moab {
// vec utilities that could be common between quads on a plane or sphere
double dist2(double * a, double * b)
@@ -24,24 +29,26 @@ double area2D(double *a, double *b, double *c)
// (b-a)x(c-a) / 2
return ((b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])) /=
2;
}
-int borderPointsOfXinY2(double * X, double * Y, int nsides, double * P, in=
t side[4])
+int borderPointsOfXinY2(double * X, int nX, double * Y, int nY, double * P=
, int side[MAXEDGES])
{
// 2 triangles, 3 corners, is the corner of X in Y?
// Y must have a positive area
/*
*/
int extraPoint =3D 0;
- for (int i =3D 0; i < nsides; i++)
+ for (int i =3D 0; i < nX; i++)
{
- // compute twice the area of all 4 triangles formed by a side of Y and=
a corner of X; if one is negative, stop
+ // compute twice the area of all nY triangles formed by a side of Y an=
d a corner of X; if one is negative, stop
+ // (negative means it is outside; X and Y are all oriented such that t=
hey are positive oriented;
+ // if one area is negative, it means it is outside the convex region,=
for sure)
double * A =3D X + 2 * i;
=20
int inside =3D 1;
- for (int j =3D 0; j < nsides; j++)
+ for (int j =3D 0; j < nY; j++)
{
double * B =3D Y + 2 * j;
=20
- int j1 =3D (j + 1) % nsides;
+ int j1 =3D (j + 1) % nY;
double * C =3D Y + 2 * j1; // no copy of data
=20
double area2 =3D (B[0] - A[0]) * (C[1] - A[1])
@@ -54,7 +61,8 @@ int borderPointsOfXinY2(double * X, double * Y, int nside=
s, double * P, int side
}
if (inside)
{
- side[i] =3D 1;
+ side[i] =3D 1;// so vertex i of X is inside the convex region formed=
by Y
+ // so side has nX dimension (first array)
P[extraPoint * 2] =3D A[0];
P[extraPoint * 2 + 1] =3D A[1];
extraPoint++;
@@ -84,7 +92,8 @@ int SortAndRemoveDoubles2(double * P, int & nP, double ep=
silon_1)
}
c[0] /=3D nP;
c[1] /=3D nP;
- double angle[24]; // could be at most 24 points; much less usually
+ // how many
+ std::vector<double> angle(nP); // could be at most nP points
for (k =3D 0; k < nP; k++)
{
double x =3D P[2 * k] - c[0], y =3D P[2 * k + 1] - c[1];
@@ -108,7 +117,7 @@ int SortAndRemoveDoubles2(double * P, int & nP, double =
epsilon_1)
if (angle[k] > angle[k + 1])
{
sorted =3D 0;
- swap2(angle + k, angle + k + 1);
+ swap2(&angle[k], &angle[k+1]);
swap2(P + (2 * k), P + (2 * k + 2));
swap2(P + (2 * k + 1), P + (2 * k + 3));
}
@@ -146,8 +155,8 @@ int SortAndRemoveDoubles2(double * P, int & nP, double =
epsilon_1)
=20
// the marks will show what edges of blue intersect the red
=20
-int EdgeIntersections2(double * blue, double * red, int nsides, int markb[=
4], int markr[4],
- double * points, int & nPoints)
+int EdgeIntersections2(double * blue, int nsBlue, double * red, int nsRed,
+ int markb[MAXEDGES], int markr[MAXEDGES], double * points, int & nPoin=
ts)
{
/* EDGEINTERSECTIONS computes edge intersections of two elements
[P,n]=3DEdgeIntersections(X,Y) computes for the two given elements * r=
ed
@@ -158,30 +167,20 @@ int EdgeIntersections2(double * blue, double * red, i=
nt nsides, int markb[4], in
with blue are given.
*/
=20
- // points is an array with 48 slots (24 * 2 doubles)
+ // points is an array with enough slots (24 * 2 doubles)
nPoints =3D 0;
- markb[0] =3D markb[1] =3D markb[2] =3D markb[3] =3D 0; // no neighbors o=
f red involved yet
- markr[0] =3D markr[1] =3D markr[2] =3D markr[3] =3D 0;
- /*for i=3D1:3 % find all intersections of edg=
es
- for j=3D1:3
- b=3DY(:,j)-X(:,i);
- A=3D[X(:,mod(i,3)+1)-X(:,i) -Y(:,mod(j,3)+1)+Y(:,j)];
- if rank(A)=3D=3D2 % edges not parallel
- r=3DA\b;
- if r(1)>=3D0 & r(1)<=3D1 & r(2)>=3D0 & r(2)<=3D1, % intersection found
- k=3Dk+1; P(:,k)=3DX(:,i)+r(1)*(X(:,mod(i,3)+1)-X(:,i)); n(i)=3D1;
- end;
- end;
- end;
- end;*/
- for (int i =3D 0; i < nsides; i++)
- {
- for (int j =3D 0; j < nsides; j++)
+ for (int i=3D0; i<MAXEDGES; i++){
+ markb[i]=3Dmarkr[i] =3D 0;
+ }
+
+ for (int i =3D 0; i < nsBlue; i++)
+ {
+ for (int j =3D 0; j < nsRed; j++)
{
double b[2];
double a[2][2]; // 2*2
- int iPlus1 =3D (i + 1) % nsides;
- int jPlus1 =3D (j + 1) % nsides;
+ int iPlus1 =3D (i + 1) % nsBlue;
+ int jPlus1 =3D (j + 1) % nsRed;
for (int k =3D 0; k < 2; k++)
{
b[k] =3D red[2 * j + k] - blue[2 * i + k];
@@ -636,7 +635,7 @@ double oriented_spherical_angle(double * A, double * B,=
double * C)
CartVect a(A), b(B), c(C);
CartVect normalOAB =3D a * b;
CartVect normalOCB =3D c * b;
- CartVect orient =3D (b-a)*(c-a);
+ CartVect orient =3D (c-b)*(a-b);
double ang =3D angle(normalOAB, normalOCB); // this is between 0 and M_PI
if (ang!=3Dang)
{
@@ -644,8 +643,8 @@ double oriented_spherical_angle(double * A, double * B,=
double * C)
std::cout << a << " " << b << " " << c <<"\n";
std::cout << ang << "\n";
}
- if (orient%a < 0)
- return (2*M_PI-ang);// the other angle
+ if (orient%b < 0)
+ return (2*M_PI-ang);// the other angle, supplement
=20
return ang;
=20
@@ -861,4 +860,136 @@ void departure_point_case1(CartVect & arrival_point, =
double t, double delta_t, C
departure_point =3D spherical_to_cart(sph_dep);
return;
}
+// break the nonconvex quads into triangles; remove the quad from the set?=
yes.
+// maybe radius is not needed;
+//
+ErrorCode enforce_convexity(Interface * mb, EntityHandle lset)
+{
+ // look at each quad; compute all 4 angles; if one is reflex, break alon=
g that diagonal
+ // replace it with 2 triangles, and remove from set;
+ // it should work for all polygons / tested first for case 1, with dt 0.=
5 (too much deformation)
+ // get all entities of dimension 2
+ // then get the connectivity, etc
+ Range inputRange;
+ ErrorCode rval =3D mb->get_entities_by_dimension(lset, 2, inputRange);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+
+ std::vector<double> coords;
+ coords.resize(3*MAXEDGES); // at most 10 vertices per polygon
+ // we should create a queue with new polygons that need processing for r=
eflex angles
+ // (obtuse)
+ std::queue<EntityHandle> newPolys;
+ int brokenPolys=3D0;
+ Range::iterator eit =3D inputRange.begin();
+ while (eit !=3D inputRange.end() || !newPolys.empty())
+ {
+ EntityHandle eh;
+ if (eit !=3D inputRange.end())
+ {
+ eh =3D *eit;
+ eit++;
+ }
+ else
+ {
+ eh =3D newPolys.front();
+ newPolys.pop();
+ }
+ // get the nodes, then the coordinates
+ const EntityHandle * verts;
+ int num_nodes;
+ rval =3D mb->get_connectivity(eh, verts, num_nodes);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ coords.resize(3 * num_nodes);
+ if (num_nodes < 4)
+ continue; // if already triangles, don't bother
+ // get coordinates
+ rval =3D mb->get_coords(verts, num_nodes, &coords[0]);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ // compute each angle
+ bool alreadyBroken =3D false;
+
+ for (int i=3D0; i<num_nodes; i++)
+ {
+ double * A =3D &coords[3*i];
+ double * B =3D &coords[3*((i+1)%num_nodes)];
+ double * C =3D &coords[3*((i+2)%num_nodes)];
+ double angle =3D oriented_spherical_angle(A, B, C);
+ if (angle-M_PI > 0.) // even almost reflex is bad; break it!
+ {
+ if (alreadyBroken)
+ {
+ mb->list_entities(&eh, 1);
+ mb->list_entities(verts, num_nodes);
+ double * D =3D &coords[3*((i+3)%num_nodes)];
+ std::cout<< "ABC: " << angle << " \n";
+ std::cout<< "BCD: " << oriented_spherical_angle( B, C, D) << " \=
n";
+ std::cout<< "CDA: " << oriented_spherical_angle( C, D, A) << " \=
n";
+ std::cout<< "DAB: " << oriented_spherical_angle( D, A, B)<< " \n=
";
+ std::cout << " this quad has at least 2 angles > 180, it has ser=
ious issues\n";
+
+ return MB_FAILURE;
+ }
+ // the bad angle is at i+1;
+ // create 1 triangle and one polygon; add the polygon to the input=
range, so
+ // it will be processed too
+ // also, add both to the set :) and remove the original polygon fr=
om the set
+ // break the next triangle, even though not optimal
+ // so create the triangle i+1, i+2, i+3; remove i+2 from original =
list
+ // even though not optimal in general, it is good enough.
+ EntityHandle conn3[3]=3D{ verts[ (i+1)%num_nodes],
+ verts[ (i+2)%num_nodes],
+ verts[ (i+3)%num_nodes] };
+ // create a polygon with num_nodes-1 vertices, and connectivity
+ // verts[i+1], verts[i+3], (all except i+2)
+ std::vector<EntityHandle> conn(num_nodes-1);
+ for (int j=3D1; j<num_nodes; j++)
+ {
+ conn[j-1]=3Dverts[(i+j+2)%num_nodes];
+ }
+ EntityHandle newElement;
+ rval =3D mb->create_element(MBTRI, conn3, 3, newElement);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+
+ rval =3D mb->add_entities(lset, &newElement, 1);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ if (num_nodes =3D=3D 4)
+ {
+ // create another triangle
+ rval =3D mb->create_element(MBTRI, &conn[0], 3, newElement);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ }
+ else
+ {
+ // create another polygon, and add it to the inputRange
+ rval =3D mb->create_element(MBPOLYGON, &conn[0], num_nodes-1, ne=
wElement);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ newPolys.push(newElement); // because it has less number of edge=
s, the
+ // reverse should work to find it.
+ }
+ rval =3D mb->add_entities(lset, &newElement, 1);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ mb->remove_entities(lset, &eh, 1);
+ brokenPolys++;
+ /*std::cout<<"remove: " ;
+ mb->list_entities(&eh, 1);
+
+ std::stringstream fff;
+ fff << "file0" << brokenQuads<< ".vtk";
+ mb->write_file(fff.str().c_str(), 0, 0, &lset, 1);*/
+ alreadyBroken=3Dtrue; // get out of the loop, element is broken
+ }
+ }
+ }
+ std::cout << brokenPolys << " concave polygons were decomposed in convex=
ones \n";
+ return MB_SUCCESS;
+}
+
} //namespace moab
diff --git a/tools/mbcslam/CslamUtils.hpp b/tools/mbcslam/CslamUtils.hpp
index e244138..c32a264 100644
--- a/tools/mbcslam/CslamUtils.hpp
+++ b/tools/mbcslam/CslamUtils.hpp
@@ -11,16 +11,20 @@
#include "moab/Core.hpp"
#include "moab/Interface.hpp"
=20
+// maximum number of edges on each convex polygon of interest
+#define MAXEDGES 10
+#define MAXEDGES2 20 // used for coordinates in plane
+
namespace moab
{
double dist2(double * a, double * b);
double area2D(double *a, double *b, double *c);
-int borderPointsOfXinY2(double * X, double * Y, int nsides, double * P, in=
t side[4]);
+int borderPointsOfXinY2(double * X, int nX, double * Y, int nY, double * P=
, int side[MAXEDGES]);
int SortAndRemoveDoubles2(double * P, int & nP, double epsilon);
// the marks will show what edges of blue intersect the red
=20
-int EdgeIntersections2(double * blue, double * red, int nsides, int markb[=
4], int markr[4],
- double * points, int & nPoints);
+int EdgeIntersections2(double * blue, int nsBlue, double * red, int nsRed,
+ int markb[MAXEDGES], int markr[MAXEDGES], double * points, int & nPoin=
ts);
=20
// vec utils related to gnomonic projection on a sphere
=20
@@ -122,5 +126,9 @@ double distance_on_great_circle(CartVect & p1, CartVect=
& p2);
=20
void departure_point_case1(CartVect & arrival_point, double t, double delt=
a_t, CartVect & departure_point);
=20
+// break the nonconvex quads into triangles; remove the quad from the set?=
yes.
+// maybe radius is not needed;
+//
+ErrorCode enforce_convexity(Interface * mb, EntityHandle set);
}
#endif /* CSLAMUTILS_HPP_ */
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/fathomteam/moab/commits/1a3252077efd/
Changeset: 1a3252077efd
Branch: None
User: danwu
Date: 2013-06-26 20:10:56
Summary: Support reading MPAS file type in ReadNC (in progress).
Affected #: 7 files
diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index 350e6ae..30eb430 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -52,6 +52,268 @@ NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int f=
ileId, const FileOptions&
return NULL;
}
=20
+ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarD=
ata>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDi=
m) !=3D vdatas[i].varDims.end()))
+ vdatas[i].has_t =3D true;
+
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ // get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[=
i].varTags[t]);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t)
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+
+ // set up the dimensions and counts
+ // first variable dimension is time, if it exists
+ if (vdatas[i].has_t)
+ {
+ if (vdatas[i].varDims.size() !=3D 1)
+ {
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else
+ {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(tstep_nums.size());
+ }
+ }
+
+ // set up other dimensions and counts
+ if (vdatas[i].varDims.empty()) {
+ // scalar variable
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else {
+ for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
+ if (tDim !=3D vdatas[i].varDims[idx]){
+ // push other variable dimensions, except time, which was alre=
ady pushed
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
+ }
+ }
+ }
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
+ sz *=3D vdatas[i].readCounts[t][idx];
+ vdatas[i].sz =3D sz;
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ vdatas[i].varDatas[t] =3D new char[sz];
+ break;
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ vdatas[i].varDatas[t] =3D new double[sz];
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ vdatas[i].varDatas[t] =3D new int[sz];
+ break;
+ default:
+ std::cerr << "Unrecognized data type for tag " << std::endl;
+ rval =3D MB_FAILURE;
+ }
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vecto=
r<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::set<std::string>& dummyVarNames =3D _readNC->dummyVarNames;;
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_variable_to_set_allocate(vdatas, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables to set.");
+
+ // finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if (dummyVarNames.find(vdatas[i].varName) !=3D dummyVarNames.end() )
+ continue;// this is a dummy one, we don't have it; we created it fo=
r the dummy tag
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ void* data =3D vdatas[i].varDatas[t];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (char*) data NCREQ);
+ ERRORS(success, "Failed to read char data.");
+ break;
+ case NC_DOUBLE:
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (double*) data NCREQ);
+ ERRORS(success, "Failed to read double data.");
+ break;
+ case NC_FLOAT: {
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (float*) data NCREQ);
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT:
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (int*) data NCREQ);
+ ERRORS(success, "Failed to read int data.");
+ break;
+ case NC_SHORT:
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (short*) data NCREQ);
+ ERRORS(success, "Failed to read short data.");
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vd=
atas[i].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], =
&file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode NCHelper::convert_variable(ReadNC::VarData& var_data, int tstep_=
num)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ // Get ptr to tag space
+ void* data =3D var_data.varDatas[tstep_num];
+
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D var_data.readCounts[tstep_num].size=
(); idx++)
+ sz *=3D var_data.readCounts[tstep_num][idx];
+
+ // Finally, read into that space
+ int success =3D 0;
+ int* idata;
+ double* ddata;
+ float* fdata;
+ short* sdata;
+
+ switch (var_data.varDataType) {
+ case NC_FLOAT:
+ ddata =3D (double*) var_data.varDatas[tstep_num];
+ fdata =3D (float*) var_data.varDatas[tstep_num];
+ // Convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ ddata[i] =3D fdata[i];
+ break;
+ case NC_SHORT:
+ idata =3D (int*) var_data.varDatas[tstep_num];
+ sdata =3D (short*) var_data.varDatas[tstep_num];
+ // Convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ idata[i] =3D sdata[i];
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (2 <=3D dbgOut.get_verbosity() && !success) {
+ double dmin, dmax;
+ int imin, imax;
+ switch (var_data.varDataType) {
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ ddata =3D (double*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ dmin =3D dmax =3D ddata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (ddata[i] < dmin)
+ dmin =3D ddata[i];
+ if (ddata[i] > dmax)
+ dmax =3D ddata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (double): min =3D %f, max =3D %f\n"=
, var_data.varName.c_str(), dmin, dmax);
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ idata =3D (int*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ imin =3D imax =3D idata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (idata[i] < imin)
+ imin =3D idata[i];
+ if (idata[i] > imax)
+ imax =3D idata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (int): min =3D %d, max =3D %d\n", v=
ar_data.varName.c_str(), imin, imax);
+ break;
+ case NC_NAT:
+ case NC_BYTE:
+ case NC_CHAR:
+ break;
+ default: // Default case added to remove compiler warnings
+ success =3D 1;
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& =
opts, EntityHandle file_set, Range& faces)
{
Interface*& mbImpl =3D _readNC->mbImpl;
@@ -73,7 +335,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, c=
onst FileOptions& opts,
0, scd_box, locallyPeriodic, &parData);
ERRORR(rval, "Trouble creating scd vertex sequence.");
=20
- // add box set and new vertices, elements to the file set
+ // Add box set and new vertices, elements to the file set
tmp_range.insert(scd_box->start_vertex(), scd_box->start_vertex() + scd_=
box->num_vertices() - 1);
tmp_range.insert(scd_box->start_element(), scd_box->start_element() + sc=
d_box->num_elements() - 1);
tmp_range.insert(scd_box->box_set());
@@ -82,7 +344,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, c=
onst FileOptions& opts,
=20
dbgOut.tprintf(1, "scdbox %d quads, %d vertices\n", scd_box->num_element=
s(), scd_box->num_vertices());
=20
- // get a ptr to global id memory
+ // Get a ptr to global id memory
void* data;
int count;
const Range::iterator topv =3D tmp_range.upper_bound(tmp_range.begin(), =
tmp_range.end(), scd_box->start_vertex()
@@ -92,7 +354,7 @@ ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, c=
onst FileOptions& opts,
assert(count =3D=3D scd_box->num_vertices());
int* gid_data =3D (int*) data;
=20
- // set the vertex coordinates
+ // Set the vertex coordinates
double *xc, *yc, *zc;
rval =3D scd_box->get_coordinate_arrays(xc, yc, zc);
ERRORR(rval, "Couldn't get vertex coordinate arrays.");
@@ -169,7 +431,7 @@ ErrorCode ScdNCHelper::read_variables(EntityHandle file=
_set, std::vector<std::st
ERRORR(rval, "Trouble creating coordinate tags to entities quads");
=20
if (!vsetdatas.empty()) {
- rval =3D read_scd_variable_to_set(file_set, vsetdatas, tstep_nums);
+ rval =3D read_variable_to_set(file_set, vsetdatas, tstep_nums);
ERRORR(rval, "Trouble read variables to set.");
}
=20
@@ -195,7 +457,7 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::vec=
tor<std::string>& var_nam
=20
std::map<std::string, ReadNC::VarData>::iterator mit;
=20
- // if empty read them all
+ // If empty read them all
if (var_names.empty()) {
for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
ReadNC::VarData vd =3D (*mit).second;
@@ -265,189 +527,10 @@ ErrorCode ScdNCHelper::read_scd_variable_setup(std::=
vector<std::string>& var_nam
return MB_SUCCESS;
}
=20
-ErrorCode ScdNCHelper::read_scd_variable_to_set_allocate(std::vector<ReadN=
C::VarData>& vdatas, std::vector<int>& tstep_nums)
+ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle f=
ile_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
{
- std::vector<int>& dimVals =3D _readNC->dimVals;
- int tDim =3D _readNC->tDim;
- DebugOutput& dbgOut =3D _readNC->dbgOut;
-
- ErrorCode rval =3D MB_SUCCESS;
-
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDi=
m) !=3D vdatas[i].varDims.end()))
- vdatas[i].has_t =3D true;
-
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
-
- // get the tag to read into
- if (!vdatas[i].varTags[t]) {
- rval =3D _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[=
i].varTags[t]);
- ERRORR(rval, "Trouble getting tag.");
- }
-
- // assume point-based values for now?
- if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t)
- ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
-
- // set up the dimensions and counts
- // first variable dimension is time, if it exists
- if (vdatas[i].has_t)
- {
- if (vdatas[i].varDims.size() !=3D 1)
- {
- vdatas[i].readDims[t].push_back(tstep_nums[t]);
- vdatas[i].readCounts[t].push_back(1);
- }
- else
- {
- vdatas[i].readDims[t].push_back(0);
- vdatas[i].readCounts[t].push_back(tstep_nums.size());
- }
- }
-
- // set up other dimensions and counts
- if (vdatas[i].varDims.empty()) {
- // scalar variable
- vdatas[i].readDims[t].push_back(0);
- vdatas[i].readCounts[t].push_back(1);
- }
- else {
- for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
- if (tDim !=3D vdatas[i].varDims[idx]){
- // push other variable dimensions, except time, which was alre=
ady pushed
- vdatas[i].readDims[t].push_back(0);
- vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
- }
- }
- }
- std::size_t sz =3D 1;
- for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
- sz *=3D vdatas[i].readCounts[t][idx];
- vdatas[i].sz =3D sz;
- switch (vdatas[i].varDataType) {
- case NC_BYTE:
- case NC_CHAR:
- vdatas[i].varDatas[t] =3D new char[sz];
- break;
- case NC_DOUBLE:
- case NC_FLOAT:
- vdatas[i].varDatas[t] =3D new double[sz];
- break;
- case NC_INT:
- case NC_SHORT:
- vdatas[i].varDatas[t] =3D new int[sz];
- break;
- default:
- std::cerr << "Unrecognized data type for tag " << std::endl;
- rval =3D MB_FAILURE;
- }
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
-
- return rval;
-}
-
-ErrorCode ScdNCHelper::read_scd_variable_to_set(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
-{
- std::set<std::string>& dummyVarNames =3D _readNC->dummyVarNames;;
- Interface*& mbImpl =3D _readNC->mbImpl;
- DebugOutput& dbgOut =3D _readNC->dbgOut;
-
- ErrorCode rval =3D read_scd_variable_to_set_allocate(vdatas, tstep_nums);
- ERRORR(rval, "Trouble allocating read variables to set.");
-
- // finally, read into that space
- int success;
- std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- if (dummyVarNames.find(vdatas[i].varName)!=3D dummyVarNames.end() )
- continue;// this is a dummy one, we don't have it; we created it fo=
r the dummy tag
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- void* data =3D vdatas[i].varDatas[t];
-
- switch (vdatas[i].varDataType) {
- case NC_BYTE:
- case NC_CHAR:
- success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (char*) data NCREQ);
- ERRORS(success, "Failed to read char data.");
- break;
- case NC_DOUBLE:
- success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (double*) data NCREQ);
- ERRORS(success, "Failed to read double data.");
- break;
- case NC_FLOAT: {
- success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (float*) data NCREQ);
- ERRORS(success, "Failed to read float data.");
- break;
- }
- case NC_INT:
- success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (int*) data NCREQ);
- ERRORS(success, "Failed to read int data.");
- break;
- case NC_SHORT:
- success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (short*) data NCREQ);
- ERRORS(success, "Failed to read short data.");
- break;
- default:
- success =3D 1;
- }
-
- if (success)
- ERRORR(MB_FAILURE, "Trouble reading variable.");
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
-
-#ifdef NCWAIT
- int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
- ERRORS(success, "Failed on wait_all.");
-#endif
-
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D convert_scd_variable(vdatas[i], t);
- if (MB_SUCCESS !=3D tmp_rval)
- rval =3D tmp_rval;
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
- // debug output, if requested
- if (1 =3D=3D dbgOut.get_verbosity()) {
- dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
- for (unsigned int i =3D 1; i < vdatas.size(); i++)
- dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
- dbgOut.tprintf(1, "\n");
- }
-
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vd=
atas[i].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], =
&file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
- if (MB_SUCCESS !=3D tmp_rval)
- rval =3D tmp_rval;
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
-
- return rval;
-}
-
-ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle f=
ile_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
-{
- Interface*& mbImpl =3D _readNC->mbImpl;
- std::vector<std::string>& dimNames =3D _readNC->dimNames;
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ std::vector<std::string>& dimNames =3D _readNC->dimNames;
std::vector<int>& dimVals =3D _readNC->dimVals;
int (&lDims)[6] =3D _readNC->lDims;
int (&lCDims)[6] =3D _readNC->lCDims;
@@ -473,7 +556,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allo=
cate(EntityHandle file_se
rval =3D mbImpl->get_entities_by_dimension(file_set, 1, edges);
ERRORR(rval, "Trouble getting edges in set.");
=20
- // get faces in set
+ // Get faces in set
Range faces;
rval =3D mbImpl->get_entities_by_dimension(file_set, 2, faces);
ERRORR(rval, "Trouble getting faces in set.");
@@ -496,8 +579,8 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allo=
cate(EntityHandle file_se
dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
=20
std::vector<std::string>::iterator vit;
- int idx_lev =3D 0;
- int idx_ilev =3D 0;
+ int idx_lev =3D -1;
+ int idx_ilev =3D -1;
if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "lev")) !=
=3D dimNames.end())
idx_lev =3D vit - dimNames.begin();
if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ilev")) !=
=3D dimNames.end())
@@ -507,13 +590,13 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_al=
locate(EntityHandle file_se
else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(=
), idx_ilev) !=3D vdatas[i].varDims.end())
vdatas[i].numLev =3D dimVals[idx_ilev];
=20
- // get the tag to read into
+ // Get the tag to read into
if (!vdatas[i].varTags[t]) {
rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
ERRORR(rval, "Trouble getting tag.");
}
=20
- // assume point-based values for now?
+ // Assume point-based values for now?
if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t) {
ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
}
@@ -521,8 +604,8 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allo=
cate(EntityHandle file_se
ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given f=
or time-independent variable.");
}
=20
- // set up the dimensions and counts
- // first time
+ // Set up the dimensions and counts
+ // First time
vdatas[i].readDims[t].push_back(tstep_nums[t]);
vdatas[i].readCounts[t].push_back(1);
=20
@@ -570,7 +653,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allo=
cate(EntityHandle file_se
break;
}
=20
- // get ptr to tag space
+ // Get ptr to tag space
void* data;
int count;
rval =3D mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), r=
ange->end(), count, data);
@@ -590,7 +673,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(Enti=
tyHandle file_set, std::v
ErrorCode rval =3D read_scd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
ERRORR(rval, "Trouble allocating read variables.");
=20
- // finally, read into that space
+ // Finally, read into that space
int success;
std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
@@ -638,7 +721,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(Enti=
tyHandle file_set, std::v
success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
&tmpfloatdata[0] NCREQ);
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdat=
a[0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
@@ -652,7 +735,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(Enti=
tyHandle file_set, std::v
success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
&tmpintdata[0] NCREQ);
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[=
0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpintdata.size(); idx++)
@@ -666,7 +749,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(Enti=
tyHandle file_set, std::v
success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
&tmpshortdata[0] NCREQ);
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdat=
a[0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpshortdata.size(); idx+=
+)
@@ -692,7 +775,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(Enti=
tyHandle file_set, std::v
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D convert_scd_variable(vdatas[i], t);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
if (MB_SUCCESS !=3D tmp_rval)
rval =3D tmp_rval;
}
@@ -708,89 +791,6 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset(Ent=
ityHandle file_set, std::v
return rval;
}
=20
-ErrorCode ScdNCHelper::convert_scd_variable(ReadNC::VarData& var_data, int=
tstep_num)
-{
- DebugOutput& dbgOut =3D _readNC->dbgOut;
-
- // get ptr to tag space
- void* data =3D var_data.varDatas[tstep_num];
-
- std::size_t sz =3D 1;
- for (std::size_t idx =3D 0; idx !=3D var_data.readCounts[tstep_num].size=
(); idx++)
- sz *=3D var_data.readCounts[tstep_num][idx];
-
- // finally, read into that space
- int success =3D 0;
- int* idata;
- double* ddata;
- float* fdata;
- short* sdata;
-
- switch (var_data.varDataType) {
- case NC_FLOAT:
- ddata =3D (double*) var_data.varDatas[tstep_num];
- fdata =3D (float*) var_data.varDatas[tstep_num];
- // convert in-place
- for (int i =3D sz - 1; i >=3D 0; i--)
- ddata[i] =3D fdata[i];
- break;
- case NC_SHORT:
- idata =3D (int*) var_data.varDatas[tstep_num];
- sdata =3D (short*) var_data.varDatas[tstep_num];
- // convert in-place
- for (int i =3D sz - 1; i >=3D 0; i--)
- idata[i] =3D sdata[i];
- break;
- default:
- success =3D 1;
- }
-
- if (2 <=3D dbgOut.get_verbosity() && !success) {
- double dmin, dmax;
- int imin, imax;
- switch (var_data.varDataType) {
- case NC_DOUBLE:
- case NC_FLOAT:
- ddata =3D (double*) data;
- if (sz =3D=3D 0)
- break;
-
- dmin =3D dmax =3D ddata[0];
- for (unsigned int i =3D 1; i < sz; i++) {
- if (ddata[i] < dmin)
- dmin =3D ddata[i];
- if (ddata[i] > dmax)
- dmax =3D ddata[i];
- }
- dbgOut.tprintf(2, "Variable %s (double): min =3D %f, max =3D %f\n"=
, var_data.varName.c_str(), dmin, dmax);
- break;
- case NC_INT:
- case NC_SHORT:
- idata =3D (int*) data;
- if (sz =3D=3D 0)
- break;
-
- imin =3D imax =3D idata[0];
- for (unsigned int i =3D 1; i < sz; i++) {
- if (idata[i] < imin)
- imin =3D idata[i];
- if (idata[i] > imax)
- imax =3D idata[i];
- }
- dbgOut.tprintf(2, "Variable %s (int): min =3D %d, max =3D %d\n", v=
ar_data.varName.c_str(), imin, imax);
- break;
- case NC_NAT:
- case NC_BYTE:
- case NC_CHAR:
- break;
- default: //default case added to remove compiler warnings
- success =3D 1;
- }
- }
-
- return MB_SUCCESS;
-}
-
ErrorCode UcdNCHelper::read_variables(EntityHandle file_set, std::vector<s=
td::string>& var_names, std::vector<int>& tstep_nums)
{
std::vector<ReadNC::VarData> vdatas;
@@ -799,6 +799,11 @@ ErrorCode UcdNCHelper::read_variables(EntityHandle fil=
e_set, std::vector<std::st
ErrorCode rval =3D read_ucd_variable_setup(var_names, tstep_nums, vdatas=
, vsetdatas);
ERRORR(rval, "Trouble setting up read variable.");
=20
+ if (!vsetdatas.empty()) {
+ rval =3D read_variable_to_set(file_set, vsetdatas, tstep_nums);
+ ERRORR(rval, "Trouble read variables to set.");
+ }
+
if (!vdatas.empty()) {
#ifdef PNETCDF_FILE
// in serial, we will use the old read, everything is contiguous
@@ -814,183 +819,4 @@ ErrorCode UcdNCHelper::read_variables(EntityHandle fi=
le_set, std::vector<std::st
return MB_SUCCESS;
}
=20
-ErrorCode UcdNCHelper::read_ucd_variable_to_set_allocate(std::vector<ReadN=
C::VarData>& vdatas, std::vector<int>& tstep_nums)
-{
- std::vector<int>& dimVals =3D _readNC->dimVals;
- int tDim =3D _readNC->tDim;
- DebugOutput& dbgOut =3D _readNC->dbgOut;
-
- ErrorCode rval =3D MB_SUCCESS;
-
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDi=
m) !=3D vdatas[i].varDims.end()))
- vdatas[i].has_t =3D true;
-
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
-
- // get the tag to read into
- if (!vdatas[i].varTags[t]) {
- rval =3D _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[=
i].varTags[t]);
- ERRORR(rval, "Trouble getting tag.");
- }
-
- // assume point-based values for now?
- if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t)
- ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
-
- // set up the dimensions and counts
- // first variable dimension is time, if it exists
- if (vdatas[i].has_t)
- {
- if (vdatas[i].varDims.size() !=3D 1)
- {
- vdatas[i].readDims[t].push_back(tstep_nums[t]);
- vdatas[i].readCounts[t].push_back(1);
- }
- else
- {
- vdatas[i].readDims[t].push_back(0);
- vdatas[i].readCounts[t].push_back(tstep_nums.size());
- }
- }
-
- // set up other dimensions and counts
- if (vdatas[i].varDims.empty()) {
- // scalar variable
- vdatas[i].readDims[t].push_back(0);
- vdatas[i].readCounts[t].push_back(1);
- }
- else {
- for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
- if (tDim !=3D vdatas[i].varDims[idx]){
- // push other variable dimensions, except time, which was alre=
ady pushed
- vdatas[i].readDims[t].push_back(0);
- vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
- }
- }
- }
- std::size_t sz =3D 1;
- for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
- sz *=3D vdatas[i].readCounts[t][idx];
- vdatas[i].sz =3D sz;
- switch (vdatas[i].varDataType) {
- case NC_BYTE:
- case NC_CHAR:
- vdatas[i].varDatas[t] =3D new char[sz];
- break;
- case NC_DOUBLE:
- case NC_FLOAT:
- vdatas[i].varDatas[t] =3D new double[sz];
- break;
- case NC_INT:
- case NC_SHORT:
- vdatas[i].varDatas[t] =3D new int[sz];
- break;
- default:
- std::cerr << "Unrecognized data type for tag " << std::endl;
- rval =3D MB_FAILURE;
- }
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
-
- return rval;
-}
-
-ErrorCode UcdNCHelper::read_ucd_variable_to_set(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas, std::vector<int> &tstep_nums)
-{
- std::set<std::string>& dummyVarNames =3D _readNC->dummyVarNames;;
- Interface*& mbImpl =3D _readNC->mbImpl;
- DebugOutput& dbgOut =3D _readNC->dbgOut;
-
- ErrorCode rval =3D read_ucd_variable_to_set_allocate(vdatas, tstep_nums);
- ERRORR(rval, "Trouble allocating read variables to set.");
-
- // finally, read into that space
- int success;
- std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- if (dummyVarNames.find(vdatas[i].varName) !=3D dummyVarNames.end() )
- continue; // this is a dummy one, we don't have it; we created it f=
or the dummy tag
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- void* data =3D vdatas[i].varDatas[t];
-
- switch (vdatas[i].varDataType) {
- case NC_BYTE:
- case NC_CHAR:
- success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (char*) data NCREQ);
- ERRORS(success, "Failed to read char data.");
- break;
- case NC_DOUBLE:
- success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (double*) data NCREQ);
- ERRORS(success, "Failed to read double data.");
- break;
- case NC_FLOAT: {
- success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (float*) data NCREQ);
- ERRORS(success, "Failed to read float data.");
- break;
- }
- case NC_INT:
- success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (int*) data NCREQ);
- ERRORS(success, "Failed to read int data.");
- break;
- case NC_SHORT:
- success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
- (short*) data NCREQ);
- ERRORS(success, "Failed to read short data.");
- break;
- default:
- success =3D 1;
- }
-
- if (success)
- ERRORR(MB_FAILURE, "Trouble reading variable.");
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
-
-#ifdef NCWAIT
- int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
- ERRORS(success, "Failed on wait_all.");
-#endif
-
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D convert_ucd_variable(vdatas[i], t);
- if (MB_SUCCESS !=3D tmp_rval)
- rval =3D tmp_rval;
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
- // debug output, if requested
- if (1 =3D=3D dbgOut.get_verbosity()) {
- dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
- for (unsigned int i =3D 1; i < vdatas.size(); i++)
- dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
- dbgOut.tprintf(1, "\n");
- }
-
- for (unsigned int i =3D 0; i < vdatas.size(); i++) {
- for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
- dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vd=
atas[i].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], =
&file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
- if (MB_SUCCESS !=3D tmp_rval)
- rval =3D tmp_rval;
- if (vdatas[i].varDims.size() <=3D 1)
- break;
- }
- }
-
- return rval;
-}
-
} // namespace moab
diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 6aac571..8f63336 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -20,20 +20,32 @@ public:
NCHelper(ReadNC* readNC, int fileId) : _readNC(readNC), _fileId(fileId) =
{}
virtual ~NCHelper() {}
=20
+ //! Get appropriate helper instance for ReadNC class
static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOpt=
ions& opts);
=20
- //! Interfaces to be implemented by child classes
+ //! Interfaces to be implemented in child classes
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set) =3D 0;
virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces) =3D 0;
virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums) =3D 0;
virtual std::string get_mesh_type_name() =3D 0;
=20
protected:
+ //! Read set variables, common to scd mesh and ucd mesh
+ ErrorCode read_variable_to_set(EntityHandle file_set, std::vector<ReadNC=
::VarData>& vdatas, std::vector<int>& tstep_nums);
+
+ //! Convert variables in place
+ ErrorCode convert_variable(ReadNC::VarData& var_data, int tstep_num);
+
+private:
+ //! Used by read_variable_to_set()
+ ErrorCode read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vd=
atas, std::vector<int>& tstep_nums);
+
+protected:
ReadNC* _readNC;
int _fileId;
};
=20
-//! Child helper class for structured mesh, e.g. CAM_EL or CAM_FV
+//! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
class ScdNCHelper : public NCHelper
{
public:
@@ -46,27 +58,27 @@ private:
//! Implementation of NCHelper::read_variables()
virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums);
=20
- //! These functions are used by read_variables(), fully implemented
+ //! Separate set and non-set variables for scd mesh
ErrorCode read_scd_variable_setup(std::vector<std::string>& var_names,
std::vector<int>& tstep_nums,
std::vector<ReadNC::VarData>& vdatas,
std::vector<ReadNC::VarData>& vsetdata=
s);
- ErrorCode read_scd_variable_to_set_allocate(std::vector<ReadNC::VarData>=
& vdatas,
- std::vector<int>& tstep_nums=
);
- ErrorCode read_scd_variable_to_set(EntityHandle file_set, std::vector<Re=
adNC::VarData>& vdatas,
- std::vector<int>& tstep_nums);
+
+ //! Read non-set variables for scd mesh
ErrorCode read_scd_variable_to_nonset_allocate(EntityHandle file_set, st=
d::vector<ReadNC::VarData>& vdatas,
std::vector<int>& tstep_n=
ums);
ErrorCode read_scd_variable_to_nonset(EntityHandle file_set, std::vector=
<ReadNC::VarData>& vdatas,
std::vector<int>& tstep_nums);
- ErrorCode convert_scd_variable(ReadNC::VarData& var_data, int tstep_num);
};
=20
-//! Child helper class for unstructured mesh, e.g. CAM_SE (HOMME) or MPAS
+//! Child helper class for ucd mesh, e.g. CAM_SE (HOMME) or MPAS
class UcdNCHelper : public NCHelper
{
public:
- UcdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ UcdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId),
+ cDim(-1), eDim(-1), vDim(-1), levDim(-1),
+ nCells(0), nEdges(0), nVertices(0),
+ nLocalCells(0), nLocalEdges(0), nLocalVertices(0) {}
virtual ~UcdNCHelper() {}
=20
private:
@@ -74,15 +86,13 @@ private:
virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names,
std::vector<int> &tstep_nums);
=20
- //! These functions are used by read_variables(), partially implemented
+ //! Separate set and non-set variables for ucd mesh (implemented differe=
ntly in child classes)
virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_=
names,
std::vector<int>& tstep_nums,
std::vector<ReadNC::VarData>& =
vdatas,
std::vector<ReadNC::VarData>& =
vsetdatas) =3D 0;
- ErrorCode read_ucd_variable_to_set_allocate(std::vector<ReadNC::VarData>=
& vdatas,
- std::vector<int>& tstep_nums=
);
- ErrorCode read_ucd_variable_to_set(EntityHandle file_set, std::vector<Re=
adNC::VarData>& vdatas,
- std::vector<int>& tstep_nums);
+
+ //! Read non-set variables for ucd mesh (implemented differently in chil=
d classes)
virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file=
_set, std::vector<ReadNC::VarData>& vdatas,
std::vector<int>&=
tstep_nums) =3D 0;
#ifdef PNETCDF_FILE
@@ -92,7 +102,23 @@ private:
virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
std::vector<int>& tstep_nu=
ms) =3D 0;
#endif
- virtual ErrorCode convert_ucd_variable(ReadNC::VarData& var_data, int ts=
tep_num) =3D 0;
+
+protected:
+ //! Dimension numbers for nCells, nEdges, nVertices, nLevels
+ int cDim, eDim, vDim, levDim;
+
+ //! Coordinate values for vertices
+ std::vector<double> xVertVals, yVertVals, zVertVals;
+
+ int nCells;
+ int nEdges;
+ int nVertices;
+
+ int nLocalCells;
+ int nLocalEdges;
+ int nLocalVertices;
+
+ Range localGidCells, localGidEdges, localGidVerts;
};
=20
} // namespace moab
diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 6694abb..60d63c0 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -2,15 +2,14 @@
#include "moab/ReadUtilIface.hpp"
#include "FileOptions.hpp"
#include "moab/SpectralMeshTool.hpp"
-#include "MBTagConventions.hpp"
=20
#include <cmath>
=20
#define ERRORR(rval, str) \
- if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", =
str); return rval;}
+ if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", st=
r); return rval;}
=20
#define ERRORS(err, str) \
- if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_F=
AILURE;}
+ if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAI=
LURE;}
=20
namespace moab {
=20
@@ -92,7 +91,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptions=
& opts, EntityHandle fi
tMin =3D 0;
tName =3D dimNames[idx];
=20
- // get number of vertices (labeled as number of columns) and levels
+ // Get number of vertices (labeled as number of columns) and levels
gDims[0] =3D gDims[3] =3D -1;
if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ncol")) !=3D d=
imNames.end()) {
idx =3D vit - dimNames.begin();
@@ -144,9 +143,9 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
rval =3D _readNC->read_coordinate("lev", gDims[2], gDims[5], klVals);
ERRORR(rval, "Trouble reading z variable.");
=20
- // decide whether down is positive
+ // Decide whether down is positive
char posval[10];
- int success =3D NCFUNC(get_att_text)(_readNC->fileId, (*vmit).second=
.varId, "positive", posval);
+ int success =3D NCFUNC(get_att_text)(_fileId, (*vmit).second.varId, =
"positive", posval);
if (0 =3D=3D success && !strcmp(posval, "down")) {
for (std::vector<double>::iterator dvit =3D klVals.begin(); dvit !=
=3D klVals.end(); ++dvit)
(*dvit) *=3D -1.0;
@@ -350,7 +349,7 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi=
, const FileOptions& opts
ERRORR(rval, "Failed to get fine connectivity of spectral elements.");
}
=20
- // on this proc, I get columns ldims[1]..ldims[4], inclusive; need to fi=
nd which vertices those correpond to
+ // on this proc, I get columns lDims[1]..lDims[4], inclusive; need to fi=
nd which vertices those correspond to
unsigned int num_local_verts =3D localGid.size();
unsigned int num_total_verts =3D gDims[3] - gDims[0] + 1;
=20
@@ -367,17 +366,21 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* sc=
di, const FileOptions& opts
int i;
for (i =3D 0, rit =3D localGid.begin(); i < (int)num_local_verts; i++, +=
+rit) {
assert(*rit < ilVals.size() + 1);
- xptr[i] =3D ilVals[(*rit) - 1];
- yptr[i] =3D jlVals[(*rit) - 1];
- zptr[i] =3D klVals[lDims[2]];
+ xptr[i] =3D ilVals[(*rit) - 1]; // lon
+ yptr[i] =3D jlVals[(*rit) - 1]; // lat
+ zptr[i] =3D klVals[lDims[2]]; // dummy
}
=20
const double pideg =3D acos(-1.0) / 180.0;
for (i =3D 0; i < (int)num_local_verts; i++) {
double cosphi =3D cos(pideg * yptr[i]);
- double zmult =3D sin(pideg * yptr[i]), xmult =3D cosphi * cos(xptr[i] =
* pideg), ymult =3D cosphi * sin(xptr[i] * pideg);
+ double zmult =3D sin(pideg * yptr[i]);
+ double xmult =3D cosphi * cos(xptr[i] * pideg);
+ double ymult =3D cosphi * sin(xptr[i] * pideg);
double rad =3D 8.0e3 + klVals[lDims[2]];
- xptr[i] =3D rad * xmult, yptr[i] =3D rad * ymult, zptr[i] =3D rad * zm=
ult;
+ xptr[i] =3D rad * xmult;
+ yptr[i] =3D rad * ymult;
+ zptr[i] =3D rad * zmult;
}
=20
// get ptr to gid memory for vertices
@@ -516,13 +519,14 @@ ErrorCode NCHelperHOMME::read_ucd_variable_setup(std:=
:vector<std::string>& var_n
=20
std::map<std::string, ReadNC::VarData>::iterator mit;
=20
+ // If empty read them all
if (var_names.empty()) {
for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
ReadNC::VarData vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd.v=
arDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), kDim) !=3D vd.varDims.end()) && (std::find(vd.=
varDims.begin(), vd.varDims.end(), iDim)
!=3D vd.varDims.end()))
- vdatas.push_back(vd); //3d data (time, ncol, ilev) read here
+ vdatas.push_back(vd); // 3d data (time, lev, ncol) read here
else
vsetdatas.push_back(vd);
}
@@ -536,11 +540,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_setup(std:=
:vector<std::string>& var_n
if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd=
.varDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), kDim) !=3D vd.varDims.end()) && (std::find(v=
d.varDims.begin(), vd.varDims.end(), iDim)
!=3D vd.varDims.end()))
- vdatas.push_back(vd); //3d data
+ vdatas.push_back(vd); // 3d data (time, lev, ncol) read here
else
vsetdatas.push_back(vd);
}
- else ERRORR(MB_FAILURE, "Couldn't find variable.");
+ else {
+ ERRORR(MB_FAILURE, "Couldn't find variable.");
+ }
}
}
=20
@@ -589,7 +595,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_al=
locate(EntityHandle file_
=20
Range* range =3D NULL;
=20
- // get vertices in set
+ // Get vertices in set
Range verts;
rval =3D mbImpl->get_entities_by_dimension(file_set, 0, verts);
ERRORR(rval, "Trouble getting vertices in set.");
@@ -601,8 +607,8 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_al=
locate(EntityHandle file_
dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
=20
std::vector<std::string>::iterator vit;
- int idx_lev =3D 0;
- int idx_ilev =3D 0;
+ int idx_lev =3D -1;
+ int idx_ilev =3D -1;
if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "lev")) !=
=3D dimNames.end())
idx_lev =3D vit - dimNames.begin();
if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ilev")) !=
=3D dimNames.end())
@@ -612,13 +618,13 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_=
allocate(EntityHandle file_
else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(=
), idx_ilev) !=3D vdatas[i].varDims.end())
vdatas[i].numLev =3D dimVals[idx_ilev];
=20
- // get the tag to read into
+ // Get the tag to read into
if (!vdatas[i].varTags[t]) {
rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
ERRORR(rval, "Trouble getting tag.");
}
=20
- // assume point-based values for now?
+ // Assume point-based values for now?
if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t) {
ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
}
@@ -626,23 +632,24 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_=
allocate(EntityHandle file_
ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given f=
or time-independent variable.");
}
=20
- // set up the dimensions and counts
- // first time
+ // Set up the dimensions and counts
+ // First: time
vdatas[i].readDims[t].push_back(tstep_nums[t]);
vdatas[i].readCounts[t].push_back(1);
=20
- // then numLev/numVertices
+ // Next: numLev
if (vdatas[i].numLev !=3D 1) {
vdatas[i].readDims[t].push_back(0);
vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
}
=20
+ // Finally: nVertices
switch (vdatas[i].entLoc) {
case ReadNC::ENTLOCVERT:
// vertices
// we will start from the first localGid, actually; we will rese=
t that
// later on, anyway, in a loop
- vdatas[i].readDims[t].push_back(localGid[0]-1);
+ vdatas[i].readDims[t].push_back(localGid[0] - 1);
vdatas[i].readCounts[t].push_back(localGid.size());
assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
range =3D &verts;
@@ -655,7 +662,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_al=
locate(EntityHandle file_
break;
}
=20
- // get ptr to tag space
+ // Get ptr to tag space
void* data;
int count;
rval =3D mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), r=
ange->end(), count, data);
@@ -677,7 +684,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_as=
ync(EntityHandle file_set
ErrorCode rval =3D read_ucd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
ERRORR(rval, "Trouble allocating read variables.");
=20
- // finally, read into that space
+ // Finally, read into that space
int success;
// MPI_offset or size_t?
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
@@ -693,7 +700,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_as=
ync(EntityHandle file_set
size_t idxReq =3D 0;
void* data =3D vdatas[i].varDatas[t];
size_t ni =3D vdatas[i].readCounts[t][2];
- size_t nj =3D 1; // for HOMME, nj holds # quads, so here should set =
to 1
+ size_t nj =3D 1; // For HOMME, nj holds # quads, so here should set =
to 1
size_t nk =3D vdatas[i].readCounts[t][1];
=20
switch (vdatas[i].varDataType) {
@@ -731,7 +738,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_as=
ync(EntityHandle file_set
&(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
&(tmpdoubledata[indexInDoubleArray]) NCREQ2);
ERRORS(success, "Failed to read double data in loop");
- // we need to increment the index in float array for the
+ // we need to increment the index in double array for the
// next subrange
indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
}
@@ -817,7 +824,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_as=
ync(EntityHandle file_set
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D convert_ucd_variable(vdatas[i], t);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
if (MB_SUCCESS !=3D tmp_rval)
rval =3D tmp_rval;
}
@@ -836,11 +843,12 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_=
async(EntityHandle file_set
ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set=
, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
{
DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
=20
ErrorCode rval =3D read_ucd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
ERRORR(rval, "Trouble allocating read variables.");
=20
- // finally, read into that space
+ // Finally, read into that space
int success;
std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
@@ -848,7 +856,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(En=
tityHandle file_set, std:
std::size_t sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
void* data =3D vdatas[i].varDatas[t];
size_t ni =3D vdatas[i].readCounts[t][2];
- size_t nj =3D 1; // for HOMME, nj holds # quads, so here should set =
to 1
+ size_t nj =3D 1; // For HOMME, nj holds # quads, so here should set =
to 1
size_t nk =3D vdatas[i].readCounts[t][1];
=20
switch (vdatas[i].varDataType) {
@@ -868,7 +876,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(En=
tityHandle file_set, std:
break;
}
case NC_DOUBLE: {
- // copy from float case
+ // Copy from float case
std::vector<double> tmpdoubledata(sz);
=20
// in the case of ucd mesh, and on multiple proc,
@@ -877,31 +885,30 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(=
EntityHandle file_set, std:
// basically, we have to give a different point
// for data to start, for every subrange :(
size_t nbDims =3D vdatas[i].readDims[t].size();
- // assume that the last dimension is for the ncol,
- // node varying variable
=20
+ // Assume that the last dimension is for the ncol
size_t indexInDoubleArray =3D 0;
size_t ic =3D 0;
for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
pair_iter !=3D localGid.pair_end();
pair_iter++, ic++) {
EntityHandle starth =3D pair_iter->first;
- EntityHandle endh =3D pair_iter->second; // inclusive
- vdatas[i].readDims[t][nbDims-1] =3D (NCDF_SIZE) (starth - 1);
- vdatas[i].readCounts[t][nbDims-1] =3D (NCDF_SIZE) (endh - star=
th + 1);
+ EntityHandle endh =3D pair_iter->second; // Inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
=20
- success =3D NCFUNCAG(_vara_double)(fileId, vdatas[i].varId,
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
&(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
&(tmpdoubledata[indexInDoubleArray]) NCREQ);
ERRORS(success, "Failed to read float data in loop");
- // we need to increment the index in float array for the
+ // We need to increment the index in double array for the
// next subrange
indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
}
assert(ic =3D=3D localGid.psize());
=20
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpdoubleda=
ta[0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
@@ -919,31 +926,30 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(=
EntityHandle file_set, std:
// basically, we have to give a different point
// for data to start, for every subrange :(
size_t nbDims =3D vdatas[i].readDims[t].size();
- // assume that the last dimension is for the ncol,
- // node varying variable
=20
+ // Assume that the last dimension is for the ncol
size_t indexInFloatArray =3D 0;
size_t ic =3D 0;
for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
pair_iter !=3D localGid.pair_end();
pair_iter++, ic++) {
EntityHandle starth =3D pair_iter->first;
- EntityHandle endh =3D pair_iter->second; // inclusive
+ EntityHandle endh =3D pair_iter->second; // Inclusive
vdatas[i].readDims[t][nbDims-1] =3D (NCDF_SIZE) (starth - 1);
vdatas[i].readCounts[t][nbDims-1] =3D (NCDF_SIZE) (endh - star=
th + 1);
=20
- success =3D NCFUNCAG(_vara_float)(fileId, vdatas[i].varId,
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId,
&(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
&(tmpfloatdata[indexInFloatArray]) NCREQ);
ERRORS(success, "Failed to read float data in loop");
- // we need to increment the index in float array for the
+ // We need to increment the index in float array for the
// next subrange
indexInFloatArray +=3D (endh - starth + 1) * 1 * vdatas[i].num=
Lev;
}
assert(ic =3D=3D localGid.psize());
=20
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdat=
a[0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
@@ -957,7 +963,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(En=
tityHandle file_set, std:
success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
&tmpintdata[0] NCREQ);
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[=
0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpintdata.size(); idx++)
@@ -971,7 +977,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(En=
tityHandle file_set, std:
success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
&tmpshortdata[0] NCREQ);
if (vdatas[i].numLev !=3D 1)
- // switch from k varying slowest to k varying fastest
+ // Switch from k varying slowest to k varying fastest
success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdat=
a[0]);
else {
for (std::size_t idx =3D 0; idx !=3D tmpshortdata.size(); idx+=
+)
@@ -997,7 +1003,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(E=
ntityHandle file_set, std:
for (unsigned int i =3D 0; i < vdatas.size(); i++) {
for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
- ErrorCode tmp_rval =3D convert_ucd_variable(vdatas[i], t);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
if (MB_SUCCESS !=3D tmp_rval)
rval =3D tmp_rval;
}
@@ -1014,86 +1020,4 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset=
(EntityHandle file_set, std:
}
#endif
=20
-ErrorCode NCHelperHOMME::convert_ucd_variable(ReadNC::VarData& var_data, i=
nt tstep_num)
-{
- DebugOutput& dbgOut =3D _readNC->dbgOut;
- Range& localGid =3D _readNC->localGid;
-
- // get ptr to tag space
- void* data =3D var_data.varDatas[tstep_num];
-
- std::size_t sz =3D var_data.numLev * localGid.size(); // how many nodes =
are we reading?
-
- // finally, read into that space
- int success =3D 0;
- int* idata;
- double* ddata;
- float* fdata;
- short* sdata;
-
- switch (var_data.varDataType) {
- case NC_FLOAT:
- ddata =3D (double*) var_data.varDatas[tstep_num];
- fdata =3D (float*) var_data.varDatas[tstep_num];
- // convert in-place
- for (int i =3D sz - 1; i >=3D 0; i--)
- ddata[i] =3D fdata[i];
- break;
- case NC_SHORT:
- idata =3D (int*) var_data.varDatas[tstep_num];
- sdata =3D (short*) var_data.varDatas[tstep_num];
- // convert in-place
- for (int i =3D sz - 1; i >=3D 0; i--)
- idata[i] =3D sdata[i];
- break;
- default:
- success =3D 1;
- }
-
- if (2 <=3D dbgOut.get_verbosity() && !success) {
- double dmin, dmax;
- int imin, imax;
- switch (var_data.varDataType) {
- case NC_DOUBLE:
- case NC_FLOAT:
- ddata =3D (double*) data;
- if (sz =3D=3D 0)
- break;
-
- dmin =3D dmax =3D ddata[0];
- for (unsigned int i =3D 1; i < sz; i++) {
- if (ddata[i] < dmin)
- dmin =3D ddata[i];
- if (ddata[i] > dmax)
- dmax =3D ddata[i];
- }
- dbgOut.tprintf(2, "Variable %s (double): min =3D %f, max =3D %f\n"=
, var_data.varName.c_str(), dmin, dmax);
- break;
- case NC_INT:
- case NC_SHORT:
- idata =3D (int*) data;
- if (sz =3D=3D 0)
- break;
-
- imin =3D imax =3D idata[0];
- for (unsigned int i =3D 1; i < sz; i++) {
- if (idata[i] < imin)
- imin =3D idata[i];
- if (idata[i] > imax)
- imax =3D idata[i];
- }
- dbgOut.tprintf(2, "Variable %s (int): min =3D %d, max =3D %d\n", v=
ar_data.varName.c_str(), imin, imax);
- break;
- case NC_NAT:
- case NC_BYTE:
- case NC_CHAR:
- break;
- default: //default case added to remove compiler warnings
- success =3D 1;
- }
- }
-
- return MB_SUCCESS;
-}
-
} // namespace moab
diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index 3fc3724..b7dc7ac 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -45,8 +45,6 @@ private:
virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
std::vector<int>& tstep_nu=
ms);
#endif
- //! Implementation of UcdNCHelper::convert_ucd_variable()
- virtual ErrorCode convert_ucd_variable(ReadNC::VarData& var_data, int ts=
tep_num);
=20
private:
int _spectralOrder; // Read from variable 'np'
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/fathomteam/moab/commits/23f9da1daf5d/
Changeset: 23f9da1daf5d
Branch: None
User: danwu
Date: 2013-06-26 20:11:28
Summary: Merge branch 'master' of https://bitbucket.org/danwu/moab
Affected #: 29 files
diff --git a/MeshFiles/unittest/io/Makefile.am b/MeshFiles/unittest/io/Make=
file.am
index ece20cf..8257e5f 100644
--- a/MeshFiles/unittest/io/Makefile.am
+++ b/MeshFiles/unittest/io/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST =3D HommeMapping.nc \
brick_cubit10.2.cub \
brick_cubit10.cub \
camEul26x48x96.t3.nc \
+ fv26x46x72.t.3.nc \
cubtest12.cub \
cubtest.jou \
dum.sat \
diff --git a/MeshFiles/unittest/mpas_p8.h5m b/MeshFiles/unittest/mpas_p8.h5m
new file mode 100644
index 0000000..75662d2
Binary files /dev/null and b/MeshFiles/unittest/mpas_p8.h5m differ
diff --git a/doc/DG/moabDG.h b/doc/DG/moabDG.h
new file mode 100644
index 0000000..d2e14f0
--- /dev/null
+++ b/doc/DG/moabDG.h
@@ -0,0 +1,259 @@
+/*! \page developerguide Developer's Guide (MOAB 4.6)
+=20
+ \subpage dg-contents
+=20
+ \subpage dg-figures
+
+ \page dg-contents Table of Contents
+
+ \ref sequence
+
+ \ref manager
+
+ \ref s-mesh
+
+ \ref sets
+
+ \section sequence 1. EntitySequence & SequenceData
+
+ \subsection figure1 Figure 1: EntitySequences For One SequenceData
+
+The <I>SequenceData</I> class manages as set of arrays of per-entity value=
s. Each
+<I>SequenceData</I> has a start and end handle denoting the block of entit=
ies for which
+the arrays contain data. The arrays managed by a <I>SequenceData</I> insta=
nce are
+divided into three groups:
+
+- Type-specific data (connectivity, coordinates, etc.): zero or more array=
s.
+- Adjacency data: zero or one array.
+- Dense tag data: zero or more arrays.
+.
+
+The abstract <I>EntitySequence</I> class is a non-strict subset of a <I>Se=
quenceData</I>.
+It contains a pointer to a <I>SequenceData</I> and the start and end handl=
es to indi-
+cate the subset of the referenced <I>SequenceData</I>. The <I>EntitySequen=
ce</I> class is
+used to represent the regions of valid (or allocated) handles in a <I>Sequ=
enceData</I>.
+A <I>SequenceData</I> is expected to be referenced by one or more <I>Entit=
ySequence</I>
+instances.
+
+Initial <I>EntitySequence</I> and <I>SequenceData</I> pairs are typically =
created in one
+of two configurations. When reading from a file, a <I>SequenceData</I> wil=
l be created
+to represent all of a single type of entity contained in a file. As all en=
tries in the <I>SequenceData</I> correspond to valid handles (entities read=
from the file) a single
+<I>EntitySequence</I> instance corresponding to the entire <I>SequenceData=
</I> is initially
+created. The second configuration arises when allocating a single entity. =
If no
+entities have been allocated yet, a new <I>SequenceData</I> must be create=
d to store
+the entity data. It is created with a constant size (e.g. 4k entities). Th=
e new
+<I>EntitySequence</I> corresponds to only the first entity in the <I>Seque=
nceData</I>: the
+one allocated entity. As subsequent entities are allocated, the <I>EntityS=
equence</I>
+is extended to cover more of the corresponding <I>SequenceData</I>.
+
+Concrete subclasses of the <I>EntitySequence</I> class are responsible for=
rep-
+resenting specific types of entities using the array storage provided by t=
he
+<I>SequenceData</I> class. They also handle allocating <I>SequenceData</I>=
instances with
+appropriate arrays for storing a particular type of entity. Each concrete =
subclass
+typically provides two constructors corresponding to the two initial alloc=
ation
+configurations described in the previous paragraph. <I>EntitySequence</I> =
imple-
+mentations also provide a split method, which is a type of factory method.=
It
+modifies the called sequence and creates a new sequence such that the rang=
e of
+entities represented by the original sequence is split.
+
+The <I>VertexSequence</I> class provides an <I>EntitySequence</I> for stor=
ing ver-
+tex data. It references a SequenceData containing three arrays of doubles
+for storing the blocked vertex coordinate data. The <I>ElementSequence</I>=
class
+extends the <I>EntitySequence</I> interface with element-specific function=
ality. The
+<I>UnstructuredElemSeq</I> class is the concrete implementation of <I>Elem=
entSequence</I>
+used to represent unstructured elements, polygons, and polyhedra. <I>MeshS=
etSequence</I>
+is the <I>EntitySequence</I> used for storing entity sets.
+
+Each <I>EntitySequence</I> implementation also provides an implementation =
of
+the values per entity method. This value is used to determine if an exist-
+ing <I>SequenceData</I> that has available entities is suitable for storin=
g a particular
+entity. For example, <I>UnstructuredElemSeq</I> returns the number of node=
s per el-
+ement from values per entity. When allocating a new element with a specific
+number of nodes, this value is used to determine if that element may be st=
ored
+in a specific <I>SequenceData</I>. For vertices, this value is always zero=
. This could
+be changed to the number of coordinates per vertex, allowing representatio=
n of
+mixed-dimension data. However, API changes would be required to utilize su=
ch
+a feature. Sequences for which the corresponding data cannot be used to st=
ore
+new entities (e.g. structured mesh discussed in a later section) will retu=
rn -1 or
+some other invalid value.
+
+ \ref dg-contents
+
+ \section manager 2. TypeSequenceManager & SequenceManager=20
+
+The <I>TypeSequenceManager</I> class maintains an organized set of <I>Enti=
tySequence</I>
+instances and corresponding <I>SequenceData</I> instances. It is used to m=
anage
+all such instances for entities of a single <I>EntityType</I>. <I>TypeSequ=
enceManager</I>
+enforces the following four rules on its contained data:
+
+-# No two <I>SequenceData</I> instances may overlap. =20
+-# No two <I>EntitySequence</I> instances may overlap.
+-# Every <I>EntitySequence</I> must be a subset of a <I>SequenceData</I>.
+-# Any pair of <I>EntitySequence</I> instances referencing the same <I>Seq=
uenceData</I> must be separated by at least one unallocated handle.
+.
+
+ \subsection figure2 Figure 2: SequenceManager and Related Classes
+
+The first three rules are required for the validity of the data model. The
+fourth rule avoids unnecessary inefficiency. It is implemented by merging =
such
+adjacent sequences. In some cases, other classes (e.g. <I>SequenceManager<=
/I>) can
+modify an <I>EntitySequence</I> such that the fourth rule is violated. In =
such cases,
+the <I>TypeSequenceManager::notify</I> prepended or <I>TypeSequenceManager=
::notify</I> appended
+method must be called to maintain the integrity of the data<sup>1</sup>. T=
he above rules
+(including the fourth) are assumed in many other methods of the <I>TypeSeq=
uenceManager</I>
+class, such that those methods will fail or behave unexpectedly if the man=
aged
+data does not conform to the rules.
+
+<I>TypeSequenceManager</I> contains three principal data structures. The f=
irst is
+a <I>std::set</I> of <I>EntitySequence</I> pointers sorted using a custom =
comparison op-
+erator that queries the start and end handles of the referenced sequences.=
The
+comparison operation is defined as: <I>a->end_handle() < b->start_handle()=
</I>.
+This method of comparison has the advantage that a sequence corresponding =
to
+a specific handle can be located by searching the set for a =E2=80=9Cseque=
nce=E2=80=9D beginning
+and ending with the search value. The lower bound and find methods pro-
+vided by the library are guaranteed to return the sequence, if it exists. =
Using
+such a comparison operator will result in undefined behavior if the set co=
ntains
+overlapping sequences. This is acceptable, as rule two above prohibits such
+a configuration. However, some care must be taken in writing and modifying
+methods in <I>TypeSequenceManager</I> so as to avoid having overlapping se=
quences
+as a transitory state of some operation.
+
+The second important data member of <I>TypeSequenceManager</I> is a pointer
+to the last referenced <I>EntitySequence</I>. This =E2=80=9Ccached=E2=80=
=9D value is used to speed up
+searches by entity handle. This pointer is never null unless the sequence =
is empty.
+This rule is maintained to avoid unnecessary branches in fast query paths.=
In
+cases where the last referenced sequence is deleted, <I>TypeSequenceManage=
r</I> will
+typically assign an arbitrary sequence (e.g. the first one) to the last re=
ferenced
+pointer.
+
+The third data member of <I>TypeSequenceManager</I> is a <I>std::set</I> o=
f <I>SequenceData</I>
+instances that are not completely covered by a <I>EntitySequence</I> insta=
nce<sup>2</sup>.
+This list is searched when allocating new handles. <I>TypeSequenceManager<=
/I> also
+embeds in each <I>SequenceData</I> instance a reference to the first corre=
sponding
+<I>EntitySequence</I> so that it may be located quickly from only the <I>S=
equenceData</I>
+pointer.
+
+The <I>SequenceManager</I> class contains an array of <I>TypeSequenceManag=
er</I> in-
+stances, one for each <I>EntityType</I>. It also provides all type-specifi=
c operations
+such as allocating the correct <I>EntitySequence</I> subtype for a given <=
I>EntityType</I>.
+
+<sup>1</sup>This source of potential error can be eliminated with changes =
to the entity set representation. This is discussed in a later section.
+
+<sup>2</sup>Given rule four for the data managed by a <I>TypeSequenceManag=
er</I>, any <I>SequenceData</I> for which all handles are allocated will be=
referenced by exactly one <I>EntitySequence</I>.
+
+ \ref dg-contents
+
+ \section s-mesh 3. Structured Mesh
+
+Structured mesh storage is implemented using subclasses of <I>SequenceData=
</I>:
+<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSe=
q</I> class is
+used to access the structured element connectivity. A standard <I>VertexSe=
quence</I>
+instance is used to access the ScdVertexData because the vertex data stora=
ge
+is the same as for unstructured mesh.
+
+ \ref dg-contents
+
+ \section sets 4. Entity Sets
+
+- MeshSetSequence
+
+The <I>MeshSetSequence</I> class is the same as most other subclasses of <=
I>EntitySequence</I>
+in that it utilizes SequenceData to store its data. A single array in the =
<I>SequenceData</I>
+is used to store instances of the MeshSet class, one per allocated <I>Enti=
tyHandle</I>.
+<I>SequenceData</I> allocates all of its managed arrays using malloc and f=
ree as
+simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction =
and de-
+struction of <I>MeshSet</I> instances within that array. This is similar t=
o what is
+done by <I>std::vector</I> and other container classes that may own more s=
torage
+than is required at a given time for contained objects.
+
+- MeshSet
+
+ \subsection figure3 Figure 3: SequenceManager and Related Classes
+
+The <I>MeshSet</I> class is used to represent a single entity set instance=
in MOAB.
+The class is optimized to minimize storage (further possible improvements =
in
+storage size are discussed later.)
+
+Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> clas=
s.
+The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER<=
/I>,
+<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MES=
HSET_TRACK_OWNER</I>
+indicates that reverse links from the contained entities back to the ownin=
g set
+should be maintained in the adjacency list of each entity. The <I>MESHSET_=
SET</I>
+and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most c=
ode only
+tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESH=
SET_SET</I> bit is
+ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplica=
te handles
+and that the order that the handles are added to the set should be preserv=
ed.
+In practice, such sets are stored as a simple list of handles. <I>MESHSET_=
SET</I> (or in
+practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of =
the handles
+need not be preserved and that the set may not contain duplicate handles. =
Such
+sets are stored in a sorted range-compacted format similar to that of the =
Range
+class.
+
+The memory for storing contents, parents, and children are each handled in
+the same way. The data in the class is composed of a 2-bit =E2=80=98size=
=E2=80=99 field and two
+values, where the two values may either be two handles or two pointers. Th=
e size
+bit-fields are grouped together to reduce the required amount of memory. I=
f the
+numerical value of the 2-bit size field is 0 then the corresponding list i=
s empty.
+If the 2-bit size field is either 1 or 2, then the contents of the corresp=
onding list
+are stored directly in the corresponding two data fields of the MeshSet ob=
ject.
+If the 2-bit size field has a value of 3 (11 binary), then the correspondi=
ng two
+data fields store the begin and end pointers of an external array of handl=
es.
+The number of handles in the external array can be obtained by taking the
+difference of the start and end pointers. Note that unlike <I>std::vector<=
/I>, we
+do not store both an allocated and used size. We store only the =E2=80=98u=
sed=E2=80=99 size
+and call std::realloc whenever the used size is modified, thus we rely on =
the
+std::malloc implementation in the standard C library to track =E2=80=98all=
ocated=E2=80=99 size
+for us. In practice this performs well but does not return memory to the =
=E2=80=98system=E2=80=99
+when lists shrink (unless they shrink to zero). This overall scheme could =
exhibit
+poor performance if the size of one of the data lists in the set frequentl=
y changes
+between less than two and more than two handles, as this will result in fr=
equent
+releasing and re-allocating of the memory for the corresponding array.
+
+If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents l=
ist (parent
+and child lists are unaffected) is stored in a range-compacted format. In =
this
+format the number of handles stored in the array is always a multiple of t=
wo.
+Each consecutive pair of handles indicate the start and end, inclusive, of=
a range
+of handles contained in the set. All such handle range pairs are stored in=
sorted
+order and do not overlap. Nor is the end handle of one range ever one less=
than
+the start handle of the next. All such =E2=80=98adjacent=E2=80=99 range pa=
irs are merged into a
+single pair. The code for insertion and removal of handles from range-form=
atted
+set content lists is fairly complex. The implementation will guarantee tha=
t a
+given call to insert entities into a range or remove entities from a range=
is never
+worse than O(ln n) + O(m + n), where =E2=80=98n=E2=80=99 is the number of =
handles to insert
+and =E2=80=98m=E2=80=99 is the number of handles already contained in the =
set. So it is generally
+much more efficient to build Ranges of handles to insert (and remove) and =
call
+MOAB to insert (or remove) the entire list at once rather than making may
+calls to insert (or remove) one or a few handles from the contents of a se=
t.
+The set storage could probably be further minimized by allowing up to six
+handles in one of the lists to be elided. That is, as there are six potent=
ial =E2=80=98slots=E2=80=99
+in the MeshSet object then if two of the lists are empty it should be poss=
ible to store up to six values of the remaining list directly in the MeshSe=
t object.
+However, the additional runtime cost of such complexity could easily outwe=
igh
+any storage advantage. Further investigation into this has not been done b=
ecause
+the primary motivation for the storage optimization was to support binary =
trees.
+
+Another possible optimization of storage would be to remove the <I>MeshSet=
</I>
+object entirely and instead store the data in a =E2=80=98blocked=E2=80=99 =
format. The corre-
+sponding <I>SequenceData</I> would contain four arrays: flags, parents, ch=
ildren, and
+contents instead of a single array of <I>MeshSet</I> objects. If this were=
done then
+no storage need ever be allocated for parent or child links if none of the=
sets
+in a <I>SequenceData</I> has parent or child links. The effectiveness of t=
he storage
+reduction would depend greatly on how sets get grouped into <I>SequenceDat=
as</I>.
+This alternate storage scheme might also allow for better cache utilizatio=
n as it
+would group like data together. It is often the case that application code=
that
+is querying the contents of one set will query the contents of many but ne=
ver
+query the parents or children of any set. Or that an application will quer=
y only
+parent or child links of a set without every querying other set properties=
. The
+downside of this solution is that it makes the implementation a little les=
s mod-
+ular and maintainable because the existing logic contained in the <I>MeshS=
et</I> class
+would need to be spread throughout the <I>MeshSetSequence</I> class.
+
+ \ref dg-contents
+
+ \page dg-figures List of Figures
+
+ \ref figure1
+
+ \ref figure2
+
+ \ref figure3
+*/
diff --git a/doc/UG/moabUG.h b/doc/UG/moabUG.h
new file mode 100644
index 0000000..cea942d
--- /dev/null
+++ b/doc/UG/moabUG.h
@@ -0,0 +1,1064 @@
+/*! \page userguide User's Guide (MOAB 4.6)
+=20
+ \subpage team=20
+=20
+ \subpage contents
+=20
+ \subpage figures
+=20
+ \subpage tables
+=20
+ \subpage differences
+
+ \subpage building
+
+ \page team MOAB team members
+ <h2>The MOAB Team, including: </h2>
+=20
+ - Timothy J. Tautges (Argonne National Lab, Univ Wisconsin-Madison)=20
+ - Iulian Grindeanu (Argonne National Lab)=20
+ - Rajeev Jain (Argonne National Lab)
+ - Xiabing Xu (Argonne National Lab)
+
+
+ <h2>Emeritus members:</h2>
+=20
+ - Jason A. Kraftcheck
+ - Brandon M. Smith
+ - Hong-Jun Kim
+ - Jim Porter
+=20
+ \page contents Table of Contents
+=20
+ \ref introduction =20
+
+ \ref interface =20
+
+ \ref twoone =20
+
+ \ref twotwo =20
+
+ \ref twothree =20
+
+ \ref twofour =20
+
+ \ref api =20
+
+ \ref services =20
+
+ \ref fourone =20
+
+ \ref fourtwo =20
+
+ \ref fourthree =20
+
+ \ref fourfour =20
+
+ \ref fourfive =20
+
+ \ref foursix =20
+
+ \ref parallel =20
+
+ \ref fiveone =20
+
+ \ref fivetwo =20
+
+ \ref fivethree =20
+
+ \ref fivefour =20
+
+ \ref applications =20
+
+ \ref implementation =20
+
+ \ref representation =20
+
+ \ref element =20
+
+ \ref nineone =20
+
+ \ref ninetwo =20
+
+ \ref ninethree =20
+
+ \ref performance =20
+
+ \ref conclusions =20
+
+ \ref references=20
+
+ \section introduction 1. Introduction
+
+In scientific computing, systems of partial differential equations (PDEs) =
are solved on computers. One of the most widely used methods to solve PDEs=
numerically is to solve over discrete neighborhoods or =E2=80=9Celements=
=E2=80=9D of the domain. Popular discretization methods include Finite Dif=
ference (FD), Finite Element (FE), and Finite Volume (FV). These methods r=
equire the decomposition of the domain into a discretized representation, w=
hich is referred to as a =E2=80=9Cmesh=E2=80=9D. The mesh is one of the fu=
ndamental types of data linking the various tools in the analysis process (=
mesh generation, analysis, visualization, etc.). Thus, the representation =
of mesh data and operations on those data play a very important role in PDE=
-based simulations.
+=20
+MOAB is a component for representing and evaluating mesh data. MOAB can s=
tore structured and unstructured mesh, consisting of elements in the finite=
element =E2=80=9Czoo=E2=80=9D, along with polygons and polyhedra. The fun=
ctional interface to MOAB is simple, consisting of only four fundamental da=
ta types. This data is quite powerful, allowing the representation of most=
types of metadata commonly found on the mesh. Internally MOAB uses array-=
based storage for fine-grained data, which in many cases provides more effi=
cient access, especially for large portions of mesh and associated data. M=
OAB is optimized for efficiency in space and time, based on access to mesh =
in chunks rather than through individual entities, while also versatile eno=
ugh to support individual entity access.
+
+The MOAB data model consists of the following four fundamental types: mesh=
interface instance, mesh entities (vertex, edge, tri, etc.), sets, and tag=
s. Entities are addressed through handles rather than pointers, to allow t=
he underlying representation of an entity to change without changing the ha=
ndle to that entity. Sets are arbitrary groupings of mesh entities and oth=
er sets. Sets also support parent/child relationships as a relation distin=
ct from sets containing other sets. The directed graph provided by set par=
ent/child relationships is useful for embedding graphs whose nodes include =
collections of mesh entities; this approach has been used to represent a wi=
de variety of application-specific data, including geometric model topology=
, processor partitions, and various types of search trees. Tags are named =
data which can be assigned to the mesh as a whole, individual entities, or =
sets. Tags are a mechanism for attaching data to individual entities, and =
sets are a mechanism for describing relations between entities; the combina=
tion of these two mechanisms is a powerful yet simple interface for represe=
nting metadata or application-specific data.
+
+Various mesh-related tools are provided with MOAB or can be used directly =
with MOAB. These tools can be used for mesh format translation (mbconvert)=
, mesh skinning (Skinner class), solution transfer between meshes (MBCouple=
r tool), ray tracing and other geometric searches (OrientedBoxTreeTool, Ada=
ptiveKDTree), visualization (vtkMOABReader tool), and relation between mesh=
and geometric models (the separately-packed Lasso tool). These tools are =
described later in this document.
+
+MOAB is written in the C++ programming language, with applications interac=
ting with MOAB mostly through its moab::Interface class. All of the MOAB f=
unctions and classes are isolated in and accessed through the moab namespac=
e<sup>1</sup>. The remainder of this report gives class and function names =
without the =E2=80=9Cmoab::=E2=80=9D namespace qualification; unless otherw=
ise noted, the namespace qualifier should be added to all class and functio=
n names referenced here. MOAB also implements the iMesh interface, which i=
s specified in C but can be called directly from other languages. Almost a=
ll of the functionality in MOAB can be accessed through the iMesh interface=
. MOAB is developed and supported on the Linux and MacOS operating systems=
, as well as various HPC operating systems. MOAB can be used on parallel c=
omputing systems as well, including both clusters and high-end parallel sys=
tems like IBM BG/P and Cray systems. MOAB is released under a standard LGP=
L open source software license.
+
+MOAB is used in several ways in various applications. MOAB serves as the =
underlying mesh data representation in several scientific computing applica=
tions [1]. MOAB can also be used as a mesh format translator, using reader=
s and writers included in MOAB. MOAB has also been used as a bridge to cou=
ple results in multi-physics analysis and to link these applications with o=
ther mesh services [2].
+
+The remainder of this report is organized as follows. Section 2, =E2=80=
=9CGetting Started=E2=80=9D, provides a few simple examples of using MOAB t=
o perform simple tasks on a mesh. Section 3 discusses the MOAB data model =
in more detail, including some aspects of the implementation. Section 4 su=
mmarizes the MOAB function API. Section 5 describes some of the tools incl=
uded with MOAB, and the implementation of mesh readers/writers for MOAB. S=
ection 6 describes how to build MOAB-based applications. Section 7 contain=
s a brief description of MOAB=E2=80=99s relation to the iMesh mesh interfac=
e. Sections 8 and 9 discuss MOAB's representations of structured and spect=
ral element meshes, respectively. Section 10 gives helpful hints for acces=
sing MOAB in an efficient manner from applications. Section 11 gives a con=
clusion and future plans for MOAB development. Section 12 gives references=
cited in this report.
+
+Several other sources of information about MOAB may also be of interest to=
readers. Meta-data conventions define how sets and /or tags are used toge=
ther to represent various commonly-used simulation constructs; conventions =
used by MOAB are described in Ref [4], which is also included in the MOAB s=
ource distribution. This document is maintained separately from this docum=
ent, since it is expected to change over time. The MOAB project maintains =
a wiki [5], which links to most MOAB-related information. MOAB also uses s=
everal mailing lists [6],[7] for MOAB-related discussions. Potential users=
are encouraged to interact with the MOAB team using these mailing lists.
+
+<sup>1</sup> Non-namespaced names are also provided for backward compatibi=
lity, with the =E2=80=9CMB=E2=80=9D prefix added to the class or variable n=
ame.
+
+ \ref contents
+
+ \section interface 2. MOAB Data Model
+The MOAB data model describes the basic types used in MOAB and the languag=
e used to communicate that data to applications. This chapter describes th=
at data model, along with some of the reasons for some of the design choice=
s in MOAB.
+
+ \ref contents
+
+ \subsection twoone 2.1. MOAB Interface
+MOAB is written in C++. The primary interface with applications is throug=
h member functions of the abstract base class Interface. The MOAB library =
is created by instantiating Core, which implements the Interface API. Mult=
iple instances of MOAB can exist concurrently in the same application; mesh=
entities are not shared between these instancesi<sup>2</sup>. MOAB is mos=
t easily viewed as a database of mesh objects accessed through the instance=
. No other assumptions explicitly made about the nature of the mesh stored=
there; for example, there is no fundamental requirement that elements fill=
space or do not overlap each other geometrically.
+=20
+<sup>2</sup> One exception to this statement is when the parallel interfac=
e to MOAB is used; in this case, entity sharing between instances is handle=
d explicitly using message passing. This is described in more detail in Se=
ction 5 of this document.
+
+ \ref contents
+
+ \subsection twotwo 2.2. Mesh Entities
+MOAB represents the following topological mesh entities: vertex, edge, tri=
angle, quadrilateral, polygon, tetrahedron, pyramid, prism, knife, hexahedr=
on, polyhedron. MOAB uses the EntityType enumeration to refer to these ent=
ity types (see Table 1). This enumeration has several special characterist=
ics, chosen intentionally: the types begin with vertex, entity types are gr=
ouped by topological dimension, with lower-dimensional entities appearing b=
efore higher dimensions; the enumeration includes an entity type for sets (=
described in the next section); and MBMAXTYPE is included at the end of thi=
s enumeration, and can be used to terminate loops over type. In addition t=
o these defined values, the an increment operator (++) is defined such that=
variables of type EntityType can be used as iterators in loops.
+MOAB refers to entities using =E2=80=9Chandles=E2=80=9D. Handles are impl=
emented as long integer data types, with the four highest-order bits used t=
o store the entity type (mesh vertex, edge, tri, etc.) and the remaining bi=
ts storing the entity id. This scheme is convenient for applications becau=
se:
+- Handles sort lexicographically by type and dimension; this can be useful=
for grouping and iterating over entities by type.
+- The type of an entity is indicated by the handle itself, without needing=
to call a function.
+- Entities allocated in sequence will typically have contiguous handles; t=
his characteristic can be used to efficiently store and operate on large li=
sts of handles.
+.
+
+This handle implementation is exposed to applications intentionally, becau=
se of optimizations that it enables, and is unlikely to change in future ve=
rsions.
+
+ \subsection tableone Table 1: Values defined for the EntityType enumerat=
ed type.
+<table border=3D"1">
+<tr>
+<td>MBVERTEX =3D 0</td>
+<td>MBPRISM</td>
+</tr>
+<tr>
+<td>MBEDGE</td>
+<td>MBKNIFE</td>
+</tr>
+<tr>
+<td>MBTRI</td>
+<td>MBHEX</td>
+</tr>
+<tr>
+<td>MBQUAD</td>
+<td>MBPOLYHEDRON</td>
+</tr>
+<tr>
+<td>MBPOLYGON</td>
+<td>MBENTITYSET</td>
+</tr>
+<tr>
+<td>MBTET</td>
+<td>MBMAXTYPE</td>
+</tr>
+<tr>
+<td>MBPYRAMID</td>
+<td></td>
+</tr>
+</table>
+
+MOAB defines a special class for storing lists of entity handles, named Ra=
nge. This class stores handles as a series of (start_handle, end_handle) s=
ubrange tuples. If a list of handles has large contiguous ranges, it can b=
e represented in almost constant size using Range. Since entities are typi=
cally created in groups, e.g. during mesh generation or file import, a high=
degree of contiguity in handle space is typical. Range provides an interf=
ace similar to C++ STL containers like std::vector, containing iterator dat=
a types and functions for initializing and iterating over entity handles st=
ored in the range. Range also provides functions for efficient Boolean ope=
rations like subtraction and intersection. Most API functions in MOAB come=
in both range-based and vector-based variants. By definition, a list of e=
ntities stored in an Range is always sorted, and can contain a given entity=
handle only once. Range cannot store the handle 0 (zero).
+
+Typical usage of an Range object would look like:
+
+\code
+using namespace moab;
+ int my_function(Range &from_range) {
+ int num_in_range =3D from_range.size();
+ Range to_range;
+ Range::iterator rit;
+ for (rit =3D from_range.begin(); rit !=3D from_range.end(); rit++) {
+ EntityHandle this_ent =3D *rit;
+ to_range.insert(this_ent);
+ }
+ }
+\endcode
+
+Here, the range is iterated similar to how std::vector is iterated.
+
+ \ref contents
+
+ \subsection adjacencies 2.2.1. Adjacencies & AEntities=20
+
+The term adjacencies is used to refer to those entities topologically conn=
ected to a given entity, e.g. the faces bounded by a given edge or the vert=
ices bounding a given region. The same term is used for both higher-dimens=
ional (or bounded) and lower-dimensional (or bounding) adjacent entities. =
MOAB provides functions for querying adjacent entities by target dimension,=
using the same functions for higher- and lower-dimension adjacencies. By =
default, MOAB stores the minimum data necessary to recover adjacencies betw=
een entities. When a mesh is initially loaded into MOAB, only entity-verte=
x (i.e. =E2=80=9Cdownward=E2=80=9D) adjacencies are stored, in the form of =
entity connectivity. When =E2=80=9Cupward=E2=80=9D adjacencies are request=
ed for the first time, e.g. from vertices to regions, MOAB stores all verte=
x-entity adjacencies explicitly, for all entities in the mesh. Non-vertex =
entity to entity adjacencies are never stored, unless explicitly requested =
by the application.
+
+In its most fundamental form, a mesh need only be represented by its verti=
ces and the entities of maximal topological dimension. For example, a hexa=
hedral mesh can be represented as the connectivity of the hex elements and =
the vertices forming the hexes. Edges and faces in a 3D mesh need not be e=
xplicitly represented. We refer to such entities as =E2=80=9CAEntities=E2=
=80=9D, where =E2=80=98A=E2=80=99 refers to =E2=80=9CAuxiliary=E2=80=9D, =
=E2=80=9CAncillary=E2=80=9D, and a number of other words mostly beginning w=
ith =E2=80=98A=E2=80=99. Individual AEntities are created only when reques=
ted by applications, either using mesh modification functions or by request=
ing adjacencies with a special =E2=80=9Ccreate if missing=E2=80=9D flag pas=
sed as =E2=80=9Ctrue=E2=80=9D. This reduces the overall memory usage when =
representing large meshes. Note entities must be explicitly represented be=
fore they can be assigned tag values or added to entity sets (described in =
following Sections).
+
+\ref contents
+
+ \subsection twothree 2.3. Entity Sets
+Entity sets are used to store arbitrary collections of entities and other =
sets. Sets are used for a variety of things in mesh-based applications, fr=
om the set of entities discretizing a given geometric model entity to the e=
ntities partitioned to a specific processor in a parallel finite element ap=
plication. MOAB entity sets can also store parent/child relations with oth=
er entity sets, with these relations distinct from contains relations. Par=
ent/child relations are useful for building directed graphs with graph node=
s representing collections of mesh entities; this construct can be used, fo=
r example, to represent an interface of mesh faces shared by two distinct c=
ollections of mesh regions. MOAB also defines one special set, the =E2=80=
=9Croot set=E2=80=9D or the interface itself; all entities are part of this=
set by definition. Defining a root set allows the use of a single set of =
MOAB API functions to query entities in the overall mesh as well as its sub=
sets.
+
+MOAB entity sets can be one of two distinct types: list-type entity sets p=
reserve the order in which entities are added to the set, and can store a g=
iven entity handle multiple times in the same set; set-type sets are always=
ordered by handle, regardless of the order of addition to the set, and can=
store a given entity handle only once. This characteristic is assigned wh=
en the set is created, and cannot be changed during the set=E2=80=99s lifet=
ime.
+
+MOAB provides the option to track or not track entities in a set. When en=
tities (and sets) are deleted by other operations in MOAB, they will also b=
e removed from containing sets for which tracking has been enabled. This b=
ehavior is assigned when the set is created, and cannot be changed during t=
he set=E2=80=99s lifetime. The cost of turning tracking on for a given set=
is sizeof(EntityHandle) for each entity added to the set; MOAB stores cont=
aining sets in the same list which stores adjacencies to other entities.
+
+Using an entity set looks like the following:
+\code
+using namespace moab;
+// load a file using MOAB, putting the loaded mesh into a file set
+EntityHandle file_set;
+ErrorCode rval =3D moab->create_meshset(MESHSET_SET, file_set);
+rval =3D moab->load_file(=E2=80=9Cfname.vtk=E2=80=9D, &file_set);
+Range set_ents;
+// get all the 3D entities in the set
+rval =3D moab->get_entities_by_dimension(file_set, 3, set_ents);
+\endcode
+
+Entity sets are often used in conjunction with tags (described in the next=
section), and provide a powerful mechanism to store a variety of meta-data=
with meshes.
+
+\ref contents
+
+ \subsection twofour 2.4. Tags=20
+
+Applications of a mesh database often need to attach data to mesh entities=
. The types of attached data are often not known at compile time, and can =
vary across individual entities and entity types. MOAB refers to this atta=
ched data as a =E2=80=9Ctag=E2=80=9D. Tags can be thought of loosely as a =
variable, which can be given a distinct value for individual entities, enti=
ty sets, or for the interface itself. A tag is referenced using a handle, =
similarly to how entities are referenced in MOAB. Each MOAB tag has the fo=
llowing characteristics, which can be queried through the MOAB interface:
+- Name
+- Size (in bytes)
+- Storage type
+- Data type (integer, double, opaque, entity handle)
+- Handle
+.
+
+The storage type determines how tag values are stored on entities. =20
+
+- Dense: Dense tag values are stored in arrays which match arrays of conti=
guous entity handles. Dense tags are more efficient in both storage and me=
mory if large numbers of entities are assigned the same tag. Storage for a=
given dense tag is not allocated until a tag value is set on an entity; me=
mory for a given dense tag is allocated for all entities in a given sequenc=
e at the same time.
+- Sparse: Sparse tags are stored as a list of (entity handle, tag value) t=
uples, one list per sparse tag, sorted by entity handle.
+- Bit: Bit tags are stored similarly to dense tags, but with special handl=
ing to allow allocation in bit-size amounts per entity.
+.
+
+MOAB also supports variable-length tags, which can have a different length=
for each entity they are assigned to. Variable length tags are stored sim=
ilarly to sparse tags.
+
+The data type of a tag can either be one understood at compile time (integ=
er, double, entity handle), in which case the tag value can be saved and re=
stored properly to/from files and between computers of different architectu=
re (MOAB provides a native HDF5-based save/restore format for this purpose;=
see Section 4.6). The opaque data type is used for character strings, or =
for allocating =E2=80=9Craw memory=E2=80=9D for use by applications (e.g. f=
or storage application-defined structures or other abstract data types). T=
hese tags are saved and restored as raw memory, with no special handling fo=
r endian or precision differences.
+
+An application would use the following code to attach a double-precision t=
ag to vertices in a mesh, e.g. to assign a temperature field to those verti=
ces:
+
+\code
+using namespace moab;
+// load a file using MOAB and get the vertices
+ErrorCode rval =3D moab->load_file(=E2=80=9Cfname.vtk=E2=80=9D);
+Range verts;
+rval =3D moab->get_entities_by_dimension(0, 0, verts);
+// create a tag called =E2=80=9CTEMPERATURE=E2=80=9D
+Tag temperature;
+double def_val =3D -1.0d-300, new_val =3D 273.0;
+rval =3D moab->tag_create(=E2=80=9CTEMPERATURE=E2=80=9D, sizeof(double), M=
B_TAG_DENSE,=20
+ MB_TYPE_DOUBLE, temperature, &def_val);
+// assign a value to vertices
+for (Range::iterator vit =3D verts.begin();=20
+ vit !=3D verts.end(); vit++)=20
+ rval =3D moab->tag_set_data(temperature, &(*rit), 1, &new_val);
+
+\endcode
+
+The semantic meaning of a tag is determined by applications using it. How=
ever, to promote interoperability between applications, there are a number =
of tag names reserved by MOAB which are intended to be used by convention. =
Mesh readers and writers in MOAB use these tag conventions, and applicatio=
ns can use them as well to access the same data. Ref. [4] maintains an up-t=
o-date list of conventions for meta-data usage in MOAB.
+
+ \ref contents
+
+ \section api 3. MOAB API Design Philosophy and Summary
+
+This section describes the design philosophy behind MOAB, and summarizes t=
he functions, data types and enumerated variables in the MOAB API. A compl=
ete description of the MOAB API is available in online documentation in the=
MOAB distribution [8].
+
+MOAB is designed to operate efficiently on collections of entities. Entit=
ies are often created or referenced in groups (e.g. the mesh faces discreti=
zing a given geometric face, the 3D elements read from a file), with those =
groups having some form of temporal or spatial locality. The interface pro=
vides special mechanisms for reading data directly into the native storage =
used in MOAB, and for writing large collections of entities directly from t=
hat storage, to avoid data copies. MOAB applications structured to take ad=
vantage of that locality will typically operate more efficiently.
+
+MOAB has been designed to maximize the flexibility of mesh data which can =
be represented. There is no explicit constraint on the geometric structure=
of meshes represented in MOAB, or on the connectivity between elements. I=
n particular, MOAB allows the representation of multiple entities with the =
same exact connectivity; however, in these cases, explicit adjacencies must=
be used to distinguish adjacencies with AEntities bounding such entities.
+
+The number of vertices used to represent a given topological entity can va=
ry, depending on analysis needs; this is often the case in FEA. For exampl=
e, applications often use =E2=80=9Cquadratic=E2=80=9D or 10-vertex tetrahed=
ral, with vertices at edge midpoints as well as corners. MOAB does not dis=
tinguish these variants by entity type, referring to all variants as =E2=80=
=9Ctetrahedra=E2=80=9D. The number of vertices for a given entity is used =
to distinguish the variants, with canonical numbering conventions used to d=
etermine placement of the vertices [9]. This is similar to how such variat=
ions are represented in the Exodus [10] and Patran [11] file formats. In p=
ractice, we find that this simplifies coding in applications, since in many=
cases the handling of entities depends only on the number of corner vertic=
es in the element. Some MOAB API functions provide a flag which determines=
whether corner or all vertices are requested.
+
+The MOAB API is designed to balance complexity and ease of use. This bala=
nce is evident in the following general design characteristics:
+
+- Entity lists: Lists of entities are passed to and from MOAB in a variety=
of forms. Lists output from MOAB are passed as either STL vector or Range=
data types. Either of these constructs may be more efficient in both time=
and memory, depending on the semantics of the data being requested. Input=
lists are passed as either Range=E2=80=99s, or as a pointer to EntityHandl=
e and a size. The latter allows the same function to be used when passing =
individual entities, without requiring construction of an otherwise unneede=
d STL vector.
+- Entity sets: Most query functions accept an entity set as input. Applic=
ations can pass zero to indicate a request for the whole interface. Note t=
hat this convention applies only to query functions; attempts to add or sub=
tract entities to/from the interface using set-based modification functions=
, or to add parents or children to the interface set, will fail. Allowing =
specification of the interface set in this manner avoids the need for a sep=
arate set of API functions to query the database as a whole.
+- Implicit Booleans in output lists: A number of query functions in MOAB a=
llow specification of a Boolean operation (Interface::INTERSECT or Interfac=
e::UNION). This operation is applied to the results of the query, often el=
iminating the need for code the application would need to otherwise impleme=
nt. For example, to find the set of vertices shared by a collection of qua=
drilaterals, the application would pass that list of quadrilaterals to a re=
quest for vertex adjacencies, with Interface::INTERSECT passed for the Bool=
ean flag. The list of vertices returned would be the same as if the applic=
ation called that function for each individual entity, and computed the int=
ersection of the results over all the quadrilaterals. Applications may als=
o input non-empty lists to store the results, in which case the intersectio=
n is also performed with entities already in the list. In many cases, this=
allows optimizations in both time and memory inside the MOAB implementatio=
n.=20
+.
+
+Since these objectives are at odds with each other, tradeoffs had to be ma=
de between them. Some specific issues that came up are:
+
+- Using ranges: Where possible, entities can be referenced using either ra=
nges (which allow efficient storage of long lists) or STL vectors (which al=
low list order to be preserved), in both input and output arguments.
+- Entities in sets: Accessing the entities in a set is done using the same=
functions which access entities in the entire mesh. The whole mesh is ref=
erenced by specifying a set handle of zero<sup>3</sup>.
+- Entity vectors on input: Functions which could normally take a single en=
tity as input are specified to take a vector of handles instead. Single en=
tities are specified by taking the address of that entity handle and specif=
ying a list length of one. This minimizes the number of functions, while p=
reserving the ability to input single entities.<sup>4</sup>
+.
+
+Table 2 lists basic data types and enumerated variables defined and used b=
y MOAB. Values of the ErrorCode enumeration are returned from most MOAB fu=
nctions, and can be compared to those listed in Appendix [ref-appendix].
+
+MOAB uses several pre-defined tag names to define data commonly found in v=
arious mesh-based analyses. Ref. [4] describes these meta-data conventions=
in more detail. These conventions will be added to as new conventions eme=
rge for using sets and tags in MOAB applications.
+
+ \subsection tabletwo Table 2: Basic data types and enums defined in MOAB.
+
+<table border=3D"1">
+<tr>
+<th>Enum / Type</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>ErrorCode</td>
+<td>Specific error codes returned from MOAB</td>
+</tr>
+<tr>
+<td>EntityHandle</td>
+<td>Type used to represent entity handles</td>
+</tr>
+<tr>
+<td>Tag</td>
+<td>Type used to represent tag handles</td>
+</tr>
+<tr>
+<td>TagType</td>
+<td>Type used to represent tag storage type</td>
+</tr>
+<tr>
+<td>DataType</td>
+<td>Type used to represent tag data type</td>
+</tr>
+</table>
+
+Table 3 lists the various groups of functions that comprise the MOAB API. =
This is listed here strictly as a reference to the various types of functi=
onality supported by MOAB; for a more detailed description of the scope and=
syntax of the MOAB API, see the online documentation [8].
+
+ \subsection tablethree Table 3: Groups of functions in MOAB API. See Re=
f. [8] for more details.
+
+<table border=3D"1">
+<tr>
+<th>Function group</th>
+<th>Examples</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>Constructor, destructor, interface</td>
+<td>Interface, ~Core, query_interface</td>
+<td>Construct/destroy interface; get pointer to read/write interface</td>
+</tr>
+<tr>
+<td>Entity query</td>
+<td>get_entities_by_dimension, get_entities_by_handle</td>
+<td>Get entities by dimension, type, etc.</td>
+</tr>
+<tr>
+<td>Adjacencies</td>
+<td>get_adjacencies, set_adjacencies, add_adjacencies</td>
+<td>Get topologically adjacent entities; set or add explicit adjacencies</=
td>
+</tr>
+<tr>
+<td>Vertex coordinates</td>
+<td>get_coords, set_coords</td>
+<td>Get/set vertex coordinates</td>
+</tr>
+<tr>
+<td>Connectivity</td>
+<td>get_connectivity, set_connectivity</td>
+<td>Get/set connectivity of non-vertex entities</td>
+</tr>
+<tr>
+<td>Sets</td>
+<td>create_meshset, add_entities, add_parent_child</td>
+<td>Create and work with entity sets</td>
+</tr>
+<tr>
+<td>Tags</td>
+<td>tag_get_data, tag_create</td>
+<td>Create, read, write tag data</td>
+</tr>
+<tr>
+<td>Handles</td>
+<td>type_from_handle, id_from_handle</td>
+<td>Go between handles and types/ids</td>
+</tr>
+<tr>
+<td>File handling</td>
+<td>load_mesh, save_mesh</td>
+<td>Read/write mesh files</td>
+</tr>
+<tr>
+<td>Geometric dimension</td>
+<td>get_dimension, set_dimension</td>
+<td>Get/set geometric dimension of mesh</td>
+</tr>
+<tr>
+<td>Mesh modification</td>
+<td>create_vertex, delete_entity</td>
+<td>Create or delete mesh entities</td>
+</tr>
+<tr>
+<td>Information</td>
+<td>list_entities, get_last_error</td>
+<td>Get or print certain information</td>
+</tr>
+<tr>
+<td>High-order nodes</td>
+<td>high_order_node</td>
+<td>Get information on high-order nodes</td>
+</tr>
+<tr>
+<td>Canonical numbering</td>
+<td>side_number</td>
+<td>Get canonical numbering information</td>
+</tr>
+</table>
+
+<sup>3</sup>In iMesh, the whole mesh is specified by a special entity set =
handle, referred to as the =E2=80=9Croot set=E2=80=9D.
+
+<sup>4</sup>Note that STL vectors of entity handles can be input in this m=
anner by using &vector[0] and vector.size() for the 1d vector address and s=
ize, respectively.
+
+ \ref contents
+
+ \section services 4. Related Mesh Services
+
+A number of mesh-based services are often used in conjunction with a mesh =
library. For example, parallel applications often need to visualize the me=
sh and associated data. Other services, like spatial interpolation or find=
ing the faces on the =E2=80=9Cskin=E2=80=9D of a 3D mesh, can be implemente=
d more efficiently using knowledge of specific data structures in MOAB. Se=
veral of these services provided with MOAB are described in this chapter.
+
+ \ref contents
+
+ \subsection fourone 4.1. Visualization
+
+Visualization is one of the most common needs associated with meshes. The=
primary tool used to visualize MOAB meshes is VisIt [12]. Users can speci=
fy that VisIt read mesh directly out of the MOAB instance, by specifying th=
e ITAPS-MOABC mesh format and a file readable by MOAB (see xxx).
+
+There are some initial capabilities in VisIt for limited viewing and manip=
ulation of tag data and some types of entity sets. Tag data is visualized =
using the same mechanisms used to view other field data in VisIt, e.g. usin=
g a pseudocolor plot; sets are viewed using VisIt=E2=80=99s SIL window, acc=
essed by selecting the SIL icon in the data selection window. xxx shows a =
vertex-based radiation temperature field computed by the Cooper rad-hydro c=
ode [1] for a subset of geometric volumes in a mesh. =20
+
+Reorganization of VisIt=E2=80=99s set handling is also underway, to increa=
se versatility and flexibility of this important mechanism.
+
+ \ref contents
+
+ \subsection fourtwo 4.2. Parallel Decomposition
+
+To support parallel simulation, applications often need to partition a mes=
h into parts, designed to balance the load and minimize communication betwe=
en sets. MOAB includes the MBZoltan tool for this purpose, constructed on =
the well-known Zoltan partitioning library [13]. After computing the parti=
tion using Zoltan, MBZoltan stores the partition as either tags on individu=
al entities in the partition, or as tagged sets, one set per part. Since a=
partition often exhibits locality similar to how the entities were created=
, storing it as sets (based on Range=E2=80=99s) is often more memory-effici=
ent than an entity tag-based representation. Xxx shows a partition compute=
d with MBZoltan (and visualized in VisIt).=20
+
+ \ref contents
+
+ \subsection fourthree 4.3. Skinner
+
+An operation commonly applied to mesh is to compute the outermost =E2=80=
=9Cskin=E2=80=9D bounding a contiguous block of elements. This skin consis=
ts of elements of one fewer topological dimension, arranged in one or more =
topological balls on the boundary of the elements. The Skinner tool comput=
es the skin of a mesh in a memory-efficient manner. Skinner uses knowledge=
about whether vertex-entity adjacencies and AEntities exist to minimize me=
mory requirements and searching time required during the skinning process. =
This skin can be provided as a single collection of entities, or as sets o=
f entities distinguished by forward and reverse orientation with respect to=
higher-dimensional entities in the set being skinned.
+
+The following code fragment shows how Skinner can be used to compute the s=
kin of a range of hex elements:
+
+ \code
+using namespace moab;
+Range hexes, faces;
+ErrorCode rval =3D moab->get_entities_by_dimension(0, 3, hexes);
+Skinner myskinner(moab);
+bool verts_too =3D false;
+ErrorCode rval =3D myskinner.find_skin(hexes, verts_too, faces);
+\endcode
+
+Skinner can also skin a mesh based on geometric topology groupings importe=
d with the mesh. The geometric topology groupings contain information abou=
t the mesh =E2=80=9Cowned=E2=80=9D by each of the entities in the geometric=
model, e.g. the model vertices, edges, etc. Links between the mesh sets c=
orresponding to those entities can be inferred directly from the mesh. Ski=
nning a mesh this way will typically be much faster than doing so on the ac=
tual mesh elements, because there is no need to create and destroy interior=
faces on the mesh.
+
+ \ref contents
+
+ \subsection fourfour 4.4. Tree Decompositions
+
+MOAB provides several mechanisms for spatial decomposition and searching i=
n a mesh:
+
+- AdaptiveKDTree: Adaptive KD tree, a space-filling decomposition with axi=
s-aligned splitting planes, enabling fast searching.
+- BSPTree: Binary Space Partition tree, with non-axis-aligned partitions, =
for fast spatial searches with slightly better memory efficiency than KD tr=
ees.
+- OrientedBoxTreeTool: Oriented Bounding Box tree hierarchy, useful for fa=
st ray-tracing on collections of mesh facets.
+.
+
+These trees have various space and time searching efficiencies. All are i=
mplemented based on entity sets and parent/child relations between those se=
ts, allowing storage of a tree decomposition using MOAB=E2=80=99s native fi=
le storage mechanism (see Section 4.6.1). MOAB=E2=80=99s entity set implem=
entation is specialized for memory efficiency when representing binary tree=
s. Tree decompositions in MOAB have been used to implement fast ray tracin=
g to support radiation transport [14], solution coupling between meshes [2]=
, and embedded boundary mesh generation [15]. MOAB also includes the DAGMC=
tool, supporting Monte Carlo radiation transport.
+
+The following code fragment shows very basic use of AdaptiveKDTree. A ran=
ge of entities is put in the tree; the leaf containing a given point is fou=
nd, and the entities in that leaf are returned.
+\code
+using namespace moab;
+// create the adaptive kd tree from a range of tets
+EntityHandle tree_root
+AdaptiveKDTree myTree(moab);
+ErrorCode rval =3D myTree.build_tree(tets, tree_root);
+
+// get the overall bounding box corners
+double boxmax[3], boxmin;
+rval =3D myTree.get_tree_box(tree_root, boxmax, boxmin);
+
+// get the tree leaf containing point xyz, and the tets in that leaf
+AdaptiveKDTreeIter treeiter;
+rval =3D myTree.leaf_containing_point(tree_root, xyz, treeiter);
+Range leaf_tets;
+rval =3D moab->get_entities_by_dimension(treeiter.handle(), 3,=20
+ leaf_tets, false);
+\endcode
+
+More detailed examples of using the various tree decompositions in MOAB ca=
n be found in [ref-treeexamples].
+
+ \ref contents
+
+ \subsection fourfive 4.5. File Reader/Writer Interfaces
+
+Mesh readers and writers communicate mesh into/out of MOAB from/to disk fi=
les. Reading a mesh often involves importing large sets of data, for examp=
le coordinates of all the nodes in the mesh. Normally, this process would =
involve reading data from the file into a temporary data buffer, then copyi=
ng data from there into its destination in MOAB. To avoid the expense of c=
opying data, MOAB has implemented a reader/writer interface that provides d=
irect access to blocks of memory used to represent mesh.
+
+The reader interface, declared in ReadUtilIface, is used to request blocks=
of memory for storing coordinate positions and element connectivity. The =
pointers returned from these functions point to the actual memory used to r=
epresent those data in MOAB. Once data is written to that memory, no furth=
er copying is done. This not only saves time, but it also eliminates the n=
eed to allocate a large memory buffer for intermediate storage of these dat=
a.=20
+
+MOAB allocates memory for nodes and elements (and their corresponding dens=
e tags) in chunks, to avoid frequent allocation/de-allocation of small chun=
ks of memory. The chunk size used depends on from where the mesh is being =
created, and can strongly affect the performance (and memory layout) of MOA=
B. Since dense tags are allocated at the chunk size, this can also affect =
overall memory usage in cases where the mesh size is small but the number o=
f dense tags or dense tag size is large. When creating vertices and elemen=
ts through the normal MOAB API, default chunk sizes defined in the Sequence=
Manager class are used. However, most of the file readers in MOAB allocate=
the exact amount of space necessary to represent the mesh being read. The=
re are also a few exceptions to this:
+
+- When compiled in parallel, this space is increased by a factor of 1.5, t=
o allow subsequent creation of ghost vertices/elements in the same chunk as=
the original mesh.
+- The .cub file reader, which creates nodes and elements for individual ge=
ometric entities in separate calls, allocates using the default vertex/elem=
ent sequence sizes, which are defined in the SequenceManager class in MOAB.
+.
+
+Applications calling the reader interface functions directly can specify t=
he allocation chunk size as an optional parameter.
+
+The reader interface consists of the following functions:
+
+- get_node_arrays: Given the number of vertices requested, the number of g=
eometric dimensions, and a requested start id, allocates a block of vertex =
handles and returns pointers to coordinate arrays in memory, along with the=
actual start handle for that block of vertices.
+- get_element_array: Given the number of elements requested, the number of=
vertices per element, the element type and the requested start id, allocat=
es the block of elements, and returns a pointer to the connectivity array f=
or those elements and the actual start handle for that block. The number o=
f vertices per element is necessary because those elements may include high=
er-order nodes, and MOAB stores these as part of the normal connectivity ar=
ray.
+- update_adjacencies: This function takes the start handle for a block of =
elements and the connectivity of those elements, and updates adjacencies fo=
r those elements. Which adjacencies are updated depends on the options set=
in AEntityFactory.
+.
+
+The following code fragment illustrates the use of ReadUtilIface to read a=
mesh directly into MOAB=E2=80=99s native representation. This code assume=
s that connectivity is specified in terms of vertex indices, with vertex in=
dices starting from 1.
+
+\code
+// get the read iface from moab
+ReadUtilIface *iface;
+ErrorCode rval =3D moab->get_interface("ReadUtilIface", &iface);
+
+// allocate a block of vertex handles and read xyz=E2=80=99s into them
+std::vector<double*> arrays;
+EntityHandle startv, *starth;
+rval =3D iface->get_node_arrays(3, num_nodes, 0, startv, arrays);
+for (int i =3D 0; i < num_nodes; i++)
+ infile >> arrays[0][i] >> arrays[1][i] >> arrays[2][i];
+
+// allocate block of hex handles and read connectivity into them
+rval =3D iface->get_element_array(num_hexes, 8, MBHEX, 0, starth);
+for (int i =3D 0; i < 8*num_hexes; i++)
+ infile >> starth[i];
+
+// change connectivity indices to vertex handles
+for (int i =3D 0; i < 8*num_hexes; i++)
+ starth[i] +=3D startv-1;
+\endcode
+
+The writer interface, declared in WriteUtilIface, provides functions that =
support writing vertex coordinates and element connectivity to storage loca=
tions input by the application. Assembling these data is a common task for=
writing mesh, and can be non-trivial when exporting only subsets of a mesh=
. The writer interface declares the following functions:
+
+- get_node_arrays: Given already-allocated memory and the number of vertic=
es and dimensions, and a range of vertices, this function writes vertex coo=
rdinates to that memory. If a tag is input, that tag is also written with =
integer vertex ids, starting with 1, corresponding to the order the vertice=
s appear in that sequence (these ids are used to write the connectivity arr=
ay in the form of vertex indices).
+- get_element_array: Given a range of elements and the tag holding vertex =
ids, and a pointer to memory, the connectivity of the specified elements ar=
e written to that memory, in terms of the indices referenced by the specifi=
ed tag. Again, the number of vertices per element is input, to allow the d=
irect output of higher-order vertices.
+- gather_nodes_from_elements: Given a range of elements, this function ret=
urns the range of vertices used by those elements. If a bit-type tag is in=
put, vertices returned are also marked with 0x1 using that tag. If no tag =
is input, the implementation of this function uses its own bit tag for mark=
ing, to avoid using an n2 algorithm for gathering vertices.
+- reorder: Given a permutation vector, this function reorders the connecti=
vity for entities with specified type and number of vertices per entity to =
match that permutation. This function is needed for writing connectivity i=
nto numbering systems other than that used internally in MOAB.
+.
+
+The following code fragment shows how to use WriteUtilIface to write the v=
ertex coordinates and connectivity indices for a subset of entities.
+
+\code
+using namespace moab;
+// get the write iface from moab
+WriteUtilIface *iface;
+ErrorCode rval =3D moab->get_interface("WriteUtilIface", &iface);
+
+// get all hexes the model, and choose the first 10 of those
+Range tmp_hexes, hexes, verts;
+rval =3D moab->get_entities_by_type(0, MBHEX, tmp_hexes);
+for (int i =3D 0; i < 10; i++) hexes.insert(tmp_hexes[i]);
+rval =3D iface->gather_nodes_from_elements(hexes, 0, verts);
+
+// assign vertex ids
+iface->assign_ids(verts, 0, 1);
+
+// allocate space for coordinates & write them
+std::vector<double*> arrays(3);
+for (int i =3D 0; i < 3; i++) arrays[i] =3D new double[verts.size()];
+iface->get_node_arrays(3, verts.size(), verts, 0, 1, arrays);
+
+// put connect=E2=80=99y in array, in the form of indices into vertex array
+std::vector<int> conn(8*hexes.size());
+iface->get_element_array(hexes.size(), 8, 0, hexes, 0, 1, &conn[0]);
+\endcode
+
+ \ref contents
+
+ \subsection foursix 4.6. File Readers/Writers Packaged With MOAB
+
+MOAB has been designed to efficiently represent data and metadata commonly=
found in finite element mesh files. Readers and writers are included with=
MOAB which import/export specific types of metadata in terms of MOAB sets =
and tags, as described earlier in this document. The number of readers and=
writers in MOAB will probably grow over time, and so they are not enumerat=
ed here. See the src/io/README file in the MOAB source distribution for a =
current list of supported formats.
+
+Because of its generic support for readers and writers, described in the p=
revious section, MOAB is also a good environment for constructing new mesh =
readers and writers. The ReadTemplate and WriteTemplate classes in src/io =
are useful starting points for constructing new file readers/writers; appli=
cations are encouraged to submit their own readers/writers for inclusion in=
MOAB=E2=80=99s contrib/io directory in the MOAB source.=20
+
+The usefulness of a file reader/writer is determined not only by its abili=
ty to read and write nodes and elements, but also in its ability to store t=
he various types of meta-data included with the typical mesh. MOAB readers=
and writers are distinguished by their ability to preserve meta-data in me=
shes that they read and write. For example, MOAB=E2=80=99s CUB reader impo=
rts not only the mesh saved from CUBIT, but also the grouping of mesh entit=
ies into sets which reflect the geometric topology of the model used to gen=
erate the mesh. See [4] for a more detailed description of meta-data conve=
ntions used in MOAB=E2=80=99s file readers and writers, and the individual =
file reader/writer header files in src/io for details about the specific re=
aders and writers.
+
+Three specific file readers in MOAB bear further discussion: MOAB=E2=80=99=
s native HDF5-based file reader/writer; the CUB reader, used to import mesh=
and meta-data represented in CUBIT; and the CGM reader, which imports geom=
etric models. These are described next.
+
+ \ref contents
+
+ \subsection native 4.6.1. Native HD5-Based Reader/Writer
+
+A mesh database must be able to save and restore the data stored in its da=
ta model, at least to the extent to which it understands the semantics of t=
hat data. MOAB defines an HDF5-based file format that can store data embed=
ded in MOAB. By convention, these files are given an =E2=80=9C.h5m=E2=80=
=9D file extension. When reading or writing large amounts of data, it is r=
ecommended to use this file format, as it is the most complete and also the=
most efficient of the file readers/writers in MOAB.=20
+
+ \subsection cub 4.6.2. CUB Reader
+
+CUBIT is a toolkit for generating tetrahedral and hexahedral finite elemen=
t meshes from solid model geometry [16]. This tool saves and restores data=
in a custom =E2=80=9C.cub=E2=80=9D file, which stores both mesh and geomet=
ry (and data relating the two). The CUB reader in MOAB can import and inte=
rpret much of the meta-data information saved in .cub files. Ref. [4] desc=
ribes the conventions used to store this meta-data in the MOAB data model. =
The information read from .cub files, and stored in the MOAB data model, i=
ncludes:
+
+- Geometric model entities and topology
+- Model entity names and ids
+- Groups, element blocks, nodesets, and sidesets, including model entities=
stored in them
+- Mesh scheme and interval size information assigned to model entities
+.
+
+Note that although information about model entities is recovered, MOAB by =
default does not depend on a solid modeling engine; this information is sto=
red in the form of entity sets and parent/child relations between them. Se=
e Ref. [4] for more information.
+
+ \ref contents
+
+ \subsection cgm 4.6.3. CGM Reader
+
+The Common Geometry Module (CGM) [17] is a library for representing solid =
model and other types of solid geometry data. The CUBIT mesh generation to=
olkit uses CGM for its geometric modeling support, and CGM can restore geom=
etric models in the exact state in which they were represented in CUBIT. M=
OAB contains a CGM reader, which can be enabled with a configure option. U=
sing this reader, MOAB can read geometric models, and represent their model=
topology using entity sets linked by parent/child relations. The mesh in =
these models comes directly from the modeling engine faceting routines; the=
se are the same facets used to visualize solid models in other graphics eng=
ines. When used in conjunction with the VisIt visualization tool (see Sect=
ion ), this provides a solution for visualizing geometric models. Xxx sho=
ws a model imported using MOAB=E2=80=99s CGM reader and visualized with Vis=
It.=20
+
+ \ref contents
+
+ \section parallel 5. Parallel Mesh Representation and Query
+
+A parallel mesh representation must strike a careful balance between provi=
ding an interface to mesh similar to that of a serial mesh, while also allo=
wing the discovery of parallel aspects of the mesh and performance of paral=
lel mesh-based operations efficiently. MOAB supports a spatial domain-deco=
mposed view of a parallel mesh, where each subdomain is assigned to a proce=
ssor, lower-dimensional entities on interfaces between subdomains are share=
d between processors, and ghost entities can be exchanged with neighboring =
processors. Locally, each subdomain, along with any locally-represented gh=
ost entities, are accessed through a local MOAB instance. Parallel aspects=
of the mesh, e.g. whether entities are shared, on an interface, or ghost e=
ntities, are embedded in the same data model (entities, sets, tags, interfa=
ce) used in the rest of MOAB. MOAB provides a suite of parallel functions =
for initializing and communicating with a parallel mesh, along with functio=
ns to query the parallel aspects of the mesh.
+
+ \ref contents
+
+ \subsection fiveone 5.1. Nomenclature & Representation
+
+Before discussing how to access parallel aspects of a mesh, several terms =
need to be defined: =20
+
+<B>Shared entity:</B> An entity shared by one or several other processors.
+
+<B>Multi-shared entity:</B> An entity shared by more than two processors.
+
+<B>Owning Processor:</B> Each shared entity is owned by exactly one proces=
sor. This processor has the right to set tag values on the entity and have=
those values propagated to any sharing processors. =20
+
+<B>Part:</B> The collection of entities assigned to a given processor. Wh=
en reading mesh in parallel, the entities in a Part, along with any lower-d=
imensional entities adjacent to those, will be read onto the assigned proce=
ssor.
+
+<B>Partition:</B> A collection of Parts which take part in parallel collec=
tive communication, usually associated with an MPI communicator.
+
+<B>Interface:</B> A collection of mesh entities bounding entities in multi=
ple parts. Interface entities are owned by a single processor, but are rep=
resented on all parts/processors they bound.
+
+<B>Ghost entity:</B> A shared, non-interface, non-owned entity.
+
+<B>Parallel status:</B> A characteristic of entities and sets represented =
in parallel. The parallel status, or =E2=80=9Cpstatus=E2=80=9D, is represen=
ted by a bit field stored in an unsigned character, with bit values as desc=
ribed in Table 4.
+
+ \subsection tablefour Table 4: Bits representing various parallel charac=
teristics of a mesh. Also listed are enumerated values that can be used in=
bitmask expressions; these enumerated variables are declared in MBParallel=
Conventions.h.
+
+<table border=3D"1">
+<tr>
+<th>Bit</th>
+<th>Name</th>
+<th>Represents</th>
+</tr>
+<tr>
+<td>0x1</td>
+<td>PSTATUS_NOT_OWNED</td>
+<td>Not owned by the local processor</td>
+</tr>
+<tr>
+<td>0x2</td>
+<td>PSTATUS_SHARED</td>
+<td>Shared by exactly two processorstd>
+</tr>
+<tr>
+<td>0x4</td>
+<td>PSTATUS_MULTISHARED</td>
+<td>Shared by three or more processors</td>
+</tr>
+<tr>
+<td>0x8</td>
+<td>PSTATUS_INTERFACE</td>
+<td>Part of lower-dimensional interface shared by multiple processors</td>
+</tr>
+<tr>
+<td>0x10</td>
+<td>PSTATUS_GHOST</td>
+<td>Non-owned, non-interface entities represented locally</td>
+</tr>
+</table>
+
+Parallel functionality is described in the following sections. First, met=
hods to load a mesh into a parallel representation are described; next, fun=
ctions for accessing parallel aspects of a mesh are described; functions fo=
r communicating mesh and tag data are described.
+
+ \ref contents
+
+ \subsection fivetwo 5.2. Parallel Mesh Initialization
+
+Parallel mesh is initialized in MOAB in several steps:
+
+-# Establish a local mesh on each processor, either by reading the mesh i=
nto that representation from disk, or by creating mesh locally through the =
normal MOAB interface. =20
+-# Find vertices, then other entities, shared between processors, based o=
n a globally-consistent vertex numbering stored on the GLOBAL_ID tag. =20
+-# Exchange ghost or halo elements within a certain depth of processor in=
terfaces with neighboring processors. =20
+.
+
+These steps can be executed by a single call to MOAB=E2=80=99s load_file f=
unction, using the procedure described in Section 5.2.1. Or, they can be e=
xecuted in smaller increments calling specific functions in MOAB=E2=80=99s =
ParallelComm class, as described in Section 5.2.2. Closely related to the =
latter method is the handling of communicators, described in more detail in=
Section.
+
+ \ref contents
+
+ \subsection initialization 5.2.1. Parallel Mesh Initialization by Loadin=
g a File
+
+In the file reading approach, a mesh must contain some definition of the p=
artition (the assignment of mesh, usually regions, to processors). Partiti=
ons can be derived from other set structures already on the mesh, or can be=
computed explicitly for that purpose by tools like mbzoltan (see Section 4=
.2). For example, geometric volumes used to generate the mesh, and region-=
based material type assignments, are both acceptable partitions (see Ref. [=
4] for information about this and other meta-data often accompanying mesh).=
In addition to defining the groupings of regions into parts, the assignme=
nt of specific parts to processors can be done implicitly or using addition=
al data stored with the partition.
+
+MOAB implements several specific methods for loading mesh into a parallel =
representation:
+
+- READ_PART: each processor reads only the mesh used by its part(s).
+
+- READ_DELETE: each processor reads the entire mesh, then deletes the mesh=
not used by its part(s).
+
+- BCAST_DELETE: the root processor reads and broadcasts the mesh; each pro=
cessor then deletes the mesh not used by its part(s).
+
+The READ_DELETE and BCAST_DELETE methods are supported for all file types =
MOAB is able to read, while READ_PART is only implemented for MOAB=E2=80=99=
s native HDF5-based file format.
+
+Various other options control the selection of part sets or other details =
of the parallel read process. For example, the application can specify the=
tags, and optionally tag values, which identify parts, and whether those p=
arts should be distributed according to tag value or using round-robin assi=
gnment.
+
+The options used to specify loading method, the data used to identify part=
s, and other parameters controlling the parallel read process, are shown in=
Table 5. =20
+ \subsection tablefive Table 5: Options passed to MOAB=E2=80=99s load_fil=
e function identifying the partition and other parameters controlling the p=
arallel read of mesh data. Options and values should appear in option stri=
ng as =E2=80=9Coption=3Dval=E2=80=9D, with a delimiter (usually =E2=80=9C;=
=E2=80=9D) between options.
+
+<table border=3D"1">
+<tr>
+<th>Option</th>
+<th>Value</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>PARTITION</td>
+<td><tag_name></td>
+<td>Sets with the specified tag name should be used as part sets</td>
+</tr>
+<tr>
+<td>PARTITION_VAL</td>
+<td><val1, val2-val3, ...></td>
+<td>Integer values to be combined with tag name, with ranges input using v=
al1, val2-val3. Not meaningful unless PARTITION option is also given.</td>
+</tr>
+<tr>
+<td>PARTITION_DISTRIBUTE</td>
+<td>(none)</td>
+<td>If present, or values are not input using PARTITION_VAL, sets with tag=
indicated in PARTITION option are partitioned across processors in round-r=
obin fashion.</td>
+</tr>
+<tr>
+<td>PARALLEL_RESOLVE_SHARED_ENTS</td>
+<td><pd.sd></td>
+<td>Resolve entities shared between processors, where partition is made up=
of pd- dimensional entities, and entities of dimension sd and lower should=
be resolved.</td>
+</tr>
+<tr>
+<td>PARALLEL_GHOSTS</td>
+<td><gd.bd.nl[.ad]></td>
+<td>Exchange ghost elements at shared inter-processor interfaces. Ghost e=
lements of dimension gd will be exchanged. Ghost elements are chosen going=
through bd-dimensional interface entities. Number of layers of ghost elem=
ents is specified in nl. If ad is present, lower-dimensional entities boun=
ding exchanged ghost entities will also be exchanged; allowed values for ad=
are 1 (exchange bounding edges), 2 (faces), or 3 (edges and faces).</td>
+</tr>
+<tr>
+<td>CPUTIME</td>
+<td>(none)</td>
+<td>Print cpu time required for each step of parallel read & initializatio=
n.</td>
+</tr>
+<tr>
+<td>MPI_IO_RANK</td>
+<td><r></td>
+<td>If read method requires reading mesh onto a single processor, processo=
r with rank r is used to do that read.</td>
+</tr>
+</table>
+
+Several example option strings controlling parallel reading and initializa=
tion are:
+
+<B>=E2=80=9CPARALLEL=3DREAD_DELETE; PARTITION=3DMATERIAL_SET; PARTITION_VA=
L=3D100, 200, 600-700=E2=80=9D:</B> The whole mesh is read by every process=
or; this processor keeps mesh in sets assigned the tag whose name is =E2=80=
=9CMATERIAL_SET=E2=80=9D and whose value is any one of 100, 200, and 600-70=
0 inclusive.
+
+<B>=E2=80=9CPARALLEL=3DREAD_PART; PARTITION=3DPARALLEL_PARTITION, PARTITIO=
N_VAL=3D2=E2=80=9D:</B> Each processor reads only its mesh; this processor,=
whose rank is 2, is responsible for elements in a set with the PARALLEL_PA=
RTITION tag whose value is 2. This would by typical input for a mesh which=
had already been partitioned with e.g. Zoltan or Parmetis.
+
+<B>=E2=80=9CPARALLEL=3DBCAST_DELETE; PARTITION=3DGEOM_DIMENSION, PARTITION=
_VAL=3D3, PARTITION_DISTRIBUTE=E2=80=9D:</B> The root processor reads the f=
ile and broadcasts the whole mesh to all processors. If a list is construc=
ted with entity sets whose GEOM_DIMENSION tag is 3, i.e. sets corresponding=
to geometric volumes in the original geometric model, this processor is re=
sponsible for all elements with index R+iP, i >=3D 0 (i.e. a round-robin di=
stribution).
+
+ \ref contents
+
+ \subsection functions 5.2.2. Parallel Mesh Initialization Using Functions
+
+After creating the local mesh on each processor, an application can call t=
he following functions in ParallelComm to establish information on shared m=
esh entities. See the [ref-directparmesh example] in the MOAB source tree =
for a complete example of how this is done from an application.
+
+- ParallelComm::resolve_shared_entities (collective): Resolves shared enti=
ties between processors, based on GLOBAL_ID tag values of vertices. Variou=
s forms are available, based on entities to be evaluated and maximum dimens=
ion for which entity sharing should be found.
+
+- ParallelComm::exchange_ghost_cells (collective): Exchange ghost entities=
with processors sharing an interface with this processor, based on specifi=
ed ghost dimension (dimension of ghost entities exchanged), bridge dimensio=
n, number of layers, and type of adjacencies to ghost entities. An entity =
is sent as a ghost if it is within that number of layers, across entities o=
f the bridge dimension, with entities owned by the receiving processor, or =
if it is a lower-dimensional entity adjacent to a ghost entity and that opt=
ion is requested.
+.
+
+ \ref contents
+
+ \subsection communicator 5.2.3. Communicator Handling
+
+The ParallelComm constructor takes arguments for an MPI communicator and a=
MOAB instance. The ParallelComm instance stores the MPI communicator, and=
registers itself with the MOAB instance. Applications can specify the Par=
allelComm index to be used for a given file operation, thereby specifying t=
he MPI communicator for that parallel operation. For example:
+
+\code
+using namespace moab;
+// pass a communicator to the constructor, getting back the index
+MPI_Comm my_mpicomm;
+int pcomm_index;
+ParallelComm my_pcomm(moab, my_mpicomm, &pcomm_index);
+
+// write the pcomm index into a string option
+char load_opt[32];
+sprintf(load_opt, "PARALLEL=3DBCAST_DELETE;PARALLEL_COMM=3D%d",=20
+ pcomm_index);
+
+// specify that option in a parallel read operation
+ErrorCode rval =3D moab->load_file(load_opt, fname, ...)
+\endcode
+
+In the above code fragment, the ParallelComm instance with index pcomm_ind=
ex will be used in the parallel file read, so that the operation executes o=
ver the specified MPI communicator. If no ParallelComm instance is specifi=
ed for a parallel file operation, a default instance will be defined, using=
MPI_COMM_WORLD.
+
+Applications needing to retrieve a ParallelComm instance created previousl=
y and stored with the MOAB instance, e.g. by a different code component, ca=
n do so using a static function on ParallelComm:
+
+\code
+ParallelComm *my_pcomm =3D ParallelComm::get_pcomm(moab, pcomm_index);
+\endcode
+
+ParallelComm also provides the ParallelComm::get_all_pcomm function, for r=
etrieving all ParallelComm instances stored with a MOAB instance. For synt=
ax and usage of this function, see the MOAB online documentation for Parall=
elComm.hpp [8].
+
+ \ref contents
+
+ \subsection fivethree 5.3. Parallel Mesh Query Functions
+
+Various functions are commonly used in parallel mesh-based applications. =
Functions marked as being collective must be called collectively for all pr=
ocessors that are members of the communicator associated with the ParallelC=
omm instance used for the call.
+
+<B>ParallelComm::get_pstatus:</B> Get the parallel status for the entity.
+
+<B>ParallelComm::get_pstatus_entities:</B> Get all entities whose pstatus =
satisfies (pstatus & val).
+
+<B>ParallelComm::get_owner:</B> Get the rank of the owning processor for t=
he specified entity.
+
+<B>ParallelComm::get_owner_handle:</B> Get the rank of the owning processo=
r for the specified entity, and the entity's handle on the owning processor.
+
+<B>ParallelComm::get_sharing_data:</B> Get the sharing processor(s) and ha=
ndle(s) for an entity or entities. Various overloaded versions are availab=
le, some with an optional =E2=80=9Coperation=E2=80=9D argument, where Inter=
face::INTERSECT or Interface::UNION can be specified. This is similar to t=
he operation arguments to Interface::get_adjacencies.
+
+<B>ParallelComm::get_shared_entities:</B> Get entities shared with the giv=
en processor, or with all processors. This function has optional arguments=
for specifying dimension, whether interface entities are requested, and wh=
ether to return just owned entities.
+
+<B>ParallelComm::get_interface_procs:</B> Return all processors with whom =
this processor shares an interface.
+
+<B>ParallelComm::get_comm_procs:</B> Return all processors with whom this =
processor communicates.
+
+ \ref contents
+
+ \subsection fivefour 5.4. Parallel Mesh Communication
+
+Once a parallel mesh has been initialized, applications can call the Paral=
lelComm::exchange_tags function for exchanging tag values between processor=
s. This function causes the owning processor to send the specified tag val=
ues for all shared, owned entities to other processors sharing those entiti=
es. Asynchronous communication is used to hide latency, and only point-to-=
point communication is used in these calls.
+
+ \ref contents
+
+ \section applications 6. Building MOAB-Based Applications
+
+There are two primary mechanisms supported by MOAB for building applicatio=
ns, one based on MOAB-defined make variables, and the other based on the us=
e of libtool and autoconf. Both assume the use of a =E2=80=9Cmake=E2=80=9D=
-based build system. =20
+
+The easiest way to incorporate MOAB into an application=E2=80=99s build pr=
ocess is to include the =E2=80=9Cmoab.make=E2=80=9D file into the applicati=
on=E2=80=99s Makefile, adding the make variables MOAB_INCLUDES and MOAB_LIB=
S_LINK to application=E2=80=99s compile and link commands, respectively. M=
OAB_INCLUDES contains compiler options specifying the location of MOAB incl=
ude files, and any preprocessor definitions required by MOAB. MOAB_LIBS_LI=
NK contains both the options telling where libraries can be found, and the =
link options which incorporate those libraries into the application. Any l=
ibraries depended on by the particular configuration of MOAB are included i=
n that definition, e.g. the HDF5 library. Using this method to incorporate=
MOAB is the most straightforward; for example, the following Makefile is u=
sed to build one of the example problems packaged with the MOAB source:
+\code
+include ${MOAB_LIB_DIR}/moab.make
+
+GetEntities : GetEntities.o
+ ${CXX} $< ${MOAB_LIBS_LINK} -o $@
+
+.cpp.o :=20
+ ${CXX} ${MOAB_INCLUDES} -c $<
+\endcode
+
+Here, the MOAB_LIB_DIR environment variable or make argument definition sp=
ecifies where the MOAB library is installed; this is also the location of t=
he moab.make file. Once that file has been included, MOAB_INCLUDES and MOA=
B_LIBS_LINK can be used, as shown.
+
+Other make variables are defined in the moab.make file which simplify buil=
ding applications:
+
+- MOAB_LIBDIR, MOAB_INCLUDEDIR: the directories into which MOAB libraries =
and include files will be installed, respectively. Note that some include =
files are put in a subdirectory named =E2=80=9Cmoab=E2=80=9D below that dir=
ectory, to reflect namespace naming conventions used in MOAB.
+
+- MOAB_CXXFLAGS, MOAB_CFLAGS, MOAB_LDFLAGS: Options passed to the C++ and =
C compilers and the linker, respectively.
+
+- MOAB_CXX, MOAB_CC, MOAB_FC: C++, C, and Fortran compilers specified to M=
OAB at configure time, respectively.
+.
+
+The second method for incorporating MOAB into an application=E2=80=99s bui=
ld system is to use autoconf and libtool. MOAB is configured using these t=
ools, and generates the =E2=80=9C.la=E2=80=9D files that hold information o=
n library dependencies that can be used in application build systems also b=
ased on autoconf and libtool. Further information on this subject is beyon=
d the scope of this User=E2=80=99s Guide; see the =E2=80=9C.la=E2=80=9D fil=
es as installed by MOAB, and contact the MOAB developer=E2=80=99s mailing l=
ist [6] for more details.
+
+ \ref contents
+
+ \section implementation 7. iMesh (ITAPS Mesh Interface) Implementation =
in MOAB
+
+iMesh is a common API to mesh data developed as part of the Interoperable =
Tools for Advanced Petascale Simulations (ITAPS) project [18]. Application=
s using the iMesh interface can operate on any implementation of that inter=
face, including MOAB. MOAB-based applications can take advantage of other =
services implemented on top of iMesh, including the MESQUITE mesh improveme=
nt toolkit [19] and the GRUMMP mesh improvement library [20].
+
+MOAB=E2=80=99s native interface is accessed through the Interface abstract=
C++ base class. Wrappers are not provided in other languages; rather, app=
lications wanting to access MOAB from those languages should do so through =
iMesh. In most cases, the data models and functionality available through =
MOAB and iMesh are identical. However, there are a few differences, subtle=
and not-so-subtle, between the two:
+
+<B>SPARSE tags used by default:</B> MOAB=E2=80=99s iMesh implementation cr=
eates SPARSE tags by default, because of semantic requirements of other tag=
-related functions in iMesh. To create DENSE tags through iMesh, use the i=
Mesh_createTagWithOptions extension function (see below).
+
+<B>Higher-order elements:</B> ITAPS currently handles higher-order element=
s (e.g. a 10-node tetrahedron) usi[21]<sup>5</sup>. As described in [sec-e=
ntities], MOAB supports higher-order entities by allowing various numbers o=
f vertices to define topological entities like quadrilateral or tetrahedron=
. Applications can specify flags to the connectivity and adjacency functio=
ns specifying whether corner or all vertices are requested.
+
+<B>Self-adjacencies:</B> In MOAB=E2=80=99s native interface, entities are =
always self-adjacent<sup>6</sup>; that is, adjacencies of equal dimension r=
equested from an entity will always include that entity, while from iMesh w=
ill not include that entity.
+
+<B>Option strings:</B> The iMesh specification requires that options in th=
e options string passed to various functions (e.g. iMesh_load) be prepended=
with the implementation name required to parse them, and delimited with sp=
aces. Thus, a MOAB-targeted option would appear as =E2=80=9Cmoab:PARALLEL=
=3DREAD_PART moab:PARTITION=3DMATERIAL_SET=E2=80=9D.
+
+To provide complete MOAB support from other languages through iMesh, a col=
lection of iMesh extension functions are also available. A general descrip=
tion of these extensions appears below; for a complete description, see the=
online documentation for iMesh-extensions.h [8].
+
+- Recursive get_entities functions: There are many cases where sets includ=
e other sets (see [4] for more information). MOAB provides iMesh_getEntiti=
esRec, and other recursive-supporting functions, to get all non-set entitie=
s of a given type or topology accessible from input set(s). Similar functi=
ons are available for number of entities of a given type/topology.
+
+- Get entities by tag, and optionally tag value: It is common to search fo=
r entities with a given tag, and possibly tag value(s); functions like iMes=
h_getEntitiesByTag are provided for this purpose.
+
+- Options to createTag: To provide more control over the tag type, the iMe=
sh_createTagWithOptions is provided. The storage type is controlled with t=
he =E2=80=9C
+
+- MBCNType: Canonical numbering evaluations are commonly needed by applica=
tions, e.g. to apply boundary conditions locally. The MBCN package provide=
s these evaluations in terms of entity types defined in MOAB [9]; the getMB=
CNType is required to translate between iMesh_Topology and MBCN type.
+
+- Iterator step: Step an iterator a specified number of entities; allows a=
dvancement of an iterator without needing to allocate memory to hold the en=
tity handles stepped over.
+
+- Direct access to tag storage: The Interface::tag_iterate function allows=
an application get a pointer to the memory used to store a given tag. For=
dense tags on contiguous ranges of entities, this provides more efficient =
access to tags. The iMesh functionn iMesh_tagIterate provides access to th=
is functionlity. See examples/TagIterateC.c and examples/TagIterateF.F for=
examples of how to use this from C and Fortran, respectively.=20
+.
+
+As required by the iMesh specification, MOAB generates the =E2=80=9CiMesh-=
Defs.inc=E2=80=9D file and installs it with the iMesh and MOAB libraries. =
This file defines make variables which can be used to build iMesh-based app=
lications. The method used here is quite similar to that used for MOAB its=
elf (see Section 6). In particular, the IMESH_INCLUDES and IMESH_LIBS make=
variables can be used with application compile and link commands, respecti=
vely, with other make variables similar to those provided in moab.make also=
available.
+
+Note that using the iMesh interface from Fortran-based applications requir=
es a compiler that supports Cray pointers, along with the pass-by-value (%V=
AL) extension. Almost all compilers support those extensions; however, if =
using the gcc series of compilers, you must use gfortran 4.3 or later.
+
+<sup>5</sup>There are currently no implementations of this interface.
+
+<sup>6</sup>iMesh and MOAB both define adjacencies using the topological c=
oncept of closure. Since the closure of an entity includes the entity itse=
lf, the d-dimensional entities on the closure of a given entity should incl=
ude the entity itself.
+
+ \ref contents
+
+ \section representation 8. Structured Mesh Representation
+
+A structured mesh is defined as a D-dimensional mesh whose interior vertic=
es have 2D connected edges. Structured mesh can be stored without connect=
ivity, if certain information is kept about the parametric space of each st=
ructured block of mesh. MOAB can represent structured mesh with implicit c=
onnectivity, saving approximately 57% of the storage cost compared to an un=
structured representation<sup>7</sup>. Since connectivity must be computed=
on the fly, these queries execute a bit slower than those for unstructured=
mesh. More information on the theory behind MOAB's structured mesh repres=
entation can be found in=20
+
+Currently, MOAB's structured mesh representation can only be used by creat=
ing structured mesh at runtime; that is, structured mesh is saved/restored =
in an unstructured format in MOAB's HDF5-based native save format. For mor=
e details on how to use MOAB's structured mesh representation, see the scds=
eq_test.cpp source file in the test/ directory.
+
+<sup>7</sup> This assumes vertex coordinates are represented explicitly, a=
nd that there are approximately the same number of vertices and hexahedra i=
n a structured hex mesh.
+
+ \ref contents
+
+ \section element 9. Spectral Element Meshes
+
+The Spectral Element Method (SEM) is a high-order method, using a polynomi=
al Legendre interpolation basis with Gauss-Lobatto quadrature points, in co=
ntrast to the Lagrange basis used in (linear) finite elements [20]. SEM ob=
tains exponential convergence with decreasing mesh characteristic sizes, an=
d codes implementing this method typically have high floating-point intensi=
ty, making the method highly efficient on modern CPUs. Most Nth-order SEM =
codes require tensor product cuboid (quad/hex) meshes, with each d-dimensio=
nal element containing (N+1)d degrees of freedom (DOFs). There are various=
methods for representing SEM meshes and solution fields on them; this docu=
ment discusses these methods and the tradeoffs between them. The mesh part=
s of this discussion are given in terms of the iMesh mesh interface and its=
implementation by the MOAB mesh library [21].
+
+The figure above shows a two-dimensional 3rd-order SEM mesh consisting of =
four quadrilaterals. For this mesh, each quadrilateral has (N+1)^2=3D16 DO=
Fs, with corner and edge degrees of freedom shared between neighboring quad=
rilaterals.
+
+ \ref contents
+
+ \subsection nineone 9.1. Representations
+
+There are various representations of this mesh in a mesh database like MOA=
B, depending on how DOFs are related to mesh entities and tags on those ent=
ities. We mention several possible representations:
+
+-# Corner vertices, element-based DOFs: Each quadrilateral is defined by f=
our vertices, ordered in CCW order typical of FE meshes. DOFs are stored a=
s tags on quadrilaterals, with size (N+1)^2 values, ordered lexicographical=
ly (i.e. as a 2D array tag(i,j) with i varying faster than j.) In the figu=
re above, the connectivity for face 1 would be (1, 4, 16, 13), and DOFs wou=
ld be ordered (1..16). Note that in this representation, tag values for DO=
Fs shared by neighboring elements must be set multiple times, since there a=
re as many copies of these DOFs as elements sharing them.
+-# High-order FE-like elements: Each DOF is represented by a mesh vertex. =
Quadrilaterals each have (N+1)^2 vertices, ordered as they would be for hig=
h-order finite elements (corner vertices first, then mid-edge and mid-face =
elements; see [22]). Mid -face, -edge, and -region vertices for a given ed=
ge/face/region would be ordered lexicographically, according to positive di=
rection in a corresponding reference element. In the figure above, the con=
nectivity array for face 1 would be (1, 4, 16, 13, 2, 3, 8, 12, 14, 15, 5, =
9, 6, 7, 10, 11). DOF values are stored as tags on vertices. Since DOFs a=
re uniquely associated with vertices and vertices are shared by neighboring=
elements, tag values only need to be set once. Full vertex-quadrilateral =
adjacencies are available, for all vertices.
+-# Linear FE-like elements, one vertex per DOF, array with DOF vertices: E=
ach quadrilateral is defined by four (corner) vertices, with additional ver=
tices representing mid-edge and mid-face DOFs. An additional =E2=80=9CDOF =
array=E2=80=9D tag is assigned to each quadrilateral, storing the array of =
vertices representing the (N+1)^2 DOFs for the quadrilateral, ordered lexic=
ographically. For the figure above, the connectivity array for face 1 woul=
d be (1, 4, 16, 13), and the DOF array would be (1..16), assuming that vert=
ex handles are integers as shown in the figure. DOF values are stored as t=
ags on vertices, and lexicographically-ordered arrays of DOFs can be retrie=
ved using the DOF array tag as input to the tag_get_data function in MOAB. =
Adjacency functions would only be meaningful for corner vertices, but tag =
values would only need to be set once per DOF.
+-# High-order FE-like elements, array with DOF vertices: This is a combina=
tion of options 2 and 3. The advantage would be full vertex-quad adjacency=
support and direct availability of lexicographically-ordered vertex arrays=
, at the expense of more memory.
+-# Convert to linear mesh: Since a spectral element is a cuboid with highe=
r-order vertices, it can always be converted to N^2 linear cuboids using th=
e high-order vertices as corners of the finer quads/hexes. This is how rea=
ders in ParaView and VisIt typically import spectral meshes (CAM-SE also ex=
ports connectivity in this form).
+
+As a convenience for applications, functions could also be provided for im=
portant tasks, like assembling the vertex handles for an entity in lexograp=
hic order (useful for option 2 above), and getting an array of tag values i=
n lexicographic order (for option 3 above).
+
+ \ref contents
+
+ \subsection ninetwo 9.2. Tradeoffs
+
+There are various competing tradeoffs in the various representation types.=
These include:
+
+- Adjacencies: being able to retrieve the element(s) using a given (corner=
or higher-order) vertex.
+- Connectivity list: being able to retrieve the connectivity of a given el=
ement, consisting of all (corner + higher-order) vertices in the element, u=
sually in lexicographical order. This is closely linked with being able to=
access the connectivity list as a const*, i.e. using the list straight fro=
m memory without needing to copy it.
+- Memory vs. time: There is a memory vs. execution time tradeoff between d=
uplicating interface vertex solution/tag variables in neighboring elements =
(more memory but more time-efficient and allows direct access to tag storag=
e by applications) versus using vertex-based tags (less memory but requires=
assembly of variables into lexicographically-ordered arrays, and prevents =
direct access from applications).
+.
+
+The lower-memory option (storing variables on vertices and assembling into=
lexicographically-ordered arrays for application use) usually ends up cost=
ing more in memory anyway, since applications must allocate their own stora=
ge for these arrays. On the other hand, certain applications will always c=
hoose to do that, instead of sharing storage with MOAB for these variables.=
In the case where applications do share memory with MOAB, other tools wou=
ld need to interpret the lexicographically-ordered field arrays specially, =
instead of simply treating the vertex tags as a point-based field.
+
+ \ref contents
+
+ \subsection ninethree 9.3. MOAB Representation
+In choosing the right MOAB representation for spectral meshes, we are tryi=
ng to balance a) minimal memory usage, b) access to properly-ordered and -a=
ligned tag storage, and c) maximal compatibility with tools likely to use M=
OAB. The solution we propose is to use a representation most like option 2=
) above, with a few optional behaviors based on application requirements. =20
+
+In brief, we propose to represent elements using the linear, FE-ordered co=
nnectivity list (containing only corner vertices from the spectral element)=
, with field variables written to either vertices, lexicographically-ordere=
d arrays on elements, or both, and with a lexicographically-ordered array (=
stored on tag SPECTRAL_VERTICES) of all (corner+higher-order) vertices stor=
ed on elements. In the either/or case, the choice will be evident from the=
tag size and the entities on which the tag is set. In the both case, the =
tag name will have a =E2=80=9C-LEX=E2=80=9D suffix for the element tags, an=
d the size of the element tag will be (N+1)^2 times that of the vertex-base=
d tag. Finally, the file set containing the spectral elements (or the root=
set, if no file set was input to the read) will contain a =E2=80=9CSPECTRA=
L_ORDER=E2=80=9D tag whose value is N. These conventions are described in =
the =E2=80=9CMetadata Information=E2=80=9D document distributed with the MO=
AB source code.
+
+ \ref contents
+
+ \section performance 10. Performance and Using MOAB Efficiently from App=
lications
+
+MOAB is designed to operate efficiently on groups of entities and for larg=
e meshes. Applications will be most efficient when they operate on entitie=
s in groups, especially groups which are close in their order of creation. =
The MOAB API is structured to encourage operations on groups of entities. =
Conversely, MOAB will not perform as well as other libraries if there are =
frequent deletion and creation of entities. For those types of application=
s, a mesh library using a C++ object-based representation is more appropria=
te. In this section, performance of MOAB when executing a variety of tasks=
is described, and compared to that of other representations. Of course, t=
hese metrics are based on the particular models and environments where they=
are run, and may or may not be representative of other application types.
+
+One useful measure of MOAB performance is in the representation and query =
of a large mesh. MOAB includes a performance test, located in the test/per=
f directory, in which a single rectangular region of hexahedral elements is=
created then queried; the following steps are performed:
+
+- Create the vertices and hexes in the mesh
+- For each vertex, get the set of connected hexahedra
+- For each hex, get the connected vertices, their coordinates, average the=
m, and assign them as a tag on the hexes
+.
+
+This test can be run on your system to determine the runtime and memory pe=
rformance for these queries in MOAB.
+
+ \ref contents
+
+ \section conclusions 11. Conclusions and Future Plans
+
+MOAB, a Mesh-Oriented datABase, provides a simple but powerful data abstra=
ction to structured and unstructured mesh, and makes that abstraction avail=
able through a function API. MOAB provides the mesh representation for the=
VERDE mesh verification tool, which demonstrates some of the powerful mesh=
metadata representation capabilities in MOAB. MOAB includes modules that =
import mesh in the ExodusII, CUBIT .cub and Vtk file formats, as well as th=
e capability to write mesh to ExodusII, all without licensing restrictions =
normally found in ExodusII-based applications. MOAB also has the capabilit=
y to represent and query structured mesh in a way that optimizes storage sp=
ace using the parametric space of a structured mesh; see Ref. [17] for deta=
ils.
+
+Initial results have demonstrated that the data abstraction provided by MO=
AB is powerful enough to represent many different kinds of mesh data found =
in real applications, including geometric topology groupings and relations,=
boundary condition groupings, and inter-processor interface representation=
. Our future plans are to further explore how these abstractions can be us=
ed in the design through analysis process.
+
+ \ref contents
+
+ \section references 12. References
+
+[1] M. Fatenejad and G.A. Moses, =E2=80=9CCooper radiation hydrodynamics c=
ode..=E2=80=9D
+
+[2] T.J. Tautges and A. Caceres, =E2=80=9CScalable parallel solution coupl=
ing for multiphysics reactor simulation,=E2=80=9D Journal of Physics: Confe=
rence Series, vol. 180, 2009.
+
+[3] T.J. Tautges, MOAB Meta-Data Information, 2010.
+
+[4] T.J. Tautges, =E2=80=9CMOAB - ITAPS =E2=80=93 Trac.=E2=80=9D, http://t=
rac.mcs.anl.gov/projects/ITAPS/wiki/MOAB
+
+[5] =E2=80=9CMOAB Developers Email List.=E2=80=9D, moab-dev at mcs.anl.gov.
+
+[6] =E2=80=9CMOAB Users Email List.=E2=80=9D, moab at mcs.anl.gov.
+
+[7] =E2=80=9CMOAB online documentation.=E2=80=9D, http://gnep.mcs.anl.gov:=
8010/moab-docs/
+
+[8] T.J. Tautges, =E2=80=9CCanonical numbering systems for finite-element =
codes,=E2=80=9D Communications in Numerical Methods in Engineering, vol. O=
nline, Mar. 2009.
+
+[9] L.A. Schoof and V.R. Yarberry, EXODUS II: A Finite Element Data Model,=
Albuquerque, NM: Sandia National Laboratories, 1994.
+
+[10] M. PATRAN, =E2=80=9CPATRAN User=E2=80=99s Manual,=E2=80=9D 2005.
+
+[11] VisIt User's Guide.
+
+[12] K. Devine, E. Boman, R. Heaphy, B. Hendrickson, and C. Vaughan, =E2=
=80=9CZoltan Data Management Services for Parallel Dynamic Applications,=E2=
=80=9D Computing in Science and Engineering, vol. 4, 2002, pp. 90=E2=80=93=
97.
+
+[13] T.J. Tautges, P.P.H. Wilson, J. Kraftcheck, B.F. Smith, and D.L. Hend=
erson, =E2=80=9CAcceleration Techniques for Direct Use of CAD-Based Geomet=
ries in Monte Carlo Radiation Transport,=E2=80=9D International Conference =
on Mathematics, Computational Methods & Reactor Physics (M&C 2009), Sarato=
ga Springs, NY: American Nuclear Society, 2009.
+
+[14] H. Kim and T. Tautges, =E2=80=9CEBMesh: An Embedded Boundary Meshing =
Tool,=E2=80=9D in preparation.
+
+[15] G.D. Sjaardema, T.J. Tautges, T.J. Wilson, S.J. Owen, T.D. Blacker, W=
.J. Bohnhoff, T.L. Edwards, J.R. Hipp, R.R. Lober, and S.A. Mitchell, CUBIT=
mesh generation environment Volume 1: Users manual, Sandia National Labora=
tories, May 1994, 1994.
+
+[16] T.J. Tautges, =E2=80=9CCGM: A geometry interface for mesh generation,=
analysis and other applications,=E2=80=9D Engineering with Computers, vol=
. 17, 2001, pp. 299-314.
+
+[17] T. J. Tautges, MOAB-SD: Integrated structured and unstructured mesh r=
epresentation, Engineering with Computers, vol. 20, no. 3, pp. 286-293, 200=
4.
+
+[18] =E2=80=9CInteroperable Technologies for Advanced Petascale Simulation=
s (ITAPS),=E2=80=9D Interoperable Technologies for Advanced Petascale Simul=
ations (ITAPS).
+
+[19] P. Knupp, =E2=80=9CMesh quality improvement for SciDAC applications,=
=E2=80=9D Journal of Physics: Conference Series, vol. 46, 2006, pp. 458-46=
2.
+
+[20] M. O. Deville, P. F. Fischer, and E. H. Mund, High-order methods for =
incompressible fluid flow. Cambridge, UK; New York: Cambridge University Pr=
ess, 2002.
+
+[21] T. J. Tautges, =E2=80=9CMOAB Wiki.=E2=80=9D [Online]. Available: http=
://trac.mcs.anl.gov/projects/ITAPS/wiki/MOAB. [Accessed: 30-Oct-2012].
+
+[22] T. J. Tautges, =E2=80=9CCanonical numbering systems for finite-elemen=
t codes,=E2=80=9D International Journal for Numerical Methods in Biomedical=
Engineering, vol. 26, no. 12, pp. 1559=E2=80=931572, 2010.
+
+
+ \ref contents
+
+ \page differences Differences Between iMesh and MOAB
+
+ The data models used in MOAB and iMesh are quite similar, but not identi=
cal.The most significant differences are the following:
+
+- Tags: MOAB differentiates between DENSE, SPARSE, and BIT tags, using dif=
ferent storage models for each, while iMesh uses a single tag concept. iMe=
sh allows application to query whether an entity has been given a tag of a =
specified type; this query is incompatible with the concept of a DENSE tag =
with a default value. Thus, MOAB=E2=80=99s iMesh implementation creates SP=
ARSE tags by default, and tags created and accessed through this interface =
will use more memory than DENSE tags created through MOAB=E2=80=99s native =
interface. To mitigate this problem, MOAB implements an extension of the i=
Mesh_createTag function which allows specification of the tag type (DENSE, =
SPARSE, etc.) to be created. See later in this section for more informatio=
n.
+
+- Higher-order nodes: ITAPS currently handles higher-order elements (e.g. =
a 10-node tetrahedron) using a special =E2=80=9CShape=E2=80=9D interface. =
In this interface, higher-order nodes are only accessible through the AEnti=
ties which they resolve. MOAB=E2=80=99s iMesh implementation provides acce=
ss to higher-order nodes in the same manner described in Section , by vary=
ing the number of vertices defining each entity. As a result, if higher-or=
der entities are used in a model, the functions returning connectivity and =
vertex adjacencies always return all vertices, rather than providing an opt=
ion to return just corner vertices.
+
+- Self-adjacencies: iMesh specifies that entities are not self-adjacent; t=
hat is, requesting adjacencies of the same dimension/type results in an err=
or. MOAB does not consider this an error, returning the entity itself.
+
+- Adjacency table and AEntities: iMesh uses the concept of an =E2=80=9Cadj=
acency table=E2=80=9D to determine which AEntities are available and create=
d by default. MOAB uses input arguments to the get_adjacencies functions t=
o control whether AEntities are created. These flags provide finer-grained=
control over AEntities, but make it slightly less convenient to ensure tha=
t AEntities of a given dimension are always created.
+.
+
+ \page figures List of Figures
+=20
+ This page is intended to be empty.
+=20
+ \page tables List of Tables
+=20
+ \ref tableone
+
+ \ref tabletwo
+
+ \ref tablethree
+
+ \ref tablefour
+
+ \ref tablefive
+=20
+ \page building Building & Installing
+=20
+ MOAB uses an autoconf and libtool-based build process by default. The p=
rocedure used to build MOAB from scratch depends on whether the source code=
was obtained from a =E2=80=9Ctarball=E2=80=9D or directly from the Subvers=
ion repository. Assuming the latter, the following steps should be execute=
d for building and installing MOAB:
+ - Locate and build any required dependencies. MOAB can be built with no=
dependencies on other libraries; this may be useful for applications only =
needing basic mesh representation and not needing to export mesh to formats=
implemented in other libraries. MOAB=E2=80=99s native save/restore capabi=
lity is built on HDF5-based files; applications needing to save and restore=
files from MOAB reliably should use this library. MOAB also uses ExodusII=
, a netCDF-based file format developed at Sandia National Laboratories [10]=
. Applications needing to execute these tests should also build netCDF. N=
ote that MOAB uses netCDF=E2=80=99s C++ interface, which is not enabled by =
default in netCDF but can be enabled using the =E2=80=9C=E2=80=93enable-cxx=
=E2=80=9D option to netCDF=E2=80=99s configure script.
+ - Unpack source code into <moab>, and change current working directory t=
o that location.
+ - Execute =E2=80=9Cautoreconf =E2=80=93fi=E2=80=9D.
+ - Run configure script, by executing =E2=80=9C./configure <options>=E2=
=80=9D. Recommended options:
+ -# =E2=80=93prefix=3D<install_dir>: directory below which MOAB libr=
ary and include files will be installed; can either be the directory used f=
or MOAB source (<moab> from step 1), or a different directory.
+ -# =E2=80=93hdf5-dir=3D<hdf5_dir>: directory whose =E2=80=9Cinclude=
=E2=80=9D and =E2=80=9Clib=E2=80=9D subdirectories hold HDF5 include and li=
brary, respectively. MOAB uses HDF5 for its native save/restore format (se=
e Section 4.6.1).
+ -# =E2=80=93netcdf-dir=3D: directory whose =E2=80=9Cinclude=E2=80=
=9D and =E2=80=9Clib=E2=80=9D subdirectories hold netCDF include and librar=
y, respectively. MOAB uses netCDF-based files for many of its build tests.=
If the location of netCDF cannot be found, MOAB=E2=80=99s build tests wil=
l not function properly, but MOAB will still be usable.
+ .
+ - Run =E2=80=9Cmake check=E2=80=9D; this runs a series of build tests, t=
o verify that the MOAB build was successful. Note this check will fail if =
netCDF is not used, but MOAB itself will still be usable from applications.
+ - Run =E2=80=9Cmake install=E2=80=9D; this copies include files and libr=
aries to subdirectories of the directory specified in the =E2=80=9Cprefix=
=E2=80=9D option.
+ .
+
+These steps are sufficient for building MOAB against HDF5 and netCDF. By =
default, a small number of standard MOAB-based applications are also built,=
including mbconvert (a utility for reading and writing files), mbsize (for=
querying basic information about a mesh), and the iMesh interface (see Sec=
tion 7). Other utilities can be enabled using various other options to the=
configure script; for a complete list of build options, execute =E2=80=9C.=
/configure =E2=80=93help=E2=80=9D.
+=20
+ */
+
diff --git a/doc/user.dox.in b/doc/user.dox.in
index 4fed19e..ed65208 100644
--- a/doc/user.dox.in
+++ b/doc/user.dox.in
@@ -305,7 +305,9 @@ WARN_LOGFILE =3D
# with spaces.
=20
INPUT =3D @top_srcdir@/src @top_srcdir@/src/moab \
- @top_srcdir@/src/parallel/moab \
+ @top_srcdir@/doc/UG/moabUG.h \
+ @top_srcdir@/doc/DG \
+ @top_srcdir@/src/parallel/moab \
@top_srcdir@/src/MBTagConventions.hpp \
@top_srcdir@/src/MBCN.h \
@top_srcdir@/src/MBEntityType.h \
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dc89d66..38b4130 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -38,6 +38,7 @@
ScdVertexData.cpp
SequenceData.cpp
SequenceManager.cpp
+ SetIterator.cpp
Skinner.cpp
SparseTag.cpp
StructuredElementSeq.cpp
@@ -46,6 +47,7 @@
SweptVertexData.cpp
SysUtil.cpp
TagInfo.cpp
+ Types.cpp
TypeSequenceManager.cpp
UnstructuredElemSeq.cpp
Util.cpp
@@ -53,7 +55,6 @@
VarLenSparseTag.cpp
VertexSequence.cpp
WriteUtil.cpp
- moab_mpe.c
)
include_directories(
${MOAB_SOURCE_DIR}/src
diff --git a/src/ScdInterface.cpp b/src/ScdInterface.cpp
index e2b18bb..8084640 100644
--- a/src/ScdInterface.cpp
+++ b/src/ScdInterface.cpp
@@ -7,12 +7,12 @@
#include "ScdVertexData.hpp"
#ifdef USE_MPI
# include "moab/ParallelComm.hpp"
+# include "moab/TupleList.hpp"
+# include "moab/gs.hpp"
#endif
#include "assert.h"
#include <iostream>
#include <functional>
-#include "moab/TupleList.hpp"
-#include "moab/gs.hpp"
=20
#define ERRORR(rval, str) {if (MB_SUCCESS !=3D rval) \
{std::cerr << str; return rval; }}
diff --git a/src/Skinner.cpp b/src/Skinner.cpp
index fb80e58..1d284b7 100644
--- a/src/Skinner.cpp
+++ b/src/Skinner.cpp
@@ -1510,6 +1510,34 @@ ErrorCode Skinner::create_side( EntityHandle elem,
rval =3D thisMB->get_connectivity( elem, conn, len, false, &storage );
if (MB_SUCCESS !=3D rval) return rval;
=20
+ // treat separately MBPOLYGON; we want to create the edge in the
+ // forward sense always ; so figure out the sense first, then get out
+ if (MBPOLYGON=3D=3Dtype && 1=3D=3Dd && MBEDGE=3D=3Dside_type)
+ {
+ // first find the first vertex in the conn list
+ int i=3D0;
+ for (i=3D0; i<len; i++)
+ {
+ if (conn[i]=3D=3Dside_conn[0])
+ break;
+ }
+ if (len =3D=3D i)
+ return MB_FAILURE; // not found, big error
+ int prevIndex =3D (i+len-1)%len;
+ int nextIndex =3D (i+1)%len;
+ EntityHandle conn2[2] =3D {side_conn[0], side_conn[1]};
+ if (conn[prevIndex]=3D=3Dside_conn[1])
+ {
+ // reverse, so the edge will be forward
+ conn2[0]=3Dside_conn[1];
+ conn2[1]=3Dside_conn[0];
+ }
+ else if ( conn[nextIndex]!=3Dside_conn[1])
+ return MB_FAILURE; // it is not adjacent to the polygon
+
+ return thisMB->create_element( MBEDGE, conn2, 2, side_elem );
+
+ }
// Find which side we are creating and get indices of all nodes
// (including higher-order, if any.)
CN::SideNumber( type, conn, side_conn, ncorner, d, side, sense, offset );
diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt
index f83eb4f..d6c3e44 100644
--- a/src/io/CMakeLists.txt
+++ b/src/io/CMakeLists.txt
@@ -12,7 +12,9 @@
ReadSmf.cpp
ReadSms.cpp
ReadSTL.cpp
+ ReadTemplate.cpp
ReadTetGen.cpp
+ ReadTxt.cpp
ReadVtk.cpp
SMF_State.cpp
Tqdcfr.cpp
diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index c225841..146227c 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -147,7 +147,7 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
#ifdef USE_MPI
for (int i =3D 0; i < 6; i++)
parData.gDims[i] =3D gDims[i];
- for (int i =3D 0; i < 3; i++)
+ for (int i =3D 0; i < 2; i++)
parData.gPeriodic[i] =3D globallyPeriodic[i];
parData.partMethod =3D partMethod;
int pdims[3];
diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index cdc4392..9141938 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -158,7 +158,7 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
#ifdef USE_MPI
for (int i =3D 0; i < 6; i++)
parData.gDims[i] =3D gDims[i];
- for (int i =3D 0; i < 3; i++)
+ for (int i =3D 0; i < 2; i++)
parData.gPeriodic[i] =3D globallyPeriodic[i];
parData.partMethod =3D partMethod;
int pdims[3];
diff --git a/src/moab/Interface.hpp b/src/moab/Interface.hpp
index 030b9d1..d7ad8aa 100644
--- a/src/moab/Interface.hpp
+++ b/src/moab/Interface.hpp
@@ -22,8 +22,8 @@
* together to describe geometric topology, boundary condition, and inter-=
processor interface=20
* groupings in a mesh.
*
- * MOAB's API is documented in the moab::Interface class. The User's Guid=
e is located in
- * doc/MOABv4-UG.doc in MOAB's source tree. Questions and comments should=
be sent to moab-dev=20
+ * MOAB's API is documented in the moab::Interface class. The User's Guid=
e and Developer's Guide are located in
+ * <a href=3D"pages.html">related pages</a>. Questions and comments shoul=
d be sent to moab-dev=20
* _at_ mcs.anl.gov.
*/
=20
diff --git a/test/parallel/par_intx_sph.cpp b/test/parallel/par_intx_sph.cpp
index de30f8b..bf5cbb8 100644
--- a/test/parallel/par_intx_sph.cpp
+++ b/test/parallel/par_intx_sph.cpp
@@ -42,9 +42,12 @@ using namespace moab;
// some input data
double EPS1=3D0.2; // this is for box error
std::string input_mesh_file("Homme_2pt.h5m"); // input file, partitioned c=
orrectly
+std::string mpas_file("mpas_p8.h5m");
double CubeSide =3D 6.; // the above file starts with cube side 6; radius =
depends on cube side
+double radius;
void test_intx_in_parallel();
void test_intx_in_parallel_elem_based();
+void test_intx_mpas();
=20
int main(int argc, char **argv)
{
@@ -73,7 +76,10 @@ int main(int argc, char **argv)
}
}
//result +=3D RUN_TEST(test_intx_in_parallel);
+ radius =3D CubeSide/2*sqrt(3.);
result +=3D RUN_TEST(test_intx_in_parallel_elem_based);
+ radius =3D1.;
+ result +=3D RUN_TEST(test_intx_mpas);
=20
MPI_Finalize();
return result;
@@ -92,9 +98,9 @@ ErrorCode manufacture_lagrange_mesh_on_sphere(Interface =
* mb, EntityHandle eule
* circumscribed sphere radius
* radius =3D length * math.sqrt(3) /2
*/
- double radius =3D CubeSide/2*sqrt(3.);// our value depends on cube side
+ //radius =3D CubeSide/2*sqrt(3.);// our value depends on cube side
Range quads;
- rval =3D mb->get_entities_by_type(euler_set, MBQUAD, quads);
+ rval =3D mb->get_entities_by_dimension(euler_set, 2, quads);
CHECK_ERR(rval);
=20
Range connecVerts;
@@ -177,10 +183,10 @@ void test_intx_in_parallel()
=20
Intx2MeshOnSphere worker(&mb);
=20
- double radius=3D CubeSide/2 * sqrt(3.) ; // input
+ //double radius=3D CubeSide/2 * sqrt(3.) ; // input
worker.SetRadius(radius);
worker.set_box_error(EPS1);//
- worker.SetEntityType(MBQUAD);
+ //worker.SetEntityType(MBQUAD);
=20
worker.SetErrorTolerance(radius*1.e-8);
worker.locate_departure_points(euler_set);
@@ -244,10 +250,10 @@ void test_intx_in_parallel_elem_based()
=20
Intx2MeshOnSphere worker(&mb);
=20
- double radius=3D CubeSide/2 * sqrt(3.) ; // input
+ //double radius=3D CubeSide/2 * sqrt(3.) ; // input
worker.SetRadius(radius);
worker.set_box_error(EPS1);//
- worker.SetEntityType(MBQUAD);
+ //worker.SetEntityType(MBQUAD);
=20
worker.SetErrorTolerance(radius*1.e-8);
std::cout << "error tolerance epsilon_1=3D"<< radius*1.e-8 << "\n";
@@ -282,3 +288,79 @@ void test_intx_in_parallel_elem_based()
" intersection area:" << intx_area << " rel error: " << fabs((intx_=
area-arrival_area)/arrival_area) << "\n";
CHECK_ERR(rval);
}
+
+void test_intx_mpas()
+{
+ std::string opts =3D std::string("PARALLEL=3DREAD_PART;PARTITION=3DPARAL=
LEL_PARTITION")+
+ std::string(";PARALLEL_RESOLVE_SHARED_ENTS");
+ Core moab;
+ Interface & mb =3D moab;
+ EntityHandle euler_set;
+ ErrorCode rval;
+ rval =3D mb.create_meshset(MESHSET_SET, euler_set);
+ CHECK_ERR(rval);
+ std::string example(TestDir + "/" + mpas_file);
+
+ rval =3D mb.load_file(example.c_str(), &euler_set, opts.c_str());
+
+ ParallelComm* pcomm =3D ParallelComm::get_pcomm(&mb, 0);
+ CHECK_ERR(rval);
+
+ rval =3D pcomm->check_all_shared_handles();
+ CHECK_ERR(rval);
+
+ // everybody will get a DP tag, including the non owned entities; so exc=
hange tags is not required for LOC (here)
+ rval =3D manufacture_lagrange_mesh_on_sphere(&mb, euler_set);
+ CHECK_ERR(rval);
+
+ int rank =3D pcomm->proc_config().proc_rank();
+
+ std::stringstream ste;
+ ste<<"initial" << rank<<".vtk";
+ mb.write_file(ste.str().c_str(), 0, 0, &euler_set, 1);
+
+ Intx2MeshOnSphere worker(&mb);
+
+ //double radius=3D CubeSide/2 * sqrt(3.) ; // input
+ worker.SetRadius(radius);
+ worker.set_box_error(EPS1);//
+ //worker.SetEntityType(MBQUAD);
+
+ worker.SetErrorTolerance(radius*1.e-8);
+ std::cout << "error tolerance epsilon_1=3D"<< radius*1.e-8 << "\n";
+ // worker.locate_departure_points(euler_set);
+
+ // we need to make sure the covering set is bigger than the euler mesh
+ EntityHandle covering_lagr_set;
+ rval =3D mb.create_meshset(MESHSET_SET, covering_lagr_set);
+ CHECK_ERR(rval);
+
+ rval =3D worker.create_departure_mesh_2nd_alg(euler_set, covering_lagr_s=
et);
+ CHECK_ERR(rval);
+
+ std::stringstream ss;
+ ss<<"partial" << rank<<".vtk";
+ mb.write_file(ss.str().c_str(), 0, 0, &covering_lagr_set, 1);
+ rval =3D enforce_convexity(&mb, covering_lagr_set);
+ CHECK_ERR(rval);
+ std::stringstream ss2;
+ ss2<<"partialConvex" << rank<<".vtk";
+ mb.write_file(ss2.str().c_str(), 0, 0, &covering_lagr_set, 1);
+ EntityHandle outputSet;
+ rval =3D mb.create_meshset(MESHSET_SET, outputSet);
+ CHECK_ERR(rval);
+ rval =3D worker.intersect_meshes(covering_lagr_set, euler_set, outputSet=
);
+ CHECK_ERR(rval);
+
+ //std::string opts_write("PARALLEL=3DWRITE_PART");
+ //rval =3D mb.write_file("manuf.h5m", 0, opts_write.c_str(), &outputSet,=
1);
+ std::string opts_write("");
+ std::stringstream outf;
+ outf<<"intersect" << rank<<".h5m";
+ rval =3D mb.write_file(outf.str().c_str(), 0, 0, &outputSet, 1);
+ double intx_area =3D area_on_sphere(&mb, outputSet, radius);
+ double arrival_area =3D area_on_sphere(&mb, euler_set, radius) ;
+ std::cout<< "On rank : " << rank << " arrival area: " << arrival_area<<
+ " intersection area:" << intx_area << " rel error: " << fabs((intx_=
area-arrival_area)/arrival_area) << "\n";
+ CHECK_ERR(rval);
+}
diff --git a/tools/mbcslam/CslamUtils.cpp b/tools/mbcslam/CslamUtils.cpp
index 61d1bf0..1166a7a 100644
--- a/tools/mbcslam/CslamUtils.cpp
+++ b/tools/mbcslam/CslamUtils.cpp
@@ -12,6 +12,11 @@
#include "ElemUtil.hpp"
#include "moab/MergeMesh.hpp"
=20
+// this is for sstream
+#include <sstream>
+
+#include <queue>
+
namespace moab {
// vec utilities that could be common between quads on a plane or sphere
double dist2(double * a, double * b)
@@ -24,24 +29,26 @@ double area2D(double *a, double *b, double *c)
// (b-a)x(c-a) / 2
return ((b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])) /=
2;
}
-int borderPointsOfXinY2(double * X, double * Y, int nsides, double * P, in=
t side[4])
+int borderPointsOfXinY2(double * X, int nX, double * Y, int nY, double * P=
, int side[MAXEDGES])
{
// 2 triangles, 3 corners, is the corner of X in Y?
// Y must have a positive area
/*
*/
int extraPoint =3D 0;
- for (int i =3D 0; i < nsides; i++)
+ for (int i =3D 0; i < nX; i++)
{
- // compute twice the area of all 4 triangles formed by a side of Y and=
a corner of X; if one is negative, stop
+ // compute twice the area of all nY triangles formed by a side of Y an=
d a corner of X; if one is negative, stop
+ // (negative means it is outside; X and Y are all oriented such that t=
hey are positive oriented;
+ // if one area is negative, it means it is outside the convex region,=
for sure)
double * A =3D X + 2 * i;
=20
int inside =3D 1;
- for (int j =3D 0; j < nsides; j++)
+ for (int j =3D 0; j < nY; j++)
{
double * B =3D Y + 2 * j;
=20
- int j1 =3D (j + 1) % nsides;
+ int j1 =3D (j + 1) % nY;
double * C =3D Y + 2 * j1; // no copy of data
=20
double area2 =3D (B[0] - A[0]) * (C[1] - A[1])
@@ -54,7 +61,8 @@ int borderPointsOfXinY2(double * X, double * Y, int nside=
s, double * P, int side
}
if (inside)
{
- side[i] =3D 1;
+ side[i] =3D 1;// so vertex i of X is inside the convex region formed=
by Y
+ // so side has nX dimension (first array)
P[extraPoint * 2] =3D A[0];
P[extraPoint * 2 + 1] =3D A[1];
extraPoint++;
@@ -84,7 +92,8 @@ int SortAndRemoveDoubles2(double * P, int & nP, double ep=
silon_1)
}
c[0] /=3D nP;
c[1] /=3D nP;
- double angle[24]; // could be at most 24 points; much less usually
+ // how many
+ std::vector<double> angle(nP); // could be at most nP points
for (k =3D 0; k < nP; k++)
{
double x =3D P[2 * k] - c[0], y =3D P[2 * k + 1] - c[1];
@@ -108,7 +117,7 @@ int SortAndRemoveDoubles2(double * P, int & nP, double =
epsilon_1)
if (angle[k] > angle[k + 1])
{
sorted =3D 0;
- swap2(angle + k, angle + k + 1);
+ swap2(&angle[k], &angle[k+1]);
swap2(P + (2 * k), P + (2 * k + 2));
swap2(P + (2 * k + 1), P + (2 * k + 3));
}
@@ -146,8 +155,8 @@ int SortAndRemoveDoubles2(double * P, int & nP, double =
epsilon_1)
=20
// the marks will show what edges of blue intersect the red
=20
-int EdgeIntersections2(double * blue, double * red, int nsides, int markb[=
4], int markr[4],
- double * points, int & nPoints)
+int EdgeIntersections2(double * blue, int nsBlue, double * red, int nsRed,
+ int markb[MAXEDGES], int markr[MAXEDGES], double * points, int & nPoin=
ts)
{
/* EDGEINTERSECTIONS computes edge intersections of two elements
[P,n]=3DEdgeIntersections(X,Y) computes for the two given elements * r=
ed
@@ -158,30 +167,20 @@ int EdgeIntersections2(double * blue, double * red, i=
nt nsides, int markb[4], in
with blue are given.
*/
=20
- // points is an array with 48 slots (24 * 2 doubles)
+ // points is an array with enough slots (24 * 2 doubles)
nPoints =3D 0;
- markb[0] =3D markb[1] =3D markb[2] =3D markb[3] =3D 0; // no neighbors o=
f red involved yet
- markr[0] =3D markr[1] =3D markr[2] =3D markr[3] =3D 0;
- /*for i=3D1:3 % find all intersections of edg=
es
- for j=3D1:3
- b=3DY(:,j)-X(:,i);
- A=3D[X(:,mod(i,3)+1)-X(:,i) -Y(:,mod(j,3)+1)+Y(:,j)];
- if rank(A)=3D=3D2 % edges not parallel
- r=3DA\b;
- if r(1)>=3D0 & r(1)<=3D1 & r(2)>=3D0 & r(2)<=3D1, % intersection found
- k=3Dk+1; P(:,k)=3DX(:,i)+r(1)*(X(:,mod(i,3)+1)-X(:,i)); n(i)=3D1;
- end;
- end;
- end;
- end;*/
- for (int i =3D 0; i < nsides; i++)
- {
- for (int j =3D 0; j < nsides; j++)
+ for (int i=3D0; i<MAXEDGES; i++){
+ markb[i]=3Dmarkr[i] =3D 0;
+ }
+
+ for (int i =3D 0; i < nsBlue; i++)
+ {
+ for (int j =3D 0; j < nsRed; j++)
{
double b[2];
double a[2][2]; // 2*2
- int iPlus1 =3D (i + 1) % nsides;
- int jPlus1 =3D (j + 1) % nsides;
+ int iPlus1 =3D (i + 1) % nsBlue;
+ int jPlus1 =3D (j + 1) % nsRed;
for (int k =3D 0; k < 2; k++)
{
b[k] =3D red[2 * j + k] - blue[2 * i + k];
@@ -636,7 +635,7 @@ double oriented_spherical_angle(double * A, double * B,=
double * C)
CartVect a(A), b(B), c(C);
CartVect normalOAB =3D a * b;
CartVect normalOCB =3D c * b;
- CartVect orient =3D (b-a)*(c-a);
+ CartVect orient =3D (c-b)*(a-b);
double ang =3D angle(normalOAB, normalOCB); // this is between 0 and M_PI
if (ang!=3Dang)
{
@@ -644,8 +643,8 @@ double oriented_spherical_angle(double * A, double * B,=
double * C)
std::cout << a << " " << b << " " << c <<"\n";
std::cout << ang << "\n";
}
- if (orient%a < 0)
- return (2*M_PI-ang);// the other angle
+ if (orient%b < 0)
+ return (2*M_PI-ang);// the other angle, supplement
=20
return ang;
=20
@@ -861,4 +860,136 @@ void departure_point_case1(CartVect & arrival_point, =
double t, double delta_t, C
departure_point =3D spherical_to_cart(sph_dep);
return;
}
+// break the nonconvex quads into triangles; remove the quad from the set?=
yes.
+// maybe radius is not needed;
+//
+ErrorCode enforce_convexity(Interface * mb, EntityHandle lset)
+{
+ // look at each quad; compute all 4 angles; if one is reflex, break alon=
g that diagonal
+ // replace it with 2 triangles, and remove from set;
+ // it should work for all polygons / tested first for case 1, with dt 0.=
5 (too much deformation)
+ // get all entities of dimension 2
+ // then get the connectivity, etc
+ Range inputRange;
+ ErrorCode rval =3D mb->get_entities_by_dimension(lset, 2, inputRange);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+
+ std::vector<double> coords;
+ coords.resize(3*MAXEDGES); // at most 10 vertices per polygon
+ // we should create a queue with new polygons that need processing for r=
eflex angles
+ // (obtuse)
+ std::queue<EntityHandle> newPolys;
+ int brokenPolys=3D0;
+ Range::iterator eit =3D inputRange.begin();
+ while (eit !=3D inputRange.end() || !newPolys.empty())
+ {
+ EntityHandle eh;
+ if (eit !=3D inputRange.end())
+ {
+ eh =3D *eit;
+ eit++;
+ }
+ else
+ {
+ eh =3D newPolys.front();
+ newPolys.pop();
+ }
+ // get the nodes, then the coordinates
+ const EntityHandle * verts;
+ int num_nodes;
+ rval =3D mb->get_connectivity(eh, verts, num_nodes);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ coords.resize(3 * num_nodes);
+ if (num_nodes < 4)
+ continue; // if already triangles, don't bother
+ // get coordinates
+ rval =3D mb->get_coords(verts, num_nodes, &coords[0]);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ // compute each angle
+ bool alreadyBroken =3D false;
+
+ for (int i=3D0; i<num_nodes; i++)
+ {
+ double * A =3D &coords[3*i];
+ double * B =3D &coords[3*((i+1)%num_nodes)];
+ double * C =3D &coords[3*((i+2)%num_nodes)];
+ double angle =3D oriented_spherical_angle(A, B, C);
+ if (angle-M_PI > 0.) // even almost reflex is bad; break it!
+ {
+ if (alreadyBroken)
+ {
+ mb->list_entities(&eh, 1);
+ mb->list_entities(verts, num_nodes);
+ double * D =3D &coords[3*((i+3)%num_nodes)];
+ std::cout<< "ABC: " << angle << " \n";
+ std::cout<< "BCD: " << oriented_spherical_angle( B, C, D) << " \=
n";
+ std::cout<< "CDA: " << oriented_spherical_angle( C, D, A) << " \=
n";
+ std::cout<< "DAB: " << oriented_spherical_angle( D, A, B)<< " \n=
";
+ std::cout << " this quad has at least 2 angles > 180, it has ser=
ious issues\n";
+
+ return MB_FAILURE;
+ }
+ // the bad angle is at i+1;
+ // create 1 triangle and one polygon; add the polygon to the input=
range, so
+ // it will be processed too
+ // also, add both to the set :) and remove the original polygon fr=
om the set
+ // break the next triangle, even though not optimal
+ // so create the triangle i+1, i+2, i+3; remove i+2 from original =
list
+ // even though not optimal in general, it is good enough.
+ EntityHandle conn3[3]=3D{ verts[ (i+1)%num_nodes],
+ verts[ (i+2)%num_nodes],
+ verts[ (i+3)%num_nodes] };
+ // create a polygon with num_nodes-1 vertices, and connectivity
+ // verts[i+1], verts[i+3], (all except i+2)
+ std::vector<EntityHandle> conn(num_nodes-1);
+ for (int j=3D1; j<num_nodes; j++)
+ {
+ conn[j-1]=3Dverts[(i+j+2)%num_nodes];
+ }
+ EntityHandle newElement;
+ rval =3D mb->create_element(MBTRI, conn3, 3, newElement);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+
+ rval =3D mb->add_entities(lset, &newElement, 1);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ if (num_nodes =3D=3D 4)
+ {
+ // create another triangle
+ rval =3D mb->create_element(MBTRI, &conn[0], 3, newElement);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ }
+ else
+ {
+ // create another polygon, and add it to the inputRange
+ rval =3D mb->create_element(MBPOLYGON, &conn[0], num_nodes-1, ne=
wElement);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ newPolys.push(newElement); // because it has less number of edge=
s, the
+ // reverse should work to find it.
+ }
+ rval =3D mb->add_entities(lset, &newElement, 1);
+ if (MB_SUCCESS !=3D rval)
+ return rval;
+ mb->remove_entities(lset, &eh, 1);
+ brokenPolys++;
+ /*std::cout<<"remove: " ;
+ mb->list_entities(&eh, 1);
+
+ std::stringstream fff;
+ fff << "file0" << brokenQuads<< ".vtk";
+ mb->write_file(fff.str().c_str(), 0, 0, &lset, 1);*/
+ alreadyBroken=3Dtrue; // get out of the loop, element is broken
+ }
+ }
+ }
+ std::cout << brokenPolys << " concave polygons were decomposed in convex=
ones \n";
+ return MB_SUCCESS;
+}
+
} //namespace moab
diff --git a/tools/mbcslam/CslamUtils.hpp b/tools/mbcslam/CslamUtils.hpp
index e244138..c32a264 100644
--- a/tools/mbcslam/CslamUtils.hpp
+++ b/tools/mbcslam/CslamUtils.hpp
@@ -11,16 +11,20 @@
#include "moab/Core.hpp"
#include "moab/Interface.hpp"
=20
+// maximum number of edges on each convex polygon of interest
+#define MAXEDGES 10
+#define MAXEDGES2 20 // used for coordinates in plane
+
namespace moab
{
double dist2(double * a, double * b);
double area2D(double *a, double *b, double *c);
-int borderPointsOfXinY2(double * X, double * Y, int nsides, double * P, in=
t side[4]);
+int borderPointsOfXinY2(double * X, int nX, double * Y, int nY, double * P=
, int side[MAXEDGES]);
int SortAndRemoveDoubles2(double * P, int & nP, double epsilon);
// the marks will show what edges of blue intersect the red
=20
-int EdgeIntersections2(double * blue, double * red, int nsides, int markb[=
4], int markr[4],
- double * points, int & nPoints);
+int EdgeIntersections2(double * blue, int nsBlue, double * red, int nsRed,
+ int markb[MAXEDGES], int markr[MAXEDGES], double * points, int & nPoin=
ts);
=20
// vec utils related to gnomonic projection on a sphere
=20
@@ -122,5 +126,9 @@ double distance_on_great_circle(CartVect & p1, CartVect=
& p2);
=20
void departure_point_case1(CartVect & arrival_point, double t, double delt=
a_t, CartVect & departure_point);
=20
+// break the nonconvex quads into triangles; remove the quad from the set?=
yes.
+// maybe radius is not needed;
+//
+ErrorCode enforce_convexity(Interface * mb, EntityHandle set);
}
#endif /* CSLAMUTILS_HPP_ */
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/fathomteam/moab/commits/2819cc86fa05/
Changeset: 2819cc86fa05
Branch: None
User: danwu
Date: 2013-07-01 15:48:48
Summary: Added read_mpas_nc.cpp and mpasx1.642.t.2.nc (a small MPAS fil=
e), as a unit test for reading MPAS files. Fixed a few bugs to make this te=
st pass
Affected #: 11 files
diff --git a/MeshFiles/unittest/io/mpasx1.642.t.2.nc b/MeshFiles/unittest/i=
o/mpasx1.642.t.2.nc
new file mode 100644
index 0000000..f1e8c94
Binary files /dev/null and b/MeshFiles/unittest/io/mpasx1.642.t.2.nc differ
diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index 30eb430..eb58441 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -93,16 +93,16 @@ ErrorCode NCHelper::read_variable_to_set_allocate(std::=
vector<ReadNC::VarData>&
}
}
=20
- // set up other dimensions and counts
+ // Set up other dimensions and counts
if (vdatas[i].varDims.empty()) {
- // scalar variable
+ // Scalar variable
vdatas[i].readDims[t].push_back(0);
vdatas[i].readCounts[t].push_back(1);
}
else {
for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
if (tDim !=3D vdatas[i].varDims[idx]){
- // push other variable dimensions, except time, which was alre=
ady pushed
+ // Push other variable dimensions, except time, which was alre=
ady pushed
vdatas[i].readDims[t].push_back(0);
vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
}
@@ -314,6 +314,41 @@ ErrorCode NCHelper::convert_variable(ReadNC::VarData& =
var_data, int tstep_num)
return MB_SUCCESS;
}
=20
+ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle file_set) {
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ int (&lDims)[6] =3D _readNC->lDims;
+
+ // Get the number of vertices
+ int num_verts;
+ ErrorCode rval =3D mbImpl->get_number_entities_by_dimension(file_set, 0,=
num_verts);
+ ERRORR(rval, "Trouble getting number of vertices.");
+
+ // Check against parameters
+ if (num_verts > 0)
+ {
+ int expected_verts =3D (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1=
] + 1) * (-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
+ if (num_verts !=3D expected_verts) {
+ ERRORR(MB_FAILURE, "Number of vertices doesn't match.");
+ }
+ }
+
+ // Check the number of elements too
+ int num_elems;
+ rval =3D mbImpl->get_number_entities_by_dimension(file_set, (-1 =3D=3D l=
Dims[2] ? 2 : 3), num_elems);
+ ERRORR(rval, "Trouble getting number of elements.");
+
+ // Check against parameters
+ if (num_elems > 0)
+ {
+ int expected_elems =3D (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]) *=
(-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2]);
+ if (num_elems !=3D expected_elems) {
+ ERRORR(MB_FAILURE, "Number of elements doesn't match.");
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& =
opts, EntityHandle file_set, Range& faces)
{
Interface*& mbImpl =3D _readNC->mbImpl;
@@ -592,7 +627,7 @@ ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allo=
cate(EntityHandle file_se
=20
// Get the tag to read into
if (!vdatas[i].varTags[t]) {
- rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
+ rval =3D _readNC->get_tag_to_nonset(vdatas[i], tstep_nums[t], vdat=
as[i].varTags[t], vdatas[i].numLev);
ERRORR(rval, "Trouble getting tag.");
}
=20
diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 8f63336..0ac9b0c 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -25,6 +25,7 @@ public:
=20
//! Interfaces to be implemented in child classes
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set) =3D 0;
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set) =3D 0;
virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces) =3D 0;
virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums) =3D 0;
virtual std::string get_mesh_type_name() =3D 0;
@@ -53,6 +54,8 @@ public:
virtual ~ScdNCHelper() {}
=20
private:
+ //! Implementation of NCHelper::check_existing_mesh()
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set);
//! Implementation of NCHelper::create_mesh()
virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
//! Implementation of NCHelper::read_variables()
diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 60d63c0..e963564 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -191,10 +191,46 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOpt=
ions& opts, EntityHandle fi
// with no corresponding variables
_readNC->init_dims_with_no_cvars_info();
=20
- // This check is for HOMME and other ucd mesh. When ReadNC class instance
- // gets out of scope in a script (and deleted), the localGid will be lost
- rval =3D _readNC->check_ucd_localGid(file_set);
- ERRORR(rval, "Trouble checking local Gid for ucd mesh.");
+ return MB_SUCCESS;
+}
+
+// When noMesh option is used on this read, the old ReadNC class instance =
for last read can get out
+// of scope (and deleted). The old instance initialized localGidVerts prop=
erly when the mesh was
+// created, but it is now lost. The new instance (will not create the mesh=
with noMesh option) has
+// to restore it based on the existing mesh from last read
+ErrorCode NCHelperHOMME::check_existing_mesh(EntityHandle tmp_set)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ Tag& mGlobalIdTag =3D _readNC->mGlobalIdTag;
+ bool& noMesh =3D _readNC->noMesh;
+ Range& localGid =3D _readNC->localGid;
+
+ if (noMesh && localGid.empty()) {
+ // We need to populate localGid range with the gids of vertices from t=
he tmp_set
+ // localGid is important in reading the variable data into the nodes
+ // also, for our purposes, localGid is truly the GLOBAL_ID tag data, n=
ot other
+ // file_id tags that could get passed around in other scenarios for pa=
rallel reading
+ // for nodal_partition, this local gid is easier, should be initialize=
d with only
+ // the owned nodes
+
+ // We need to get all vertices from tmp_set (it is the input set in no=
_mesh scenario)
+ Range local_verts;
+ ErrorCode rval =3D mbImpl->get_entities_by_dimension(tmp_set, 0, local=
_verts);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ if (!local_verts.empty()) {
+ std::vector<int> gids(local_verts.size());
+
+ // !IMPORTANT : this has to be the GLOBAL_ID tag
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, local_verts, &gids[0]);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ // This will do a smart copy
+ std::copy(gids.begin(), gids.end(), range_inserter(localGid));
+ }
+ }
=20
return MB_SUCCESS;
}
@@ -282,9 +318,9 @@ ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi=
, const FileOptions& opts
int cornerVarId;
success =3D NCFUNC(inq_varid)(connectId, "element_corners", &cornerVarId=
);
ERRORS(success, "Failed to get variable id.");
- NCDF_SIZE tmp_dims[2] =3D {0, 0}, tmp_counts[2] =3D {4, static_cast<size=
_t>(num_quads)};
+ NCDF_SIZE tmp_starts[2] =3D {0, 0}, tmp_counts[2] =3D {4, static_cast<si=
ze_t>(num_quads)};
std::vector<int> tmp_conn(4 * num_quads), tmp_conn2(4 * num_quads);
- success =3D NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_dims, tmp_co=
unts, &tmp_conn2[0] NCREQ);
+ success =3D NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_starts, tmp_=
counts, &tmp_conn2[0] NCREQ);
ERRORS(success, "Failed to get temporary connectivity.");
success =3D NCFUNC(close)(connectId);
ERRORS(success, "Failed on close.");
@@ -620,7 +656,7 @@ ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_al=
locate(EntityHandle file_
=20
// Get the tag to read into
if (!vdatas[i].varTags[t]) {
- rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
+ rval =3D _readNC->get_tag_to_nonset(vdatas[i], tstep_nums[t], vdat=
as[i].varTags[t], vdatas[i].numLev);
ERRORR(rval, "Trouble getting tag.");
}
=20
diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index b7dc7ac..f900829 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -23,6 +23,8 @@ public:
private:
//! Implementation of NCHelper::init_mesh_vals()
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
+ //! Implementation of NCHelper::check_existing_mesh()
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set);
//! Implementation of NCHelper::create_mesh()
virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
//! Implementation of NCHelper::get_mesh_type_name()
diff --git a/src/io/NCHelperMPAS.cpp b/src/io/NCHelperMPAS.cpp
index 9f66ead..0d4573f 100644
--- a/src/io/NCHelperMPAS.cpp
+++ b/src/io/NCHelperMPAS.cpp
@@ -174,8 +174,104 @@ ErrorCode NCHelperMPAS::init_mesh_vals(const FileOpti=
ons& opts, EntityHandle fil
return MB_SUCCESS;
}
=20
+// When noMesh option is used on this read, the old ReadNC class instance =
for last read can get out
+// of scope (and deleted). The old instance initialized some variables pro=
perly when the mesh was
+// created, but they are now lost. The new instance (will not create the m=
esh with noMesh option)
+// has to restore them based on the existing mesh from last read
+ErrorCode NCHelperMPAS::check_existing_mesh(EntityHandle tmp_set)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ Tag& mGlobalIdTag =3D _readNC->mGlobalIdTag;
+ bool& noMesh =3D _readNC->noMesh;
+
+ if (noMesh) {
+ ErrorCode rval;
+
+ if (localGidVerts.empty()) {
+ // Get all vertices from tmp_set (it is the input set in no_mesh sce=
nario)
+ Range local_verts;
+ rval =3D mbImpl->get_entities_by_dimension(tmp_set, 0, local_verts);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ if (!local_verts.empty()) {
+ std::vector<int> gids(local_verts.size());
+
+ // !IMPORTANT : this has to be the GLOBAL_ID tag
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, local_verts, &gids[0]);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ // Restore localGidVerts
+ std::copy(gids.rbegin(), gids.rend(), range_inserter(localGidVerts=
));
+ nLocalVertices =3D localGidVerts.size();
+ }
+ }
+
+ if (localGidEdges.empty()) {
+ // Get all edges from tmp_set (it is the input set in no_mesh scenar=
io)
+ Range local_edges;
+ rval =3D mbImpl->get_entities_by_dimension(tmp_set, 1, local_edges);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ if (!local_edges.empty()) {
+ std::vector<int> gids(local_edges.size());
+
+ // !IMPORTANT : this has to be the GLOBAL_ID tag
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, local_edges, &gids[0]);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ // Restore localGidEdges
+ std::copy(gids.rbegin(), gids.rend(), range_inserter(localGidEdges=
));
+ nLocalEdges =3D localGidEdges.size();
+ }
+ }
+
+ if (localGidCells.empty()) {
+ // Get all cells from tmp_set (it is the input set in no_mesh scenar=
io)
+ Range local_cells;
+ rval =3D mbImpl->get_entities_by_dimension(tmp_set, 2, local_cells);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ if (!local_cells.empty()) {
+ std::vector<int> gids(local_cells.size());
+
+ // !IMPORTANT : this has to be the GLOBAL_ID tag
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, local_cells, &gids[0]);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ // Restore localGidCells
+ std::copy(gids.rbegin(), gids.rend(), range_inserter(localGidCells=
));
+ nLocalCells =3D localGidCells.size();
+
+ // Restore cellHandleToGlobalID
+ Range::const_iterator rit;
+ int i;
+ for (rit =3D local_cells.begin(), i =3D 0; rit !=3D local_cells.en=
d(); ++rit, i++)
+ cellHandleToGlobalID[*rit] =3D gids[i];
+ }
+ }
+
+ // Restore numCellGroups
+ if (0 =3D=3D numCellGroups) {
+ Tag numCellGroupsTag;
+ rval =3D mbImpl->tag_get_handle("__NUM_CELL_GROUPS", 1, MB_TYPE_INTE=
GER, numCellGroupsTag);
+ rval =3D mbImpl->tag_get_data(numCellGroupsTag, &tmp_set, 1, &numCel=
lGroups);
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi, const FileOptions&=
opts, EntityHandle file_set, Range& faces)
{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ Tag& mGlobalIdTag =3D _readNC->mGlobalIdTag;
+ const Tag*& mpFileIdTag =3D _readNC->mpFileIdTag;
bool& isParallel =3D _readNC->isParallel;
#ifdef USE_MPI
ParallelComm*& myPcomm =3D _readNC->myPcomm;
@@ -208,62 +304,78 @@ ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scd=
i, const FileOptions& opts,
nLocalCells++;
start_cell_idx +=3D std::min(rank, iextra);
start_cell_idx++; // 0 based -> 1 based
+
localGidCells.insert(start_cell_idx, start_cell_idx + nLocalCells - 1);
=20
// Read number of edges on each cell
int nEdgesOnCellVarId;
int success =3D NCFUNC(inq_varid)(_fileId, "nEdgesOnCell", &nEdgesOnCell=
VarId);
ERRORS(success, "Failed to get variable id of nEdgesOnCell.");
- NCDF_SIZE tmp_dims_1[1] =3D {static_cast<size_t>(start_cell_idx - 1)};
+ NCDF_SIZE tmp_starts_1[1] =3D {static_cast<size_t>(start_cell_idx - 1)};
NCDF_SIZE tmp_counts_1[1] =3D {static_cast<size_t>(nLocalCells)};
std::vector<int> num_edges_on_cell(nLocalCells);
- success =3D NCFUNCAG(_vara_int)(_fileId, nEdgesOnCellVarId, tmp_dims_1, =
tmp_counts_1, &num_edges_on_cell[0] NCREQ);
+ success =3D NCFUNCAG(_vara_int)(_fileId, nEdgesOnCellVarId, tmp_starts_1=
, tmp_counts_1, &num_edges_on_cell[0] NCREQ);
ERRORS(success, "Failed to read variable values of nEdgesOnCell.");
=20
// Read vertices on each cell (connectivity)
int verticesOnCellVarId;
success =3D NCFUNC(inq_varid)(_fileId, "verticesOnCell", &verticesOnCell=
VarId);
ERRORS(success, "Failed to get variable id of verticesOnCell.");
- NCDF_SIZE tmp_dims_2[2] =3D {static_cast<size_t>(start_cell_idx - 1), 0};
+ NCDF_SIZE tmp_starts_2[2] =3D {static_cast<size_t>(start_cell_idx - 1), =
0};
NCDF_SIZE tmp_counts_2[2] =3D {static_cast<size_t>(nLocalCells), maxCell=
Edges};
std::vector<int> vertices_on_cell(nLocalCells * maxCellEdges);
- success =3D NCFUNCAG(_vara_int)(_fileId, verticesOnCellVarId, tmp_dims_2=
, tmp_counts_2, &vertices_on_cell[0] NCREQ);
+ success =3D NCFUNCAG(_vara_int)(_fileId, verticesOnCellVarId, tmp_starts=
_2, tmp_counts_2, &vertices_on_cell[0] NCREQ);
ERRORS(success, "Failed to read variable values of verticesOnCell.");
=20
// Read edges on each cell
int edgesOnCellVarId;
success =3D NCFUNC(inq_varid)(_fileId, "edgesOnCell", &edgesOnCellVarId);
ERRORS(success, "Failed to get variable id of edgesOnCell.");
- NCDF_SIZE tmp_dims_3[2] =3D {static_cast<size_t>(start_cell_idx - 1), 0};
+ NCDF_SIZE tmp_starts_3[2] =3D {static_cast<size_t>(start_cell_idx - 1), =
0};
NCDF_SIZE tmp_counts_3[2] =3D {static_cast<size_t>(nLocalCells), maxCell=
Edges};
std::vector<int> edges_on_cell(nLocalCells * maxCellEdges);
- success =3D NCFUNCAG(_vara_int)(_fileId, edgesOnCellVarId, tmp_dims_3, t=
mp_counts_3, &edges_on_cell[0] NCREQ);
+ success =3D NCFUNCAG(_vara_int)(_fileId, edgesOnCellVarId, tmp_starts_3,=
tmp_counts_3, &edges_on_cell[0] NCREQ);
ERRORS(success, "Failed to read variable values of edgesOnCell.");
=20
// Divide cells into groups based on the number of edges
std::vector<int> cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
for (int i =3D 0; i < nLocalCells; i++) {
+ int cell_index =3D start_cell_idx + i; // Global cell index
int num_edges =3D num_edges_on_cell[i];
- cells_with_n_edges[num_edges].push_back(i);
+ cells_with_n_edges[num_edges].push_back(cell_index);
}
=20
// For each non-empty cell group, create cells and set connectivity arra=
y initially based on file ids
EntityHandle start_element;
EntityHandle* conn_arr_cells_with_n_edges[MAX_EDGES_PER_CELL + 1];
Range tmp_range;
+ void* data;
+ int count;
+ int* gid_data;
std::set<int> local_vertices_set;
std::set<int> local_edges_set;
+ numCellGroups =3D 0;
for (int i =3D 3; i <=3D maxCellEdges; i++) {
int num_cells =3D cells_with_n_edges[i].size();
if (num_cells > 0) {
numCellGroups++;
+
rval =3D _readNC->readMeshIface->get_element_connect(num_cells, i, M=
BPOLYGON, 0, start_element, conn_arr_cells_with_n_edges[i], num_cells);
tmp_range.insert(start_element, start_element + num_cells - 1);
faces.insert(start_element, start_element + num_cells - 1);
=20
+ // Get ptr to gid memory for cells
+ Range cell_range(start_element, start_element + num_cells - 1);
+ rval =3D mbImpl->tag_iterate(mGlobalIdTag, cell_range.begin(), cell_=
range.end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator on global id tag.");
+ assert(count =3D=3D (int) num_cells);
+ gid_data =3D (int*) data;
+ std::copy(cells_with_n_edges[i].begin(), cells_with_n_edges[i].end()=
, gid_data);
+
for (int j =3D 0; j < num_cells; j++) {
- int cell_idx =3D cells_with_n_edges[i][j];
- CellEntityHandleToIndex[start_element + j] =3D cell_idx;
+ int cell_idx =3D cells_with_n_edges[i][j]; // Global cell index
+ cellHandleToGlobalID[start_element + j] =3D cell_idx;
+ cell_idx -=3D start_cell_idx; // Local cell index
for (int k =3D 0; k < i; k++) {
conn_arr_cells_with_n_edges[i][i * j + k] =3D vertices_on_cell[c=
ell_idx * maxCellEdges + k];
local_vertices_set.insert(vertices_on_cell[cell_idx * maxCellEdg=
es + k]);
@@ -273,6 +385,13 @@ ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi=
, const FileOptions& opts,
}
}
=20
+ // Set tag for numCellGroups
+ Tag numCellGroupsTag =3D 0;
+ rval =3D mbImpl->tag_get_handle("__NUM_CELL_GROUPS", 1, MB_TYPE_INTEGER,=
numCellGroupsTag, MB_TAG_SPARSE | MB_TAG_CREAT);
+ ERRORR(rval, "Trouble creating __NUM_CELL_GROUPS tag.");
+ rval =3D mbImpl->tag_set_data(numCellGroupsTag, &file_set, 1, &numCellGr=
oups);
+ ERRORR(rval, "Trouble setting data for __NUM_CELL_GROUPS tag.");
+
// Collect localGid for vertices
std::copy(local_vertices_set.rbegin(), local_vertices_set.rend(), range_=
inserter(localGidVerts));
nLocalVertices =3D localGidVerts.size();
@@ -296,6 +415,23 @@ ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi=
, const FileOptions& opts,
zptr[vert_idx] =3D zVertVals[(*rit) - 1];
}
=20
+ // Get ptr to gid memory for vertices
+ Range vert_range(start_vertex, start_vertex + nLocalVertices - 1);
+ rval =3D mbImpl->tag_iterate(mGlobalIdTag, vert_range.begin(), vert_rang=
e.end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator on global id tag.");
+ assert(count =3D=3D (int) nLocalVertices);
+ gid_data =3D (int*) data;
+ std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
+
+ // Duplicate global id data, which will be used to resolve sharing
+ if (mpFileIdTag) {
+ rval =3D mbImpl->tag_iterate(*mpFileIdTag, vert_range.begin(), vert_ra=
nge.end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator on file id tag.");
+ assert(count =3D=3D (int) nLocalVertices);
+ gid_data =3D (int*) data;
+ std::copy(localGidVerts.begin(), localGidVerts.end(), gid_data);
+ }
+
// Create map from file ids to vertex handles
std::map<EntityHandle, EntityHandle> vert_handles;
for (rit =3D localGidVerts.begin(), vert_idx =3D 0; rit !=3D localGidVer=
ts.end(); ++rit, vert_idx++)
@@ -334,6 +470,14 @@ ErrorCode NCHelperMPAS::create_mesh(ScdInterface* scdi=
, const FileOptions& opts,
conn_arr_edges[edge_idx + 1] =3D vert_handles[gloabl_vert_id_2];
}
=20
+ // Get ptr to gid memory for edges
+ Range edge_range(start_edge, start_edge + nLocalEdges - 1);
+ rval =3D mbImpl->tag_iterate(mGlobalIdTag, edge_range.begin(), edge_rang=
e.end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator on global id tag.");
+ assert(count =3D=3D (int) nLocalEdges);
+ gid_data =3D (int*) data;
+ std::copy(localGidEdges.begin(), localGidEdges.end(), gid_data);
+
// Add new vertices, elements and edges to the file set
rval =3D _readNC->mbImpl->add_entities(file_set, tmp_range);
ERRORR(rval, "Couldn't add new vertices/faces/edges to file set.");
@@ -355,27 +499,8 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::v=
ector<std::string>& var_na
if (var_names.empty()) {
for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
ReadNC::VarData vd =3D (*mit).second;
- if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd.v=
arDims.end()) && (std::find(vd.varDims.begin(),
- vd.varDims.end(), cDim) !=3D vd.varDims.end()) && (std::find(vd.=
varDims.begin(), vd.varDims.end(), levDim)
- !=3D vd.varDims.end()))
- vdatas.push_back(vd); // 3d data (Time, nCells, nVertLevels) read =
here
- else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D=
vd.varDims.end()) && (std::find(vd.varDims.begin(),
- vd.varDims.end(), eDim) !=3D vd.varDims.end()) && (std::find(vd.=
varDims.begin(), vd.varDims.end(), levDim)
- !=3D vd.varDims.end()))
- vdatas.push_back(vd); // 3d data (Time, nEdges, nVertLevels) read =
here
- else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D=
vd.varDims.end()) && (std::find(vd.varDims.begin(),
- vd.varDims.end(), vDim) !=3D vd.varDims.end()) && (std::find(vd.=
varDims.begin(), vd.varDims.end(), levDim)
- !=3D vd.varDims.end()))
- vdatas.push_back(vd); // 3d data (Time, nVertices, nVertLevels) re=
ad here
- else if (1 =3D=3D vd.varDims.size())
- vsetdatas.push_back(vd);
- }
- }
- else {
- for (unsigned int i =3D 0; i < var_names.size(); i++) {
- mit =3D varInfo.find(var_names[i]);
- if (mit !=3D varInfo.end()) {
- ReadNC::VarData vd =3D (*mit).second;
+ if (3 =3D=3D vd.varDims.size())
+ {
if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd=
.varDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), cDim) !=3D vd.varDims.end()) && (std::find(v=
d.varDims.begin(), vd.varDims.end(), levDim)
!=3D vd.varDims.end()))
@@ -388,6 +513,30 @@ ErrorCode NCHelperMPAS::read_ucd_variable_setup(std::v=
ector<std::string>& var_na
vd.varDims.end(), vDim) !=3D vd.varDims.end()) && (std::find(v=
d.varDims.begin(), vd.varDims.end(), levDim)
!=3D vd.varDims.end()))
vdatas.push_back(vd); // 3d data (Time, nVertices, nVertLevels) =
read here
+ }
+ else if (1 =3D=3D vd.varDims.size())
+ vsetdatas.push_back(vd);
+ }
+ }
+ else {
+ for (unsigned int i =3D 0; i < var_names.size(); i++) {
+ mit =3D varInfo.find(var_names[i]);
+ if (mit !=3D varInfo.end()) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if (3 =3D=3D vd.varDims.size()) {
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D =
vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), cDim) !=3D vd.varDims.end()) && (std::find=
(vd.varDims.begin(), vd.varDims.end(), levDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); // 3d data (Time, nCells, nVertLevels) r=
ead here
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) =
!=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), eDim) !=3D vd.varDims.end()) && (std::find=
(vd.varDims.begin(), vd.varDims.end(), levDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); // 3d data (Time, nEdges, nVertLevels) r=
ead here
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) =
!=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), vDim) !=3D vd.varDims.end()) && (std::find=
(vd.varDims.begin(), vd.varDims.end(), levDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); // 3d data (Time, nVertices, nVertLevels=
) read here
+ }
else if (1 =3D=3D vd.varDims.size())
vsetdatas.push_back(vd);
}
@@ -488,7 +637,7 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_all=
ocate(EntityHandle file_s
=20
// Get the tag to read into
if (!vdatas[i].varTags[t]) {
- rval =3D _readNC->get_tag(vdatas[i], tstep_nums[t], vdatas[i].varT=
ags[t], vdatas[i].numLev);
+ rval =3D _readNC->get_tag_to_nonset(vdatas[i], tstep_nums[t], vdat=
as[i].varTags[t], vdatas[i].numLev);
ERRORR(rval, "Trouble getting tag.");
}
=20
@@ -649,7 +798,8 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset_asy=
nc(EntityHandle file_set,
ERRORR(rval, "Failed to get tag iterator.");
=20
for (int j =3D 0; j < count; j++) {
- int cell_idx =3D CellEntityHandleToIndex[*(iter + j)];
+ int cell_idx =3D cellHandleToGlobalID[*(iter + j)]; // Glo=
bal cell index
+ cell_idx -=3D localGidCells[0]; // Local cell index
for (int level =3D 0; level < vdatas[i].numLev; level++)
((double*) ptr)[j * vdatas[i].numLev + level] =3D tmpdou=
bledata[cell_idx * vdatas[i].numLev + level];
}
@@ -788,7 +938,8 @@ ErrorCode NCHelperMPAS::read_ucd_variable_to_nonset(Ent=
ityHandle file_set, std::
ERRORR(rval, "Failed to get tag iterator.");
=20
for (int j =3D 0; j < count; j++) {
- int cell_idx =3D CellEntityHandleToIndex[*(iter + j)];
+ int cell_idx =3D cellHandleToGlobalID[*(iter + j)]; // Glo=
bal cell index
+ cell_idx -=3D localGidCells[0]; // Local cell index
for (int level =3D 0; level < vdatas[i].numLev; level++)
((double*) ptr)[j * vdatas[i].numLev + level] =3D tmpdou=
bledata[cell_idx * vdatas[i].numLev + level];
}
diff --git a/src/io/NCHelperMPAS.hpp b/src/io/NCHelperMPAS.hpp
index 7f056ec..70deab0 100644
--- a/src/io/NCHelperMPAS.hpp
+++ b/src/io/NCHelperMPAS.hpp
@@ -23,6 +23,8 @@ public:
private:
//! Implementation of NCHelper::init_mesh_vals()
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
+ //! Implementation of NCHelper::check_existing_mesh()
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set);
//! Implementation of NCHelper::create_mesh()
virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& quads);
//! Implementation of NCHelper::get_mesh_type_name()
@@ -50,7 +52,7 @@ private:
int maxCellEdges;
int numCellGroups;
std::vector<int> verticesOnEdge;
- std::map<EntityHandle, int> CellEntityHandleToIndex;
+ std::map<EntityHandle, int> cellHandleToGlobalID;
Range facesOwned;
};
=20
diff --git a/src/io/ReadNC.cpp b/src/io/ReadNC.cpp
index dddf21c..78c3fbc 100644
--- a/src/io/ReadNC.cpp
+++ b/src/io/ReadNC.cpp
@@ -10,7 +10,6 @@
#include <iostream>
#include <sstream>
#include <map>
-#include <dirent.h>
=20
#include "moab/Core.hpp"
#include "moab/ReaderIface.hpp"
@@ -20,13 +19,11 @@
#include "moab/ScdInterface.hpp"
#include "moab/SpectralMeshTool.hpp"
=20
-//#include "bil.h"
-
#define ERRORR(rval, str) \
- if (MB_SUCCESS !=3D rval) {readMeshIface->report_error("%s", str); ret=
urn rval;}
+ if (MB_SUCCESS !=3D rval) { readMeshIface->report_error("%s", str); retu=
rn rval; }
=20
#define ERRORS(err, str) \
- if (err) {readMeshIface->report_error("%s", str); return MB_FAILURE;}
+ if (err) { readMeshIface->report_error("%s", str); return MB_FAILURE; }
=20
namespace moab {
=20
@@ -36,8 +33,7 @@ ReaderIface* ReadNC::factory(Interface* iface) {
=20
ReadNC::ReadNC(Interface* impl) :
mbImpl(impl), CPU_WORD_SIZE(-1), IO_WORD_SIZE(-1), fileId(-1), tMin(-1),=
tMax(-1), iDim(-1), jDim(-1), tDim(-1), iCDim(-1),
- jCDim(-1), numUnLim(-1), mCurrentMeshHandle(0), startVertex(0), startEle=
m(0), mGlobalIdTag(0), mpFileIdTag(NULL), max_line_length(-1),
- max_str_length(-1), vertexOffset(0), dbgOut(stderr), isParallel(false), =
partMethod(-1),
+ jCDim(-1), numUnLim(-1), mGlobalIdTag(0), mpFileIdTag(NULL), dbgOut(stde=
rr), isParallel(false), partMethod(-1),
#ifdef USE_MPI
myPcomm(NULL),=20
#endif
@@ -73,15 +69,8 @@ void ReadNC::reset() {
iDim =3D jDim =3D tDim =3D -1;
iCDim =3D jCDim =3D -1;
numUnLim =3D -1;
- mCurrentMeshHandle =3D 0;
- startVertex =3D startElem =3D 0;
mGlobalIdTag =3D 0;
- max_line_length =3D -1;
- max_str_length =3D -1;
- vertexOffset =3D 0;
dbgOut =3D stderr;
- mCurrentMeshHandle =3D 0;
- vertexOffset =3D 0;
=20
#ifdef USE_MPI
myPcomm =3D NULL;
@@ -102,18 +91,16 @@ ErrorCode ReadNC::load_file(const char* file_name, con=
st EntityHandle* file_set,
std::vector<std::string> var_names;
std::vector<int> tstep_nums;
std::vector<double> tstep_vals;
- /*
- if (file_id_tag)
- mGlobalIdTag =3D *file_id_tag;
- else {
- */
- //! get and cache predefined tag handles
+
+ // Get and cache predefined tag handles
int dum_val =3D 0;
rval =3D mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, =
mGlobalIdTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum_val);
if (MB_SUCCESS !=3D rval)
return rval;
- mpFileIdTag =3D file_id_tag; // store the pointer to the tag ; if not nu=
ll, set when global id tag
- // is set too, with the same data , duplicated
+
+ // Store the pointer to the tag; if not null, set when global id tag
+ // is set too, with the same data, duplicated
+ mpFileIdTag =3D file_id_tag;
=20
std::string partition_tag_name;
rval =3D parse_options(opts, var_names, tstep_nums, tstep_vals);
@@ -135,28 +122,11 @@ ErrorCode ReadNC::load_file(const char* file_name, co=
nst EntityHandle* file_set,
=20
ERRORS(success, "Trouble opening file.");
=20
- // BIL data
-
- if (BIL_mode_enabled(file_name)) {
-
- rval =3D get_BIL_dir();
- ERRORS(rval, "Failed to find directory with BIL data.");
-
- dbgOut.tprintf(1, "Reading BIL data from directory: %s\n", BIL_dir.c_s=
tr());
-
- rval =3D load_BIL(BIL_dir, file_set, opts, file_id_tag);
- ERRORR(rval, "Trouble reading BIL data.");
-
- return rval;
- }
-
- // end of BIL
-
// Read the header (num dimensions, dimensions, num variables, global at=
tribs)
rval =3D read_header();
- ERRORR(rval, " ");
+ ERRORR(rval, "Trouble reading file header.");
=20
- // make sure there's a file set to put things in
+ // Make sure there's a file set to put things in
EntityHandle tmp_set;
if (noMesh && !file_set) {
ERRORR(MB_FAILURE, "NOMESH option requires non-NULL file set on input.=
\n");
@@ -168,7 +138,7 @@ ErrorCode ReadNC::load_file(const char* file_name, cons=
t EntityHandle* file_set,
else
tmp_set =3D *file_set;
=20
- // get the scd interface
+ // Get the scd interface
ScdInterface *scdi =3D NULL;
rval =3D mbImpl->query_interface(scdi);
if (!scdi)
@@ -177,21 +147,25 @@ ErrorCode ReadNC::load_file(const char* file_name, co=
nst EntityHandle* file_set,
if (myHelper !=3D NULL)
delete myHelper;
=20
+ // Get appropriate NC helper instance based on information read from the=
header
myHelper =3D NCHelper::get_nc_helper(this, fileId, opts);
if (myHelper =3D=3D NULL) {
ERRORR(MB_FAILURE, "Failed to get NCHelper class instance.");
}
=20
+ // Initialize mesh values
rval =3D myHelper->init_mesh_vals(opts, tmp_set);
ERRORR(rval, "Trouble initializing mesh values.");
=20
- // Create mesh vertex/edge/face sequences
- Range faces;
+ // Check existing mesh from last read
if (noMesh && !noVars) {
- rval =3D check_verts_faces(tmp_set);
- ERRORR(rval, "Mesh characteristics didn't match from last read.\n");
+ rval =3D myHelper->check_existing_mesh(tmp_set);
+ ERRORR(rval, "Trouble checking mesh from last read.\n");
}
- else if (!noMesh) {
+
+ // Create mesh vertex/edge/face sequences
+ Range faces;
+ if (!noMesh) {
rval =3D myHelper->create_mesh(scdi, opts, tmp_set, faces);
ERRORR(rval, "Trouble creating mesh.");
}
@@ -203,20 +177,23 @@ ErrorCode ReadNC::load_file(const char* file_name, co=
nst EntityHandle* file_set,
return rval;
}
else {
- // read dimension variable by default, the ones that are also variables
+ // Read dimension variable by default, the ones that are also variables
std::vector<std::string> filteredDimNames;
for (unsigned int i =3D 0; i < dimNames.size(); i++) {
std::map<std::string, VarData>::iterator mit =3D varInfo.find(dimNam=
es[i]);
if (mit !=3D varInfo.end())
filteredDimNames.push_back(dimNames[i]);
}
- rval =3D myHelper->read_variables(tmp_set, filteredDimNames, tstep_num=
s);
- if (MB_FAILURE =3D=3D rval)
- return rval;
+
+ if (!filteredDimNames.empty()) {
+ rval =3D myHelper->read_variables(tmp_set, filteredDimNames, tstep_n=
ums);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+ }
}
=20
#ifdef USE_MPI
- // create partition set, and populate with elements
+ // Create partition set, and populate with elements
if (isParallel) {
EntityHandle partn_set;
rval =3D mbImpl->create_meshset(MESHSET_SET, partn_set);
@@ -234,11 +211,11 @@ ErrorCode ReadNC::load_file(const char* file_name, co=
nst EntityHandle* file_set,
=20
myPcomm->partition_sets().insert(partn_set);
=20
- //write partition tag name on partition set
+ // Write partition tag name on partition set
Tag part_tag;
rval =3D mbImpl->tag_get_handle(partitionTagName.c_str(), 1, MB_TYPE_I=
NTEGER, part_tag);
if (MB_SUCCESS !=3D rval) {
- // fall back to the partition tag
+ // Fall back to the partition tag
part_tag =3D myPcomm->partition_tag();
}
=20
@@ -249,85 +226,21 @@ ErrorCode ReadNC::load_file(const char* file_name, co=
nst EntityHandle* file_set,
}
#endif
=20
- // create nc conventional tags when loading header info only
+ // Create nc conventional tags when loading header info only
if (noMesh && noVars) {
- rval =3D create_tags(scdi, tmp_set, tstep_nums);
+ rval =3D create_conventional_tags(scdi, tmp_set, tstep_nums);
ERRORR(rval, "Trouble creating nc conventional tags.");
}
=20
mbImpl->release_interface(scdi);
=20
- // close the file
+ // Close the file
success =3D NCFUNC(close)(fileId);
ERRORS(success, "Trouble closing file.");
=20
return MB_SUCCESS;
}
=20
-ErrorCode ReadNC::load_BIL(std::string, const EntityHandle*, const FileOpt=
ions&, const Tag*) {
- /*
- BIL_Init( MPI_COMM_WORLD );
-
- void ** buffer;
-
- DIR * dir;
- struct dirent * ent;
- dir =3D opendir(dir_name.c_str());
- if (dir !=3D NULL) {
- while ((ent =3D readdir(dir)) !=3D NULL) {
- if (strlen(ent->d_name) > 3) { //filter out . and ..
-
- dbgOut.tprintf(1,"reading block from %s\n",ent->d_name);
-
- int num_dims =3D 3;
- int time_d =3D 1;
- int lev_d =3D 26;
- int ncol_d =3D 3458;
- int block_start[3] =3D {0,0,0};
- int block_size[3] =3D {time_d, lev_d, ncol_d};
- const char * file_name =3D ent->d_name;
- const char * var_name =3D "T";
-
- BIL_Add_block_nc(num_dims, block_start, block_size,
- file_name, var_name, buffer);
- }
- }
- closedir (dir);
- }
-
- BIL_Read();
-
- BIL_Finalize();
- */
- return MB_SUCCESS;
-}
-
-ErrorCode ReadNC::get_BIL_dir() {
- std::map<std::string, AttData> dirAtt;
- ErrorCode result =3D get_attributes(NC_GLOBAL, 1, dirAtt);
- ERRORR(result, "Failed to get BIL_DIR attribute");
-
- std::string attname;
- std::map<std::string, AttData>::iterator attIt =3D dirAtt.find("BIL_DIR"=
);
-
- unsigned int sz =3D attIt->second.attLen;
- char *att_data =3D (char *) malloc(sz + 1);
- att_data[sz] =3D '\000';
- int success =3D NCFUNC(get_att_text)(fileId, attIt->second.attVarId, att=
It->second.attName.c_str(), (char*) att_data);
- ERRORS(success, "Trouble getting BIL data directory.");
- BIL_dir =3D std::string(att_data);
-
- return MB_SUCCESS;
-}
-
-bool ReadNC::BIL_mode_enabled(const char* file_name) {
- std::string file_path =3D std::string(file_name);
- int idx =3D file_path.find_last_of("/");
- std::string file =3D file_path.substr(idx + 1);
-
- return (file =3D=3D "BIL_DIR.nc");
-}
-
ErrorCode ReadNC::parse_options(const FileOptions& opts, std::vector<std::=
string>& var_names, std::vector<int>& tstep_nums,
std::vector<double>& tstep_vals) {
int tmpval;
@@ -420,65 +333,6 @@ ErrorCode ReadNC::parse_options(const FileOptions& opt=
s, std::vector<std::string
return MB_SUCCESS;
}
=20
-// In a script, the ReadNC class instance can get out of scope (and delete=
d). In that
-// case, the localGid (initialized properly when the mesh was created) wil=
l be lost,
-// so it has to be properly refilled with the Global Ids of the local vert=
ices
-ErrorCode ReadNC::check_ucd_localGid(EntityHandle tmp_set) {
- if (noMesh && localGid.empty()) {
- // we need to populate localGid range with the gids of vertices from t=
he tmp_set
- // localGid is important in reading the variable data into the nodes
- // also, for our purposes, localGid is truly the GLOBAL_ID tag data, n=
ot other
- // file_id tags that could get passed around in other scenarios for pa=
rallel reading
- // for nodal_partition, this local gid is easier, should be initialize=
d with only
- // the owned nodes
-
- // we need to get all vertices from tmp_set (it is the input set in no=
_mesh scenario)
- Range local_verts;
- ErrorCode rval =3D mbImpl->get_entities_by_dimension(tmp_set, 0, local=
_verts);
- if (MB_FAILURE =3D=3D rval)
- return rval;
-
- if (!local_verts.empty()) {
- std::vector<int> gids(local_verts.size());
-
- // !IMPORTANT : this has to be the GLOBAL_ID tag
- rval =3D mbImpl->tag_get_data(mGlobalIdTag, local_verts, &gids[0]);
- if (MB_FAILURE =3D=3D rval)
- return rval;
-
- // this will do a smart copy
- std::copy(gids.begin(), gids.end(), range_inserter(localGid));
- }
- }
-
- return MB_SUCCESS;
-}
-
-ErrorCode ReadNC::check_verts_faces(EntityHandle file_set) {
- // check parameters on this read against what was on the mesh from last =
read
- // get the number of vertices
- int num_verts;
- ErrorCode rval =3D mbImpl->get_number_entities_by_dimension(file_set, 0,=
num_verts);
- ERRORR(rval, "Trouble getting number of vertices.");
-
- // check against parameters
- //int expected_verts =3D (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1=
] + 1) * (-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
- //if (num_verts !=3D expected_verts)
- //ERRORR(MB_FAILURE, "Number of vertices doesn't match.");
-
- // check the number of elements too
- int num_elems;
- rval =3D mbImpl->get_number_entities_by_dimension(file_set, (-1 =3D=3D l=
Dims[2] ? 2 : 3), num_elems);
- ERRORR(rval, "Trouble getting number of elements.");
-
- // check against parameters
- //int expected_elems =3D (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]) *=
(-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2]);
- //if (num_elems !=3D expected_elems)
- //ERRORR(MB_FAILURE, "Number of elements doesn't match.");
-
- return MB_SUCCESS;
-}
-
ErrorCode ReadNC::get_tag_to_set(VarData& var_data, int tstep_num, Tag& ta=
gh) {
std::ostringstream tag_name;
if ((!var_data.has_t) || (var_data.varDims.size() <=3D 1))
@@ -515,7 +369,7 @@ ErrorCode ReadNC::get_tag_to_set(VarData& var_data, int=
tstep_num, Tag& tagh) {
return rval;
}
=20
-ErrorCode ReadNC::get_tag(VarData& var_data, int tstep_num, Tag& tagh, int=
num_lev) {
+ErrorCode ReadNC::get_tag_to_nonset(VarData& var_data, int tstep_num, Tag&=
tagh, int num_lev) {
std::ostringstream tag_name;
if (!tstep_num) {
std::string tmp_name =3D var_data.varName + "0";
@@ -654,7 +508,7 @@ ErrorCode ReadNC::get_attributes(int var_id, int num_at=
ts, std::map<std::string,
}
=20
ErrorCode ReadNC::get_dimensions(int file_id, std::vector<std::string>& di=
m_names, std::vector<int>& dim_vals) {
- // get the number of dimensions
+ // Get the number of dimensions
int num_dims;
int success =3D NCFUNC(inq_ndims)(file_id, &num_dims);
ERRORS(success, "Trouble getting number of dimensions.");
@@ -747,7 +601,7 @@ ErrorCode ReadNC::read_tag_values(const char*, const ch=
ar*, const FileOptions&,
return MB_FAILURE;
}
=20
-ErrorCode ReadNC::create_tags(ScdInterface* scdi, EntityHandle file_set, c=
onst std::vector<int>& tstep_nums) {
+ErrorCode ReadNC::create_conventional_tags(ScdInterface* scdi, EntityHandl=
e file_set, const std::vector<int>& tstep_nums) {
ErrorCode rval;
std::string tag_name;
=20
diff --git a/src/io/ReadNC.hpp b/src/io/ReadNC.hpp
index 39b3f43..3e44e5a 100644
--- a/src/io/ReadNC.hpp
+++ b/src/io/ReadNC.hpp
@@ -118,18 +118,17 @@ private:
class VarData
{
public:
- VarData() : varId(-1), numAtts(-1), read(false), entLoc(ENTLOCSET), nu=
mLev(1), sz(0), has_t(false) {}
+ VarData() : varId(-1), numAtts(-1), entLoc(ENTLOCSET), numLev(1), sz(0=
), has_t(false) {}
int varId;
int numAtts;
nc_type varDataType;
- std::vector<int> varDims; // the dimension indices making up this mult=
i-dimensional variable
- std::map<std::string,AttData> varAtts;
+ std::vector<int> varDims; // The dimension indices making up this mult=
i-dimensional variable
+ std::map<std::string, AttData> varAtts;
std::string varName;
- bool read;
- std::vector<Tag> varTags; // one tag for each timestep, varTags[t]
+ std::vector<Tag> varTags; // One tag for each time step, varTags[t]
std::vector<void*> varDatas;
- std::vector<std::vector<NCDF_SIZE> > readDims; // start value for this=
[t][dim]
- std::vector<std::vector<NCDF_SIZE> > readCounts; // number of data val=
ues for this [t][dim]
+ std::vector<std::vector<NCDF_SIZE> > readDims; // Start value for this=
[t][dim]
+ std::vector<std::vector<NCDF_SIZE> > readCounts; // Number of data val=
ues for this [t][dim]
int entLoc;
int numLev;
int sz;
@@ -158,14 +157,8 @@ private:
ErrorCode read_coordinate(const char* var_name, int lmin, int lmax,
std::vector<double>& cvals);
=20
- //! number of dimensions in this nc file
- unsigned int number_dimensions();
-
//! make sure that localGid is properly initialized for ucd mesh
- ErrorCode check_ucd_localGid(EntityHandle file_set);
-
- //! check number of vertices and faces against what's already in file_set
- ErrorCode check_verts_faces(EntityHandle file_set);
+ //ErrorCode check_ucd_localGid(EntityHandle file_set);
=20
ErrorCode parse_options(const FileOptions& opts,
std::vector<std::string>& var_names,
@@ -174,11 +167,11 @@ private:
=20
ErrorCode get_tag_to_set(VarData& var_data, int tstep_num, Tag& tagh);
=20
- ErrorCode get_tag(VarData &var_data, int tstep_num, Tag &tagh, int num_l=
ev);
+ ErrorCode get_tag_to_nonset(VarData& var_data, int tstep_num, Tag& tagh,=
int num_lev);
=20
//! create nc conventional tags
- ErrorCode create_tags(ScdInterface* scdi, EntityHandle file_set,
- const std::vector<int> &tstep_nums);
+ ErrorCode create_conventional_tags(ScdInterface* scdi, EntityHandle file=
_set,
+ const std::vector<int>& tstep_nums);
=20
//! create a character string attString of attMap. with '\0'
//! terminating each attribute name, ';' separating the data type
@@ -196,15 +189,6 @@ private:
//! coordinate variables - this info is used for creating tags
void init_dims_with_no_cvars_info();
=20
- ErrorCode load_BIL(std::string dir_name,
- const EntityHandle* file_set,
- const FileOptions& opts,
- const Tag* file_id_tag);
-
- ErrorCode get_BIL_dir();
-
- bool BIL_mode_enabled(const char* file_name);
-
template <typename T> ErrorCode kji_to_jik(size_t ni, size_t nj, size_t =
nk, void* dest, T* source)
{
size_t nik =3D ni * nk, nij =3D ni * nj;
@@ -292,12 +276,6 @@ private:
//! number of the dimension of unlimited dimension, if any
int numUnLim;
=20
- //! Meshset Handle for the mesh that is currently being read
- EntityHandle mCurrentMeshHandle;
-
- //! starting vertex and element handles for this read
- EntityHandle startVertex, startElem;
-
//! Cached tags for reading. Note that all these tags are defined when t=
he
//! core is initialized.
Tag mGlobalIdTag;
@@ -306,15 +284,10 @@ private:
//! it gets deleted at the end of resolve sharing, but it will have same=
data
//! as the global id tag
//! global id tag is preserved, and is needed later on.
- const Tag * mpFileIdTag;
-
- int max_line_length, max_str_length;
-
- //! range of entities in initial mesh, before this read
- Range initRange;
+ const Tag* mpFileIdTag;
=20
//! offset of first vertex id
- int vertexOffset;
+ //int vertexOffset;
=20
//! debug stuff
DebugOutput dbgOut;
@@ -337,35 +310,20 @@ private:
//! parallel data object, to be cached with ScdBox
ScdParData parData;
=20
- //! directory where data is stored for BIL reader
- std::string BIL_dir;
-
#ifdef USE_MPI
ParallelComm* myPcomm;
#endif
=20
- //! read option
+ //! Read options
bool noMesh;
-
- //! read option
bool noVars;
-
- //! read option
bool spectralMesh;
-
- //! read option
std::string partitionTagName;
=20
//! Helper class instance
NCHelper* myHelper;
};
=20
-//! inline functions
-inline unsigned int ReadNC::number_dimensions()=20
-{
- return dimVals.size();
-}
-
} // namespace moab
=20
#endif
diff --git a/test/io/Makefile.am b/test/io/Makefile.am
index 3eeeaf1..d9bab74 100644
--- a/test/io/Makefile.am
+++ b/test/io/Makefile.am
@@ -12,7 +12,7 @@ AM_CPPFLAGS +=3D -DSRCDIR=3D$(srcdir) \
=20
if NETCDF_FILE
EXODUS_TEST =3D exodus_test
- NC_TEST =3D read_nc read_ucd_nc
+ NC_TEST =3D read_nc read_ucd_nc read_mpas_nc
else
EXODUS_TEST =3D=20
NC_TEST =3D=20
@@ -58,6 +58,7 @@ gmsh_test_SOURCES =3D $(srcdir)/../TestUtil.hpp gmsh_test=
.cc
nastran_test_SOURCES =3D $(srcdir)/../TestUtil.hpp nastran_test.cc
read_nc_SOURCES =3D $(srcdir)/../TestUtil.hpp read_nc.cpp
read_ucd_nc_SOURCES =3D $(srcdir)/../TestUtil.hpp read_ucd_nc.cpp
+read_mpas_nc_SOURCES =3D $(srcdir)/../TestUtil.hpp read_mpas_nc.cpp
ideas_test_SOURCES =3D $(srcdir)/../TestUtil.hpp ideas_test.cc
stl_test_SOURCES =3D $(srcdir)/../TestUtil.hpp stl_test.cc
smf_test_SOURCES =3D $(srcdir)/../TestUtil.hpp smf_test.cc
diff --git a/test/io/read_mpas_nc.cpp b/test/io/read_mpas_nc.cpp
new file mode 100644
index 0000000..49ce0e2
--- /dev/null
+++ b/test/io/read_mpas_nc.cpp
@@ -0,0 +1,267 @@
+#include "TestUtil.hpp"
+#include "moab/Core.hpp"
+
+using namespace moab;
+
+#ifdef MESHDIR
+static const char example[] =3D STRINGIFY(MESHDIR) "/io/mpasx1.642.t.2.nc";
+#else
+static const char example[] =3D "/io/mpasx1.642.t.2.nc";
+#endif
+
+#ifdef USE_MPI
+#include "moab_mpi.h"
+#endif
+
+void test_read_all();
+void test_read_onevar();
+void test_read_onetimestep();
+void test_read_nomesh();
+void test_read_novars();
+
+ErrorCode get_options(std::string& opts);
+
+int main(int argc, char* argv[])
+{
+ int result =3D 0;
+
+#ifdef USE_MPI
+ int fail =3D MPI_Init(&argc, &argv);
+ if (fail)
+ return 1;
+#else
+ argv[0] =3D argv[argc-argc]; // To remove the warnings in serial mode ab=
out unused variables
+#endif
+
+ //result +=3D RUN_TEST(test_read_all);
+ //result +=3D RUN_TEST(test_read_onevar);
+ //result +=3D RUN_TEST(test_read_onetimestep);
+ //result +=3D RUN_TEST(test_read_nomesh);
+ result +=3D RUN_TEST(test_read_novars);
+
+#ifdef USE_MPI
+ fail =3D MPI_Finalize();
+ if (fail)
+ return 1;
+#endif
+
+ return result;
+}
+
+void test_read_all()
+{
+ const double eps =3D 1e-20;
+ double val[2];
+ Core moab;
+ Interface& mb =3D moab;
+
+ std::string opts;
+ ErrorCode rval =3D get_options(opts);
+ CHECK_ERR(rval);
+
+ rval =3D mb.load_file(example, NULL, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check tags for vertex variable vorticity
+ Tag vorticity_tag0, vorticity_tag1;
+ rval =3D mb.tag_get_handle("vorticity0", 1, MB_TYPE_DOUBLE, vorticity_ta=
g0);
+ CHECK_ERR(rval);
+ rval =3D mb.tag_get_handle("vorticity1", 1, MB_TYPE_DOUBLE, vorticity_ta=
g1);
+ CHECK_ERR(rval);
+
+ // Get vertices (1280 edges)
+ Range verts;
+ rval =3D mb.get_entities_by_type(0, MBVERTEX, verts);
+ assert(rval =3D=3D MB_SUCCESS);
+ CHECK_EQUAL((size_t)1280, verts.size());
+ CHECK_EQUAL((size_t)1, verts.psize());
+
+ // Check vorticity tag values on first two vertices
+ EntityHandle vert_ents[] =3D {verts[0], verts[1]};
+ rval =3D mb.tag_get_data(vorticity_tag0, &vert_ents[0], 2, val);
+ CHECK_REAL_EQUAL(1.1, val[0], eps);
+ CHECK_REAL_EQUAL(1.2, val[1], eps);
+ rval =3D mb.tag_get_data(vorticity_tag1, &vert_ents[0], 2, val);
+ CHECK_REAL_EQUAL(2.1, val[0], eps);
+ CHECK_REAL_EQUAL(2.2, val[1], eps);
+
+ // Check tags for edge variable u
+ Tag u_tag0, u_tag1;
+ rval =3D mb.tag_get_handle("u0", 1, MB_TYPE_DOUBLE, u_tag0);
+ CHECK_ERR(rval);
+ rval =3D mb.tag_get_handle("u1", 1, MB_TYPE_DOUBLE, u_tag1);
+ CHECK_ERR(rval);
+
+ // Get edges (1920 edges)
+ Range edges;
+ rval =3D mb.get_entities_by_type(0, MBEDGE, edges);
+ assert(rval =3D=3D MB_SUCCESS);
+ CHECK_EQUAL((size_t)1920, edges.size());
+ CHECK_EQUAL((size_t)1, edges.psize());
+
+ // Check u tag values on two specified edges
+ EntityHandle edge_ents[] =3D {edges[5], edges[6]};
+ rval =3D mb.tag_get_data(u_tag0, &edge_ents[0], 2, val);
+ CHECK_REAL_EQUAL(1.113138721544778, val[0], eps);
+ CHECK_REAL_EQUAL(-1.113138721930009, val[1], eps);
+ rval =3D mb.tag_get_data(u_tag1, &edge_ents[0], 2, val);
+ CHECK_REAL_EQUAL(2.113138721544778, val[0], eps);
+ CHECK_REAL_EQUAL(-2.113138721930009, val[1], eps);
+
+ // Check tags for cell variable ke
+ Tag ke_tag0, ke_tag1;
+ rval =3D mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+ CHECK_ERR(rval);
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_ERR(rval);
+
+ // Get cells (12 pentagons and 630 hexagons)
+ Range cells;
+ rval =3D mb.get_entities_by_type(0, MBPOLYGON, cells);
+ assert(rval =3D=3D MB_SUCCESS);
+ CHECK_EQUAL((size_t)642, cells.size());
+ CHECK_EQUAL((size_t)2, cells.psize());
+
+ // Check ke tag values on first pentagon and first hexagon
+ EntityHandle cell_ents[] =3D {cells[0], cells[12]};
+ rval =3D mb.tag_get_data(ke_tag0, &cell_ents[0], 2, val);
+ CHECK_REAL_EQUAL(1.5, val[0], eps);
+ CHECK_REAL_EQUAL(1.6, val[1], eps);
+ rval =3D mb.tag_get_data(ke_tag1, &cell_ents[0], 2, val);
+ CHECK_REAL_EQUAL(2.5, val[0], eps);
+ CHECK_REAL_EQUAL(2.6, val[1], eps);
+}
+
+void test_read_onevar()=20
+{
+ Core moab;
+ Interface& mb =3D moab;
+ std::string opts;
+ ErrorCode rval =3D get_options(opts);
+ CHECK_ERR(rval);
+
+ opts +=3D std::string(";VARIABLE=3Dke");
+ rval =3D mb.load_file(example, NULL, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check for proper tags
+ Tag ke_tag0, ke_tag1;
+ rval =3D mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+ CHECK_ERR(rval);
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_onetimestep()
+{
+ Core moab;
+ Interface& mb =3D moab;
+ std::string opts;
+ ErrorCode rval =3D get_options(opts);
+ CHECK_ERR(rval);
+
+ opts +=3D std::string(";TIMESTEP=3D1");
+ rval =3D mb.load_file( example, NULL, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check for proper tags
+ Tag ke_tag0, ke_tag1;
+ rval =3D mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_nomesh()=20
+{
+ Core moab;
+ Interface& mb =3D moab;
+
+ // Need a set for nomesh to work right
+ EntityHandle set;
+ ErrorCode rval =3D mb.create_meshset(MESHSET_SET, set);
+ CHECK_ERR(rval);
+
+ std::string orig, opts;
+ rval =3D get_options(orig);
+ CHECK_ERR(rval);
+
+ opts =3D orig + std::string(";TIMESTEP=3D0");
+ rval =3D mb.load_file(example, &set, opts.c_str());
+ CHECK_ERR(rval);
+ =20
+ // Check for proper tags
+ Tag ke_tag0, ke_tag1;
+ rval =3D mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+ CHECK_ERR(rval);
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ // Now read 2nd timestep with nomesh option
+ opts =3D orig + std::string(";TIMESTEP=3D1;NOMESH");
+ rval =3D mb.load_file(example, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check for proper tag
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_ERR(rval);
+}
+
+void test_read_novars()
+{
+ Core moab;
+ Interface& mb =3D moab;
+
+ // Need a set for nomesh to work right
+ EntityHandle set;
+ ErrorCode rval =3D mb.create_meshset(MESHSET_SET, set);
+ CHECK_ERR(rval);
+
+ std::string orig, opts;
+ rval =3D get_options(orig);
+ CHECK_ERR(rval);
+
+ opts =3D orig + std::string(";NOMESH;VARIABLE=3D");
+ rval =3D mb.load_file(example, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ opts =3D orig + std::string(";VARIABLE=3D;TIMESTEP=3D0");
+ rval =3D mb.load_file(example, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check for proper tag
+ Tag ke_tag0, ke_tag1;
+ rval =3D mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ opts =3D orig + std::string(";VARIABLE=3Dke;TIMESTEP=3D0;NOMESH");
+ rval =3D mb.load_file(example, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check for proper tags
+ rval =3D mb.tag_get_handle("ke0", 1, MB_TYPE_DOUBLE, ke_tag0);
+ CHECK_ERR(rval);
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_EQUAL(rval, MB_TAG_NOT_FOUND);
+
+ // Now read 2nd timestep with nomesh option
+ opts =3D orig + std::string(";VARIABLE=3Dke;TIMESTEP=3D1;NOMESH");
+ rval =3D mb.load_file(example, &set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Check for proper tag
+ rval =3D mb.tag_get_handle("ke1", 1, MB_TYPE_DOUBLE, ke_tag1);
+ CHECK_ERR(rval);
+}
+
+ErrorCode get_options(std::string &opts)=20
+{
+#ifdef USE_MPI
+ // Use parallel options
+ opts =3D std::string(";;PARALLEL=3DREAD_PART;PARTITION_METHOD=3DTRIVIAL_=
PARTITION");
+ return MB_SUCCESS;
+#else
+ opts =3D std::string(";;");
+ return MB_SUCCESS;
+#endif
+}
https://bitbucket.org/fathomteam/moab/commits/044aeccd9c74/
Changeset: 044aeccd9c74
Branch: None
User: danwu
Date: 2013-07-01 17:09:22
Summary: The commented out code to check the number of elements in orig=
inal ReadNC::check_verts_quads() seems incorrect when it is tested. Still k=
eep it commented out at this time.
Affected #: 1 file
diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index eb58441..e0eae99 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -337,6 +337,7 @@ ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle=
file_set) {
rval =3D mbImpl->get_number_entities_by_dimension(file_set, (-1 =3D=3D l=
Dims[2] ? 2 : 3), num_elems);
ERRORR(rval, "Trouble getting number of elements.");
=20
+ /*
// Check against parameters
if (num_elems > 0)
{
@@ -345,6 +346,7 @@ ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle=
file_set) {
ERRORR(MB_FAILURE, "Number of elements doesn't match.");
}
}
+ */
=20
return MB_SUCCESS;
}
https://bitbucket.org/fathomteam/moab/commits/71d97b5e6a62/
Changeset: 71d97b5e6a62
Branch: None
User: danwu
Date: 2013-07-01 21:08:40
Summary: Added mpastrvpart.cpp to test parallel reading of MPAS file
Affected #: 2 files
diff --git a/test/parallel/Makefile.am b/test/parallel/Makefile.am
index d86a8bf..72fb443 100644
--- a/test/parallel/Makefile.am
+++ b/test/parallel/Makefile.am
@@ -55,7 +55,7 @@ else
endif
=20
if PNETCDF_FILE
- PNETCDF_TESTS =3D ucdtrvpart read_nc_par=20
+ PNETCDF_TESTS =3D ucdtrvpart read_nc_par mpastrvpart
else
PNETCDF_TESTS =3D=20
endif
@@ -90,6 +90,7 @@ scdpart_SOURCES =3D scdpart.cpp
if PNETCDF_FILE
ucdtrvpart_SOURCES =3D ucdtrvpart.cpp
read_nc_par_SOURCES=3D../io/read_nc.cpp
+ mpastrvpart_SOURCES =3D mpastrvpart.cpp
endif
=20
if ENABLE_mbcoupler
diff --git a/test/parallel/mpastrvpart.cpp b/test/parallel/mpastrvpart.cpp
new file mode 100644
index 0000000..386b126
--- /dev/null
+++ b/test/parallel/mpastrvpart.cpp
@@ -0,0 +1,122 @@
+#include "TestUtil.hpp"
+#include "moab/Core.hpp"
+#include "moab/ParallelComm.hpp"
+#include "moab/ProgOptions.hpp"
+#include "MBParallelConventions.h"
+#include "moab/Util.hpp"
+
+using namespace moab;
+
+#ifdef MESHDIR
+static const char example[] =3D STRINGIFY(MESHDIR) "/io/mpasx1.642.t.2.nc";
+#endif
+
+void test_read_parallel_mpas_trivial();
+void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, =
bool test_nb_edges);
+
+void test_multiple_loads_of_same_file();
+
+std::string partition_method;
+
+int main(int argc, char* argv[])
+{
+ MPI_Init(&argc, &argv);
+ int result =3D 0;
+
+ result +=3D RUN_TEST(test_read_parallel_mpas_trivial);
+ result +=3D RUN_TEST(test_multiple_loads_of_same_file);
+
+ MPI_Finalize();
+ return result;
+}
+
+void test_read_parallel_mpas_trivial()
+{
+ partition_method =3D std::string(";PARTITION_METHOD=3DTRIVIAL_PARTITION;=
PARALLEL_RESOLVE_SHARED_ENTS");
+
+ test_read_parallel(1280, true, 1920, true);
+}
+ =20
+void test_read_parallel(int num_verts, bool test_nb_nodes, int num_edges, =
bool test_nb_edges)
+{
+ Core moab;
+ Interface& mb =3D moab;
+ EntityHandle file_set;
+ ErrorCode rval;
+ rval =3D mb.create_meshset(MESHSET_SET, file_set);
+ CHECK_ERR(rval);
+
+ std::string opt =3D std::string("PARALLEL=3DREAD_PART") +
+ partition_method;
+ rval =3D mb.load_file(example, &file_set, opt.c_str());
+ CHECK_ERR(rval);
+
+ ParallelComm* pcomm =3D ParallelComm::get_pcomm(&mb, 0);
+
+ rval =3D pcomm->check_all_shared_handles();
+ CHECK_ERR(rval);
+
+ // Get the total # owned verts
+ Range verts;
+ rval =3D mb.get_entities_by_type(0, MBVERTEX, verts);
+ CHECK_ERR(rval);
+ rval =3D pcomm->filter_pstatus(verts, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+ CHECK_ERR(rval);
+
+ int my_verts_num =3D verts.size(), total_verts;
+ std::cout << "proc: " << pcomm->proc_config().proc_rank() << " verts:" <=
< my_verts_num << "\n";
+ MPI_Reduce(&my_verts_num, &total_verts, 1, MPI_INTEGER, MPI_SUM, 0, pcom=
m->proc_config().proc_comm());
+
+ if (0 =3D=3D pcomm->proc_config().proc_rank())
+ {
+ std::cout << "total vertices: " << total_verts << "\n";
+ if (test_nb_nodes)
+ CHECK_EQUAL(total_verts, num_verts);
+ }
+
+ // Get the total # owned edges
+ Range edges;
+ rval =3D mb.get_entities_by_type(0, MBEDGE, edges);
+ CHECK_ERR(rval);
+ rval =3D pcomm->filter_pstatus(edges, PSTATUS_NOT_OWNED, PSTATUS_NOT);
+ CHECK_ERR(rval);
+
+ int my_edges_num =3D edges.size(), total_edges;
+ std::cout << "proc: " << pcomm->proc_config().proc_rank() << " edges:" <=
< my_edges_num << "\n";
+ MPI_Reduce(&my_edges_num, &total_edges, 1, MPI_INTEGER, MPI_SUM, 0, pcom=
m->proc_config().proc_comm());
+
+ if (0 =3D=3D pcomm->proc_config().proc_rank())
+ {
+ std::cout << "total edges: " << total_edges << "\n";
+ if (test_nb_edges)
+ CHECK_EQUAL(total_edges, num_edges);
+ }
+
+ std::string write_options("PARALLEL=3DWRITE_PART;");
+ mb.write_file("test_mpas.h5m", NULL, write_options.c_str());
+}
+
+void test_multiple_loads_of_same_file()
+{
+ Core moab;
+ Interface& mb =3D moab;
+ EntityHandle file_set;
+ ErrorCode rval;
+ rval =3D mb.create_meshset(MESHSET_SET, file_set);
+ CHECK_ERR(rval);
+
+ // Read first only header information, no mesh, no variable
+ std::string opts("PARALLEL=3DREAD_PART;PARTITION;NOMESH;VARIABLE=3D;PART=
ITION_METHOD=3DTRIVIAL_PARTITION");
+ rval =3D mb.load_file(example, &file_set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Create mesh, no variable
+ opts=3D"PARALLEL=3DREAD_PART;PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;PART=
ITION_METHOD=3DTRIVIAL_PARTITION;VARIABLE=3D";
+ rval =3D mb.load_file(example, &file_set, opts.c_str());
+ CHECK_ERR(rval);
+
+ // Read variable ke at timestep 0, no mesh
+ opts =3D "PARALLEL=3DREAD_PART;PARTITION;PARTITION_METHOD=3DTRIVIAL_PART=
ITION;NOMESH;VARIABLE=3Dke;TIMESTEP=3D0";
+ rval =3D mb.load_file(example, &file_set, opts.c_str());
+ CHECK_ERR(rval);
+}
https://bitbucket.org/fathomteam/moab/commits/eccc26879798/
Changeset: eccc26879798
Branch: None
User: danwu
Date: 2013-07-01 23:13:59
Summary: Merged fathomteam/moab into master
Affected #: 9 files
diff --git a/doc/DG/moabDG.h b/doc/DG/moabDG.h
index d2e14f0..1091094 100644
--- a/doc/DG/moabDG.h
+++ b/doc/DG/moabDG.h
@@ -1,10 +1,45 @@
-/*! \page developerguide Developer's Guide (MOAB 4.6)
-=20
- \subpage dg-contents
-=20
- \subpage dg-figures
+/*! \page developerguide Developer's Guide (MOAB 4.6)
+=20
+ \subpage dg-contents
+=20
+ \subpage dg-figures
+
+ \subpage dg-tables
+*/
+
+/*! \page dg-contents Table of Contents
+
+ \subpage sequence-info
+
+ \subpage meta-data-info
+*/
+
+/*! \page dg-figures List of Figures
+
+ \ref figure1
+
+ \ref figure2
+
+ \ref figure3
+*/
+
+/*! \page dg-tables List of Tables
+
+ \ref table1
+
+ \ref table2
+
+ \ref table3
+
+ \ref table4
+
+ \ref table5
+
+ \ref table6
+
+*/
=20
- \page dg-contents Table of Contents
+/*! \page sequence-info Sequence Info
=20
\ref sequence
=20
@@ -14,10 +49,9 @@
=20
\ref sets
=20
- \section sequence 1. EntitySequence & SequenceData
+ \section sequence EntitySequence & SequenceData=20
=20
\subsection figure1 Figure 1: EntitySequences For One SequenceData
-
The <I>SequenceData</I> class manages as set of arrays of per-entity value=
s. Each
<I>SequenceData</I> has a start and end handle denoting the block of entit=
ies for which
the arrays contain data. The arrays managed by a <I>SequenceData</I> insta=
nce are
@@ -77,9 +111,9 @@ a feature. Sequences for which the corresponding data ca=
nnot be used to store
new entities (e.g. structured mesh discussed in a later section) will retu=
rn -1 or
some other invalid value.
=20
- \ref dg-contents
+ \ref sequence-info "Top"
=20
- \section manager 2. TypeSequenceManager & SequenceManager=20
+ \section manager TypeSequenceManager & SequenceManager=20
=20
The <I>TypeSequenceManager</I> class maintains an organized set of <I>Enti=
tySequence</I>
instances and corresponding <I>SequenceData</I> instances. It is used to m=
anage
@@ -141,119 +175,920 @@ such as allocating the correct <I>EntitySequence</I=
> subtype for a given <I>Enti
=20
<sup>2</sup>Given rule four for the data managed by a <I>TypeSequenceManag=
er</I>, any <I>SequenceData</I> for which all handles are allocated will be=
referenced by exactly one <I>EntitySequence</I>.
=20
- \ref dg-contents
-
- \section s-mesh 3. Structured Mesh
-
-Structured mesh storage is implemented using subclasses of <I>SequenceData=
</I>:
-<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSe=
q</I> class is
-used to access the structured element connectivity. A standard <I>VertexSe=
quence</I>
-instance is used to access the ScdVertexData because the vertex data stora=
ge
-is the same as for unstructured mesh.
-
- \ref dg-contents
-
- \section sets 4. Entity Sets
-
-- MeshSetSequence
-
-The <I>MeshSetSequence</I> class is the same as most other subclasses of <=
I>EntitySequence</I>
-in that it utilizes SequenceData to store its data. A single array in the =
<I>SequenceData</I>
-is used to store instances of the MeshSet class, one per allocated <I>Enti=
tyHandle</I>.
-<I>SequenceData</I> allocates all of its managed arrays using malloc and f=
ree as
-simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction =
and de-
-struction of <I>MeshSet</I> instances within that array. This is similar t=
o what is
-done by <I>std::vector</I> and other container classes that may own more s=
torage
-than is required at a given time for contained objects.
-
-- MeshSet
-
- \subsection figure3 Figure 3: SequenceManager and Related Classes
-
-The <I>MeshSet</I> class is used to represent a single entity set instance=
in MOAB.
-The class is optimized to minimize storage (further possible improvements =
in
-storage size are discussed later.)
-
-Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> clas=
s.
-The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER<=
/I>,
-<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MES=
HSET_TRACK_OWNER</I>
-indicates that reverse links from the contained entities back to the ownin=
g set
-should be maintained in the adjacency list of each entity. The <I>MESHSET_=
SET</I>
-and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most c=
ode only
-tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESH=
SET_SET</I> bit is
-ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplica=
te handles
-and that the order that the handles are added to the set should be preserv=
ed.
-In practice, such sets are stored as a simple list of handles. <I>MESHSET_=
SET</I> (or in
-practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of =
the handles
-need not be preserved and that the set may not contain duplicate handles. =
Such
-sets are stored in a sorted range-compacted format similar to that of the =
Range
-class.
-
-The memory for storing contents, parents, and children are each handled in
-the same way. The data in the class is composed of a 2-bit =E2=80=98size=
=E2=80=99 field and two
-values, where the two values may either be two handles or two pointers. Th=
e size
-bit-fields are grouped together to reduce the required amount of memory. I=
f the
-numerical value of the 2-bit size field is 0 then the corresponding list i=
s empty.
-If the 2-bit size field is either 1 or 2, then the contents of the corresp=
onding list
-are stored directly in the corresponding two data fields of the MeshSet ob=
ject.
-If the 2-bit size field has a value of 3 (11 binary), then the correspondi=
ng two
-data fields store the begin and end pointers of an external array of handl=
es.
-The number of handles in the external array can be obtained by taking the
-difference of the start and end pointers. Note that unlike <I>std::vector<=
/I>, we
-do not store both an allocated and used size. We store only the =E2=80=98u=
sed=E2=80=99 size
-and call std::realloc whenever the used size is modified, thus we rely on =
the
-std::malloc implementation in the standard C library to track =E2=80=98all=
ocated=E2=80=99 size
-for us. In practice this performs well but does not return memory to the =
=E2=80=98system=E2=80=99
-when lists shrink (unless they shrink to zero). This overall scheme could =
exhibit
-poor performance if the size of one of the data lists in the set frequentl=
y changes
-between less than two and more than two handles, as this will result in fr=
equent
-releasing and re-allocating of the memory for the corresponding array.
-
-If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents l=
ist (parent
-and child lists are unaffected) is stored in a range-compacted format. In =
this
-format the number of handles stored in the array is always a multiple of t=
wo.
-Each consecutive pair of handles indicate the start and end, inclusive, of=
a range
-of handles contained in the set. All such handle range pairs are stored in=
sorted
-order and do not overlap. Nor is the end handle of one range ever one less=
than
-the start handle of the next. All such =E2=80=98adjacent=E2=80=99 range pa=
irs are merged into a
-single pair. The code for insertion and removal of handles from range-form=
atted
-set content lists is fairly complex. The implementation will guarantee tha=
t a
-given call to insert entities into a range or remove entities from a range=
is never
-worse than O(ln n) + O(m + n), where =E2=80=98n=E2=80=99 is the number of =
handles to insert
-and =E2=80=98m=E2=80=99 is the number of handles already contained in the =
set. So it is generally
-much more efficient to build Ranges of handles to insert (and remove) and =
call
-MOAB to insert (or remove) the entire list at once rather than making may
-calls to insert (or remove) one or a few handles from the contents of a se=
t.
-The set storage could probably be further minimized by allowing up to six
-handles in one of the lists to be elided. That is, as there are six potent=
ial =E2=80=98slots=E2=80=99
-in the MeshSet object then if two of the lists are empty it should be poss=
ible to store up to six values of the remaining list directly in the MeshSe=
t object.
-However, the additional runtime cost of such complexity could easily outwe=
igh
-any storage advantage. Further investigation into this has not been done b=
ecause
-the primary motivation for the storage optimization was to support binary =
trees.
-
-Another possible optimization of storage would be to remove the <I>MeshSet=
</I>
-object entirely and instead store the data in a =E2=80=98blocked=E2=80=99 =
format. The corre-
-sponding <I>SequenceData</I> would contain four arrays: flags, parents, ch=
ildren, and
-contents instead of a single array of <I>MeshSet</I> objects. If this were=
done then
-no storage need ever be allocated for parent or child links if none of the=
sets
-in a <I>SequenceData</I> has parent or child links. The effectiveness of t=
he storage
-reduction would depend greatly on how sets get grouped into <I>SequenceDat=
as</I>.
-This alternate storage scheme might also allow for better cache utilizatio=
n as it
-would group like data together. It is often the case that application code=
that
-is querying the contents of one set will query the contents of many but ne=
ver
-query the parents or children of any set. Or that an application will quer=
y only
-parent or child links of a set without every querying other set properties=
. The
-downside of this solution is that it makes the implementation a little les=
s mod-
-ular and maintainable because the existing logic contained in the <I>MeshS=
et</I> class
-would need to be spread throughout the <I>MeshSetSequence</I> class.
-
- \ref dg-contents
-
- \page dg-figures List of Figures
-
- \ref figure1
-
- \ref figure2
-
- \ref figure3
+ \ref sequence-info "Top"
+
+ \section s-mesh Structured Mesh
+
+Structured mesh storage is implemented using subclasses of <I>SequenceData=
</I>:
+<I>ScdElementData</I> and <I>ScdVertexData</I>. The <I>StructuredElementSe=
q</I> class is
+used to access the structured element connectivity. A standard <I>VertexSe=
quence</I>
+instance is used to access the ScdVertexData because the vertex data stora=
ge
+is the same as for unstructured mesh.
+
+ \ref sequence-info "Top"
+
+ \section sets Entity Sets
+
+- MeshSetSequence
+
+The <I>MeshSetSequence</I> class is the same as most other subclasses of <=
I>EntitySequence</I>
+in that it utilizes SequenceData to store its data. A single array in the =
<I>SequenceData</I>
+is used to store instances of the MeshSet class, one per allocated <I>Enti=
tyHandle</I>.
+<I>SequenceData</I> allocates all of its managed arrays using malloc and f=
ree as
+simple arrays of bytes. <I>MeshSetSequence</I> does in-place construction =
and de-
+struction of <I>MeshSet</I> instances within that array. This is similar t=
o what is
+done by <I>std::vector</I> and other container classes that may own more s=
torage
+than is required at a given time for contained objects.
+
+- MeshSet
+
+ \subsection figure3 Figure 3: SequenceManager and Related Classes
+
+The <I>MeshSet</I> class is used to represent a single entity set instance=
in MOAB.
+The class is optimized to minimize storage (further possible improvements =
in
+storage size are discussed later.)
+
+Figure 3 shows the memory layout of an instance of the <I>MeshSet</I> clas=
s.
+The flags member holds the set creation bit flags: <I>MESHSET_TRACK_OWNER<=
/I>,
+<I>MESHSET_SET</I>, and <I>MESHSET_ORDERED</I>. The presence of the <I>MES=
HSET_TRACK_OWNER</I>
+indicates that reverse links from the contained entities back to the ownin=
g set
+should be maintained in the adjacency list of each entity. The <I>MESHSET_=
SET</I>
+and <I>MESHSET_ORDERED</I> bits are mutually exclusive, and as such most c=
ode only
+tests for the <I>MESHSET_ORDERED</I>, meaning that in practice the <I>MESH=
SET_SET</I> bit is
+ignored. <I>MESHSET_ORDERED</I> indicates that the set may contain duplica=
te handles
+and that the order that the handles are added to the set should be preserv=
ed.
+In practice, such sets are stored as a simple list of handles. <I>MESHSET_=
SET</I> (or in
+practice, the lack of <I>MESHSET_ORDERED</I>) indicates that the order of =
the handles
+need not be preserved and that the set may not contain duplicate handles. =
Such
+sets are stored in a sorted range-compacted format similar to that of the =
Range
+class.
+
+The memory for storing contents, parents, and children are each handled in
+the same way. The data in the class is composed of a 2-bit =E2=80=98size=
=E2=80=99 field and two
+values, where the two values may either be two handles or two pointers. Th=
e size
+bit-fields are grouped together to reduce the required amount of memory. I=
f the
+numerical value of the 2-bit size field is 0 then the corresponding list i=
s empty.
+If the 2-bit size field is either 1 or 2, then the contents of the corresp=
onding list
+are stored directly in the corresponding two data fields of the MeshSet ob=
ject.
+If the 2-bit size field has a value of 3 (11 binary), then the correspondi=
ng two
+data fields store the begin and end pointers of an external array of handl=
es.
+The number of handles in the external array can be obtained by taking the
+difference of the start and end pointers. Note that unlike <I>std::vector<=
/I>, we
+do not store both an allocated and used size. We store only the =E2=80=98u=
sed=E2=80=99 size
+and call std::realloc whenever the used size is modified, thus we rely on =
the
+std::malloc implementation in the standard C library to track =E2=80=98all=
ocated=E2=80=99 size
+for us. In practice this performs well but does not return memory to the =
=E2=80=98system=E2=80=99
+when lists shrink (unless they shrink to zero). This overall scheme could =
exhibit
+poor performance if the size of one of the data lists in the set frequentl=
y changes
+between less than two and more than two handles, as this will result in fr=
equent
+releasing and re-allocating of the memory for the corresponding array.
+
+If the <I>MESHSET_ORDERED</I> flag is not present, then the set contents l=
ist (parent
+and child lists are unaffected) is stored in a range-compacted format. In =
this
+format the number of handles stored in the array is always a multiple of t=
wo.
+Each consecutive pair of handles indicate the start and end, inclusive, of=
a range
+of handles contained in the set. All such handle range pairs are stored in=
sorted
+order and do not overlap. Nor is the end handle of one range ever one less=
than
+the start handle of the next. All such =E2=80=98adjacent=E2=80=99 range pa=
irs are merged into a
+single pair. The code for insertion and removal of handles from range-form=
atted
+set content lists is fairly complex. The implementation will guarantee tha=
t a
+given call to insert entities into a range or remove entities from a range=
is never
+worse than O(ln n) + O(m + n), where =E2=80=98n=E2=80=99 is the number of =
handles to insert
+and =E2=80=98m=E2=80=99 is the number of handles already contained in the =
set. So it is generally
+much more efficient to build Ranges of handles to insert (and remove) and =
call
+MOAB to insert (or remove) the entire list at once rather than making may
+calls to insert (or remove) one or a few handles from the contents of a se=
t.
+The set storage could probably be further minimized by allowing up to six
+handles in one of the lists to be elided. That is, as there are six potent=
ial =E2=80=98slots=E2=80=99
+in the MeshSet object then if two of the lists are empty it should be poss=
ible to store up to six values of the remaining list directly in the MeshSe=
t object.
+However, the additional runtime cost of such complexity could easily outwe=
igh
+any storage advantage. Further investigation into this has not been done b=
ecause
+the primary motivation for the storage optimization was to support binary =
trees.
+
+Another possible optimization of storage would be to remove the <I>MeshSet=
</I>
+object entirely and instead store the data in a =E2=80=98blocked=E2=80=99 =
format. The corre-
+sponding <I>SequenceData</I> would contain four arrays: flags, parents, ch=
ildren, and
+contents instead of a single array of <I>MeshSet</I> objects. If this were=
done then
+no storage need ever be allocated for parent or child links if none of the=
sets
+in a <I>SequenceData</I> has parent or child links. The effectiveness of t=
he storage
+reduction would depend greatly on how sets get grouped into <I>SequenceDat=
as</I>.
+This alternate storage scheme might also allow for better cache utilizatio=
n as it
+would group like data together. It is often the case that application code=
that
+is querying the contents of one set will query the contents of many but ne=
ver
+query the parents or children of any set. Or that an application will quer=
y only
+parent or child links of a set without every querying other set properties=
. The
+downside of this solution is that it makes the implementation a little les=
s mod-
+ular and maintainable because the existing logic contained in the <I>MeshS=
et</I> class
+would need to be spread throughout the <I>MeshSetSequence</I> class.
+
+ \ref sequence-info "Top"
*/
+
+/*! \page meta-data-info I/O and Meta-Data Storage Conventions in MOAB
+
+ <Center><H3> Timothy J. Tautges </H3></Center>
+
+ \ref meta-introduction
+
+ \ref meta-conventions
+
+ \ref meta-options
+
+ \ref meta-references
+
+ \ref appendixA
+
+ \ref appendixB
+
+ \ref appendixC
+
+ \ref appendixD
+
+ \ref appendixE
+
+ \section meta-introduction Introduction
+
+The Mesh-Oriented datABase (MOAB) is a library for representing finite ele=
ment and other types of mesh data [1]. Various types of meta-data are ofte=
n used in conjunction with a mesh. Examples include boundary condition gro=
upings, material types, and provenance information for the mesh. Because t=
he data model used in MOAB is so abstract, conventions are useful for descr=
ibing how meta-data is stored into that data model. This document describe=
s those conventions for several types of data commonly found in meshes stor=
ed in MOAB. Because the data models used by MOAB and iMesh, the ITAPS mesh=
interface [2], are so similar, the conventions described here apply almost=
unmodified to iMesh as well as to MOAB.
+
+The meshes represented in MOAB originate in a variety of forms, including =
mesh read from files of various formats (e.g. CUBIT =E2=80=9C.cub=E2=80=9D =
file, VTK, etc.) as well as mesh written into MOAB directly by various soft=
ware libraries (e.g. MeshKit). Although there is no standard for naming or=
storing meta-data with a mesh, there is a great deal of commonality in the=
types of meta-data typically found with mesh data. This document describe=
s conventions that have been established for commonly encountered meta-data=
. Various mesh readers implemented in MOAB attempt to read meta-data from =
a file and write it into the MOAB data model using these conventions. Alth=
ough there is no requirement to store a given type of meta-data in the form=
described here, a number of services have been written to handle meta-data=
using these conventions, no matter the source of the meta-data being proce=
ssed.
+
+Several specific tools are often used in concert with MOAB and bear specia=
l mention here. The CUBIT toolkit generates finite element meshes, and sav=
es them to a native save file (referred to as a =E2=80=9C.cub=E2=80=9D file=
) which MOAB is able to read. Reading CUBIT meshes into MOAB through the .=
cub file format is preferred over other formats, since most other mesh form=
ats written by CUBIT do not save most meta-data. The MeshKit library also =
generates mesh using CGM and MOAB, and uses the same conventions for storin=
g meshes into MOAB. Finally, MOAB includes a CGM reader which can read a g=
eometric model into a faceted representation in MOAB. Meta-data from all t=
hese tools are stored in MOAB using the conventions described here.=20
+
+The MOAB data model consists of the following basic types:
+- <B>Entity</B>: The basic elements of topology, e.g. vertex, edge, triang=
le, tetrahedron, etc. MOAB represents all types in the finite element zoo,=
plus polygons and polyhedra.
+- <B>Entity Set</B>: An arbitrary collection of entities and other sets. =
Sets can have parent/child relations with other sets, and these relations a=
re distinct from =E2=80=9Ccontains=E2=80=9D relations.
+- <B>Interface</B>: The interface object through which other entities are =
accessed, in the sense of object-oriented-programming. iMesh refers to the=
interface as the =E2=80=9Croot=E2=80=9D set.
+- <B>Tag</B>: A piece of data that can be assigned a distinct value to eac=
h entity and entity set, and to the interface itself. Tags have a prescrib=
ed name, size in bytes, and data type; allowed data types are integer, doub=
le, entity handle, and byte or opaque.
+.
+
+The following section describes each meta-data tag convention in detail; t=
hese conventions are also summarized in Table 1.
+
+ \ref meta-data-info "Top"
+
+ \section meta-conventions Meta-Data Conventions
+
+Meta-data is stored in MOAB and iMesh in the form of tags applied to eithe=
r entities or entity sets. For meta-data represented as entity sets, the c=
ontents of those sets are determined by the convention, with tags on those =
sets identifying them with the convention and adding any other semantic dat=
a.
+
+Each meta-data convention is described in a subsection below. Each conven=
tion begins with a short description of:
+- Whether tags associated with the convention are assigned to entities or =
entity sets
+- The tag(s) associated with the convention; information for each tag incl=
udes the name, the data type (I=3Dinteger, D=3Ddouble, C=3Dcharacter, H=3Dh=
andle), and the tag length. Tag lengths are specified after an asterisk (*=
); for example, C*32 implies a tag with character type and length 32. Unsp=
ecified lengths correspond to length one.
+.
+
+<H3>Name</H3>
+
+(Data: Entity sets, entities; Tag(s): NAME/C*32)
+
+Character strings are used in many different contexts in applications. MO=
AB uses the =E2=80=9CNAME=E2=80=9D tag to store character strings used to n=
ame entities. This tag is of byte-type and is of length 32 bytes. Note th=
at the string stored in this tag may or may not be terminated with a NULL c=
haracter. It is always prudent account for missing NULL terminator, to avo=
id buffer overflow errors in the application. Applications are free to def=
ine their own version of the NAME tag with a longer length, though this def=
inition may conflict with other services attempting to use this tag with th=
e conventional size. Applications needing a string tag with a longer or va=
riable length can also use MOAB=E2=80=99s variable-length tag type, though =
this will not be compatible with iMesh.
+
+<H3>Title </H3>
+
+(Data: Entity sets (file or instance); Tag(s): TITLE/C*strlen)
+
+The title tag is meant to hold the overall identifier of a mesh, written a=
t generation time or read from a file generated with a non-MOAB tool. The =
tag length is variable, and is set by the application directly (by calling =
the tag_create function) or indirectly (by embedding the title in a file re=
ad by MOAB).
+
+<H3> Global Identifier </H3>
+
+(Data: Entity sets, entities; Tag(s): GLOBAL_ID/I)
+
+Global identifiers are used in many different contexts in applications. G=
eometric model entities are identified by dimension and id, e.g. =E2=80=9CV=
olume 1=E2=80=9D. Mesh vertices and elements are identified similarly in m=
esh generation codes. Boundary conditions and material types are identifie=
d similarly. This tag is used to store such information. This tag is curr=
ently stored in a 32-byte integer, though this may change in the future.
+
+<H3> Geometric Model Information </H3>
+
+(Data: Entity sets; Tag(s): GEOM_DIMENSION/I, GLOBAL_ID/I, NAME/C*32, CATE=
GORY/C*32, GEOM_SENSE_2(EH[2]), GEOM_SENSE_N_ENTS(EH*N), GEOM_SENSE_N_SENSE=
S(I*N))
+
+Mesh generation is often performed starting from a geometric model, repres=
ented in some form of CAD engine. Many of the meshes used by MOAB are gene=
rated based on the CGM library. Geometric models contain both topological =
information (the topological entities in the geometric model) and shape inf=
ormation (the geometric shape of those entities), as well as other meta-dat=
a written to the entities in a model. When a mesh is read from a CUBIT .cu=
b file, meta-data from the geometric model is read and represented in the M=
OAB data model, as described below. <B> Note that although MOAB reads and r=
epresents meta-data associated with the geometric model, it does not repres=
ent the geometric model itself.</B> Therefore, shape-related information, =
e.g. the arc length of an edge or surface normal at a given point, can be r=
etrieved only from the model represented in CGM or another geometric modeli=
ng engine.
+
+The information contained in a geometric model, read into and represented =
in MOAB, consists of:
+- Model entities (vertex, edge, face, volume)
+- Topological relationships between model entities
+- Groups of model entities
+- Model entity/group ids
+- Model entity/group names
+.
+The storage of this information into MOAB's data model is described for ea=
ch type is described below.
+
+- <B>Entities </B>
+
+Entities in the geometric model (VERTEX, EDGE, FACE, VOLUME) are each repr=
esented by an entity set<sup>1</sup>. These sets are tagged with the =E2=
=80=9CGEOM_DIMENSION=E2=80=9D tag, with integer value equal to the topologi=
cal dimension of the entity (VERTEX =3D 0, EDGE =3D 1, etc.) These sets co=
ntain the mesh owned by the corresponding entity in the geometric model. N=
ote this does not include mesh owned by bounding entities; thus, the set fo=
r a FACE will not contain the mesh vertices owned by bounding EDGEs in the =
geometric model. These sets may or may not contain mesh entities of interm=
ediate dimension, e.g. mesh edges owned by a FACE or faces owned by a VOLUM=
E, depending on the application generating the mesh or the file from which =
the mesh was read. These sets are all set-types, i.e. the order of entitie=
s in the sets is not significant, except in the case of EDGE sets, where or=
der of the mesh vertices and edges corresponds to the relative order of ver=
tices and edges at the time of mesh generation. In MOAB, these sets are no=
n-tracking by default, i.e. entities do not have knowledge of which geometr=
y sets they are members of.
+
+<sup>1</sup>Body-type entities from CUBIT are not explicitly represented i=
n MOAB.
+
+- <B> Topological Relationships </B>
+
+In the geometric model, each FACE is bounded by zero or more EDGEs; other =
topological relationships between geometric entities exist in a similar man=
ner. These relationships are embedded in the data model using parent/child=
relations between entity sets. For example, the entity set corresponding =
to a FACE will have child sets, each corresponding to a bounding EDGE, and =
parent sets, each corresponding to a VOLUME bounded by that FACE. The rela=
tive order of sets in those parent/child lists is not significant, thus, =
=E2=80=9Cloops=E2=80=9D bounding a FACE cannot reliably be inferred from th=
is data.
+
+- <B> Groups </B>
+
+Geometric entities are sometimes assigned to application-specific groups. =
These groups are represented using entity sets, tagged with a =E2=80=9CGRO=
UP=E2=80=9D tag whose value equals the group id. Group sets are =E2=80=9Cs=
et=E2=80=9D-type, and are not tracking sets. These sets contain the sets c=
orresponding to geometric entities contained in the groups in the geometric=
model, as well as any mesh entities assigned to the group.
+
+<H4> Sense </H4>
+
+A geometric face has a natural orientation, indicated by the direction of =
the normal to the face; similarly, edges have a natural orientation determi=
ned by the direction of the tangent. When faces bound regions, or edges bo=
und faces, they do so with a sense; if a region includes a face with forwar=
d sense, that means the face's natural normal direction points out of the v=
olume. If a face includes an edge with forward sense, that means that if o=
ne moves along the edge in the direction of its tangent, the material of th=
e face is on the left hand side. The sense of a face (edge) with respect t=
o a region (face) it bounds is stored using tags on the face (edge).
+
+Most models allow a face to be part of only two regions. Therefore, to st=
ore the sense of a face with respect to regions including it, a tag with tw=
o values is used. This tag is named GEOM_SENSE_2, and has 2 EntityHandle v=
alues. The first value corresponds to the entity set for the region for wh=
ich that face has a forward sense, and the second to the region for which t=
hat face has a reverse sense.
+
+Edges can bound more than two faces. Therefore, two variable-length tags =
are used, one to store the EntityHandles of the faces the edge bounds, and =
the other to store the sense with which the edge bounds the corresponding f=
ace. These tags are named GEOM_SENSE_N_ENTS and GEOM_SENSE_N_SENSES, respe=
ctively. These are stored as variable-length tags; see the MOAB user's gui=
de for information on how to work with tags of this type.=20
+
+The following sense values are used:
+- 0: forward
+- 1: reverse
+- -1: unnknown
+
+<H3> Material Type </H3>
+
+(Data: Entity sets; Tag(s): MATERIAL_SET/I)
+
+Most finite element and other PDE-based analysis codes require a material =
type for each cell or element in the simulation. MOAB uses entity sets to =
store this information, in the form of entity sets. The MATERIAL_SET tag i=
s used to identify these sets. The value of this tag is conventionally an =
integer; in most cases this stores a user-assigned identifier associated wi=
th that material.=20
+
+CUBIT assigns material types using what it calls =E2=80=9Celement blocks=
=E2=80=9D, with each element block given a user-assigned id number and opti=
onally a name. The CUBIT and Exodus file readers in MOAB read element bloc=
ks into MATERIAL_SET sets. =20
+
+In CUBIT, materials are typically assigned by assigning geometric volumes =
to element blocks. Therefore, material sets often contain entity sets corr=
esponding to those volumes. Thus, a materrial set in MOAB is unlikely to c=
ontain mesh entities directly; rather, that set contains other sets which c=
ontain mesh entities. In these cases, mesh entities can be retrieved by pa=
ssing a =E2=80=9Crecursive=E2=80=9D flag to the appropriate function (MOAB)=
, or by calling the getEntitiesRec extension function (iMesh) provided by M=
OAB.
+
+<H3> Boundary Conditions (Dirichlet, Neumann)</H3>
+
+Data: Entity sets; Tag(s): DIRICHLET_SET/I, NEUMANN_SET/I)
+
+Boundary conditions are often specified in terms of geometric model entiti=
es, similar to material types. MOAB uses entity sets to store this informa=
tion as well. The DIRICHLET_SET and NEUMANN_SET tags are used to represent=
Dirichlet- and Neumann-type boundary condition sets, resp. By convention,=
Neumann sets usually contain (indirectly) intermediate-dimension entities =
like edges in a 2D mesh or faces in a 3D mesh, while Dirichlet sets usually=
contain vertices. In addition, Neumann sets are represented as sets of fa=
ces, rather than as sides of elements. Faces can be ordered =E2=80=9Cforwa=
rd=E2=80=9D or =E2=80=9Creverse=E2=80=9D with respect to one of the boundin=
g elements, depending on whether the right-hand normal points into or out o=
f the element. Forward-sense faces are added to the Neumann set. Reverse-=
sense faces are put into a separate set; that set is tagged with the NEUSET=
_SENSE tag, with value =3D -1; and that reverse set is added to the Neumman=
n set.
+
+<H3> Parallel Mesh Constructs </H3>
+
+(Data: Entity sets, entities; Tag(s): PARALLEL_PART/I, PARALLEL_PARTITION/=
I, PSTATUS/C*1, PARALLEL_SHARED_PROC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_=
SHARED_PROCS/I*NP, PARALLEL_SHARED_HANDLES/H*NP)
+
+On a parallel computer, MOAB can represent the mesh on each processor as w=
ell as information about entities shared with neighboring processors. Some=
of this information is also relevant even when the mesh is represented on =
a serial machine. MOAB uses several tag and set conventions to describe th=
e parallel nature of a mesh. This information is summarized here; for a mo=
re complete description of MOAB=E2=80=99s parallel mesh representation and =
functionality, see [ref-moabpar].
+
+- <B> Parallel partition, parts </B>
+
+Most parallel mesh applications use a domain decomposition approach, where=
each processor solves for a subset of the domain. The set of entities sol=
ved by a given processor is referred to as a part, and the collection of pa=
rts together is called the partition. MOAB stores each part in an entity s=
et, marked with the PARALLEL_PART tag, whose value is the rank of the proce=
ssor assigned that part; an entity set which contains all part sets is give=
n the PARALLEL_PARTITION tag, whose value is currently meaningless. The MB=
Zoltan tool included as a tool in MOAB can partition a mesh for parallel so=
lution, and writes the partition to the mesh in the form of parts and parti=
tions. Both these types of sets can be accessed in a serial mesh, e.g. for=
visualization.
+
+- <B> Part interfaces </B>
+
+When a partitioned mesh has been loaded on a parallel computer, the part o=
n a given processor may share portions of its boundary with parts on other =
processors. These shared regions are called part interfaces, and are also =
represented using entity sets. These sets are marked with the PARALLEL_INT=
ERFACE tag, whose value is currently meaningless.
+
+- <B> Shared processor and handle </B>
+
+For entities shared between processors, it is helpful to know locally whic=
h other processor shares an entity, and what the entity=E2=80=99s handle is=
on the remote processor. There are two cases which are useful to distingu=
ish, first where an entity is shared with only one other processor (referre=
d to as shared), and second when a processor is shared by more than one oth=
er processor (referred to as multi-shared). Shared entities are given the=
PARALLEL_SHARED_PROC and PARALLEL_SHARED_HANDLE tags, which store the rank=
of the sharing processor and the handle of the entity on that processor, r=
espectively. Multi-shared entities are marked with the PARALLEL_SHARED_PRO=
CS and PARALLEL_SHARED_HANDLES tags; these tags have a length NP assigned a=
t compile time in MOAB, with default values of -1 for processor rank and ze=
ro for handle (which are each invalid values for the corresponding data). =
The processors/handles sharing a given entity are then written on the front=
of the arrays. So, for example, an entity on processor rank 0, shared by =
processors 1 and 2, would have a PARALLEL_SHARED_PROCS tag whose values wou=
ld be [1, 2, -1, -1, =E2=80=A6], with PARALLEL_SHARED_HANDLES values of [m,=
n, 0, 0, =E2=80=A6], where m and n would be the handles of that entity on =
processors 1 and 2. The shared versions of these tags are =E2=80=9Cdense=
=E2=80=9D, with default values which denote unshared entities. The multi-s=
hared tags are sparse tags in MOAB, with no default value.
+
+- <B> Parallel status </B>
+
+In addition to the tags above, MOAB also defines the PSTATUS tag, whose bi=
ts contain information about the parallel status of a given entity. Starti=
ng with least significant bit, these bits represent whether an entity is 1)=
not owned, 2) shared, 3) multi-shared, 4) interface, 5) a ghost entity. T=
he first bit being set indicates =E2=80=9Cnot owned=E2=80=9D so that the de=
fault value for this tag, of zero, corresponds to an owned, unshared entity=
, which will be the state of most entities on a given processor.
+
+<H3>Structured Mesh Parameters </H3>
+
+MOAB has a structured mesh interface for creating structured mesh (see =E2=
=80=9CScdInterface.hpp=E2=80=9D header file in MOAB source code). Along wi=
th an internal representation that is more memory-efficient (since it does =
not need to store connectivity), MOAB also creates and tags entity sets wit=
h structured mesh parameters, which can be accessed through the normal tag =
and set interface. The following tags are used:
+- <B>BOX_DIMS</B>: This tag stores the ijk coordinates of the lower and up=
per corner of the structured mesh box(es).
+- <B>GLOBAL_BOX_DIMS</B>: If specified when the structured mesh is created=
, a tag with this name stores the global box dimensions (which may be diffe=
rent than the local box dimensions).
+- <B>BOX_PERIODIC</B>: Stores whether the box is periodic in the i (BOX_PE=
RIODIC[0]) and j (BOX_PERIODIC[1]) directions.
+- <B>__BOX_SET</B>: Pointer to the ScdBox instance corresponding to this e=
ntity set.<sup>2</sup>
+.
+Although the structured mesh is not saved as such in HDF5-format files, th=
e entity sets and corresponding tags will be saved and restored.
+
+<sup>2</sup>The double-underscore in the tag name implies that this tag wi=
ll not be saved in a file, in this case because the ScdBox instances are no=
t preserved in a file.
+
+<H3>Spectral Mesh Constructs </H3>
+
+The Spectral Element Method (SEM) is a high-order method, using a polynomi=
al Legendre interpolation basis with Gauss-Lobatto quadrature points, in co=
ntrast to the Lagrange basis used in (linear) finite elements. A spectral =
mesh with order O contains quadrilateral or hexahedral elements comprised o=
f (O+1)d vertices. Spectral meshes are usually represented in one of two w=
ays, either as coarse elements which point to an array of higher-order vert=
ices (and with corner vertices represented in the normal manner), or as lin=
ear quads/hexes formed from the higher-order vertices, with each original c=
oarse quad/hex represented by Od fine quads/hexes. Similarly, the spectral=
variables, which are normally computed at fine vertex positions, are store=
d either on those vertices, or in lexicographically-ordered arrays on eleme=
nts (with tag values repeated on neighboring elements). MOAB can read spec=
tral meshes from a variety of formats (at this time, including CAM-SE, HOMM=
E, and Nek5000). Which of the above two representations are controlled by =
read options and are indicated by certain tags:
+- SPECTRAL_MESH: read option indicating that spectral elements should be r=
epresented as coarse linear quads/hexes and each element containing an arra=
y of lexicographically-ordered vertex handles
+- TAG_SPECTRAL_ELEMENTS: read option; if given, spectral variables are rep=
resented as lexicographically-ordered arrays on elements
+- TAG_SPECTRAL_VERTICES: read option; if given, spectral variables are rep=
resented as tags on vertices
+- CONN=3D<filename>: in CAM-SE, the connectivity of the spectral mesh is s=
tored by default in a file named =E2=80=9CHommeMapping.nc=E2=80=9D; this op=
tion can be given to read the connectivity from a different file
+- SPECTRAL_VERTICES: tag name for array of vertex handles
+- SPECTRAL_ORDER: tag name for spectral order, written to file set or (if =
no file set given) to interface after a spectral mesh is read
+.
+
+ \ref meta-data-info "Top"
+
+ \section meta-options Reader/Writer Options
+
+All mesh file readers and writers in MOAB take an option string as an argu=
ment. By default, the semicolon (=E2=80=9C;=E2=80=9D) delimits individual =
options in the option string. Options used in multiple readers are describ=
ed in this section; the options enabled in specific readers/writers are des=
cribed in the corresponding appendix at the end of this document.
+
+<H3>variable=3D<var_name>[,...]</H3>
+
+By default, all field data stored with the mesh is read with the mesh, and=
stored as tags on the associated mesh entities. This option lists specifi=
c variables that should be read along with the mesh (note also the =E2=80=
=9Cnomesh=E2=80=9D option, described elsewhere in this document). The vari=
able name listed will be read into a tag with the same name. For time-depe=
ndent variables, the time step number will be appended to the variable name=
to form the tag name. If no =E2=80=9Ctimestep=E2=80=9D or =E2=80=9Ctimeva=
l=E2=80=9D option is given, all time steps will be read, resulting in sever=
al tags being created. If the =E2=80=9Cnomesh=E2=80=9D option is given, th=
e application must pass the entity set resulting from the original mesh rea=
d in to the function, that this set must contain the mesh read only from th=
at file. The mesh in the file is checked against the mesh in the set to ve=
rify that the two correspond. The special name =E2=80=9CMOAB_ALL_VARIABLES=
=E2=80=9D can be used to indicate that all variables should be read. Multi=
ple variable names can be specified, separated from each other by commas.
+
+<H3>nomesh </H3>
+
+Indicates that no mesh should be read from the file. This option is used =
in conjunction with the =E2=80=9Cvariable=3D=E2=80=9D option, to read varia=
bles and assign them as tags to a previously-read mesh. If this option is =
used, applications should pass an entity set to the read function, which sh=
ould contain the mesh previously read from the file.
+
+<H3>timestep=3D<step_number>[, ...] </H3>
+
+Read the time step number whose time value is equal to or greater than the=
specified time value, for the specified variable(s). Tag names for the va=
riable(s) will be formed by appending the time step number to the variable =
name. Multiple time step values can be specified, separated from each othe=
r by commas.
+
+ \ref meta-data-info "Top"
+
+ \section meta-references References
+
+[1] T.J. Tautges, R. Meyers, K. Merkley, C. Stimpson, and C. Ernst, MOAB: =
A Mesh-Oriented Database, Sandia National Laboratories, 2004.
+
+[2] L. Diachin, A. Bauer, B. Fix, J. Kraftcheck, K. Jansen, X. Luo, M. Mil=
ler, C. Ollivier-Gooch, M.S. Shephard, T. Tautges, and H. Trease, =E2=80=9C=
Interoperable mesh and geometry tools for advanced petascale simulations,=
=E2=80=9D Journal of Physics: Conference Series, vol. 78, 2007, p. 012015.
+
+\ref meta-data-info "Top"
+
+ \section appendixA Appendix A: Summary
+
+ \subsection table1 Table 1: Summary of MOAB meta-data conventions.
+
+<table border=3D"1">
+<tr>
+<th>Convention</th>
+<th>Applies to (E=3Dent, S=3Dset)</th>
+<th>Tag(s) (type/length)</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>Name</td>
+<td>E, S</td>
+<td>NAME/C*32</td>
+<td></td>
+</tr>
+<tr>
+<td>Title</td>
+<td>S</td>
+<td>TITLE/C*strlen</td>
+<td>Title of mesh</td>
+</tr>
+<tr>
+<td>Global identifier</td>
+<td>E, S</td>
+<td>GLOBAL_ID/I</td>
+<td></td>
+</tr>
+<tr>
+<td>Geometric topology</td>
+<td>S</td>
+<td>GEOM_DIMENSION/I, GLOBAL_ID/I,
+NAME/C*32,
+CATEGORY/C*32.
+GEOM_SENSE_2/EH[2],
+GEOM_SENSE_N_ENTS/EH*N,
+GEOM_SENSE_N_SENSES/I*N</td>
+<td>Sets contain mesh owned by that entity; parent/child links to bounded/=
bounding entities in geometric model</td>
+</tr>
+<tr>
+<td>Material type</td>
+<td>S</td>
+<td>MATERIAL_SET/I</td>
+<td>Set contains entities or sets assigned a common material type</td>
+</tr>
+<tr>
+<td>Boundary condition</td>
+<td>S</td>
+<td>DIRICHLET_SET/I, NEUMANN_SET/I</td>
+<td>Set contains entities or sets assigned a particular boundary condition=
; neumann sets usually contain edges (2D) or faces (3D)</td>
+</tr>
+<tr>
+<td>Parallel mesh constructs</td>
+<td>E, S</td>
+<td>PARALLEL_PART/I, PARALLEL_PARTITION/I, PSTATUS/C*1, PARALLEL_SHARED_PR=
OC/I, PARALLEL/SHARED_HANDLE/H, PARALLEL_SHARED_PROCS/I*NP, PARALLEL_SHARED=
_HANDLES/H*NP</td>
+<td> Data which describes parallel mesh</td>
+</tr>
+<tr>
+<td>Structured mesh constructs</td>
+<td>S</td>
+<td>BOX_DIMS/I*6, GLOBAL_BOX_DIMS/I*6, BOX_PERIODIC/2*I, __BOX_SET/O</td>
+<td>Data describing structured mesh </td>
+</tr>
+<tr>
+<td>Spectral mesh constructs </td>
+<td>E, S</td>
+<td>SPECTRAL_ORDER/I, SPECTRAL_VERTICES/I*(O+1)^2</td>
+<td>Data marking spectral mesh constructs</td>
+</tr>
+</table>
+=20
+ \ref meta-introduction "Back to Introduction"
+
+ \subsection table2 Table 2: Summary of MOAB conventional tag names, type=
s, and purposes. Data types are I=3Dinteger, D=3Ddouble, C=3Dcharacter, H=
=3Dentity handle,O=3Dopaque. Data type with *x denote length of x elements=
of that data type.
+
+<Table border=3D"1">
+<tr>
+<th>Tag name</th>
+<th>Data type</th>
+<th>Applies to (E=3Dentity, S=3Dset)</th>
+<th>Purpose</th>
+</tr>
+<tr>
+<td>BOX_DIMS</td>
+<td>I*6</td>
+<td>S</td>
+<td>Lower and upper ijk dimensions of box, ordered (ilo, jlo, klo, ihi, jh=
i, khi)</td>
+</tr>
+<tr>
+<td>BOX_PERIODIC</td>
+<td>I*2</td>
+<td>S</td>
+<td>Indicates whether box is periodic in i (BOX_PERIODIC[0]) or j (BOX_PER=
IODIC[1])</td>
+</tr>
+<tr>
+<td>__BOX_SET</td>
+<td>O</td>
+<td>S</td>
+<td>Pointer to corresponding ScdBox instance</td>
+</tr>
+<tr>
+<td>CATEGORY</td>
+<td>C*32</td>
+<td>S</td>
+<td>String describing purpose of set; examples include =E2=80=9Cgroup=E2=
=80=9D, =E2=80=9Cvertex=E2=80=9D, =E2=80=9Cedge=E2=80=9D, =E2=80=9Csurface=
=E2=80=9D, =E2=80=9Cvolume=E2=80=9D</td>
+</tr>
+<tr>
+<td>DIRICHLET_SET </td>
+<td>I</td>
+<td>SO</td>
+<td>Entities or sets with common boundary condition</td>
+</tr>
+<tr>
+<td>GEOM_DIMENSION</td>
+<td>I</td>
+<td>S</td>
+<td>Identifies mesh entities resolving a given geometric model entity</td>
+</tr>
+<tr>
+<td>GEOM_SENSE_2</td>
+<td>EH*2</td>
+<td>S</td>
+<td> Stored on face-type geometric topology sets, values store regions hav=
ing forward and reverse sense</td>
+</tr>
+<tr>
+<td>GEOM_SENSE_N_ENTS</td>
+<td>EH*N</td>
+<td>S</td>
+<td>Stored on edge-type geometric topology sets, values store faces whose =
senses are stored in GEOM_SENSE_N_SENSES.</td>
+</tr>
+<tr>
+<td>GEOM_SENSE_N_SENSES</td>
+<td>I*N</td>
+<td>S</td>
+<td>Stored on edge-type geometric topology sets, values store senses of th=
e edge with respect to faces stored in GEOM_SENSE_N_ENTS.</td>
+</tr>
+<tr>
+<td>GLOBAL_ID</td>
+<td>I</td>
+<td>E,S</td>
+<td>Application-specific entity id</td>
+</tr>
+<tr>
+<td>MATERIAL_SET</td>
+<td>I</td>
+<td>S</td>
+<td>Entities or sets grouped by material type</td>
+</tr>
+<tr>
+<td>NAME</td>
+<td>C*32</td>
+<td>E, S</td>
+<td>User-assigned entity name(s); multiple names delimited with ?</td>
+</tr>
+<tr>
+<td>NEUMANN_SET</td>
+<td>I</td>
+<td>S</td>
+<td>Entities or sets with common boundary condition </td>
+</tr>
+<tr>
+<td>PARALLEL_PART </td>
+<td>I</td>
+<td>S</td>
+<td>Represent a part in a partition</td>
+</tr>
+<tr>
+<td>PARALLEL_PARTITION</td>
+<td>I</td>
+<td>S</td>
+<td>Represents a partition of the mesh for parallel solution, which is a c=
ollection of parts</td>
+</tr>
+<tr>
+<td>__PARALLEL_SHARED_HANDLEd</td>
+<td>H</td>
+<td>E, S</td>
+<td> Handle of this entity/set on sharing processor</td>
+</tr>
+<tr>
+<td>__PARALLEL_SHARED_PROC</td>
+<td>I</td>
+<td>E,S</td>
+<td>Rank of other processor sharing this entity/set </td>
+</tr>
+</table>
+
+\ref meta-data-info "Top"
+
+ \section appendixB Appendix B: CCMIO (Star-CD, Star-CCM+) Reader/Writer =
Conventions
+
+ \subsection table3 Table 3: Translation between CCMIO options and MOAB t=
ags.
+<Table border=3D"1">
+<tr>
+<th> Set Type</th>
+<th>CCMIO Construct</th>
+<th>MOAB Tag Name, Type</th>
+</tr>
+<tr>
+<td rowspan=3D"2">File set / Interface</td>
+<td>Title (option)</td>
+<td>=E2=80=9CTitle=E2=80=9D (C*32)</td>
+</tr>
+<tr>
+<td>CreatingProgram</td>
+<td>=E2=80=9CCreatingProgram=E2=80=9D (C*32)</td>
+</tr>
+<tr>
+<td rowspan=3D"13">Material sets</td>
+<td>Index</td>
+<td>MATERIAL_SET</td>
+</tr>
+<tr>
+<td>Label<sup>1</sup></td>
+<td>NAME</td>
+</tr>
+<tr>
+<td>MaterialId</td>
+<td>=E2=80=9CMaterialId=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>Radiation</td>
+<td>=E2=80=9CRadiation=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>PorosityId</td>
+<td>=E2=80=9CPorosityId=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>SpinId</td>
+<td>=E2=80=9CSpinId=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>GroupId</td>
+<td>=E2=80=9CGroupId=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>ColorIdx</td>
+<td>=E2=80=9CColorIdx=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>ProcessorId</td>
+<td>=E2=80=9CProcessorId=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>LightMaterial</td>
+<td>=E2=80=9CLightMaterial=E2=80=9D (I)</td>
+</tr>
+<tr>
+<td>FreeSurfaceMaterial</td>
+<td>=E2=80=9CThickness=E2=80=9D (F)</td>
+</tr>
+<tr>
+<td>Thickness</td>
+<td>=E2=80=9CThickness=E2=80=9D (F)</td>
+</tr>
+<tr>
+<td>MaterialType</td>
+<td>=E2=80=9CMaterialType=E2=80=9D (C*32)</td>
+</tr>
+<tr>
+<td rowspan=3D"5">Neumann sets</td>
+<td>Index</td>
+<td>NEUMANN_SET</td>
+</tr>
+<tr>
+<td>Label</td>
+<td>NEUMANN_SET</td>
+</tr>
+<tr>
+<td>BoundaryName</td>
+<td>NAME</td>
+</tr>
+<tr>
+<td>BoundaryType</td>
+<td>=E2=80=9CBoundaryType=E2=80=9D (C*32)</td>
+</tr>
+<tr>
+<td>ProstarRegionNumber</td>
+<td>=E2=80=9CProstarRegionNumber=E2=80=9D (I)</td>
+</tr>
+</table>
+
+Notes:
+1. If no name is present, labels the material group with =E2=80=9CMaterial=
X=E2=80=9D, where X is the index of that group.
+
+\ref meta-data-info "Top"
+
+ \section appendixC Appendix C: ExodusII Reader/Writer Conventions=20
+
+ \subsection table4 Table 4: Translation between ExodusII constructs and =
MOAB tags.
+<Table border=3D"1">
+<tr>
+<th> Data Type</th>
+<th>ExodusII Construct</th>
+<th>MOAB Tag Name, Type</th>
+</tr>
+<tr>
+<td></td>
+<td>QA records</td>
+<td>=E2=80=9CqaRecord=E2=80=9D (C*(v))<sup>2</sup></td>
+</tr>
+<tr>
+<td rowspan=3D"2">Material sets</td>
+<td>Block number</td>
+<td>MATERIAL_SET</td>
+</tr>
+<tr>
+<td>Block element type</td>
+<td>Entity type, # vertices per entity</td>
+</tr>
+<tr>
+<td rowspan=3D"2">Dirichlet sets<sup>3</sup></td>
+<td>Nodeset number</td>
+<td>DIRICHLET_SET</td>
+</tr>
+<tr>
+<td>Distribution factors</td>
+<td>=E2=80=9CdistFactor=E2=80=9D (D*(v))<sup>1</sup></td>
+</tr>
+<tr>
+<td>Neumann sets</td>
+<td>Sideset number</td>
+<td>NEUMANN_SET</td>
+</tr>
+<tr>
+<td rowspan=3D"2">Neumann sets, reverse faces3<sup>3</sup></td>
+<td>Distribution factors</td>
+<td>=E2=80=9CdistFactor=E2=80=9D (D*(v))<sup>1</sup></td>
+</tr>
+<tr>
+<td>Sides</td>
+<td>SENSE</td>
+</tr>
+<tr>
+<td>Nodes, elements</td>
+<td>node_num_map, elem_map</td>
+<td>GLOBAL_ID on nodes/elements</td>
+</tr>
+</table>
+
+Notes:
+-# Variable-length tag used for distribution factors; length for each set =
is the number of entities in
+each set, such that there is one distribution factor for each entity in th=
e set.
+-# QA records are stored as variable-length tags on file set specified on =
read. Tag is a
+concatenation of QA record strings into a single string, with '\0' used to=
delimit lines.
+-# MOAB represents sidesets as sets of faces, rather than as sides of elem=
ents. Faces can be
+ordered =E2=80=9Cforward=E2=80=9D or =E2=80=9Creverse=E2=80=9D with respec=
t to one of the bounding elements, depending on
+whether the right-hand normal points into or out of the element. Forward-s=
ense faces are added
+to the Neumann set. Reverse-sense faces are put into a separate set; that =
set is tagged with the SENSE tag, with value =3D -1; and that reverse set i=
s added to the Neummann set.
+.
+
+ \ref meta-data-info "Top"
+
+ \section appendixD Appendix D: NC (Climate Data) Reader/Writer Conventio=
ns
+
+The climate data reader in MOAB reads files with the '.nc' filename extens=
ion. By default, this reader
+reads the whole mesh in the file and creates it as structured mesh in MOAB=
, with the mesh accessible
+through MOAB's structured mesh interface. By default, all variables and ti=
mesteps are read from the
+file, and written as tags on the mesh vertices from that file. This behavi=
or is controlled by the
+=E2=80=9Cvariable=E2=80=9D, =E2=80=9Cnomesh=E2=80=9D, =E2=80=9Ctimestep=E2=
=80=9D, and =E2=80=9Ctimeval=E2=80=9D options described earlier in this doc=
ument. If MOAB
+is compiled for parallel execution and configured with a pnetcdf reader, t=
he mesh is read in parallel,
+with a 1D or 2D decomposition designed to balance read performance and com=
munication interface
+size (for details on the partitioning method used, see the src/io/ReadNC.c=
pp source file).
+
+Mesh is put into the entity set provided to the load_file function. This e=
ntity set is also annotated with
+various tags representing information read from the file. These tags are d=
escribed in Table 5.
+
+Several other things to note about reading climate data files into MOAB:
+- Time-dependent variables: MOAB currently has no mechanism for time-depen=
dent tags. Therefore, time-dependent variables are represented using one ta=
g per timestep, with the tag name set as the variable name plus the timeste=
p index. Thus, the first few timesteps for the variable TEMPERATURE would b=
e represented in tags named TEMPERATURE0, TEMPERATURE1, etc.
+- Cell- and face-centered variables: The climate data reader currently doe=
s not do cell- and face-
+centered variables correctly.
+.
+ \subsection table5 Table 5: Summary of MOAB conventional tag names, type=
s, and purposes. Data types are I=3Dinteger, D=3Ddouble, C=3Dcharacter, H=
=3Dentity handle. Data type with *x denote length of x elements of that dat=
a type; data type with *var denote variable-length tag. Tag names with two =
underscores prepended (=E2=80=9C__=E2=80=9D) denote tags not written to a f=
ile by MOAB.
+
+<Table border=3D"1">
+<tr>
+<th> Tag name </th>
+<th>Data type </th>
+<th> Applies to (E=3Dentity, S=3Dset) </th>
+<th>Purpose </th>
+</tr>
+<tr>
+<td>__NUM_DIMS </td>
+<td>I</td>
+<td>S</td>
+<td>The number of dimensions in the netcdf file.</td>
+</tr>
+<tr>
+<td>__NUM_VARS</td>=20
+<td>I</td>
+<td>S</td>
+<td>The number of variables in the netcdf file.</td>
+</tr>
+<tr>
+<td>__DIM_NAMES </td>
+<td>C*var </td>
+<td>S </td>
+<td>The dimension names, concatenated into a
+character string, with '\0' terminating each name.
+ </td>
+</tr>
+<tr>
+<td>__DIM_NAMES=20
+</td>
+<td>C*var</td>
+<td>S</td>
+<td>The variable names, concatenated into a character
+string, with '\0' terminating each name.
+</td>
+</tr>
+<tr>
+<td><dim_name>=20
+</td>
+<td>(I or=20
+D)*va=20
+</td>
+<td>S</td>
+<td>For each dimension, the values for the dimension.
+The data type for this tag corresponds to that in the
+netcdf file. The length of this tag is the number of
+values stored for the dimension in the netcdf file.</td>
+</tr>
+<tr>
+<td>__<dim_name>_LOC_MIN MAX</td>=20
+<td>2*(I or D)</td>
+<td>S</td>
+<td>The indices (0-based) of the local min and max
+values of dimension stored locally. For spatial
+dimensions like lon or lat, this will store the
+minimum and maximum indices in the loca</td>
+</tr>
+<tr>
+<td >__<dim_name>_LOC_VAL </td>=20
+<td>(I or D)*var </td>
+<td>S</td>
+<td>The indices (0-based) of the dimension stored
+locally. This tag only makes sense for dimensions
+that can be read in multiple pieces, such as time.
+Only one of __<dim_name>_LOC_VALS and
+_LOC_MIN_MAX can be used for a given
+dimension.
+</tr>
+<tr>
+<td>__<var_name>_DIMS=20
+</td>
+<td>C*n=20
+</td>
+<td>S</td>
+<td>For each variable, the tag handles for the
+dimensions defining this variable, in netcdf
+ordering (last dimension varying fastest). The
+length of this tag, n, is # dimensions for the
+variable * sizeof(TagHandle).
+</td>
+</tr>
+<tr>
+<td><var_name><timestep_ind>=20
+</td>
+<td>(data type)</td>
+<td>E</td>
+<td>Values of the variable for timestep <timestep_ind>
+for vertices. The data type of this tag corresponds
+to that of the variable from the netcdf file.
+Timestep index is 0-based.
+</td>
+</tr>
+<tr>
+<td>__GLOBAL_ATTRIBS=20
+</td>
+<td>C*Var=20
+</td>
+<td>S</td>
+<td>The global attributes, concatenated into a character
+string, with =E2=80=98\0=E2=80=99 terminating each attribute name, =E2=80=
=98;=E2=80=99
+ separating the data type and value, and =E2=80=98;=E2=80=99
+ separating one name/data type/value from the next.
+</td>
+</tr>
+<tr>
+<td>__GLOBAL_ATTRIBS_LEN=20
+</td>
+<td>I*Var=20
+</td>
+<td>S</td>
+<td>A vector of integers, marking the end position of
+each attribute (name/data type/value) in __GLOBAL_ATTRIBS tag.
+</td>
+</tr>
+<tr>
+<td>__<var_name>_ATTRIBS=20
+</td>
+<td>C*Var
+</td>
+<td>S</td>
+<td>The variable attributes, concatenated into a
+character string, with =E2=80=98\0=E2=80=99 terminating each attribute
+ name, =E2=80=98;=E2=80=99 separating the data type and value, and =E2=
=80=98;=E2=80=99
+ separating one name/data type/value from the next.
+</td>
+</tr>
+<tr>
+<td>__<var_name>_ATTRIBS_LEN=20
+</td>
+<td>I*Var
+</td>
+<td>S</td>
+<td>A vector of integers, marking the end position of
+each attribute (name/data type/value) in
+__<var_name>_ATTRIBS tags
+</td>
+</tr>
+</table>
+
+ \ref meta-data-info "Top"
+
+ \section appendixE Appendix E: Nek5000 Reader/Writer Conventions
+
+Nek5000, or Nek, is a code that uses the spectral element method to model =
fluid, heat transfer,
+electromagnetics, and other physics. Nek uses unstructured hexahedral mesh=
es, with each hex element
+resolved by a structured grid of =E2=80=9CGauss Lebato Legendre=E2=80=9D (=
GLL) points. Nek can read meshes through
+MOAB, and can output physics variables and GLL points through MOAB as well.
+
+Since fluid is a single material in Nek, no material sets are needed. Boun=
dary conditions are mapped to
+Nek's cbc array using Neumann sets and a user-provided =E2=80=9Cusr_moab2n=
ek=E2=80=9D subroutine (for an example
+of this subroutine, see examples/moab/pipe.usr in the Nek source code). GL=
L point locations and fluid
+variables on those points are stored in tags on the hex elements. All hex =
elements have the same
+number of GLL points. The number of GLL points in each direction is stored=
in a tag on the mesh
+instance. These tags are described in Table 6.
+
+GLL point locations and fluid variables are stored in lexicographic order,=
similar to their storage order
+inside the Nek code.
+
+ \subsection table6 Table 6: Summary of MOAB conventional tag names, type=
s, and purposes for Nek. Data types are I=3Dinteger, D=3Ddouble, C=3Dcharac=
ter, H=3Dentity handle. Data type with *x denote length of x elements of th=
at data type; data type with *var denote variable-length tag. Tag names wit=
h two underscores prepended (=E2=80=9C__=E2=80=9D) denote tags not written =
to a file by MOAB.
+<Table border=3D"1">
+<tr>
+<th> Tag name </th>
+<th> Data Type</th>
+<th>Applies to (E=3Dentity, S=3Dset)</th>
+<th>Purpose</th>
+</tr>
+<tr>
+<td>SEM_DIMS</td>
+<td>I*3</td>
+<td>S</td>
+<td>The dimensions of the GLL mesh in each hex
+element.
+</td>
+</tr>
+<tr>
+<td>SEM_X</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>X position of GLL points (having nx*ny*nz
+values)
+</td>
+</tr>
+<tr>
+<td>SEM_Y</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Y position of GLL points (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>SEM_Z</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Z position of GLL points (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>VEL_X</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid velocities in the x direction for GLL point
+array (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>VEL_Y</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid velocities in the y direction for GLL point
+array (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>VEL_Z</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid velocities in the z direction for GLL point
+array (having nx*ny*nz values)</td>
+</tr>
+<tr>
+<td>TEMP</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid temperature for GLL point array (having
+nx*ny*nz values)
+</td>
+</tr>
+<tr>
+<td>PRESS</td>
+<td>D*nx*ny*nz</td>
+<td>E</td>
+<td>Fluid pressure for GLL point array (having
+nx*ny*nz values)
+</td>
+</tr>
+</table>
+ \ref meta-data-info "Top"
+ */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 38b4130..a1993c9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -31,8 +31,8 @@
PolyElementSeq.cpp
Range.cpp
RangeSeqIntersectIter.cpp
- ReadUtil.cpp
ReaderWriterSet.cpp
+ ReadUtil.cpp
ScdElementData.cpp
ScdInterface.cpp
ScdVertexData.cpp
@@ -56,11 +56,40 @@
VertexSequence.cpp
WriteUtil.cpp
)
+
+ add_subdirectory( io )
+ set ( MOABIO_LIB_SRCS
+ io/IODebugTrack.cpp
+ io/ExoIIUtil.cpp
+ io/FileTokenizer.cpp
+ io/GmshUtil.cpp
+ io/ReadABAQUS.cpp
+ io/ReadGmsh.cpp
+ io/ReadIDEAS.cpp
+ io/ReadMCNP5.cpp
+ io/ReadNASTRAN.cpp
+ io/ReadSmf.cpp
+ io/ReadSms.cpp
+ io/ReadSTL.cpp
+ io/ReadTemplate.cpp
+ io/ReadTetGen.cpp
+ io/ReadTxt.cpp
+ io/ReadVtk.cpp
+ io/SMF_State.cpp
+ io/Tqdcfr.cpp
+ io/VtkUtil.cpp
+ io/WriteAns.cpp
+ io/WriteGMV.cpp
+ io/WriteGmsh.cpp
+ io/WriteSTL.cpp
+ io/WriteSmf.cpp
+ io/WriteTemplate.cpp
+ io/WriteVtk.cpp
+ )
include_directories(
${MOAB_SOURCE_DIR}/src
- ${MOAB_BINARY_DIR}/src
${MOAB_SOURCE_DIR}/src/io
- ${MOAB_BINARY_DIR}/src/io
+ ${MOAB_SOURCE_DIR}/src/parallel
)
=20
if ( MOAB_USE_MPI )
@@ -82,12 +111,73 @@
set_source_files_properties( ${MOAB_LIB_SRCS}
COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}"
)
+
+# target_link_libraries( MOAB moabio )
+ if ( MOAB_USE_NETCDF )
+ find_package( NetCDF )
+ if ( NetCDF_FOUND )
+ set ( MOAB_DEFINES "${MOAB_DEFINES} -DNETCDF_FILE" )
+ set ( MOABIO_LIB_SRCS
+ ${MOABIO_LIB_SRCS}
+ io/ReadNCDF.cpp
+ io/WriteNCDF.cpp
+ io/WriteSLAC.cpp
+ )
+ include_directories(
+ ${NetCDF_INCLUDE_DIRECTORIES}
+ )
+ endif ( NetCDF_FOUND )
+ endif ( MOAB_USE_NETCDF )
+
+ if ( MOAB_USE_HDF )
+ # HDF5
+ find_package( HDF5 )
+ if ( HDF5_FOUND )
+ set ( MOAB_DEFINES "${MOAB_DEFINES} -DHDF5_FILE" )
+ check_function_exists( H5Pset_fapl_mpio MOAB_HDF_HAVE_PARALLEL )
+ set ( MOABIO_LIB_SRCS
+ ${MOABIO_LIB_SRCS}
+ io/HDF5Common.cpp
+ io/ReadHDF5.cpp
+ io/ReadHDF5Dataset.cpp
+ io/ReadHDF5VarLen.cpp
+ io/WriteHDF5.cpp
+ )
+
+# if ( MOAB_USE_MPI AND MPI_FOUND )
+# set ( MOABIO_LIB_SRCS
+# ${MOABIO_LIB_SRCS}
+# src/parallel/WriteHDF5Parallel.cpp
+# )
+# endif (MOAB_USE_MPI AND MPI_FOUND)
+
+ include_directories(
+ ${HDF5_INCLUDE_DIRECTORIES}
+ io/mhdf/include
+ )
+ add_subdirectory( io/mhdf )
+ endif ( HDF5_FOUND )
+ endif ( MOAB_USE_HDF )
+
+ set_source_files_properties( ${MOABIO_LIB_SRCS}
+ COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}"
+ )
+
add_library( MOAB
${MOAB_LIB_SRCS}
+ ${MOABIO_LIB_SRCS}
)
- =20
- add_subdirectory( io )
- target_link_libraries( MOAB moabio )
+
+ if ( MOAB_USE_NETCDF AND NetCDF_FOUND )
+ MESSAGE( "Adding NetCDF dependency libraries: ${NetCDF_LIBRARIES}" )
+ target_link_libraries( MOAB ${NetCDF_LIBRARIES} )
+ endif ( MOAB_USE_NETCDF AND NetCDF_FOUND )
+
+ if ( MOAB_USE_HDF AND HDF5_FOUND )
+ MESSAGE( "Adding NetCDF dependency libraries: ${HDF5_LIBRARIES}" )
+# add_dependencies( MOAB mhdf )
+ target_link_libraries( MOAB mhdf ${HDF5_LIBRARIES} )
+ endif ( MOAB_USE_HDF AND HDF5_FOUND )
=20
if ( MOAB_USE_MPI AND MPI_FOUND )
add_subdirectory( parallel )
diff --git a/src/Skinner.cpp b/src/Skinner.cpp
index 1d284b7..5869777 100644
--- a/src/Skinner.cpp
+++ b/src/Skinner.cpp
@@ -453,16 +453,6 @@ ErrorCode Skinner::find_skin_noadj(const Range &source=
_entities,
if(mTargetDim < 0 || source_dim > 3)
return MB_FAILURE;
=20
- //Core *this_core =3D dynamic_cast<Core*>(thisMB);
- //bool use_adjs =3D false;
- //if (!this_core->a_entity_factory()->vert_elem_adjacencies() &&
- // create_vert_elem_adjs)
- // this_core->a_entity_factory()->create_vert_elem_adjacencies();
- //
- //if (this_core->a_entity_factory()->vert_elem_adjacencies())
- // use_adjs =3D true;
- //
- //else=20
initialize();
=20
Range::const_iterator iter, end_iter;
@@ -477,7 +467,8 @@ ErrorCode Skinner::find_skin_noadj(const Range &source_=
entities,
EntityHandle sub_conn[32];
std::vector<EntityHandle> tmp_conn_vec;
int num_nodes, num_sub_nodes, num_sides;
- int sub_indices[32];
+ int sub_indices[32];// Also, assume that no polygon has more than 32 nod=
es
+ // we could increase that, but we will not display it right in visit moa=
b h5m , anyway
EntityType sub_type;
=20
// for each source entity
@@ -490,130 +481,95 @@ ErrorCode Skinner::find_skin_noadj(const Range &sour=
ce_entities,
=20
type =3D thisMB->type_from_handle(*iter);
Range::iterator seek_iter;
- Range dum_elems, dum_sub_elems;
=20
- // get connectivity of each n-1 dimension entity
- num_sides =3D CN::NumSubEntities( type, mTargetDim );
+ // treat separately polygons (also, polyhedra will need special handli=
ng)
+ if (MBPOLYGON =3D=3D type)
+ {
+ num_sides =3D num_nodes;
+ sub_type =3D MBEDGE;
+ num_sub_nodes =3D 2;
+ }
+ else// get connectivity of each n-1 dimension entity
+ num_sides =3D CN::NumSubEntities( type, mTargetDim );
for(int i=3D0; i<num_sides; i++)
{
- CN::SubEntityNodeIndices( type, num_nodes, mTargetDim, i, sub_type, =
num_sub_nodes, sub_indices );
- assert((size_t)num_sub_nodes <=3D sizeof(sub_indices)/sizeof(sub_ind=
ices[0]));
- for(int j=3D0; j<num_sub_nodes; j++)
- sub_conn[j] =3D conn[sub_indices[j]];
- =20
-// if (use_adjs) {
-// dum_elems.clear();
-// result =3D thisMB->get_adjacencies(sub_conn, num_sub_nodes, sour=
ce_dim, false,
-// dum_elems);
-// if (MB_SUCCESS !=3D result) return result;
-// dum_elems =3D intersect( dum_elems, source_entities );
-// if (dum_elems.empty()) {
-// assert(false); // should never happen
-// return MB_FAILURE;
-// }
-// // if (dum_elems.size() > 2) {=20
-// // source entities do not form a valid source-dim patch (t-jun=
ction).
-// // do we care?
-// // }
-// =20
-// if (1 =3D=3D dum_elems.size()) {
-// // this sub_element is on the skin
-//
-// // check for existing entity
-// dum_sub_elems.clear();
-// result =3D thisMB->get_adjacencies(sub_conn, num_sub_nodes, mT=
argetDim, false,
-// dum_sub_elems);
-// if (MB_SUCCESS !=3D result) return result;
-// if (dum_sub_elems.empty()) {
-// // need to create one
-// EntityHandle tmphndl=3D0;
-// int indices[MAX_SUB_ENTITY_VERTICES];
-// EntityType new_type;
-// int num_new_nodes;
-// CN::SubEntityNodeIndices( type, num_nodes, mTargetDim, i, ne=
w_type, num_new_nodes, indices );
-// for(int j=3D0; j<num_new_nodes; j++)
-// sub_conn[j] =3D conn[indices[j]];
-// =20
-// result =3D thisMB->create_element(new_type, sub_conn, =20
-// num_new_nodes, tmphndl);
-// forward_target_entities.insert(tmphndl);
-// }
-// else {
-// // else find the relative sense of this entity to the sour=
ce_entity in this set
-// int side_no, sense =3D 0, offset;
-// if (source_entities.find(*dum_elems.begin()) =3D=3D source_e=
ntities.end()) {
-// result =3D thisMB->side_number(*dum_elems.rbegin(), *dum_s=
ub_elems.begin(),
-// side_no, sense, offset);
-// }
-// else {
-// result =3D thisMB->side_number(*dum_elems.begin(), *dum_su=
b_elems.begin(),
-// side_no, sense, offset);
-// }
-// if (-1 =3D=3D sense) reverse_target_entities.insert(*dum_sub=
_elems.begin());
-// else if (1 =3D=3D sense) forward_target_entities.insert(*dum=
_sub_elems.begin());
-// else return MB_FAILURE;
-// }
-// }
-// }
-// else {
- =20
- // see if we can match this connectivity with
- // an existing entity
- find_match( sub_type, sub_conn, num_sub_nodes, match, direct );
+ if(MBPOLYGON=3D=3Dtype)
+ {
+ sub_conn[0] =3D conn[i];
+ sub_conn[1] =3D conn[(i+1)%num_sides];
+ }
+ else
+ {
+ CN::SubEntityNodeIndices( type, num_nodes, mTargetDim, i, sub_type=
, num_sub_nodes, sub_indices );
+ assert((size_t)num_sub_nodes <=3D sizeof(sub_indices)/sizeof(sub_i=
ndices[0]));
+ for(int j=3D0; j<num_sub_nodes; j++)
+ sub_conn[j] =3D conn[sub_indices[j]];
+ }
=20
- // if there is no match, create a new entity
- if(match =3D=3D 0)
+ // see if we can match this connectivity with
+ // an existing entity
+ find_match( sub_type, sub_conn, num_sub_nodes, match, direct );
+
+ // if there is no match, create a new entity
+ if(match =3D=3D 0)
+ {
+ EntityHandle tmphndl=3D0;
+ int indices[MAX_SUB_ENTITY_VERTICES];
+ EntityType new_type;
+ int num_new_nodes;
+ if(MBPOLYGON=3D=3Dtype)
+ {
+ new_type =3D MBEDGE;
+ num_new_nodes =3D 2;
+ }
+ else
{
- EntityHandle tmphndl=3D0;
- int indices[MAX_SUB_ENTITY_VERTICES];
- EntityType new_type;
- int num_new_nodes;
CN::SubEntityNodeIndices( type, num_nodes, mTargetDim, i, new_ty=
pe, num_new_nodes, indices );
for(int j=3D0; j<num_new_nodes; j++)
sub_conn[j] =3D conn[indices[j]];
- result =3D thisMB->create_element(new_type, sub_conn, num_new_no=
des,
- tmphndl);
- assert(MB_SUCCESS =3D=3D result);
- add_adjacency(tmphndl, sub_conn, CN::VerticesPerEntity(new_type)=
);
- forward_target_entities.insert(tmphndl);
}
- // if there is a match, delete the matching entity
- // if we can.=20
- else
+ result =3D thisMB->create_element(new_type, sub_conn, num_new_node=
s,
+ tmphndl);
+ assert(MB_SUCCESS =3D=3D result);
+ add_adjacency(tmphndl, sub_conn, CN::VerticesPerEntity(new_type));
+ forward_target_entities.insert(tmphndl);
+ }
+ // if there is a match, delete the matching entity
+ // if we can.
+ else
+ {
+ if ( (seek_iter =3D forward_target_entities.find(match)) !=3D forw=
ard_target_entities.end())
{
- if ( (seek_iter =3D forward_target_entities.find(match)) !=3D fo=
rward_target_entities.end())
+ forward_target_entities.erase(seek_iter);
+ remove_adjacency(match);
+ if(/*!use_adjs &&*/ entity_deletable(match))
{
- forward_target_entities.erase(seek_iter);
- remove_adjacency(match);
- if(/*!use_adjs &&*/ entity_deletable(match))
- {
- result =3D thisMB->delete_entities(&match, 1);
- assert(MB_SUCCESS =3D=3D result);
- }
+ result =3D thisMB->delete_entities(&match, 1);
+ assert(MB_SUCCESS =3D=3D result);
+ }
+ }
+ else if ( (seek_iter =3D reverse_target_entities.find(match)) !=3D=
reverse_target_entities.end())
+ {
+ reverse_target_entities.erase(seek_iter);
+ remove_adjacency(match);
+ if(/*!use_adjs &&*/ entity_deletable(match))
+ {
+ result =3D thisMB->delete_entities(&match, 1);
+ assert(MB_SUCCESS =3D=3D result);
}
- else if ( (seek_iter =3D reverse_target_entities.find(match)) !=
=3D reverse_target_entities.end())
+ }
+ else
+ {
+ if(direct =3D=3D FORWARD)
{
- reverse_target_entities.erase(seek_iter);
- remove_adjacency(match);
- if(/*!use_adjs &&*/ entity_deletable(match))
- {
- result =3D thisMB->delete_entities(&match, 1);
- assert(MB_SUCCESS =3D=3D result);
- }
+ forward_target_entities.insert(match);
}
else
{
- if(direct =3D=3D FORWARD)
- {
- forward_target_entities.insert(match);
- }
- else
- {
- reverse_target_entities.insert(match);
- }
+ reverse_target_entities.insert(match);
}
}
- //}
+ }
}
}
=20
diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt
deleted file mode 100644
index d6c3e44..0000000
--- a/src/io/CMakeLists.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-
- # MOAB Library
- set ( MOABIO_LIB_SRCS
- ExoIIUtil.cpp
- FileTokenizer.cpp
- GmshUtil.cpp
- ReadABAQUS.cpp
- ReadGmsh.cpp
- ReadIDEAS.cpp
- ReadMCNP5.cpp
- ReadNASTRAN.cpp
- ReadSmf.cpp
- ReadSms.cpp
- ReadSTL.cpp
- ReadTemplate.cpp
- ReadTetGen.cpp
- ReadTxt.cpp
- ReadVtk.cpp
- SMF_State.cpp
- Tqdcfr.cpp
- VtkUtil.cpp
- WriteAns.cpp
- WriteGMV.cpp
- WriteGmsh.cpp
- WriteSTL.cpp
- WriteSmf.cpp=20
- WriteTemplate.cpp
- WriteVtk.cpp
- )
- include_directories(
- ${MOAB_SOURCE_DIR}/src
- ${MOAB_BINARY_DIR}/src
- ${MOAB_SOURCE_DIR}/src/parallel
- ${MOAB_BINARY_DIR}/src/parallel
- )
-
- if ( MOAB_USE_NETCDF )
- find_package( NetCDF )
- if ( NetCDF_FOUND )
- set ( MOAB_DEFINES "${MOAB_DEFINES} -DNETCDF_FILE" )
- set ( MOABIO_LIB_SRCS
- ${MOABIO_LIB_SRCS}
- ReadNCDF.cpp
- WriteNCDF.cpp
- WriteSLAC.cpp
- )
- include_directories(
- ${NetCDF_INCLUDE_DIRECTORIES}
- )
- endif ( NetCDF_FOUND )
- endif ( MOAB_USE_NETCDF )
-
- if ( MOAB_USE_HDF )
- # HDF5
- find_package( HDF5 )
- if ( HDF5_FOUND )
- set ( MOAB_DEFINES "${MOAB_DEFINES} -DHDF5_FILE" )
- check_function_exists( H5Pset_fapl_mpio MOAB_HDF_HAVE_PARALLEL )
- set ( MOABIO_LIB_SRCS
- ${MOABIO_LIB_SRCS}
- ReadHDF5.cpp
- WriteHDF5.cpp
- )
- include_directories(
- ${HDF5_INCLUDE_DIRECTORIES}
- ${MOAB_SOURCE_DIR}/mhdf/include
- )
- add_subdirectory( mhdf )
- endif ( HDF5_FOUND )
- endif ( MOAB_USE_HDF )
-
- set_source_files_properties( ${MOABIO_LIB_SRCS}
- COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}"
- )
- add_library( moabio
- ${MOABIO_LIB_SRCS}
- )
-
- if ( MOAB_USE_HDF AND HDF5_FOUND )
- target_link_libraries( moabio
- mhdf
- ${HDF5_LIBRARIES}
- )
- endif ( MOAB_USE_HDF AND HDF5_FOUND )
-
- if ( MOAB_USE_NETCDF AND NetCDF_FOUND )
- target_link_libraries( moabio
- ${NetCDF_LIBRARIES}
- )
- endif ( MOAB_USE_NETCDF AND NetCDF_FOUND )
diff --git a/src/parallel/CMakeLists.txt b/src/parallel/CMakeLists.txt
index 598b6fc..7583885 100644
--- a/src/parallel/CMakeLists.txt
+++ b/src/parallel/CMakeLists.txt
@@ -5,8 +5,14 @@ set( moab_PARALLEL_SRCS
ReadParallel.cpp
gs.cpp
TupleList.cpp
+ SharedSetData.cpp
)
=20
+include_directories(
+ ${MOAB_SOURCE_DIR}/src
+ ${MOAB_SOURCE_DIR}/src/parallel
+ )
+
if ( MOAB_USE_HDF AND MOAB_HDF_HAVE_PARALLEL )
set( moab_PARALLEL_SRCS
${moab_PARALLEL_SRCS}
@@ -45,38 +51,3 @@ target_link_libraries( MOABpar
${MPI_EXTRA_LIBRARY}
)
=20
-if ( MOAB_USE_MPI AND MPI_FOUND )
- add_executable ( mbparallelcomm_test mbparallelcomm_test.cpp )
- target_link_libraries( mbparallelcomm_test MOAB )
- set_source_files_properties( mbparallelcomm_test.cpp
- COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}" )
- add_test( TestParallelComm-BcastDelete
- ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
- ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} 0 $=
{MOAB_SOURCE_DIR}/parallel/ptest.cub )
- add_test( TestParallelComm-ReadDelete
- ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
- ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} -1 =
${MOAB_SOURCE_DIR}/parallel/ptest.cub )
- add_test( TestParallelComm-ReadParallel
- ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
- ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} -2 =
${MOAB_SOURCE_DIR}/parallel/ptest.cub )
- add_test( TestParallelComm-Broadcast
- ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
- ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} -3 =
${MOAB_SOURCE_DIR}/parallel/ptest.cub )
-
- add_executable ( parallel_unit_tests parallel_unit_tests.cpp )
- target_link_libraries( parallel_unit_tests MOAB )
- add_test( TestParallel
- ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
- ${EXECUTABLE_OUTPUT_PATH}/parallel_unit_tests ${MPIEXEC_POSTFLAGS} ${M=
OAB_SOURCE_DIR}/parallel/ptest.cub )
- set_source_files_properties( parallel_unit_tests.cpp
- COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}" )
-
- if ( MOAB_USE_HDF )
- add_executable( mhdf_parallel mhdf_parallel.c )
- target_link_libraries( mhdf_parallel MOAB MOABpar mhdf )
- add_test( TestMHDFParallel ${EXECUTABLE_OUTPUT_PATH}/mhdf_parallel )
- set_source_files_properties( mhdf_parallel.c
- COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}" )
- endif ( MOAB_USE_HDF )
-endif ( MOAB_USE_MPI AND MPI_FOUND )
-
diff --git a/src/parallel/ParallelComm.cpp b/src/parallel/ParallelComm.cpp
index ec908b9..348bad0 100644
--- a/src/parallel/ParallelComm.cpp
+++ b/src/parallel/ParallelComm.cpp
@@ -7234,7 +7234,7 @@ ErrorCode ParallelComm::post_irecv(std::vector<unsign=
ed int>& shared_procs,
RRA("Failure in waitall in tag exchange.");
}
=20
- myDebug->tprintf(1, "Exiting exchange_tags");
+ myDebug->tprintf(1, "Exiting reduce_tags");
=20
return MB_SUCCESS;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 030c3b4..3b1d28d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,9 +2,7 @@
=20
include_directories(
${MOAB_SOURCE_DIR}/src
- ${MOAB_BINARY_DIR}/src
${MOAB_SOURCE_DIR}/src/parallel
- ${MOAB_BINARY_DIR}/src/parallel
)
=20
add_executable( moab_test MBTest.cpp )
@@ -43,3 +41,39 @@
add_test( TestBSPTree ${EXECUTABLE_OUTPUT_PATH}/bsp_tree_test )
=20
=20
+if ( MOAB_USE_MPI AND MPI_FOUND )
+
+ add_executable ( mbparallelcomm_test mbparallelcomm_test.cpp )
+ target_link_libraries( mbparallelcomm_test MOAB )
+ set_source_files_properties( mbparallelcomm_test.cpp
+ COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}" )
+ add_test( TestParallelComm-BcastDelete
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
+ ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} 0 $=
{MOAB_SOURCE_DIR}/parallel/ptest.cub )
+ add_test( TestParallelComm-ReadDelete
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
+ ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} -1 =
${MOAB_SOURCE_DIR}/parallel/ptest.cub )
+ add_test( TestParallelComm-ReadParallel
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
+ ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} -2 =
${MOAB_SOURCE_DIR}/parallel/ptest.cub )
+ add_test( TestParallelComm-Broadcast
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
+ ${EXECUTABLE_OUTPUT_PATH}/mbparallelcomm_test ${MPIEXEC_POSTFLAGS} -3 =
${MOAB_SOURCE_DIR}/parallel/ptest.cub )
+
+ if ( MOAB_USE_HDF )
+ add_executable( mhdf_parallel mhdf_parallel.c )
+ target_link_libraries( mhdf_parallel MOAB MOABpar mhdf )
+ add_test( TestMHDFParallel ${EXECUTABLE_OUTPUT_PATH}/mhdf_parallel )
+ set_source_files_properties( mhdf_parallel.c
+ COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}" )
+ endif ( MOAB_USE_HDF )
+
+ add_executable ( parallel_unit_tests parallel_unit_tests.cpp )
+ target_link_libraries( parallel_unit_tests MOAB )
+ add_test( TestParallel
+ ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS}
+ ${EXECUTABLE_OUTPUT_PATH}/parallel_unit_tests ${MPIEXEC_POSTFLAGS} ${M=
OAB_SOURCE_DIR}/parallel/ptest.cub )
+ set_source_files_properties( parallel_unit_tests.cpp
+ COMPILE_FLAGS "-DIS_BUILDING_MB ${MOAB_DEFINES}" )
+
+endif ( MOAB_USE_MPI AND MPI_FOUND )
diff --git a/test/parallel/par_intx_sph.cpp b/test/parallel/par_intx_sph.cpp
index bf5cbb8..f5c4b22 100644
--- a/test/parallel/par_intx_sph.cpp
+++ b/test/parallel/par_intx_sph.cpp
@@ -5,8 +5,7 @@
* the mesh is read in parallel; lagrangian mesh is manufactured on the f=
ly (part of the test), in
* a different set.
*
- * lagrangian mesh will be located on the euler mesh; intersections will =
be performed on the
- * euler mesh
+ * intersections will be performed on the euler mesh
* Created on: Nov 14, 2012
*/
=20
@@ -45,7 +44,6 @@ std::string input_mesh_file("Homme_2pt.h5m"); // input fi=
le, partitioned correct
std::string mpas_file("mpas_p8.h5m");
double CubeSide =3D 6.; // the above file starts with cube side 6; radius =
depends on cube side
double radius;
-void test_intx_in_parallel();
void test_intx_in_parallel_elem_based();
void test_intx_mpas();
=20
@@ -75,7 +73,7 @@ int main(int argc, char **argv)
index++;
}
}
- //result +=3D RUN_TEST(test_intx_in_parallel);
+
radius =3D CubeSide/2*sqrt(3.);
result +=3D RUN_TEST(test_intx_in_parallel_elem_based);
radius =3D1.;
@@ -157,67 +155,7 @@ ErrorCode manufacture_lagrange_mesh_on_sphere(Interfa=
ce * mb, EntityHandle eule
=20
return rval;
}
-void test_intx_in_parallel()
-{
- std::string opts =3D std::string("PARALLEL=3DREAD_PART;PARTITION=3DPARAL=
LEL_PARTITION")+
- std::string(";PARALLEL_RESOLVE_SHARED_ENTS");
- Core moab;
- Interface & mb =3D moab;
- EntityHandle euler_set;
- ErrorCode rval;
- rval =3D mb.create_meshset(MESHSET_SET, euler_set);
- CHECK_ERR(rval);
- std::string example(TestDir + "/" + input_mesh_file);
-
- rval =3D mb.load_file(example.c_str(), &euler_set, opts.c_str());
-
- ParallelComm* pcomm =3D ParallelComm::get_pcomm(&mb, 0);
- CHECK_ERR(rval);
-
- rval =3D pcomm->check_all_shared_handles();
- CHECK_ERR(rval);
-
- // everybody will get a LOC tag, including the non owned entities; so ex=
change tags is not required for LOC (here)
- rval =3D manufacture_lagrange_mesh_on_sphere(&mb, euler_set);
- CHECK_ERR(rval);
-=20
- Intx2MeshOnSphere worker(&mb);
=20
- //double radius=3D CubeSide/2 * sqrt(3.) ; // input
- worker.SetRadius(radius);
- worker.set_box_error(EPS1);//
- //worker.SetEntityType(MBQUAD);
-
- worker.SetErrorTolerance(radius*1.e-8);
- worker.locate_departure_points(euler_set);
-
- // we need to make sure the covering set is bigger than the euler mesh
- EntityHandle covering_lagr_set;
- rval =3D mb.create_meshset(MESHSET_SET, covering_lagr_set);
- CHECK_ERR(rval);
-
- rval =3D worker.create_departure_mesh(covering_lagr_set);
- CHECK_ERR(rval);
- int rank =3D pcomm->proc_config().proc_rank();
- std::stringstream ss;
- ss<<"partial" << rank<<".vtk";
- mb.write_file(ss.str().c_str(), 0, 0, &covering_lagr_set, 1);
- EntityHandle outputSet;
- rval =3D mb.create_meshset(MESHSET_SET, outputSet);
- CHECK_ERR(rval);
- rval =3D worker.intersect_meshes(covering_lagr_set, euler_set, outputSet=
);
- CHECK_ERR(rval);
-
- //std::string opts_write("PARALLEL=3DWRITE_PART");
- //rval =3D mb.write_file("manuf.h5m", 0, opts_write.c_str(), &outputSet,=
1);
- std::string opts_write("");
- std::stringstream outf;
- outf<<"intersect" << rank<<".h5m";
- rval =3D mb.write_file(outf.str().c_str(), 0, 0, &outputSet, 1);
- CHECK_ERR(rval);
-
-
-}
void test_intx_in_parallel_elem_based()
{
std::string opts =3D std::string("PARALLEL=3DREAD_PART;PARTITION=3DPARAL=
LEL_PARTITION")+
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/fathomteam/moab/commits/904a842703d1/
Changeset: 904a842703d1
Branch: None
User: danwu
Date: 2013-07-01 23:26:09
Summary: In read_mpas_nc.cpp, restore some test functions that were com=
mented out before.
Affected #: 1 file
diff --git a/test/io/read_mpas_nc.cpp b/test/io/read_mpas_nc.cpp
index 49ce0e2..4ab8568 100644
--- a/test/io/read_mpas_nc.cpp
+++ b/test/io/read_mpas_nc.cpp
@@ -33,10 +33,10 @@ int main(int argc, char* argv[])
argv[0] =3D argv[argc-argc]; // To remove the warnings in serial mode ab=
out unused variables
#endif
=20
- //result +=3D RUN_TEST(test_read_all);
- //result +=3D RUN_TEST(test_read_onevar);
- //result +=3D RUN_TEST(test_read_onetimestep);
- //result +=3D RUN_TEST(test_read_nomesh);
+ result +=3D RUN_TEST(test_read_all);
+ result +=3D RUN_TEST(test_read_onevar);
+ result +=3D RUN_TEST(test_read_onetimestep);
+ result +=3D RUN_TEST(test_read_nomesh);
result +=3D RUN_TEST(test_read_novars);
=20
#ifdef USE_MPI
https://bitbucket.org/fathomteam/moab/commits/aa6f53b16e4a/
Changeset: aa6f53b16e4a
Branch: master
User: iulian07
Date: 2013-07-02 00:32:10
Summary: Merged in danwu/moab (pull request #7)
Latest code changes for MPAS reader
Affected #: 18 files
diff --git a/MeshFiles/unittest/io/mpasx1.642.t.2.nc b/MeshFiles/unittest/i=
o/mpasx1.642.t.2.nc
new file mode 100644
index 0000000..f1e8c94
Binary files /dev/null and b/MeshFiles/unittest/io/mpasx1.642.t.2.nc differ
diff --git a/src/io/Makefile.am b/src/io/Makefile.am
index b7eae6a..bb5b7cb 100644
--- a/src/io/Makefile.am
+++ b/src/io/Makefile.am
@@ -21,6 +21,7 @@ if NETCDF_FILE
NCHelperEuler.cpp NCHelperEuler.hpp \
NCHelperFV.cpp NCHelperFV.hpp \
NCHelperHOMME.cpp NCHelperHOMME.hpp \
+ NCHelperMPAS.cpp NCHelperMPAS.hpp \
ReadGCRM.cpp ReadGCRM.hpp
else
MOAB_NETCDF_SRCS =3D
@@ -33,6 +34,7 @@ if !NETCDF_FILE
NCHelperEuler.cpp NCHelperEuler.hpp \
NCHelperFV.cpp NCHelperFV.hpp \
NCHelperHOMME.cpp NCHelperHOMME.hpp \
+ NCHelperMPAS.cpp NCHelperMPAS.hpp \
ReadGCRM.cpp ReadGCRM.hpp
endif
endif
diff --git a/src/io/NCHelper.cpp b/src/io/NCHelper.cpp
index e0f021e..e0eae99 100644
--- a/src/io/NCHelper.cpp
+++ b/src/io/NCHelper.cpp
@@ -2,20 +2,858 @@
#include "NCHelperEuler.hpp"
#include "NCHelperFV.hpp"
#include "NCHelperHOMME.hpp"
+#include "NCHelperMPAS.hpp"
+
#include "moab/ReadUtilIface.hpp"
+#include "MBTagConventions.hpp"
+
+#define ERRORR(rval, str) \
+ if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", =
str); return rval;}
+
+#define ERRORS(err, str) \
+ if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_F=
AILURE;}
=20
namespace moab {
=20
NCHelper* NCHelper::get_nc_helper(ReadNC* readNC, int fileId, const FileOp=
tions& opts)
{
- if (NCHelperEuler::can_read_file(readNC, fileId))
- return new (std::nothrow) NCHelperEuler(readNC, fileId);
- else if (NCHelperFV::can_read_file(readNC, fileId))
- return new (std::nothrow) NCHelperFV(readNC, fileId);
- else if (NCHelperHOMME::can_read_file(readNC, fileId))
- return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts);
- else // Unknown NetCDF grid (will fill this in later for POP, CICE and C=
LM)
- return NULL;
+ // Check if CF convention is being followed
+ bool is_CF =3D false;
+
+ std::map<std::string, ReadNC::AttData>& globalAtts =3D readNC->globalAtt=
s;
+ std::map<std::string, ReadNC::AttData>::iterator attIt =3D globalAtts.fi=
nd("conventions");
+ if (attIt =3D=3D globalAtts.end())
+ attIt =3D globalAtts.find("Conventions");
+
+ if (attIt !=3D globalAtts.end()) {
+ unsigned int sz =3D attIt->second.attLen;
+ std::string att_data;
+ att_data.resize(sz + 1);
+ att_data[sz] =3D '\000';
+ int success =3D NCFUNC(get_att_text)(fileId, attIt->second.attVarId, a=
ttIt->second.attName.c_str(), &att_data[0]);
+ if (0 =3D=3D success && att_data.find("CF") !=3D std::string::npos)
+ is_CF =3D true;
+ }
+
+ if (is_CF) {
+ if (NCHelperEuler::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperEuler(readNC, fileId);
+ else if (NCHelperFV::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperFV(readNC, fileId);
+ else if (NCHelperHOMME::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperHOMME(readNC, fileId, opts);
+ }
+ else {
+ if (NCHelperMPAS::can_read_file(readNC, fileId))
+ return new (std::nothrow) NCHelperMPAS(readNC, fileId, opts);
+ }
+
+ // Unknown NetCDF grid (will fill this in later for POP, CICE and CLM)
+ return NULL;
+}
+
+ErrorCode NCHelper::read_variable_to_set_allocate(std::vector<ReadNC::VarD=
ata>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if ((std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDi=
m) !=3D vdatas[i].varDims.end()))
+ vdatas[i].has_t =3D true;
+
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ // get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag_to_set(vdatas[i], tstep_nums[t], vdatas[=
i].varTags[t]);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t)
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+
+ // set up the dimensions and counts
+ // first variable dimension is time, if it exists
+ if (vdatas[i].has_t)
+ {
+ if (vdatas[i].varDims.size() !=3D 1)
+ {
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else
+ {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(tstep_nums.size());
+ }
+ }
+
+ // Set up other dimensions and counts
+ if (vdatas[i].varDims.empty()) {
+ // Scalar variable
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(1);
+ }
+ else {
+ for (unsigned int idx =3D 0; idx !=3D vdatas[i].varDims.size(); id=
x++){
+ if (tDim !=3D vdatas[i].varDims[idx]){
+ // Push other variable dimensions, except time, which was alre=
ady pushed
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(dimVals[vdatas[i].varDims[id=
x]]);
+ }
+ }
+ }
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
+ sz *=3D vdatas[i].readCounts[t][idx];
+ vdatas[i].sz =3D sz;
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ vdatas[i].varDatas[t] =3D new char[sz];
+ break;
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ vdatas[i].varDatas[t] =3D new double[sz];
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ vdatas[i].varDatas[t] =3D new int[sz];
+ break;
+ default:
+ std::cerr << "Unrecognized data type for tag " << std::endl;
+ rval =3D MB_FAILURE;
+ }
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode NCHelper::read_variable_to_set(EntityHandle file_set, std::vecto=
r<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ std::set<std::string>& dummyVarNames =3D _readNC->dummyVarNames;;
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_variable_to_set_allocate(vdatas, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables to set.");
+
+ // finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ if (dummyVarNames.find(vdatas[i].varName) !=3D dummyVarNames.end() )
+ continue;// this is a dummy one, we don't have it; we created it fo=
r the dummy tag
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ void* data =3D vdatas[i].varDatas[t];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR:
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (char*) data NCREQ);
+ ERRORS(success, "Failed to read char data.");
+ break;
+ case NC_DOUBLE:
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (double*) data NCREQ);
+ ERRORS(success, "Failed to read double data.");
+ break;
+ case NC_FLOAT: {
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (float*) data NCREQ);
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT:
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (int*) data NCREQ);
+ ERRORS(success, "Failed to read int data.");
+ break;
+ case NC_SHORT:
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ (short*) data NCREQ);
+ ERRORS(success, "Failed to read short data.");
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Setting data for variable %s, time step %d\n", vd=
atas[i].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D mbImpl->tag_set_by_ptr(vdatas[i].varTags[t], =
&file_set, 1, &(vdatas[i].varDatas[t]), &vdatas[i].sz);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ if (vdatas[i].varDims.size() <=3D 1)
+ break;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode NCHelper::convert_variable(ReadNC::VarData& var_data, int tstep_=
num)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ // Get ptr to tag space
+ void* data =3D var_data.varDatas[tstep_num];
+
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D var_data.readCounts[tstep_num].size=
(); idx++)
+ sz *=3D var_data.readCounts[tstep_num][idx];
+
+ // Finally, read into that space
+ int success =3D 0;
+ int* idata;
+ double* ddata;
+ float* fdata;
+ short* sdata;
+
+ switch (var_data.varDataType) {
+ case NC_FLOAT:
+ ddata =3D (double*) var_data.varDatas[tstep_num];
+ fdata =3D (float*) var_data.varDatas[tstep_num];
+ // Convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ ddata[i] =3D fdata[i];
+ break;
+ case NC_SHORT:
+ idata =3D (int*) var_data.varDatas[tstep_num];
+ sdata =3D (short*) var_data.varDatas[tstep_num];
+ // Convert in-place
+ for (int i =3D sz - 1; i >=3D 0; i--)
+ idata[i] =3D sdata[i];
+ break;
+ default:
+ success =3D 1;
+ }
+
+ if (2 <=3D dbgOut.get_verbosity() && !success) {
+ double dmin, dmax;
+ int imin, imax;
+ switch (var_data.varDataType) {
+ case NC_DOUBLE:
+ case NC_FLOAT:
+ ddata =3D (double*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ dmin =3D dmax =3D ddata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (ddata[i] < dmin)
+ dmin =3D ddata[i];
+ if (ddata[i] > dmax)
+ dmax =3D ddata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (double): min =3D %f, max =3D %f\n"=
, var_data.varName.c_str(), dmin, dmax);
+ break;
+ case NC_INT:
+ case NC_SHORT:
+ idata =3D (int*) data;
+ if (sz =3D=3D 0)
+ break;
+
+ imin =3D imax =3D idata[0];
+ for (unsigned int i =3D 1; i < sz; i++) {
+ if (idata[i] < imin)
+ imin =3D idata[i];
+ if (idata[i] > imax)
+ imax =3D idata[i];
+ }
+ dbgOut.tprintf(2, "Variable %s (int): min =3D %d, max =3D %d\n", v=
ar_data.varName.c_str(), imin, imax);
+ break;
+ case NC_NAT:
+ case NC_BYTE:
+ case NC_CHAR:
+ break;
+ default: // Default case added to remove compiler warnings
+ success =3D 1;
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::check_existing_mesh(EntityHandle file_set) {
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ int (&lDims)[6] =3D _readNC->lDims;
+
+ // Get the number of vertices
+ int num_verts;
+ ErrorCode rval =3D mbImpl->get_number_entities_by_dimension(file_set, 0,=
num_verts);
+ ERRORR(rval, "Trouble getting number of vertices.");
+
+ // Check against parameters
+ if (num_verts > 0)
+ {
+ int expected_verts =3D (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1=
] + 1) * (-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
+ if (num_verts !=3D expected_verts) {
+ ERRORR(MB_FAILURE, "Number of vertices doesn't match.");
+ }
+ }
+
+ // Check the number of elements too
+ int num_elems;
+ rval =3D mbImpl->get_number_entities_by_dimension(file_set, (-1 =3D=3D l=
Dims[2] ? 2 : 3), num_elems);
+ ERRORR(rval, "Trouble getting number of elements.");
+
+ /*
+ // Check against parameters
+ if (num_elems > 0)
+ {
+ int expected_elems =3D (lDims[3] - lDims[0]) * (lDims[4] - lDims[1]) *=
(-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2]);
+ if (num_elems !=3D expected_elems) {
+ ERRORR(MB_FAILURE, "Number of elements doesn't match.");
+ }
+ }
+ */
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::create_mesh(ScdInterface* scdi, const FileOptions& =
opts, EntityHandle file_set, Range& faces)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ int (&gDims)[6] =3D _readNC->gDims;
+ int (&lDims)[6] =3D _readNC->lDims;
+ std::vector<double>& ilVals =3D _readNC->ilVals;
+ std::vector<double>& jlVals =3D _readNC->jlVals;
+ std::vector<double>& klVals =3D _readNC->klVals;
+ Tag& mGlobalIdTag =3D _readNC->mGlobalIdTag;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ int (&locallyPeriodic)[2] =3D _readNC->locallyPeriodic;
+ int (&globallyPeriodic)[2] =3D _readNC->globallyPeriodic;
+ ScdParData& parData =3D _readNC->parData;
+
+ Range tmp_range;
+ ScdBox *scd_box;
+
+ ErrorCode rval =3D scdi->construct_box(HomCoord(lDims[0], lDims[1], lDim=
s[2], 1), HomCoord(lDims[3], lDims[4], lDims[5], 1), NULL,
+ 0, scd_box, locallyPeriodic, &parData);
+ ERRORR(rval, "Trouble creating scd vertex sequence.");
+
+ // Add box set and new vertices, elements to the file set
+ tmp_range.insert(scd_box->start_vertex(), scd_box->start_vertex() + scd_=
box->num_vertices() - 1);
+ tmp_range.insert(scd_box->start_element(), scd_box->start_element() + sc=
d_box->num_elements() - 1);
+ tmp_range.insert(scd_box->box_set());
+ rval =3D mbImpl->add_entities(file_set, tmp_range);
+ ERRORR(rval, "Couldn't add new vertices to file set.");
+
+ dbgOut.tprintf(1, "scdbox %d quads, %d vertices\n", scd_box->num_element=
s(), scd_box->num_vertices());
+
+ // Get a ptr to global id memory
+ void* data;
+ int count;
+ const Range::iterator topv =3D tmp_range.upper_bound(tmp_range.begin(), =
tmp_range.end(), scd_box->start_vertex()
+ + scd_box->num_vertices());
+ rval =3D mbImpl->tag_iterate(mGlobalIdTag, tmp_range.begin(), topv, coun=
t, data);
+ ERRORR(rval, "Failed to get tag iterator.");
+ assert(count =3D=3D scd_box->num_vertices());
+ int* gid_data =3D (int*) data;
+
+ // Set the vertex coordinates
+ double *xc, *yc, *zc;
+ rval =3D scd_box->get_coordinate_arrays(xc, yc, zc);
+ ERRORR(rval, "Couldn't get vertex coordinate arrays.");
+
+ int i, j, k, il, jl, kl, itmp;
+ int dil =3D lDims[3] - lDims[0] + 1;
+ int djl =3D lDims[4] - lDims[1] + 1;
+ int di =3D gDims[3] - gDims[0] + 1;
+ int dj =3D gDims[4] - gDims[1] + 1;
+ assert(dil =3D=3D (int)ilVals.size() && djl =3D=3D (int)jlVals.size() &&
+ (-1 =3D=3D lDims[2] || lDims[5]-lDims[2]+1 =3D=3D (int)klVals.size()=
));
+#define INDEX(i, j, k) ()
+ for (kl =3D lDims[2]; kl <=3D lDims[5]; kl++) {
+ k =3D kl - lDims[2];
+ for (jl =3D lDims[1]; jl <=3D lDims[4]; jl++) {
+ j =3D jl - lDims[1];
+ for (il =3D lDims[0]; il <=3D lDims[3]; il++) {
+ i =3D il - lDims[0];
+ unsigned int pos =3D i + j * dil + k * dil * djl;
+ xc[pos] =3D ilVals[i];
+ yc[pos] =3D jlVals[j];
+ zc[pos] =3D (-1 =3D=3D lDims[2] ? 0.0 : klVals[k]);
+ itmp =3D (!locallyPeriodic[0] && globallyPeriodic[0] && il =3D=3D =
gDims[3] ? gDims[0] : il);
+ *gid_data =3D (-1 !=3D kl ? kl * di * dj : 0) + jl * di + itmp + 1;
+ gid_data++;
+ }
+ }
+ }
+#undef INDEX
+
+#ifndef NDEBUG
+ int num_verts =3D (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1) =
* (-1 =3D=3D lDims[2] ? 1 : lDims[5] - lDims[2] + 1);
+ std::vector<int> gids(num_verts);
+ Range verts(scd_box->start_vertex(), scd_box->start_vertex() + scd_box->=
num_vertices() - 1);
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, verts, &gids[0]);
+ ERRORR(rval, "Trouble getting gid values.");
+ int vmin =3D *(std::min_element(gids.begin(), gids.end())), vmax =3D *(s=
td::max_element(gids.begin(), gids.end()));
+ dbgOut.tprintf(1, "Vertex gids %d-%d\n", vmin, vmax);
+#endif
+
+ // add elements to the range passed in
+ faces.insert(scd_box->start_element(), scd_box->start_element() + scd_bo=
x->num_elements() - 1);
+
+ if (2 <=3D dbgOut.get_verbosity()) {
+ assert(scd_box->boundary_complete());
+ EntityHandle dum_ent =3D scd_box->start_element();
+ rval =3D mbImpl->list_entities(&dum_ent, 1);
+ ERRORR(rval, "Trouble listing first hex.");
+
+ std::vector<EntityHandle> connect;
+ rval =3D mbImpl->get_connectivity(&dum_ent, 1, connect);
+ ERRORR(rval, "Trouble getting connectivity.");
+
+ rval =3D mbImpl->list_entities(&connect[0], connect.size());
+ ERRORR(rval, "Trouble listing element connectivity.");
+ }
+
+ Range edges;
+ mbImpl->get_adjacencies(faces, 1, true, edges, Interface::UNION);
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::read_variables(EntityHandle file_set, std::vector<s=
td::string>& var_names, std::vector<int>& tstep_nums)
+{
+ std::vector<ReadNC::VarData> vdatas;
+ std::vector<ReadNC::VarData> vsetdatas;
+
+ ErrorCode rval =3D read_scd_variable_setup(var_names, tstep_nums, vdatas=
, vsetdatas);
+ ERRORR(rval, "Trouble setting up read variable.");
+
+ // create COORDS tag for quads
+ rval =3D _readNC->create_quad_coordinate_tag(file_set);
+ ERRORR(rval, "Trouble creating coordinate tags to entities quads");
+
+ if (!vsetdatas.empty()) {
+ rval =3D read_variable_to_set(file_set, vsetdatas, tstep_nums);
+ ERRORR(rval, "Trouble read variables to set.");
+ }
+
+ if (!vdatas.empty()) {
+ rval =3D read_scd_variable_to_nonset(file_set, vdatas, tstep_nums);
+ ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_setup(std::vector<std::string>& v=
ar_names, std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData=
>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
+{
+ std::map<std::string, ReadNC::VarData>& varInfo =3D _readNC->varInfo;
+ int& tMin =3D _readNC->tMin;
+ int& tMax =3D _readNC->tMax;
+ int& iDim =3D _readNC->iDim;
+ int& jDim =3D _readNC->jDim;
+ int& tDim =3D _readNC->tDim;
+ int& iCDim =3D _readNC->iCDim;
+ int& jCDim =3D _readNC->jCDim;
+
+ std::map<std::string, ReadNC::VarData>::iterator mit;
+
+ // If empty read them all
+ if (var_names.empty()) {
+ for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D vd.=
varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) !=3D=
vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) !=
=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else
+ vsetdatas.push_back(vd);
+ }
+ }
+ else {
+ for (unsigned int i =3D 0; i < var_names.size(); i++) {
+ mit =3D varInfo.find(var_names[i]);
+ if (mit !=3D varInfo.end()) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D v=
d.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) !=
=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iCDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jCDim) !=
=3D vd.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), iDim) !=3D vd.varDims.end()))
+ vdatas.push_back(vd);
+ else
+ vsetdatas.push_back(vd);
+ }
+ else ERRORR(MB_FAILURE, "Couldn't find variable.");
+ }
+ }
+
+ if (tstep_nums.empty() && -1 !=3D tMin) {
+ // no timesteps input, get them all
+ for (int i =3D tMin; i <=3D tMax; i++)
+ tstep_nums.push_back(i);
+ }
+ if (!tstep_nums.empty()) {
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ vdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vdatas[i].varDatas.resize(tstep_nums.size());
+ vdatas[i].readDims.resize(tstep_nums.size());
+ vdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ for (unsigned int i =3D 0; i < vsetdatas.size(); i++) {
+ if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.en=
d(), tDim) !=3D vsetdatas[i].varDims.end())
+ && (vsetdatas[i].varDims.size() !=3D 1)) {
+ vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vsetdatas[i].varDatas.resize(tstep_nums.size());
+ vsetdatas[i].readDims.resize(tstep_nums.size());
+ vsetdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ else {
+ vsetdatas[i].varTags.resize(1, 0);
+ vsetdatas[i].varDatas.resize(1);
+ vsetdatas[i].readDims.resize(1);
+ vsetdatas[i].readCounts.resize(1);
+ }
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_to_nonset_allocate(EntityHandle f=
ile_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ std::vector<std::string>& dimNames =3D _readNC->dimNames;
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int (&lDims)[6] =3D _readNC->lDims;
+ int (&lCDims)[6] =3D _readNC->lCDims;
+ int& tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ bool& isParallel =3D _readNC->isParallel;
+ #ifdef USE_MPI
+ ParallelComm*& myPcomm =3D _readNC->myPcomm;
+#endif
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ Range* range =3D NULL;
+
+ // get vertices in set
+ Range verts;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 0, verts);
+ ERRORR(rval, "Trouble getting vertices in set.");
+ assert("Should only have a single vertex subrange, since they were read =
in one shot" &&
+ verts.psize() =3D=3D 1);
+
+ Range edges;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 1, edges);
+ ERRORR(rval, "Trouble getting edges in set.");
+
+ // Get faces in set
+ Range faces;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 2, faces);
+ ERRORR(rval, "Trouble getting faces in set.");
+ assert("Should only have a single face subrange, since they were read in=
one shot" &&
+ faces.psize() =3D=3D 1);
+
+#ifdef USE_MPI
+ moab::Range faces_owned;
+ if (isParallel)
+ {
+ rval =3D myPcomm->filter_pstatus(faces, PSTATUS_NOT_OWNED, PSTATUS_NOT=
, -1, &faces_owned);
+ ERRORR(rval, "Trouble getting owned faces in set.");
+ }
+ else
+ faces_owned =3D faces; // not running in parallel, but still with MPI
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ std::vector<std::string>::iterator vit;
+ int idx_lev =3D -1;
+ int idx_ilev =3D -1;
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "lev")) !=
=3D dimNames.end())
+ idx_lev =3D vit - dimNames.begin();
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ilev")) !=
=3D dimNames.end())
+ idx_ilev =3D vit - dimNames.begin();
+ if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), id=
x_lev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_lev];
+ else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(=
), idx_ilev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_ilev];
+
+ // Get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag_to_nonset(vdatas[i], tstep_nums[t], vdat=
as[i].varTags[t], vdatas[i].numLev);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // Assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+ }
+ else if (vdatas[i].varDims[0] !=3D tDim) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given f=
or time-independent variable.");
+ }
+
+ // Set up the dimensions and counts
+ // First time
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+
+ // then z/y/x
+ if (vdatas[i].numLev !=3D 1) {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
+ }
+
+ switch (vdatas[i].entLoc) {
+ case ReadNC::ENTLOCVERT:
+ // vertices
+ // only structured mesh has j parameter that multiplies i to get=
total # vertices
+ vdatas[i].readDims[t].push_back(lDims[1]);
+ vdatas[i].readCounts[t].push_back(lDims[4] - lDims[1] + 1);
+ vdatas[i].readDims[t].push_back(lDims[0]);
+ vdatas[i].readCounts[t].push_back(lDims[3] - lDims[0] + 1);
+ assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
+ range =3D &verts;
+ break;
+ case ReadNC::ENTLOCNSEDGE:
+ ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
+ break;
+ case ReadNC::ENTLOCEWEDGE:
+ ERRORR(MB_FAILURE, "Reading edge data not implemented yet.");
+ break;
+ case ReadNC::ENTLOCFACE:
+ // faces
+ vdatas[i].readDims[t].push_back(lCDims[1]);
+ vdatas[i].readDims[t].push_back(lCDims[0]);
+ vdatas[i].readCounts[t].push_back(lCDims[4] - lCDims[1] + 1);
+ vdatas[i].readCounts[t].push_back(lCDims[3] - lCDims[0] + 1);
+ assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
+#ifdef USE_MPI
+ range =3D &faces_owned;
+#else
+ range =3D &faces;
+#endif
+ break;
+ case ReadNC::ENTLOCSET:
+ // set
+ break;
+ default:
+ ERRORR(MB_FAILURE, "Unrecognized entity location type.");
+ break;
+ }
+
+ // Get ptr to tag space
+ void* data;
+ int count;
+ rval =3D mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), r=
ange->end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator.");
+ assert((unsigned)count =3D=3D range->size());
+ vdatas[i].varDatas[t] =3D data;
+ }
+ }
+
+ return rval;
+}
+
+ErrorCode ScdNCHelper::read_scd_variable_to_nonset(EntityHandle file_set, =
std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+
+ ErrorCode rval =3D read_scd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables.");
+
+ // Finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ std::size_t sz =3D 1;
+ for (std::size_t idx =3D 0; idx !=3D vdatas[i].readCounts[t].size();=
idx++)
+ sz *=3D vdatas[i].readCounts[t][idx];
+ void* data =3D vdatas[i].varDatas[t];
+ size_t ni =3D vdatas[i].readCounts[t][2];
+ size_t nj =3D vdatas[i].readCounts[t][3];
+ size_t nk =3D vdatas[i].readCounts[t][1];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR: {
+ std::vector<char> tmpchardata(sz);
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpchardata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpchardata=
[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpchardata.size(); idx++)
+ ((char*) data)[idx] =3D tmpchardata[idx];
+ }
+ ERRORS(success, "Failed to read char data.");
+ break;
+ }
+ case NC_DOUBLE: {
+ std::vector<double> tmpdoubledata(sz);
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId, &vd=
atas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpdoubledata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpdoubleda=
ta[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
+ ((double*) data)[idx] =3D tmpdoubledata[idx];
+ }
+ ERRORS(success, "Failed to read double data.");
+ break;
+ }
+ case NC_FLOAT: {
+ std::vector<float> tmpfloatdata(sz);
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpfloatdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
+ ((float*) data)[idx] =3D tmpfloatdata[idx];
+ }
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT: {
+ std::vector<int> tmpintdata(sz);
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpintdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[=
0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpintdata.size(); idx++)
+ ((int*) data)[idx] =3D tmpintdata[idx];
+ }
+ ERRORS(success, "Failed to read int data.");
+ break;
+ }
+ case NC_SHORT: {
+ std::vector<short> tmpshortdata(sz);
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpshortdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpshortdata.size(); idx+=
+)
+ ((short*) data)[idx] =3D tmpshortdata[idx];
+ }
+ ERRORS(success, "Failed to read short data.");
+ break;
+ }
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ return rval;
+}
+
+ErrorCode UcdNCHelper::read_variables(EntityHandle file_set, std::vector<s=
td::string>& var_names, std::vector<int>& tstep_nums)
+{
+ std::vector<ReadNC::VarData> vdatas;
+ std::vector<ReadNC::VarData> vsetdatas;
+
+ ErrorCode rval =3D read_ucd_variable_setup(var_names, tstep_nums, vdatas=
, vsetdatas);
+ ERRORR(rval, "Trouble setting up read variable.");
+
+ if (!vsetdatas.empty()) {
+ rval =3D read_variable_to_set(file_set, vsetdatas, tstep_nums);
+ ERRORR(rval, "Trouble read variables to set.");
+ }
+
+ if (!vdatas.empty()) {
+#ifdef PNETCDF_FILE
+ // in serial, we will use the old read, everything is contiguous
+ // in parallel, we will use async read in pnetcdf
+ // the other mechanism is not working, forget about it
+ rval =3D read_ucd_variable_to_nonset_async(file_set, vdatas, tstep_num=
s);
+#else
+ rval =3D read_ucd_variable_to_nonset(file_set, vdatas, tstep_nums);
+#endif
+ ERRORR(rval, "Trouble read variables to entities verts/edges/faces.");
+ }
+
+ return MB_SUCCESS;
}
=20
} // namespace moab
diff --git a/src/io/NCHelper.hpp b/src/io/NCHelper.hpp
index 852fc61..0ac9b0c 100644
--- a/src/io/NCHelper.hpp
+++ b/src/io/NCHelper.hpp
@@ -18,19 +18,112 @@ class NCHelper
{
public:
NCHelper(ReadNC* readNC, int fileId) : _readNC(readNC), _fileId(fileId) =
{}
+ virtual ~NCHelper() {}
=20
+ //! Get appropriate helper instance for ReadNC class
static NCHelper* get_nc_helper(ReadNC* readNC, int fileId, const FileOpt=
ions& opts);
=20
+ //! Interfaces to be implemented in child classes
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set) =3D 0;
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads) =3D 0;
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set) =3D 0;
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces) =3D 0;
+ virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums) =3D 0;
virtual std::string get_mesh_type_name() =3D 0;
- virtual bool is_scd_mesh() =3D 0;
+
+protected:
+ //! Read set variables, common to scd mesh and ucd mesh
+ ErrorCode read_variable_to_set(EntityHandle file_set, std::vector<ReadNC=
::VarData>& vdatas, std::vector<int>& tstep_nums);
+
+ //! Convert variables in place
+ ErrorCode convert_variable(ReadNC::VarData& var_data, int tstep_num);
+
+private:
+ //! Used by read_variable_to_set()
+ ErrorCode read_variable_to_set_allocate(std::vector<ReadNC::VarData>& vd=
atas, std::vector<int>& tstep_nums);
=20
protected:
ReadNC* _readNC;
int _fileId;
};
=20
+//! Child helper class for scd mesh, e.g. CAM_EL or CAM_FV
+class ScdNCHelper : public NCHelper
+{
+public:
+ ScdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ virtual ~ScdNCHelper() {}
+
+private:
+ //! Implementation of NCHelper::check_existing_mesh()
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set);
+ //! Implementation of NCHelper::create_mesh()
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
+ //! Implementation of NCHelper::read_variables()
+ virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names, std::vector<int>& tstep_nums);
+
+ //! Separate set and non-set variables for scd mesh
+ ErrorCode read_scd_variable_setup(std::vector<std::string>& var_names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& vdatas,
+ std::vector<ReadNC::VarData>& vsetdata=
s);
+
+ //! Read non-set variables for scd mesh
+ ErrorCode read_scd_variable_to_nonset_allocate(EntityHandle file_set, st=
d::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_n=
ums);
+ ErrorCode read_scd_variable_to_nonset(EntityHandle file_set, std::vector=
<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nums);
+};
+
+//! Child helper class for ucd mesh, e.g. CAM_SE (HOMME) or MPAS
+class UcdNCHelper : public NCHelper
+{
+public:
+ UcdNCHelper(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId),
+ cDim(-1), eDim(-1), vDim(-1), levDim(-1),
+ nCells(0), nEdges(0), nVertices(0),
+ nLocalCells(0), nLocalEdges(0), nLocalVertices(0) {}
+ virtual ~UcdNCHelper() {}
+
+private:
+ //! Implementation of NCHelper::read_variables()
+ virtual ErrorCode read_variables(EntityHandle file_set, std::vector<std:=
:string>& var_names,
+ std::vector<int> &tstep_nums);
+
+ //! Separate set and non-set variables for ucd mesh (implemented differe=
ntly in child classes)
+ virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_=
names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& =
vdatas,
+ std::vector<ReadNC::VarData>& =
vsetdatas) =3D 0;
+
+ //! Read non-set variables for ucd mesh (implemented differently in chil=
d classes)
+ virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file=
_set, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>&=
tstep_nums) =3D 0;
+#ifdef PNETCDF_FILE
+ virtual ErrorCode read_ucd_variable_to_nonset_async(EntityHandle file_se=
t, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& ts=
tep_nums) =3D 0;
+#else
+ virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nu=
ms) =3D 0;
+#endif
+
+protected:
+ //! Dimension numbers for nCells, nEdges, nVertices, nLevels
+ int cDim, eDim, vDim, levDim;
+
+ //! Coordinate values for vertices
+ std::vector<double> xVertVals, yVertVals, zVertVals;
+
+ int nCells;
+ int nEdges;
+ int nVertices;
+
+ int nLocalCells;
+ int nLocalEdges;
+ int nLocalVertices;
+
+ Range localGidCells, localGidEdges, localGidVerts;
+};
+
} // namespace moab
=20
#endif
diff --git a/src/io/NCHelperEuler.cpp b/src/io/NCHelperEuler.cpp
index 85b6887..146227c 100644
--- a/src/io/NCHelperEuler.cpp
+++ b/src/io/NCHelperEuler.cpp
@@ -343,7 +343,7 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
ReadNC::VarData& vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D vd.va=
rDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
- vd.entLoc =3D ReadNC::ENTLOCQUAD;
+ vd.entLoc =3D ReadNC::ENTLOCFACE;
}
=20
// <coordinate_dim_name>
@@ -473,9 +473,4 @@ ErrorCode NCHelperEuler::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperEuler::create_verts_quads(ScdInterface* scdi, const File=
Options& opts, EntityHandle file_set, Range& quads)
-{
- return _readNC->create_scd_verts_quads(scdi, file_set, quads);
-}
-
} // namespace moab
diff --git a/src/io/NCHelperEuler.hpp b/src/io/NCHelperEuler.hpp
index b1c4c21..a0d6aef 100644
--- a/src/io/NCHelperEuler.hpp
+++ b/src/io/NCHelperEuler.hpp
@@ -14,21 +14,16 @@
namespace moab {
=20
//! Child helper class for Eulerian Spectral grid (CAM_EUL)
-class NCHelperEuler : public NCHelper
+class NCHelperEuler : public ScdNCHelper
{
public:
- NCHelperEuler(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ NCHelperEuler(ReadNC* readNC, int fileId) : ScdNCHelper(readNC, fileId) =
{}
=20
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
-
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads);
-
virtual std::string get_mesh_type_name() { return "CAM_EUL"; }
-
- virtual bool is_scd_mesh() { return true; }
};
=20
} // namespace moab
diff --git a/src/io/NCHelperFV.cpp b/src/io/NCHelperFV.cpp
index 93b1a99..9141938 100644
--- a/src/io/NCHelperFV.cpp
+++ b/src/io/NCHelperFV.cpp
@@ -333,7 +333,7 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
ReadNC::VarData& vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), iCDim) !=3D vd.va=
rDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), jCDim) !=3D vd.varDims.end()))
- vd.entLoc =3D ReadNC::ENTLOCQUAD;
+ vd.entLoc =3D ReadNC::ENTLOCFACE;
else if ((std::find(vd.varDims.begin(), vd.varDims.end(), jDim) !=3D v=
d.varDims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), iCDim) !=3D vd.varDims.end()))
vd.entLoc =3D ReadNC::ENTLOCNSEDGE;
@@ -469,9 +469,4 @@ ErrorCode NCHelperFV::init_mesh_vals(const FileOptions&=
opts, EntityHandle file_
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperFV::create_verts_quads(ScdInterface* scdi, const FileOpt=
ions& opts, EntityHandle file_set, Range& quads)
-{
- return _readNC->create_scd_verts_quads(scdi, file_set, quads);
-}
-
} // namespace moab
diff --git a/src/io/NCHelperFV.hpp b/src/io/NCHelperFV.hpp
index afcd9b8..7dde6dc 100644
--- a/src/io/NCHelperFV.hpp
+++ b/src/io/NCHelperFV.hpp
@@ -14,17 +14,15 @@
namespace moab {
=20
//! Child helper class for Finite Volume grid (CAM_FV)
-class NCHelperFV : public NCHelper
+class NCHelperFV : public ScdNCHelper
{
public:
- NCHelperFV(ReadNC* readNC, int fileId) : NCHelper(readNC, fileId) {}
+ NCHelperFV(ReadNC* readNC, int fileId) : ScdNCHelper(readNC, fileId) {}
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads);
virtual std::string get_mesh_type_name() { return "CAM_FV"; }
- virtual bool is_scd_mesh() { return true; }
};
=20
} // namespace moab
diff --git a/src/io/NCHelperHOMME.cpp b/src/io/NCHelperHOMME.cpp
index 32faa58..e963564 100644
--- a/src/io/NCHelperHOMME.cpp
+++ b/src/io/NCHelperHOMME.cpp
@@ -6,14 +6,14 @@
#include <cmath>
=20
#define ERRORR(rval, str) \
- if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", =
str); return rval;}
+ if (MB_SUCCESS !=3D rval) {_readNC->readMeshIface->report_error("%s", st=
r); return rval;}
=20
#define ERRORS(err, str) \
- if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_F=
AILURE;}
+ if (err) {_readNC->readMeshIface->report_error("%s", str); return MB_FAI=
LURE;}
=20
namespace moab {
=20
-NCHelperHOMME::NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions=
& opts) : NCHelper(readNC, fileId), _spectralOrder(-1)
+NCHelperHOMME::NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions=
& opts) : UcdNCHelper(readNC, fileId), _spectralOrder(-1)
{
// Calculate spectral order
std::map<std::string, ReadNC::AttData>::iterator attIt =3D readNC->globa=
lAtts.find("np");
@@ -91,7 +91,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptions=
& opts, EntityHandle fi
tMin =3D 0;
tName =3D dimNames[idx];
=20
- // get number of vertices (labeled as number of columns) and levels
+ // Get number of vertices (labeled as number of columns) and levels
gDims[0] =3D gDims[3] =3D -1;
if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ncol")) !=3D d=
imNames.end()) {
idx =3D vit - dimNames.begin();
@@ -143,9 +143,9 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
rval =3D _readNC->read_coordinate("lev", gDims[2], gDims[5], klVals);
ERRORR(rval, "Trouble reading z variable.");
=20
- // decide whether down is positive
+ // Decide whether down is positive
char posval[10];
- int success =3D NCFUNC(get_att_text)(_readNC->fileId, (*vmit).second=
.varId, "positive", posval);
+ int success =3D NCFUNC(get_att_text)(_fileId, (*vmit).second.varId, =
"positive", posval);
if (0 =3D=3D success && !strcmp(posval, "down")) {
for (std::vector<double>::iterator dvit =3D klVals.begin(); dvit !=
=3D klVals.end(); ++dvit)
(*dvit) *=3D -1.0;
@@ -180,7 +180,7 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOptio=
ns& opts, EntityHandle fi
ReadNC::VarData& vd =3D (*mit).second;
if ((std::find(vd.varDims.begin(), vd.varDims.end(), iDim) !=3D vd.var=
Dims.end()) && (std::find(vd.varDims.begin(),
vd.varDims.end(), kDim) !=3D vd.varDims.end()))
- vd.entLoc =3D ReadNC::ENTLOCNODE;
+ vd.entLoc =3D ReadNC::ENTLOCVERT;
}
=20
std::copy(gDims, gDims + 6, lDims);
@@ -191,15 +191,51 @@ ErrorCode NCHelperHOMME::init_mesh_vals(const FileOpt=
ions& opts, EntityHandle fi
// with no corresponding variables
_readNC->init_dims_with_no_cvars_info();
=20
- // This check is for HOMME and other ucd mesh. When ReadNC class instance
- // gets out of scope in a script (and deleted), the localGid will be lost
- rval =3D _readNC->check_ucd_localGid(file_set);
- ERRORR(rval, "Trouble checking local Gid for ucd mesh.");
+ return MB_SUCCESS;
+}
+
+// When noMesh option is used on this read, the old ReadNC class instance =
for last read can get out
+// of scope (and deleted). The old instance initialized localGidVerts prop=
erly when the mesh was
+// created, but it is now lost. The new instance (will not create the mesh=
with noMesh option) has
+// to restore it based on the existing mesh from last read
+ErrorCode NCHelperHOMME::check_existing_mesh(EntityHandle tmp_set)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ Tag& mGlobalIdTag =3D _readNC->mGlobalIdTag;
+ bool& noMesh =3D _readNC->noMesh;
+ Range& localGid =3D _readNC->localGid;
+
+ if (noMesh && localGid.empty()) {
+ // We need to populate localGid range with the gids of vertices from t=
he tmp_set
+ // localGid is important in reading the variable data into the nodes
+ // also, for our purposes, localGid is truly the GLOBAL_ID tag data, n=
ot other
+ // file_id tags that could get passed around in other scenarios for pa=
rallel reading
+ // for nodal_partition, this local gid is easier, should be initialize=
d with only
+ // the owned nodes
+
+ // We need to get all vertices from tmp_set (it is the input set in no=
_mesh scenario)
+ Range local_verts;
+ ErrorCode rval =3D mbImpl->get_entities_by_dimension(tmp_set, 0, local=
_verts);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ if (!local_verts.empty()) {
+ std::vector<int> gids(local_verts.size());
+
+ // !IMPORTANT : this has to be the GLOBAL_ID tag
+ rval =3D mbImpl->tag_get_data(mGlobalIdTag, local_verts, &gids[0]);
+ if (MB_FAILURE =3D=3D rval)
+ return rval;
+
+ // This will do a smart copy
+ std::copy(gids.begin(), gids.end(), range_inserter(localGid));
+ }
+ }
=20
return MB_SUCCESS;
}
=20
-ErrorCode NCHelperHOMME::create_verts_quads(ScdInterface* scdi, const File=
Options& opts, EntityHandle file_set, Range& quads)
+ErrorCode NCHelperHOMME::create_mesh(ScdInterface* scdi, const FileOptions=
& opts, EntityHandle file_set, Range& faces)
{
Interface*& mbImpl =3D _readNC->mbImpl;
std::string& fileName =3D _readNC->fileName;
@@ -282,9 +318,9 @@ ErrorCode NCHelperHOMME::create_verts_quads(ScdInterfac=
e* scdi, const FileOption
int cornerVarId;
success =3D NCFUNC(inq_varid)(connectId, "element_corners", &cornerVarId=
);
ERRORS(success, "Failed to get variable id.");
- NCDF_SIZE tmp_dims[2] =3D {0, 0}, tmp_counts[2] =3D {4, static_cast<size=
_t>(num_quads)};
+ NCDF_SIZE tmp_starts[2] =3D {0, 0}, tmp_counts[2] =3D {4, static_cast<si=
ze_t>(num_quads)};
std::vector<int> tmp_conn(4 * num_quads), tmp_conn2(4 * num_quads);
- success =3D NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_dims, tmp_co=
unts, &tmp_conn2[0] NCREQ);
+ success =3D NCFUNCAG(_vara_int)(connectId, cornerVarId, tmp_starts, tmp_=
counts, &tmp_conn2[0] NCREQ);
ERRORS(success, "Failed to get temporary connectivity.");
success =3D NCFUNC(close)(connectId);
ERRORS(success, "Failed on close.");
@@ -349,7 +385,7 @@ ErrorCode NCHelperHOMME::create_verts_quads(ScdInterfac=
e* scdi, const FileOption
ERRORR(rval, "Failed to get fine connectivity of spectral elements.");
}
=20
- // on this proc, I get columns ldims[1]..ldims[4], inclusive; need to fi=
nd which vertices those correpond to
+ // on this proc, I get columns lDims[1]..lDims[4], inclusive; need to fi=
nd which vertices those correspond to
unsigned int num_local_verts =3D localGid.size();
unsigned int num_total_verts =3D gDims[3] - gDims[0] + 1;
=20
@@ -366,27 +402,31 @@ ErrorCode NCHelperHOMME::create_verts_quads(ScdInterf=
ace* scdi, const FileOption
int i;
for (i =3D 0, rit =3D localGid.begin(); i < (int)num_local_verts; i++, +=
+rit) {
assert(*rit < ilVals.size() + 1);
- xptr[i] =3D ilVals[(*rit) - 1];
- yptr[i] =3D jlVals[(*rit) - 1];
- zptr[i] =3D klVals[lDims[2]];
+ xptr[i] =3D ilVals[(*rit) - 1]; // lon
+ yptr[i] =3D jlVals[(*rit) - 1]; // lat
+ zptr[i] =3D klVals[lDims[2]]; // dummy
}
=20
const double pideg =3D acos(-1.0) / 180.0;
for (i =3D 0; i < (int)num_local_verts; i++) {
double cosphi =3D cos(pideg * yptr[i]);
- double zmult =3D sin(pideg * yptr[i]), xmult =3D cosphi * cos(xptr[i] =
* pideg), ymult =3D cosphi * sin(xptr[i] * pideg);
+ double zmult =3D sin(pideg * yptr[i]);
+ double xmult =3D cosphi * cos(xptr[i] * pideg);
+ double ymult =3D cosphi * sin(xptr[i] * pideg);
double rad =3D 8.0e3 + klVals[lDims[2]];
- xptr[i] =3D rad * xmult, yptr[i] =3D rad * ymult, zptr[i] =3D rad * zm=
ult;
+ xptr[i] =3D rad * xmult;
+ yptr[i] =3D rad * ymult;
+ zptr[i] =3D rad * zmult;
}
=20
// get ptr to gid memory for vertices
Range vert_range(start_vertex, start_vertex + num_local_verts - 1);
- void *data;
+ void* data;
int count;
rval =3D mbImpl->tag_iterate(mGlobalIdTag, vert_range.begin(), vert_rang=
e.end(), count, data);
ERRORR(rval, "Failed to get tag iterator.");
assert(count =3D=3D (int) num_local_verts);
- int *gid_data =3D (int*) data;
+ int* gid_data =3D (int*) data;
std::copy(localGid.begin(), localGid.end(), gid_data);
// duplicate global id data, which will be used to resolve sharing
if (mpFileIdTag) {
@@ -417,7 +457,7 @@ ErrorCode NCHelperHOMME::create_verts_quads(ScdInterfac=
e* scdi, const FileOption
}
=20
// add new vertices and elements to the set
- quads.merge(tmp_range);
+ faces.merge(tmp_range);
tmp_range.insert(start_vertex, start_vertex + num_local_verts - 1);
rval =3D mbImpl->add_entities(file_set, tmp_range);
ERRORR(rval, "Couldn't add new vertices and quads/hexes to file set.");
@@ -503,4 +543,517 @@ ErrorCode NCHelperHOMME::create_verts_quads(ScdInterf=
ace* scdi, const FileOption
return MB_SUCCESS;
}
=20
+ErrorCode NCHelperHOMME::read_ucd_variable_setup(std::vector<std::string>&=
var_names, std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarDa=
ta>& vdatas, std::vector<ReadNC::VarData>& vsetdatas)
+{
+ std::map<std::string, ReadNC::VarData>& varInfo =3D _readNC->varInfo;
+ int& tMin =3D _readNC->tMin;
+ int& tMax =3D _readNC->tMax;
+ int& iDim =3D _readNC->iDim;
+ int& kDim =3D _readNC->kDim;
+ int& tDim =3D _readNC->tDim;
+
+ std::map<std::string, ReadNC::VarData>::iterator mit;
+
+ // If empty read them all
+ if (var_names.empty()) {
+ for (mit =3D varInfo.begin(); mit !=3D varInfo.end(); ++mit) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd.v=
arDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), kDim) !=3D vd.varDims.end()) && (std::find(vd.=
varDims.begin(), vd.varDims.end(), iDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); // 3d data (time, lev, ncol) read here
+ else
+ vsetdatas.push_back(vd);
+ }
+ }
+ else {
+ for (unsigned int i =3D 0; i < var_names.size(); i++) {
+
+ mit =3D varInfo.find(var_names[i]);
+ if (mit !=3D varInfo.end()) {
+ ReadNC::VarData vd =3D (*mit).second;
+ if ((std::find(vd.varDims.begin(), vd.varDims.end(), tDim) !=3D vd=
.varDims.end()) && (std::find(vd.varDims.begin(),
+ vd.varDims.end(), kDim) !=3D vd.varDims.end()) && (std::find(v=
d.varDims.begin(), vd.varDims.end(), iDim)
+ !=3D vd.varDims.end()))
+ vdatas.push_back(vd); // 3d data (time, lev, ncol) read here
+ else
+ vsetdatas.push_back(vd);
+ }
+ else {
+ ERRORR(MB_FAILURE, "Couldn't find variable.");
+ }
+ }
+ }
+
+ if (tstep_nums.empty() && -1 !=3D tMin) {
+ // no timesteps input, get them all
+ for (int i =3D tMin; i <=3D tMax; i++)
+ tstep_nums.push_back(i);
+ }
+ if (!tstep_nums.empty()) {
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ vdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vdatas[i].varDatas.resize(tstep_nums.size());
+ vdatas[i].readDims.resize(tstep_nums.size());
+ vdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ for (unsigned int i =3D 0; i < vsetdatas.size(); i++) {
+ if ((std::find(vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.en=
d(), tDim) !=3D vsetdatas[i].varDims.end())
+ && (vsetdatas[i].varDims.size() !=3D 1)) {
+ vsetdatas[i].varTags.resize(tstep_nums.size(), 0);
+ vsetdatas[i].varDatas.resize(tstep_nums.size());
+ vsetdatas[i].readDims.resize(tstep_nums.size());
+ vsetdatas[i].readCounts.resize(tstep_nums.size());
+ }
+ else {
+ vsetdatas[i].varTags.resize(1, 0);
+ vsetdatas[i].varDatas.resize(1);
+ vsetdatas[i].readDims.resize(1);
+ vsetdatas[i].readCounts.resize(1);
+ }
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_allocate(EntityHandle=
file_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nu=
ms)
+{
+ Interface*& mbImpl =3D _readNC->mbImpl;
+ std::vector<std::string>& dimNames =3D _readNC->dimNames;
+ std::vector<int>& dimVals =3D _readNC->dimVals;
+ int& tDim =3D _readNC->tDim;
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
+
+ ErrorCode rval =3D MB_SUCCESS;
+
+ Range* range =3D NULL;
+
+ // Get vertices in set
+ Range verts;
+ rval =3D mbImpl->get_entities_by_dimension(file_set, 0, verts);
+ ERRORR(rval, "Trouble getting vertices in set.");
+ assert("Should only have a single vertex subrange, since they were read =
in one shot" &&
+ verts.psize() =3D=3D 1);
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Reading variable %s, time step %d\n", vdatas[i].v=
arName.c_str(), tstep_nums[t]);
+
+ std::vector<std::string>::iterator vit;
+ int idx_lev =3D -1;
+ int idx_ilev =3D -1;
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "lev")) !=
=3D dimNames.end())
+ idx_lev =3D vit - dimNames.begin();
+ if ((vit =3D std::find(dimNames.begin(), dimNames.end(), "ilev")) !=
=3D dimNames.end())
+ idx_ilev =3D vit - dimNames.begin();
+ if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(), id=
x_lev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_lev];
+ else if (std::find(vdatas[i].varDims.begin(), vdatas[i].varDims.end(=
), idx_ilev) !=3D vdatas[i].varDims.end())
+ vdatas[i].numLev =3D dimVals[idx_ilev];
+
+ // Get the tag to read into
+ if (!vdatas[i].varTags[t]) {
+ rval =3D _readNC->get_tag_to_nonset(vdatas[i], tstep_nums[t], vdat=
as[i].varTags[t], vdatas[i].numLev);
+ ERRORR(rval, "Trouble getting tag.");
+ }
+
+ // Assume point-based values for now?
+ if (-1 =3D=3D tDim || dimVals[tDim] <=3D (int) t) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number.");
+ }
+ else if (vdatas[i].varDims[0] !=3D tDim) {
+ ERRORR(MB_INDEX_OUT_OF_RANGE, "Non-default timestep number given f=
or time-independent variable.");
+ }
+
+ // Set up the dimensions and counts
+ // First: time
+ vdatas[i].readDims[t].push_back(tstep_nums[t]);
+ vdatas[i].readCounts[t].push_back(1);
+
+ // Next: numLev
+ if (vdatas[i].numLev !=3D 1) {
+ vdatas[i].readDims[t].push_back(0);
+ vdatas[i].readCounts[t].push_back(vdatas[i].numLev);
+ }
+
+ // Finally: nVertices
+ switch (vdatas[i].entLoc) {
+ case ReadNC::ENTLOCVERT:
+ // vertices
+ // we will start from the first localGid, actually; we will rese=
t that
+ // later on, anyway, in a loop
+ vdatas[i].readDims[t].push_back(localGid[0] - 1);
+ vdatas[i].readCounts[t].push_back(localGid.size());
+ assert(vdatas[i].readDims[t].size() =3D=3D vdatas[i].varDims.siz=
e());
+ range =3D &verts;
+ break;
+ case ReadNC::ENTLOCSET:
+ // set
+ break;
+ default:
+ ERRORR(MB_FAILURE, "Unrecognized entity location type.");
+ break;
+ }
+
+ // Get ptr to tag space
+ void* data;
+ int count;
+ rval =3D mbImpl->tag_iterate(vdatas[i].varTags[t], range->begin(), r=
ange->end(), count, data);
+ ERRORR(rval, "Failed to get tag iterator.");
+ assert((unsigned)count =3D=3D range->size());
+ vdatas[i].varDatas[t] =3D data;
+ }
+ }
+
+ return rval;
+}
+
+#ifdef PNETCDF_FILE
+ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset_async(EntityHandle fi=
le_set, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
+
+ ErrorCode rval =3D read_ucd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables.");
+
+ // Finally, read into that space
+ int success;
+ // MPI_offset or size_t?
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ std::size_t sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
+ if (sz <=3D 0)
+ continue; // nothing to read, why worry?
+
+ // we will synchronize all these reads with the other processors,
+ // so the wait will be inside this double loop; is it too much?
+ size_t nb_reads =3D localGid.psize();
+ std::vector<int> requests(nb_reads), statuss(nb_reads);
+ size_t idxReq =3D 0;
+ void* data =3D vdatas[i].varDatas[t];
+ size_t ni =3D vdatas[i].readCounts[t][2];
+ size_t nj =3D 1; // For HOMME, nj holds # quads, so here should set =
to 1
+ size_t nk =3D vdatas[i].readCounts[t][1];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR: {
+ ERRORR(MB_FAILURE, "not implemented");
+ break;
+ }
+ case NC_DOUBLE: {
+ // copy from float case
+ std::vector<double> tmpdoubledata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+ // assume that the last dimension is for the ncol,
+ // node varying variable
+
+ size_t indexInDoubleArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
+
+ // do a partial read, in each subrange
+ // wait outside this loop
+ success =3D NCFUNCAG2(_vara_double)(_fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpdoubledata[indexInDoubleArray]) NCREQ2);
+ ERRORS(success, "Failed to read double data in loop");
+ // we need to increment the index in double array for the
+ // next subrange
+ indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ success =3D ncmpi_wait_all(_fileId, requests.size(), &requests[0=
], &statuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik_stride(ni, nj, nk, data, &tmpd=
oubledata[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
+ ((double*) data)[idx] =3D tmpdoubledata[idx];
+ }
+ ERRORS(success, "Failed to read double data.");
+ break;
+ }
+ case NC_FLOAT: {
+ std::vector<float> tmpfloatdata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+ // assume that the last dimension is for the ncol,
+ // node varying variable
+
+ size_t indexInFloatArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
+
+ // do a partial read, in each subrange
+ // wait outside this loop
+ success =3D NCFUNCAG2(_vara_float)(_fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpfloatdata[indexInFloatArray]) NCREQ2);
+ ERRORS(success, "Failed to read float data in loop");
+ // we need to increment the index in float array for the
+ // next subrange
+ indexInFloatArray +=3D (endh - starth + 1) * 1 * vdatas[i].num=
Lev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ success =3D ncmpi_wait_all(_fileId, requests.size(), &requests[0=
], &statuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik_stride(ni, nj, nk, data, &tmpf=
loatdata[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
+ ((float*) data)[idx] =3D tmpfloatdata[idx];
+ }
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT: {
+ ERRORR(MB_FAILURE, "not implemented");
+ break;
+ }
+ case NC_SHORT: {
+ ERRORR(MB_FAILURE, "not implemented");
+ break;
+ }
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ }
+ }
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ return rval;
+}
+#else
+ErrorCode NCHelperHOMME::read_ucd_variable_to_nonset(EntityHandle file_set=
, std::vector<ReadNC::VarData>& vdatas, std::vector<int>& tstep_nums)
+{
+ DebugOutput& dbgOut =3D _readNC->dbgOut;
+ Range& localGid =3D _readNC->localGid;
+
+ ErrorCode rval =3D read_ucd_variable_to_nonset_allocate(file_set, vdatas=
, tstep_nums);
+ ERRORR(rval, "Trouble allocating read variables.");
+
+ // Finally, read into that space
+ int success;
+ std::vector<int> requests(vdatas.size() * tstep_nums.size()), statuss(vd=
atas.size() * tstep_nums.size());
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ std::size_t sz =3D vdatas[i].numLev * vdatas[i].readCounts[t][2];
+ void* data =3D vdatas[i].varDatas[t];
+ size_t ni =3D vdatas[i].readCounts[t][2];
+ size_t nj =3D 1; // For HOMME, nj holds # quads, so here should set =
to 1
+ size_t nk =3D vdatas[i].readCounts[t][1];
+
+ switch (vdatas[i].varDataType) {
+ case NC_BYTE:
+ case NC_CHAR: {
+ std::vector<char> tmpchardata(sz);
+ success =3D NCFUNCAG(_vara_text)(_fileId, vdatas[i].varId, &vdat=
as[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpchardata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpchardata=
[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpchardata.size(); idx++)
+ ((char*) data)[idx] =3D tmpchardata[idx];
+ }
+ ERRORS(success, "Failed to read char data.");
+ break;
+ }
+ case NC_DOUBLE: {
+ // Copy from float case
+ std::vector<double> tmpdoubledata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+
+ // Assume that the last dimension is for the ncol
+ size_t indexInDoubleArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // Inclusive
+ vdatas[i].readDims[t][nbDims - 1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims - 1] =3D (NCDF_SIZE) (endh - st=
arth + 1);
+
+ success =3D NCFUNCAG(_vara_double)(_fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpdoubledata[indexInDoubleArray]) NCREQ);
+ ERRORS(success, "Failed to read float data in loop");
+ // We need to increment the index in double array for the
+ // next subrange
+ indexInDoubleArray +=3D (endh - starth + 1) * 1 * vdatas[i].nu=
mLev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpdoubleda=
ta[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpdoubledata.size(); idx=
++)
+ ((double*) data)[idx] =3D tmpdoubledata[idx];
+ }
+ ERRORS(success, "Failed to read double data.");
+ break;
+ }
+ case NC_FLOAT: {
+ std::vector<float> tmpfloatdata(sz);
+
+ // in the case of ucd mesh, and on multiple proc,
+ // we need to read as many times as subranges we have in the
+ // localGid range;
+ // basically, we have to give a different point
+ // for data to start, for every subrange :(
+ size_t nbDims =3D vdatas[i].readDims[t].size();
+
+ // Assume that the last dimension is for the ncol
+ size_t indexInFloatArray =3D 0;
+ size_t ic =3D 0;
+ for (Range::pair_iterator pair_iter =3D localGid.pair_begin();
+ pair_iter !=3D localGid.pair_end();
+ pair_iter++, ic++) {
+ EntityHandle starth =3D pair_iter->first;
+ EntityHandle endh =3D pair_iter->second; // Inclusive
+ vdatas[i].readDims[t][nbDims-1] =3D (NCDF_SIZE) (starth - 1);
+ vdatas[i].readCounts[t][nbDims-1] =3D (NCDF_SIZE) (endh - star=
th + 1);
+
+ success =3D NCFUNCAG(_vara_float)(_fileId, vdatas[i].varId,
+ &(vdatas[i].readDims[t][0]), &(vdatas[i].readCounts[t][0]),
+ &(tmpfloatdata[indexInFloatArray]) NCREQ);
+ ERRORS(success, "Failed to read float data in loop");
+ // We need to increment the index in float array for the
+ // next subrange
+ indexInFloatArray +=3D (endh - starth + 1) * 1 * vdatas[i].num=
Lev;
+ }
+ assert(ic =3D=3D localGid.psize());
+
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpfloatdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpfloatdata.size(); idx+=
+)
+ ((float*) data)[idx] =3D tmpfloatdata[idx];
+ }
+ ERRORS(success, "Failed to read float data.");
+ break;
+ }
+ case NC_INT: {
+ std::vector<int> tmpintdata(sz);
+ success =3D NCFUNCAG(_vara_int)(_fileId, vdatas[i].varId, &vdata=
s[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpintdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpintdata[=
0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpintdata.size(); idx++)
+ ((int*) data)[idx] =3D tmpintdata[idx];
+ }
+ ERRORS(success, "Failed to read int data.");
+ break;
+ }
+ case NC_SHORT: {
+ std::vector<short> tmpshortdata(sz);
+ success =3D NCFUNCAG(_vara_short)(_fileId, vdatas[i].varId, &vda=
tas[i].readDims[t][0], &vdatas[i].readCounts[t][0],
+ &tmpshortdata[0] NCREQ);
+ if (vdatas[i].numLev !=3D 1)
+ // Switch from k varying slowest to k varying fastest
+ success =3D _readNC->kji_to_jik(ni, nj, nk, data, &tmpshortdat=
a[0]);
+ else {
+ for (std::size_t idx =3D 0; idx !=3D tmpshortdata.size(); idx+=
+)
+ ((short*) data)[idx] =3D tmpshortdata[idx];
+ }
+ ERRORS(success, "Failed to read short data.");
+ break;
+ }
+ default:
+ success =3D 1;
+ }
+
+ if (success)
+ ERRORR(MB_FAILURE, "Trouble reading variable.");
+ }
+ }
+
+#ifdef NCWAIT
+ int success =3D ncmpi_wait_all(fileId, requests.size(), &requests[0], &s=
tatuss[0]);
+ ERRORS(success, "Failed on wait_all.");
+#endif
+
+ for (unsigned int i =3D 0; i < vdatas.size(); i++) {
+ for (unsigned int t =3D 0; t < tstep_nums.size(); t++) {
+ dbgOut.tprintf(2, "Converting variable %s, time step %d\n", vdatas[i=
].varName.c_str(), tstep_nums[t]);
+ ErrorCode tmp_rval =3D convert_variable(vdatas[i], t);
+ if (MB_SUCCESS !=3D tmp_rval)
+ rval =3D tmp_rval;
+ }
+ }
+ // debug output, if requested
+ if (1 =3D=3D dbgOut.get_verbosity()) {
+ dbgOut.printf(1, "Read variables: %s", vdatas.begin()->varName.c_str()=
);
+ for (unsigned int i =3D 1; i < vdatas.size(); i++)
+ dbgOut.printf(1, ", %s ", vdatas[i].varName.c_str());
+ dbgOut.tprintf(1, "\n");
+ }
+
+ return rval;
+}
+#endif
+
} // namespace moab
diff --git a/src/io/NCHelperHOMME.hpp b/src/io/NCHelperHOMME.hpp
index feb3cad..f900829 100644
--- a/src/io/NCHelperHOMME.hpp
+++ b/src/io/NCHelperHOMME.hpp
@@ -14,20 +14,42 @@
namespace moab {
=20
//! Child helper class for HOMME grid (CAM_SE)
-class NCHelperHOMME : public NCHelper
+class NCHelperHOMME : public UcdNCHelper
{
public:
NCHelperHOMME(ReadNC* readNC, int fileId, const FileOptions& opts);
static bool can_read_file(ReadNC* readNC, int fileId);
=20
private:
+ //! Implementation of NCHelper::init_mesh_vals()
virtual ErrorCode init_mesh_vals(const FileOptions& opts, EntityHandle f=
ile_set);
- virtual ErrorCode create_verts_quads(ScdInterface* scdi, const FileOptio=
ns& opts, EntityHandle file_set, Range& quads);
+ //! Implementation of NCHelper::check_existing_mesh()
+ virtual ErrorCode check_existing_mesh(EntityHandle file_set);
+ //! Implementation of NCHelper::create_mesh()
+ virtual ErrorCode create_mesh(ScdInterface* scdi, const FileOptions& opt=
s, EntityHandle file_set, Range& faces);
+ //! Implementation of NCHelper::get_mesh_type_name()
virtual std::string get_mesh_type_name() { return "CAM_SE"; }
- virtual bool is_scd_mesh() { return false; }
+
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_allocate()
+ virtual ErrorCode read_ucd_variable_to_nonset_allocate(EntityHandle file=
_set, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>&=
tstep_nums);
+ //! Implementation of UcdNCHelper::read_ucd_variable_setup()
+ virtual ErrorCode read_ucd_variable_setup(std::vector<std::string>& var_=
names,
+ std::vector<int>& tstep_nums,
+ std::vector<ReadNC::VarData>& =
vdatas,
+ std::vector<ReadNC::VarData>& =
vsetdatas);
+#ifdef PNETCDF_FILE
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset_async()
+ virtual ErrorCode read_ucd_variable_to_nonset_async(EntityHandle file_se=
t, std::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& ts=
tep_nums);
+#else
+ //! Implementation of UcdNCHelper::read_ucd_variable_to_nonset()
+ virtual ErrorCode read_ucd_variable_to_nonset(EntityHandle file_set, std=
::vector<ReadNC::VarData>& vdatas,
+ std::vector<int>& tstep_nu=
ms);
+#endif
=20
private:
- int _spectralOrder; // read from variable 'np'
+ int _spectralOrder; // Read from variable 'np'
};
=20
} // namespace moab
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/fathomteam/moab/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the moab-dev
mailing list