Updating convertIO

This commit is contained in:
Mark Berrill
2021-03-17 10:24:14 -04:00
parent 6d59317919
commit 89704cbb10
22 changed files with 1843 additions and 1679 deletions

View File

@@ -10,9 +10,9 @@ namespace IO {
// Find a character in a line // Find a character in a line
inline size_t find( const char *line, char token ) inline size_t find( const char *line, char token )
{ {
size_t i=0; size_t i = 0;
while ( 1 ) { while ( 1 ) {
if ( line[i]==token || line[i]<32 || line[i]==0 ) if ( line[i] == token || line[i] < 32 || line[i] == 0 )
break; break;
++i; ++i;
} }
@@ -21,17 +21,17 @@ inline size_t find( const char *line, char token )
// Remove preceeding/trailing whitespace // Remove preceeding/trailing whitespace
inline std::string deblank( const std::string& str ) inline std::string deblank( const std::string &str )
{ {
size_t i1 = str.size(); size_t i1 = str.size();
size_t i2 = 0; size_t i2 = 0;
for (size_t i=0; i<str.size(); i++) { for ( size_t i = 0; i < str.size(); i++ ) {
if ( str[i]!=' ' && str[i]>=32 ) { if ( str[i] != ' ' && str[i] >= 32 ) {
i1 = std::min(i1,i); i1 = std::min( i1, i );
i2 = std::max(i2,i); i2 = std::max( i2, i );
} }
} }
return str.substr(i1,i2-i1+1); return str.substr( i1, i2 - i1 + 1 );
} }
@@ -42,14 +42,14 @@ inline std::vector<std::string> splitList( const char *line, const char token )
size_t i1 = 0; size_t i1 = 0;
size_t i2 = 0; size_t i2 = 0;
while ( 1 ) { while ( 1 ) {
if ( line[i2]==token || line[i2]<32 ) { if ( line[i2] == token || line[i2] < 32 ) {
std::string tmp(&line[i1],i2-i1); std::string tmp( &line[i1], i2 - i1 );
tmp = deblank(tmp); tmp = deblank( tmp );
if ( !tmp.empty() ) if ( !tmp.empty() )
list.push_back(tmp); list.push_back( tmp );
i1 = i2+1; i1 = i2 + 1;
} }
if ( line[i2]==0 ) if ( line[i2] == 0 )
break; break;
i2++; i2++;
} }
@@ -57,8 +57,6 @@ inline std::vector<std::string> splitList( const char *line, const char token )
} }
}; // namespace IO
};
#endif #endif

View File

@@ -19,104 +19,98 @@ inline Point nullPoint()
/**************************************************** /****************************************************
* Mesh * * Mesh *
****************************************************/ ****************************************************/
Mesh::Mesh( ) Mesh::Mesh() {}
{ Mesh::~Mesh() {}
}
Mesh::~Mesh( )
{
}
/**************************************************** /****************************************************
* MeshDataStruct * * MeshDataStruct *
****************************************************/ ****************************************************/
bool MeshDataStruct::check() const bool MeshDataStruct::check() const
{ {
enum VariableType { NodeVariable=1, EdgeVariable=2, SurfaceVariable=2, VolumeVariable=3, NullVariable=0 };
bool pass = mesh != nullptr; bool pass = mesh != nullptr;
for ( const auto& var : vars ) { for ( const auto &var : vars ) {
pass = pass && static_cast<int>(var->type)>=1 && static_cast<int>(var->type)<=3; pass = pass && static_cast<int>( var->type ) >= 1 && static_cast<int>( var->type ) <= 3;
pass = pass && !var->data.empty(); pass = pass && !var->data.empty();
} }
if ( !pass ) if ( !pass ) {
std::cerr << "Invalid variable detected\n";
return false; return false;
const std::string& meshClass = mesh->className(); }
const std::string &meshClass = mesh->className();
if ( meshClass == "PointList" ) { if ( meshClass == "PointList" ) {
const auto mesh2 = dynamic_cast<IO::PointList*>( mesh.get() ); auto mesh2 = dynamic_cast<IO::PointList *>( mesh.get() );
if ( mesh2 == nullptr ) ASSERT( mesh2 );
return false; for ( const auto &var : vars ) {
for ( const auto& var : vars ) {
if ( var->type == IO::VariableType::NodeVariable ) { if ( var->type == IO::VariableType::NodeVariable ) {
pass = pass && var->data.size(0)==mesh2->points.size() && var->data.size(1)==var->dim; pass = pass && var->data.size() == ArraySize( mesh2->points.size(), var->dim );
} else if ( var->type == IO::VariableType::EdgeVariable ) { } else if ( var->type == IO::VariableType::EdgeVariable ) {
ERROR("Invalid type for PointList"); ERROR( "Invalid type for PointList" );
} else if ( var->type == IO::VariableType::SurfaceVariable ) { } else if ( var->type == IO::VariableType::SurfaceVariable ) {
ERROR("Invalid type for PointList"); ERROR( "Invalid type for PointList" );
} else if ( var->type == IO::VariableType::VolumeVariable ) { } else if ( var->type == IO::VariableType::VolumeVariable ) {
ERROR("Invalid type for PointList"); ERROR( "Invalid type for PointList" );
} else { } else {
ERROR("Invalid variable type"); ERROR( "Invalid variable type" );
} }
} }
} else if ( meshClass == "TriMesh" || meshClass == "TriList" ) { } else if ( meshClass == "TriMesh" || meshClass == "TriList" ) {
const auto mesh2 = getTriMesh( mesh ); auto mesh2 = getTriMesh( mesh );
if ( mesh2 == nullptr ) ASSERT( mesh2 );
return false; for ( const auto &var : vars ) {
for ( const auto& var : vars ) {
if ( var->type == IO::VariableType::NodeVariable ) { if ( var->type == IO::VariableType::NodeVariable ) {
pass = pass && var->data.size(0)==mesh2->vertices->points.size() && var->data.size(1)==var->dim; pass = pass &&
var->data.size() == ArraySize( mesh2->vertices->points.size(), var->dim );
} else if ( var->type == IO::VariableType::EdgeVariable ) { } else if ( var->type == IO::VariableType::EdgeVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var->type == IO::VariableType::SurfaceVariable ) { } else if ( var->type == IO::VariableType::SurfaceVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var->type == IO::VariableType::VolumeVariable ) { } else if ( var->type == IO::VariableType::VolumeVariable ) {
pass = pass && var->data.size(0)==mesh2->A.size() && var->data.size(1)==var->dim; pass = pass && var->data.size( 0 ) == mesh2->A.size() &&
var->data.size( 1 ) == var->dim;
} else { } else {
ERROR("Invalid variable type"); ERROR( "Invalid variable type" );
} }
} }
} else if ( meshClass == "DomainMesh" ) { } else if ( meshClass == "DomainMesh" ) {
const auto mesh2 = dynamic_cast<IO::DomainMesh*>( mesh.get() ); auto mesh2 = dynamic_cast<IO::DomainMesh *>( mesh.get() );
if ( mesh2 == nullptr ) ASSERT( mesh2 );
return false; for ( const auto &var : vars ) {
for ( const auto& var : vars ) { ArraySize varSize;
if ( var->type == IO::VariableType::NodeVariable ) { if ( var->type == IO::VariableType::NodeVariable ) {
pass = pass && (int) var->data.size(0)==(mesh2->nx+1) && (int) var->data.size(1)==(mesh2->ny+1) varSize = ArraySize( mesh2->nx + 1, mesh2->ny + 1, mesh2->nz + 1, var->dim );
&& (int) var->data.size(2)==(mesh2->nz+1) && var->data.size(3)==var->dim;
} else if ( var->type == IO::VariableType::EdgeVariable ) { } else if ( var->type == IO::VariableType::EdgeVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var->type == IO::VariableType::SurfaceVariable ) { } else if ( var->type == IO::VariableType::SurfaceVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var->type == IO::VariableType::VolumeVariable ) { } else if ( var->type == IO::VariableType::VolumeVariable ) {
pass = pass && (int) var->data.size(0)==mesh2->nx && (int) var->data.size(1)==mesh2->ny varSize = ArraySize( mesh2->nx, mesh2->ny, mesh2->nz, var->dim );
&& (int) var->data.size(2)==mesh2->nz && var->data.size(3)==var->dim;
} else { } else {
ERROR("Invalid variable type"); ERROR( "Invalid variable type" );
} }
if ( var->data.size() == ArraySize( varSize[0] * varSize[1] * varSize[2], varSize[3] ) )
var->data.resize( varSize );
pass = pass && var->data.size() == varSize;
} }
} else { } else {
ERROR("Unknown mesh class: "+mesh->className()); ERROR( "Unknown mesh class: " + mesh->className() );
} }
return pass; return pass;
} }
/**************************************************** /****************************************************
* PointList * * PointList *
****************************************************/ ****************************************************/
PointList::PointList( ) PointList::PointList() {}
{
}
PointList::PointList( size_t N ) PointList::PointList( size_t N )
{ {
Point tmp = nullPoint(); Point tmp = nullPoint();
points.resize(N,tmp); points.resize( N, tmp );
}
PointList::~PointList( )
{
} }
PointList::~PointList() {}
size_t PointList::numberPointsVar( VariableType type ) const size_t PointList::numberPointsVar( VariableType type ) const
{ {
size_t N = 0; size_t N = 0;
@@ -124,174 +118,168 @@ size_t PointList::numberPointsVar( VariableType type ) const
N = points.size(); N = points.size();
return N; return N;
} }
std::pair<size_t,void*> PointList::pack( int level ) const std::pair<size_t, void *> PointList::pack( int level ) const
{ {
std::pair<size_t,void*> data_out(0,NULL); std::pair<size_t, void *> data_out( 0, NULL );
if ( level==0 ) { if ( level == 0 ) {
data_out.first = (2+3*points.size())*sizeof(double); data_out.first = ( 2 + 3 * points.size() ) * sizeof( double );
double *data_ptr = new double[2+3*points.size()]; double *data_ptr = new double[2 + 3 * points.size()];
data_out.second = data_ptr; data_out.second = data_ptr;
uint64_t *data_int = reinterpret_cast<uint64_t*>(data_ptr); uint64_t *data_int = reinterpret_cast<uint64_t *>( data_ptr );
data_int[0] = level; data_int[0] = level;
data_int[1] = points.size(); data_int[1] = points.size();
double *data = &data_ptr[2]; double *data = &data_ptr[2];
for (size_t i=0; i<points.size(); i++) { for ( size_t i = 0; i < points.size(); i++ ) {
data[3*i+0] = points[i].x; data[3 * i + 0] = points[i].x;
data[3*i+1] = points[i].y; data[3 * i + 1] = points[i].y;
data[3*i+2] = points[i].z; data[3 * i + 2] = points[i].z;
} }
} }
return data_out; return data_out;
} }
void PointList::unpack( const std::pair<size_t,void*>& data_in ) void PointList::unpack( const std::pair<size_t, void *> &data_in )
{ {
uint64_t *data_int = reinterpret_cast<uint64_t*>(data_in.second); uint64_t *data_int = reinterpret_cast<uint64_t *>( data_in.second );
const double *data = reinterpret_cast<const double*>(data_in.second); const double *data = reinterpret_cast<const double *>( data_in.second );
int level = data_int[0]; int level = data_int[0];
uint64_t N = data_int[1]; uint64_t N = data_int[1];
data = &data[2]; data = &data[2];
if ( level==0 ) { if ( level == 0 ) {
ASSERT((2+3*N)*sizeof(double)==data_in.first); ASSERT( ( 2 + 3 * N ) * sizeof( double ) == data_in.first );
points.resize(N); points.resize( N );
for (size_t i=0; i<points.size(); i++) { for ( size_t i = 0; i < points.size(); i++ ) {
points[i].x = data[3*i+0]; points[i].x = data[3 * i + 0];
points[i].y = data[3*i+1]; points[i].y = data[3 * i + 1];
points[i].z = data[3*i+2]; points[i].z = data[3 * i + 2];
} }
} }
} }
/**************************************************** /****************************************************
* TriList * * TriList *
****************************************************/ ****************************************************/
TriList::TriList( ) TriList::TriList() {}
{
}
TriList::TriList( size_t N_tri ) TriList::TriList( size_t N_tri )
{ {
Point tmp = nullPoint(); Point tmp = nullPoint();
A.resize(N_tri,tmp); A.resize( N_tri, tmp );
B.resize(N_tri,tmp); B.resize( N_tri, tmp );
C.resize(N_tri,tmp); C.resize( N_tri, tmp );
} }
TriList::TriList( const TriMesh& mesh ) TriList::TriList( const TriMesh &mesh )
{ {
Point tmp = nullPoint(); Point tmp = nullPoint();
A.resize(mesh.A.size(),tmp); A.resize( mesh.A.size(), tmp );
B.resize(mesh.B.size(),tmp); B.resize( mesh.B.size(), tmp );
C.resize(mesh.C.size(),tmp); C.resize( mesh.C.size(), tmp );
ASSERT(mesh.vertices.get()!=NULL); ASSERT( mesh.vertices.get() != NULL );
const std::vector<Point>& P = mesh.vertices->points; const std::vector<Point> &P = mesh.vertices->points;
for (size_t i=0; i<A.size(); i++) for ( size_t i = 0; i < A.size(); i++ )
A[i] = P[mesh.A[i]]; A[i] = P[mesh.A[i]];
for (size_t i=0; i<B.size(); i++) for ( size_t i = 0; i < B.size(); i++ )
B[i] = P[mesh.B[i]]; B[i] = P[mesh.B[i]];
for (size_t i=0; i<C.size(); i++) for ( size_t i = 0; i < C.size(); i++ )
C[i] = P[mesh.C[i]]; C[i] = P[mesh.C[i]];
} }
TriList::~TriList( ) TriList::~TriList() {}
{
}
size_t TriList::numberPointsVar( VariableType type ) const size_t TriList::numberPointsVar( VariableType type ) const
{ {
size_t N = 0; size_t N = 0;
if ( type==VariableType::NodeVariable ) if ( type == VariableType::NodeVariable )
N = 3*A.size(); N = 3 * A.size();
else if ( type==VariableType::SurfaceVariable || type==VariableType::VolumeVariable ) else if ( type == VariableType::SurfaceVariable || type == VariableType::VolumeVariable )
N = A.size(); N = A.size();
return N; return N;
} }
std::pair<size_t,void*> TriList::pack( int level ) const std::pair<size_t, void *> TriList::pack( int level ) const
{ {
std::pair<size_t,void*> data_out(0,NULL); std::pair<size_t, void *> data_out( 0, NULL );
if ( level==0 ) { if ( level == 0 ) {
data_out.first = (2+9*A.size())*sizeof(double); data_out.first = ( 2 + 9 * A.size() ) * sizeof( double );
double *data_ptr = new double[2+9*A.size()]; double *data_ptr = new double[2 + 9 * A.size()];
data_out.second = data_ptr; data_out.second = data_ptr;
uint64_t *data_int = reinterpret_cast<uint64_t*>(data_ptr); uint64_t *data_int = reinterpret_cast<uint64_t *>( data_ptr );
data_int[0] = level; data_int[0] = level;
data_int[1] = A.size(); data_int[1] = A.size();
double *data = &data_ptr[2]; double *data = &data_ptr[2];
for (size_t i=0; i<A.size(); i++) { for ( size_t i = 0; i < A.size(); i++ ) {
data[9*i+0] = A[i].x; data[9 * i + 0] = A[i].x;
data[9*i+1] = A[i].y; data[9 * i + 1] = A[i].y;
data[9*i+2] = A[i].z; data[9 * i + 2] = A[i].z;
data[9*i+3] = B[i].x; data[9 * i + 3] = B[i].x;
data[9*i+4] = B[i].y; data[9 * i + 4] = B[i].y;
data[9*i+5] = B[i].z; data[9 * i + 5] = B[i].z;
data[9*i+6] = C[i].x; data[9 * i + 6] = C[i].x;
data[9*i+7] = C[i].y; data[9 * i + 7] = C[i].y;
data[9*i+8] = C[i].z; data[9 * i + 8] = C[i].z;
} }
} }
return data_out; return data_out;
} }
void TriList::unpack( const std::pair<size_t,void*>& data_in ) void TriList::unpack( const std::pair<size_t, void *> &data_in )
{ {
uint64_t *data_int = reinterpret_cast<uint64_t*>(data_in.second); uint64_t *data_int = reinterpret_cast<uint64_t *>( data_in.second );
const double *data = reinterpret_cast<const double*>(data_in.second); const double *data = reinterpret_cast<const double *>( data_in.second );
int level = data_int[0]; int level = data_int[0];
uint64_t N = data_int[1]; uint64_t N = data_int[1];
data = &data[2]; data = &data[2];
if ( level==0 ) { if ( level == 0 ) {
ASSERT((2+9*N)*sizeof(double)==data_in.first); ASSERT( ( 2 + 9 * N ) * sizeof( double ) == data_in.first );
A.resize(N); A.resize( N );
B.resize(N); B.resize( N );
C.resize(N); C.resize( N );
for (size_t i=0; i<A.size(); i++) { for ( size_t i = 0; i < A.size(); i++ ) {
A[i].x = data[9*i+0]; A[i].x = data[9 * i + 0];
A[i].y = data[9*i+1]; A[i].y = data[9 * i + 1];
A[i].z = data[9*i+2]; A[i].z = data[9 * i + 2];
B[i].x = data[9*i+3]; B[i].x = data[9 * i + 3];
B[i].y = data[9*i+4]; B[i].y = data[9 * i + 4];
B[i].z = data[9*i+5]; B[i].z = data[9 * i + 5];
C[i].x = data[9*i+6]; C[i].x = data[9 * i + 6];
C[i].y = data[9*i+7]; C[i].y = data[9 * i + 7];
C[i].z = data[9*i+8]; C[i].z = data[9 * i + 8];
} }
} }
} }
/**************************************************** /****************************************************
* TriMesh * * TriMesh *
****************************************************/ ****************************************************/
TriMesh::TriMesh( ) TriMesh::TriMesh() {}
{
}
TriMesh::TriMesh( size_t N_tri, size_t N_point ) TriMesh::TriMesh( size_t N_tri, size_t N_point )
{ {
vertices.reset( new PointList(N_point) ); vertices.reset( new PointList( N_point ) );
A.resize(N_tri,-1); A.resize( N_tri, -1 );
B.resize(N_tri,-1); B.resize( N_tri, -1 );
C.resize(N_tri,-1); C.resize( N_tri, -1 );
} }
TriMesh::TriMesh( size_t N_tri, std::shared_ptr<PointList> points ) TriMesh::TriMesh( size_t N_tri, std::shared_ptr<PointList> points )
{ {
vertices = points; vertices = points;
A.resize(N_tri,-1); A.resize( N_tri, -1 );
B.resize(N_tri,-1); B.resize( N_tri, -1 );
C.resize(N_tri,-1); C.resize( N_tri, -1 );
} }
TriMesh::TriMesh( const TriList& mesh ) TriMesh::TriMesh( const TriList &mesh )
{ {
// For simlicity we will just create a mesh with ~3x the verticies for now // For simlicity we will just create a mesh with ~3x the verticies for now
ASSERT(mesh.A.size()==mesh.B.size()&&mesh.A.size()==mesh.C.size()); ASSERT( mesh.A.size() == mesh.B.size() && mesh.A.size() == mesh.C.size() );
A.resize(mesh.A.size()); A.resize( mesh.A.size() );
B.resize(mesh.B.size()); B.resize( mesh.B.size() );
C.resize(mesh.C.size()); C.resize( mesh.C.size() );
vertices.reset( new PointList(3*mesh.A.size()) ); vertices.reset( new PointList( 3 * mesh.A.size() ) );
for (size_t i=0; i<A.size(); i++) { for ( size_t i = 0; i < A.size(); i++ ) {
A[i] = 3*i+0; A[i] = 3 * i + 0;
B[i] = 3*i+1; B[i] = 3 * i + 1;
C[i] = 3*i+2; C[i] = 3 * i + 2;
vertices->points[A[i]] = mesh.A[i]; vertices->points[A[i]] = mesh.A[i];
vertices->points[B[i]] = mesh.B[i]; vertices->points[B[i]] = mesh.B[i];
vertices->points[C[i]] = mesh.C[i]; vertices->points[C[i]] = mesh.C[i];
} }
} }
TriMesh::~TriMesh( ) TriMesh::~TriMesh()
{ {
vertices.reset(); vertices.reset();
A.clear(); A.clear();
@@ -301,181 +289,194 @@ TriMesh::~TriMesh( )
size_t TriMesh::numberPointsVar( VariableType type ) const size_t TriMesh::numberPointsVar( VariableType type ) const
{ {
size_t N = 0; size_t N = 0;
if ( type==VariableType::NodeVariable ) if ( type == VariableType::NodeVariable )
N = vertices->points.size(); N = vertices->points.size();
else if ( type==VariableType::SurfaceVariable || type==VariableType::VolumeVariable ) else if ( type == VariableType::SurfaceVariable || type == VariableType::VolumeVariable )
N = A.size(); N = A.size();
return N; return N;
} }
std::pair<size_t,void*> TriMesh::pack( int level ) const std::pair<size_t, void *> TriMesh::pack( int level ) const
{ {
std::pair<size_t,void*> data_out(0,NULL); std::pair<size_t, void *> data_out( 0, NULL );
if ( level==0 ) { if ( level == 0 ) {
const std::vector<Point>& points = vertices->points; const std::vector<Point> &points = vertices->points;
data_out.first = (3+3*points.size())*sizeof(double) + 3*A.size()*sizeof(int); data_out.first =
double *data_ptr = new double[4+3*points.size()+(3*A.size()*sizeof(int))/sizeof(double)]; ( 3 + 3 * points.size() ) * sizeof( double ) + 3 * A.size() * sizeof( int );
data_out.second = data_ptr; double *data_ptr =
uint64_t *data_int64 = reinterpret_cast<uint64_t*>(data_ptr); new double[4 + 3 * points.size() + ( 3 * A.size() * sizeof( int ) ) / sizeof( double )];
data_int64[0] = level; data_out.second = data_ptr;
data_int64[1] = points.size(); uint64_t *data_int64 = reinterpret_cast<uint64_t *>( data_ptr );
data_int64[2] = A.size(); data_int64[0] = level;
double *data = &data_ptr[3]; data_int64[1] = points.size();
for (size_t i=0; i<points.size(); i++) { data_int64[2] = A.size();
data[3*i+0] = points[i].x; double *data = &data_ptr[3];
data[3*i+1] = points[i].y; for ( size_t i = 0; i < points.size(); i++ ) {
data[3*i+2] = points[i].z; data[3 * i + 0] = points[i].x;
data[3 * i + 1] = points[i].y;
data[3 * i + 2] = points[i].z;
} }
int *data_int = reinterpret_cast<int*>(&data[3*points.size()]); int *data_int = reinterpret_cast<int *>( &data[3 * points.size()] );
for (size_t i=0; i<A.size(); i++) { for ( size_t i = 0; i < A.size(); i++ ) {
data_int[3*i+0] = A[i]; data_int[3 * i + 0] = A[i];
data_int[3*i+1] = B[i]; data_int[3 * i + 1] = B[i];
data_int[3*i+2] = C[i]; data_int[3 * i + 2] = C[i];
} }
} }
return data_out; return data_out;
} }
void TriMesh::unpack( const std::pair<size_t,void*>& data_in ) void TriMesh::unpack( const std::pair<size_t, void *> &data_in )
{ {
uint64_t *data_int64 = reinterpret_cast<uint64_t*>(data_in.second); uint64_t *data_int64 = reinterpret_cast<uint64_t *>( data_in.second );
const double *data = reinterpret_cast<const double*>(data_in.second); const double *data = reinterpret_cast<const double *>( data_in.second );
int level = data_int64[0]; int level = data_int64[0];
uint64_t N_P = data_int64[1]; uint64_t N_P = data_int64[1];
uint64_t N_A = data_int64[2]; uint64_t N_A = data_int64[2];
data = &data[3]; data = &data[3];
if ( level==0 ) { if ( level == 0 ) {
size_t size = (3+3*N_P)*sizeof(double)+3*N_A*sizeof(int); size_t size = ( 3 + 3 * N_P ) * sizeof( double ) + 3 * N_A * sizeof( int );
ASSERT(size==data_in.first); ASSERT( size == data_in.first );
vertices.reset( new PointList(N_P) ); vertices.reset( new PointList( N_P ) );
std::vector<Point>& points = vertices->points; std::vector<Point> &points = vertices->points;
for (size_t i=0; i<points.size(); i++) { for ( size_t i = 0; i < points.size(); i++ ) {
points[i].x = data[3*i+0]; points[i].x = data[3 * i + 0];
points[i].y = data[3*i+1]; points[i].y = data[3 * i + 1];
points[i].z = data[3*i+2]; points[i].z = data[3 * i + 2];
} }
const int *data_int = reinterpret_cast<const int*>(&data[3*N_P]); const int *data_int = reinterpret_cast<const int *>( &data[3 * N_P] );
A.resize(N_A); A.resize( N_A );
B.resize(N_A); B.resize( N_A );
C.resize(N_A); C.resize( N_A );
for (size_t i=0; i<A.size(); i++) { for ( size_t i = 0; i < A.size(); i++ ) {
A[i] = data_int[3*i+0]; A[i] = data_int[3 * i + 0];
B[i] = data_int[3*i+1]; B[i] = data_int[3 * i + 1];
C[i] = data_int[3*i+2]; C[i] = data_int[3 * i + 2];
} }
} }
} }
/**************************************************** /****************************************************
* Domain mesh * * Domain mesh *
****************************************************/ ****************************************************/
DomainMesh::DomainMesh(): DomainMesh::DomainMesh()
nprocx(0), nprocy(0), nprocz(0), rank(0), : nprocx( 0 ),
nx(0), ny(0), nz(0), nprocy( 0 ),
Lx(0), Ly(0), Lz(0) nprocz( 0 ),
rank( 0 ),
nx( 0 ),
ny( 0 ),
nz( 0 ),
Lx( 0 ),
Ly( 0 ),
Lz( 0 )
{ {
} }
DomainMesh::DomainMesh( RankInfoStruct data, DomainMesh::DomainMesh(
int nx2, int ny2, int nz2, double Lx2, double Ly2, double Lz2 ): RankInfoStruct data, int nx2, int ny2, int nz2, double Lx2, double Ly2, double Lz2 )
nprocx(data.nx), nprocy(data.ny), nprocz(data.nz), rank(data.rank[1][1][1]), : nprocx( data.nx ),
nx(nx2), ny(ny2), nz(nz2), nprocy( data.ny ),
Lx(Lx2), Ly(Ly2), Lz(Lz2) nprocz( data.nz ),
{ rank( data.rank[1][1][1] ),
} nx( nx2 ),
DomainMesh::~DomainMesh() ny( ny2 ),
nz( nz2 ),
Lx( Lx2 ),
Ly( Ly2 ),
Lz( Lz2 )
{ {
} }
DomainMesh::~DomainMesh() {}
size_t DomainMesh::numberPointsVar( VariableType type ) const size_t DomainMesh::numberPointsVar( VariableType type ) const
{ {
size_t N = 0; size_t N = 0;
if ( type==VariableType::NodeVariable ) if ( type == VariableType::NodeVariable )
N = (nx+1)*(ny+1)*(nz+1); N = ( nx + 1 ) * ( ny + 1 ) * ( nz + 1 );
else if ( type==VariableType::SurfaceVariable ) else if ( type == VariableType::SurfaceVariable )
N = (nx+1)*ny*nz + nx*(ny+1)*nz + nx*ny*(nz+1); N = ( nx + 1 ) * ny * nz + nx * ( ny + 1 ) * nz + nx * ny * ( nz + 1 );
else if ( type==VariableType::VolumeVariable ) else if ( type == VariableType::VolumeVariable )
N = nx*ny*nz; N = nx * ny * nz;
return N; return N;
} }
std::pair<size_t,void*> DomainMesh::pack( int level ) const std::pair<size_t, void *> DomainMesh::pack( int level ) const
{ {
std::pair<size_t,void*> data(0,NULL); std::pair<size_t, void *> data( 0, NULL );
data.first = 7*sizeof(double); data.first = 7 * sizeof( double );
data.second = new double[7]; data.second = new double[7];
memset(data.second,0,7*sizeof(double)); memset( data.second, 0, 7 * sizeof( double ) );
int *data_int = reinterpret_cast<int*>(data.second); int *data_int = reinterpret_cast<int *>( data.second );
double *data_double = &reinterpret_cast<double*>(data.second)[4]; double *data_double = &reinterpret_cast<double *>( data.second )[4];
data_int[0] = nprocx; data_int[0] = nprocx;
data_int[1] = nprocy; data_int[1] = nprocy;
data_int[2] = nprocz; data_int[2] = nprocz;
data_int[3] = rank; data_int[3] = rank;
data_int[4] = nx; data_int[4] = nx;
data_int[5] = ny; data_int[5] = ny;
data_int[6] = nz; data_int[6] = nz;
data_double[0] = Lx; data_double[0] = Lx;
data_double[1] = Ly; data_double[1] = Ly;
data_double[2] = Lz; data_double[2] = Lz;
return data; return data;
} }
void DomainMesh::unpack( const std::pair<size_t,void*>& data ) void DomainMesh::unpack( const std::pair<size_t, void *> &data )
{ {
const int *data_int = reinterpret_cast<const int*>(data.second); const int *data_int = reinterpret_cast<const int *>( data.second );
const double *data_double = &reinterpret_cast<const double*>(data.second)[4]; const double *data_double = &reinterpret_cast<const double *>( data.second )[4];
nprocx = data_int[0]; nprocx = data_int[0];
nprocy = data_int[1]; nprocy = data_int[1];
nprocz = data_int[2]; nprocz = data_int[2];
rank = data_int[3]; rank = data_int[3];
nx = data_int[4]; nx = data_int[4];
ny = data_int[5]; ny = data_int[5];
nz = data_int[6]; nz = data_int[6];
Lx = data_double[0]; Lx = data_double[0];
Ly = data_double[1]; Ly = data_double[1];
Lz = data_double[2]; Lz = data_double[2];
} }
/**************************************************** /****************************************************
* Converters * * Converters *
****************************************************/ ****************************************************/
std::shared_ptr<PointList> getPointList( std::shared_ptr<Mesh> mesh ) std::shared_ptr<PointList> getPointList( std::shared_ptr<Mesh> mesh )
{ {
return std::dynamic_pointer_cast<PointList>(mesh); return std::dynamic_pointer_cast<PointList>( mesh );
} }
std::shared_ptr<TriMesh> getTriMesh( std::shared_ptr<Mesh> mesh ) std::shared_ptr<TriMesh> getTriMesh( std::shared_ptr<Mesh> mesh )
{ {
std::shared_ptr<TriMesh> mesh2; std::shared_ptr<TriMesh> mesh2;
if ( std::dynamic_pointer_cast<TriMesh>(mesh).get() != NULL ) { if ( std::dynamic_pointer_cast<TriMesh>( mesh ).get() != NULL ) {
mesh2 = std::dynamic_pointer_cast<TriMesh>(mesh); mesh2 = std::dynamic_pointer_cast<TriMesh>( mesh );
} else if ( std::dynamic_pointer_cast<TriList>(mesh).get() != NULL ) { } else if ( std::dynamic_pointer_cast<TriList>( mesh ).get() != NULL ) {
std::shared_ptr<TriList> trilist = std::dynamic_pointer_cast<TriList>(mesh); std::shared_ptr<TriList> trilist = std::dynamic_pointer_cast<TriList>( mesh );
ASSERT(trilist.get()!=NULL); ASSERT( trilist.get() != NULL );
mesh2.reset( new TriMesh(*trilist) ); mesh2.reset( new TriMesh( *trilist ) );
} }
return mesh2; return mesh2;
} }
std::shared_ptr<TriList> getTriList( std::shared_ptr<Mesh> mesh ) std::shared_ptr<TriList> getTriList( std::shared_ptr<Mesh> mesh )
{ {
std::shared_ptr<TriList> mesh2; std::shared_ptr<TriList> mesh2;
if ( std::dynamic_pointer_cast<TriList>(mesh).get() != NULL ) { if ( std::dynamic_pointer_cast<TriList>( mesh ).get() != NULL ) {
mesh2 = std::dynamic_pointer_cast<TriList>(mesh); mesh2 = std::dynamic_pointer_cast<TriList>( mesh );
} else if ( std::dynamic_pointer_cast<TriMesh>(mesh).get() != NULL ) { } else if ( std::dynamic_pointer_cast<TriMesh>( mesh ).get() != NULL ) {
std::shared_ptr<TriMesh> trimesh = std::dynamic_pointer_cast<TriMesh>(mesh); std::shared_ptr<TriMesh> trimesh = std::dynamic_pointer_cast<TriMesh>( mesh );
ASSERT(trimesh.get()!=NULL); ASSERT( trimesh.get() != NULL );
mesh2.reset( new TriList(*trimesh) ); mesh2.reset( new TriList( *trimesh ) );
} }
return mesh2; return mesh2;
} }
std::shared_ptr<const PointList> getPointList( std::shared_ptr<const Mesh> mesh ) std::shared_ptr<const PointList> getPointList( std::shared_ptr<const Mesh> mesh )
{ {
return getPointList( std::const_pointer_cast<Mesh>(mesh) ); return getPointList( std::const_pointer_cast<Mesh>( mesh ) );
} }
std::shared_ptr<const TriMesh> getTriMesh( std::shared_ptr<const Mesh> mesh ) std::shared_ptr<const TriMesh> getTriMesh( std::shared_ptr<const Mesh> mesh )
{ {
return getTriMesh( std::const_pointer_cast<Mesh>(mesh) ); return getTriMesh( std::const_pointer_cast<Mesh>( mesh ) );
} }
std::shared_ptr<const TriList> getTriList( std::shared_ptr<const Mesh> mesh ) std::shared_ptr<const TriList> getTriList( std::shared_ptr<const Mesh> mesh )
{ {
return getTriList( std::const_pointer_cast<Mesh>(mesh) ); return getTriList( std::const_pointer_cast<Mesh>( mesh ) );
} }
} // IO namespace } // namespace IO

116
IO/Mesh.h
View File

@@ -6,17 +6,23 @@
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include "analysis/PointList.h"
#include "common/Array.h" #include "common/Array.h"
#include "common/Communication.h" #include "common/Communication.h"
#include "analysis/PointList.h"
namespace IO { namespace IO {
//! Possible variable types //! Possible variable types
enum class VariableType: unsigned char { NodeVariable=1, EdgeVariable=2, SurfaceVariable=2, VolumeVariable=3, NullVariable=0 }; enum class VariableType : unsigned char {
enum class DataType: unsigned char { Double=1, Float=2, Int=2, Null=0 }; NodeVariable = 1,
EdgeVariable = 2,
SurfaceVariable = 3,
VolumeVariable = 4,
NullVariable = 0
};
enum class DataType : unsigned char { Double = 1, Float = 2, Int = 2, Null = 0 };
/*! \class Mesh /*! \class Mesh
@@ -32,21 +38,22 @@ public:
//! Number of points for the given variable type //! Number of points for the given variable type
virtual size_t numberPointsVar( VariableType type ) const = 0; virtual size_t numberPointsVar( VariableType type ) const = 0;
//! Pack the data //! Pack the data
virtual std::pair<size_t,void*> pack( int level ) const = 0; virtual std::pair<size_t, void *> pack( int level ) const = 0;
//! Unpack the data //! Unpack the data
virtual void unpack( const std::pair<size_t,void*>& data ) = 0; virtual void unpack( const std::pair<size_t, void *> &data ) = 0;
protected: protected:
//! Empty constructor //! Empty constructor
Mesh(); Mesh();
Mesh(const Mesh&); Mesh( const Mesh & );
Mesh& operator=(const Mesh&); Mesh &operator=( const Mesh & );
}; };
/*! \class PointList /*! \class PointList
\brief A class used to hold a list of verticies \brief A class used to hold a list of verticies
*/ */
class PointList: public Mesh class PointList : public Mesh
{ {
public: public:
//! Empty constructor //! Empty constructor
@@ -60,13 +67,14 @@ public:
//! Number of points for the given variable type //! Number of points for the given variable type
virtual size_t numberPointsVar( VariableType type ) const; virtual size_t numberPointsVar( VariableType type ) const;
//! Pack the data //! Pack the data
virtual std::pair<size_t,void*> pack( int level ) const; virtual std::pair<size_t, void *> pack( int level ) const;
//! Unpack the data //! Unpack the data
virtual void unpack( const std::pair<size_t,void*>& data ); virtual void unpack( const std::pair<size_t, void *> &data );
//! Access the points //! Access the points
const std::vector<Point>& getPoints() const { return points; } const std::vector<Point> &getPoints() const { return points; }
public: public:
std::vector<Point> points; //!< List of points vertex std::vector<Point> points; //!< List of points vertex
}; };
@@ -74,7 +82,7 @@ public:
\brief A class used to hold a list of triangles specified by their vertex coordinates \brief A class used to hold a list of triangles specified by their vertex coordinates
*/ */
class TriMesh; class TriMesh;
class TriList: public Mesh class TriList : public Mesh
{ {
public: public:
//! Empty constructor //! Empty constructor
@@ -82,7 +90,7 @@ public:
//! Constructor for N triangles //! Constructor for N triangles
TriList( size_t N_tri ); TriList( size_t N_tri );
//! Constructor from TriMesh //! Constructor from TriMesh
TriList( const TriMesh& ); TriList( const TriMesh & );
//! Destructor //! Destructor
virtual ~TriList(); virtual ~TriList();
//! Mesh class name //! Mesh class name
@@ -90,20 +98,22 @@ public:
//! Number of points for the given variable type //! Number of points for the given variable type
virtual size_t numberPointsVar( VariableType type ) const; virtual size_t numberPointsVar( VariableType type ) const;
//! Pack the data //! Pack the data
virtual std::pair<size_t,void*> pack( int level ) const; virtual std::pair<size_t, void *> pack( int level ) const;
//! Unpack the data //! Unpack the data
virtual void unpack( const std::pair<size_t,void*>& data ); virtual void unpack( const std::pair<size_t, void *> &data );
public: public:
std::vector<Point> A; //!< First vertex std::vector<Point> A; //!< First vertex
std::vector<Point> B; //!< Second vertex std::vector<Point> B; //!< Second vertex
std::vector<Point> C; //!< Third vertex std::vector<Point> C; //!< Third vertex
}; };
/*! \class TriMesh /*! \class TriMesh
\brief A class used to hold a list of trianges specified by their vertex number and list of coordiantes \brief A class used to hold a list of trianges specified by their vertex number and list of
coordiantes
*/ */
class TriMesh: public Mesh class TriMesh : public Mesh
{ {
public: public:
//! TriMesh constructor //! TriMesh constructor
@@ -113,7 +123,7 @@ public:
//! Constructor for Nt triangles and the given points //! Constructor for Nt triangles and the given points
TriMesh( size_t N_tri, std::shared_ptr<PointList> points ); TriMesh( size_t N_tri, std::shared_ptr<PointList> points );
//! Constructor from TriList //! Constructor from TriList
TriMesh( const TriList& ); TriMesh( const TriList & );
//! Destructor //! Destructor
virtual ~TriMesh(); virtual ~TriMesh();
//! Mesh class name //! Mesh class name
@@ -121,21 +131,22 @@ public:
//! Number of points for the given variable type //! Number of points for the given variable type
virtual size_t numberPointsVar( VariableType type ) const; virtual size_t numberPointsVar( VariableType type ) const;
//! Pack the data //! Pack the data
virtual std::pair<size_t,void*> pack( int level ) const; virtual std::pair<size_t, void *> pack( int level ) const;
//! Unpack the data //! Unpack the data
virtual void unpack( const std::pair<size_t,void*>& data ); virtual void unpack( const std::pair<size_t, void *> &data );
public: public:
std::shared_ptr<PointList> vertices; //!< List of verticies std::shared_ptr<PointList> vertices; //!< List of verticies
std::vector<int> A; //!< First vertex std::vector<int> A; //!< First vertex
std::vector<int> B; //!< Second vertex std::vector<int> B; //!< Second vertex
std::vector<int> C; //!< Third vertex std::vector<int> C; //!< Third vertex
}; };
/*! \class Domain /*! \class Domain
\brief A class used to hold the domain \brief A class used to hold the domain
*/ */
class DomainMesh: public Mesh class DomainMesh : public Mesh
{ {
public: public:
//! Empty constructor //! Empty constructor
@@ -149,9 +160,10 @@ public:
//! Number of points for the given variable type //! Number of points for the given variable type
virtual size_t numberPointsVar( VariableType type ) const; virtual size_t numberPointsVar( VariableType type ) const;
//! Pack the data //! Pack the data
virtual std::pair<size_t,void*> pack( int level ) const; virtual std::pair<size_t, void *> pack( int level ) const;
//! Unpack the data //! Unpack the data
virtual void unpack( const std::pair<size_t,void*>& data ); virtual void unpack( const std::pair<size_t, void *> &data );
public: public:
int nprocx, nprocy, nprocz, rank; int nprocx, nprocy, nprocz, rank;
int nx, ny, nz; int nx, ny, nz;
@@ -159,37 +171,40 @@ public:
}; };
/*! \class Variable /*! \class Variable
\brief A base class for variables \brief A base class for variables
*/ */
struct Variable struct Variable {
{
public: public:
// Internal variables // Internal variables
unsigned char dim; //!< Number of points per grid point (1: scalar, 3: vector, ...) unsigned char dim; //!< Number of points per grid point (1: scalar, 3: vector, ...)
VariableType type; //!< Variable type VariableType type; //!< Variable type
DataType precision; //!< Variable precision to use for IO DataType precision; //!< Variable precision to use for IO
std::string name; //!< Variable name std::string name; //!< Variable name
Array<double> data; //!< Variable data Array<double> data; //!< Variable data
//! Empty constructor //! Empty constructor
Variable(): dim(0), type(VariableType::NullVariable), precision(DataType::Double) {} Variable() : dim( 0 ), type( VariableType::NullVariable ), precision( DataType::Double ) {}
//! Constructor //! Constructor
Variable( int dim_, IO::VariableType type_, const std::string& name_ ): Variable( int dim_, IO::VariableType type_, const std::string &name_ )
dim(dim_), type(type_), precision(DataType::Double), name(name_) {} : dim( dim_ ), type( type_ ), precision( DataType::Double ), name( name_ )
{
}
//! Constructor //! Constructor
Variable( int dim_, IO::VariableType type_, const std::string& name_, const Array<double>& data_ ): Variable(
dim(dim_), type(type_), precision(DataType::Double), name(name_), data(data_) {} int dim_, IO::VariableType type_, const std::string &name_, const Array<double> &data_ )
: dim( dim_ ), type( type_ ), precision( DataType::Double ), name( name_ ), data( data_ )
{
}
//! Destructor //! Destructor
virtual ~Variable() {} virtual ~Variable() {}
protected: protected:
//! Empty constructor //! Empty constructor
Variable(const Variable&); Variable( const Variable & );
Variable& operator=(const Variable&); Variable &operator=( const Variable & );
}; };
/*! \class MeshDataStruct /*! \class MeshDataStruct
\brief A class used to hold database info for saving a mesh \brief A class used to hold database info for saving a mesh
*/ */
@@ -197,9 +212,9 @@ struct MeshDataStruct {
DataType precision; //!< Precision to use for IO (mesh) DataType precision; //!< Precision to use for IO (mesh)
std::string meshName; //!< Mesh name std::string meshName; //!< Mesh name
std::shared_ptr<Mesh> mesh; //!< Mesh data std::shared_ptr<Mesh> mesh; //!< Mesh data
std::vector<std::shared_ptr<Variable> > vars; std::vector<std::shared_ptr<Variable>> vars;
//! Empty constructor //! Empty constructor
MeshDataStruct(): precision(DataType::Double) {} MeshDataStruct() : precision( DataType::Double ) {}
//! Check the data //! Check the data
bool check() const; bool check() const;
}; };
@@ -214,7 +229,6 @@ std::shared_ptr<const TriMesh> getTriMesh( std::shared_ptr<const Mesh> mesh );
std::shared_ptr<const TriList> getTriList( std::shared_ptr<const Mesh> mesh ); std::shared_ptr<const TriList> getTriList( std::shared_ptr<const Mesh> mesh );
} // IO namespace } // namespace IO
#endif #endif

View File

@@ -1,130 +1,151 @@
#include "IO/MeshDatabase.h" #include "IO/MeshDatabase.h"
#include "IO/IOHelpers.h"
#include "IO/Mesh.h" #include "IO/Mesh.h"
#include "IO/PackData.h" #include "IO/PackData.h"
#include "IO/IOHelpers.h"
#include "common/MPI.h" #include "common/MPI.h"
#include "common/Utilities.h" #include "common/Utilities.h"
#include <vector> #include <cstdio>
#include <map> #include <map>
#include <set> #include <set>
#include <cstdio> #include <vector>
#include <ProfilerApp.h> #include <ProfilerApp.h>
// MeshType // MeshType
template<> template<>
size_t packsize<IO::MeshType>( const IO::MeshType& rhs ) size_t packsize<IO::MeshType>( const IO::MeshType &rhs )
{ {
return sizeof(IO::MeshType); return sizeof( IO::MeshType );
} }
template<> template<>
void pack<IO::MeshType>( const IO::MeshType& rhs, char *buffer ) void pack<IO::MeshType>( const IO::MeshType &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(IO::MeshType)); memcpy( buffer, &rhs, sizeof( IO::MeshType ) );
} }
template<> template<>
void unpack<IO::MeshType>( IO::MeshType& data, const char *buffer ) void unpack<IO::MeshType>( IO::MeshType &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(IO::MeshType)); memcpy( &data, buffer, sizeof( IO::MeshType ) );
} }
// Variable::VariableType // Variable::VariableType
template<> template<>
size_t packsize<IO::VariableType>( const IO::VariableType& rhs ) size_t packsize<IO::VariableType>( const IO::VariableType &rhs )
{ {
return sizeof(IO::VariableType); return sizeof( IO::VariableType );
} }
template<> template<>
void pack<IO::VariableType>( const IO::VariableType& rhs, char *buffer ) void pack<IO::VariableType>( const IO::VariableType &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(IO::VariableType)); memcpy( buffer, &rhs, sizeof( IO::VariableType ) );
} }
template<> template<>
void unpack<IO::VariableType>( IO::VariableType& data, const char *buffer ) void unpack<IO::VariableType>( IO::VariableType &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(IO::VariableType)); memcpy( &data, buffer, sizeof( IO::VariableType ) );
} }
// DatabaseEntry // DatabaseEntry
template<> template<>
size_t packsize<IO::DatabaseEntry>( const IO::DatabaseEntry& rhs ) size_t packsize<IO::DatabaseEntry>( const IO::DatabaseEntry &rhs )
{ {
return packsize(rhs.name)+packsize(rhs.file)+packsize(rhs.offset); return packsize( rhs.name ) + packsize( rhs.file ) + packsize( rhs.offset );
} }
template<> template<>
void pack<IO::DatabaseEntry>( const IO::DatabaseEntry& rhs, char *buffer ) void pack<IO::DatabaseEntry>( const IO::DatabaseEntry &rhs, char *buffer )
{ {
size_t i=0; size_t i = 0;
pack(rhs.name,&buffer[i]); i+=packsize(rhs.name); pack( rhs.name, &buffer[i] );
pack(rhs.file,&buffer[i]); i+=packsize(rhs.file); i += packsize( rhs.name );
pack(rhs.offset,&buffer[i]); i+=packsize(rhs.offset); pack( rhs.file, &buffer[i] );
i += packsize( rhs.file );
pack( rhs.offset, &buffer[i] );
i += packsize( rhs.offset );
} }
template<> template<>
void unpack<IO::DatabaseEntry>( IO::DatabaseEntry& data, const char *buffer ) void unpack<IO::DatabaseEntry>( IO::DatabaseEntry &data, const char *buffer )
{ {
size_t i=0; size_t i = 0;
unpack(data.name,&buffer[i]); i+=packsize(data.name); unpack( data.name, &buffer[i] );
unpack(data.file,&buffer[i]); i+=packsize(data.file); i += packsize( data.name );
unpack(data.offset,&buffer[i]); i+=packsize(data.offset); unpack( data.file, &buffer[i] );
i += packsize( data.file );
unpack( data.offset, &buffer[i] );
i += packsize( data.offset );
} }
// VariableDatabase // VariableDatabase
template<> template<>
size_t packsize<IO::VariableDatabase>( const IO::VariableDatabase& rhs ) size_t packsize<IO::VariableDatabase>( const IO::VariableDatabase &rhs )
{ {
return packsize(rhs.name)+packsize(rhs.type)+packsize(rhs.dim); return packsize( rhs.name ) + packsize( rhs.type ) + packsize( rhs.dim );
} }
template<> template<>
void pack<IO::VariableDatabase>( const IO::VariableDatabase& rhs, char *buffer ) void pack<IO::VariableDatabase>( const IO::VariableDatabase &rhs, char *buffer )
{ {
size_t i=0; size_t i = 0;
pack(rhs.name,&buffer[i]); i+=packsize(rhs.name); pack( rhs.name, &buffer[i] );
pack(rhs.type,&buffer[i]); i+=packsize(rhs.type); i += packsize( rhs.name );
pack(rhs.dim,&buffer[i]); i+=packsize(rhs.dim); pack( rhs.type, &buffer[i] );
i += packsize( rhs.type );
pack( rhs.dim, &buffer[i] );
i += packsize( rhs.dim );
} }
template<> template<>
void unpack<IO::VariableDatabase>( IO::VariableDatabase& data, const char *buffer ) void unpack<IO::VariableDatabase>( IO::VariableDatabase &data, const char *buffer )
{ {
size_t i=0; size_t i = 0;
unpack(data.name,&buffer[i]); i+=packsize(data.name); unpack( data.name, &buffer[i] );
unpack(data.type,&buffer[i]); i+=packsize(data.type); i += packsize( data.name );
unpack(data.dim,&buffer[i]); i+=packsize(data.dim); unpack( data.type, &buffer[i] );
i += packsize( data.type );
unpack( data.dim, &buffer[i] );
i += packsize( data.dim );
} }
// MeshDatabase // MeshDatabase
template<> template<>
size_t packsize<IO::MeshDatabase>( const IO::MeshDatabase& data ) size_t packsize<IO::MeshDatabase>( const IO::MeshDatabase &data )
{ {
return packsize(data.name) return packsize( data.name ) + packsize( data.type ) + packsize( data.meshClass ) +
+ packsize(data.type) packsize( data.format ) + packsize( data.domains ) + packsize( data.variables ) +
+ packsize(data.meshClass) packsize( data.variable_data );
+ packsize(data.format)
+ packsize(data.domains)
+ packsize(data.variables)
+ packsize(data.variable_data);
} }
template<> template<>
void pack<IO::MeshDatabase>( const IO::MeshDatabase& rhs, char *buffer ) void pack<IO::MeshDatabase>( const IO::MeshDatabase &rhs, char *buffer )
{ {
size_t i = 0; size_t i = 0;
pack(rhs.name,&buffer[i]); i+=packsize(rhs.name); pack( rhs.name, &buffer[i] );
pack(rhs.type,&buffer[i]); i+=packsize(rhs.type); i += packsize( rhs.name );
pack(rhs.meshClass,&buffer[i]); i+=packsize(rhs.meshClass); pack( rhs.type, &buffer[i] );
pack(rhs.format,&buffer[i]); i+=packsize(rhs.format); i += packsize( rhs.type );
pack(rhs.domains,&buffer[i]); i+=packsize(rhs.domains); pack( rhs.meshClass, &buffer[i] );
pack(rhs.variables,&buffer[i]); i+=packsize(rhs.variables); i += packsize( rhs.meshClass );
pack(rhs.variable_data,&buffer[i]); i+=packsize(rhs.variable_data); pack( rhs.format, &buffer[i] );
i += packsize( rhs.format );
pack( rhs.domains, &buffer[i] );
i += packsize( rhs.domains );
pack( rhs.variables, &buffer[i] );
i += packsize( rhs.variables );
pack( rhs.variable_data, &buffer[i] );
i += packsize( rhs.variable_data );
} }
template<> template<>
void unpack<IO::MeshDatabase>( IO::MeshDatabase& data, const char *buffer ) void unpack<IO::MeshDatabase>( IO::MeshDatabase &data, const char *buffer )
{ {
size_t i=0; size_t i = 0;
unpack(data.name,&buffer[i]); i+=packsize(data.name); unpack( data.name, &buffer[i] );
unpack(data.type,&buffer[i]); i+=packsize(data.type); i += packsize( data.name );
unpack(data.meshClass,&buffer[i]); i+=packsize(data.meshClass); unpack( data.type, &buffer[i] );
unpack(data.format,&buffer[i]); i+=packsize(data.format); i += packsize( data.type );
unpack(data.domains,&buffer[i]); i+=packsize(data.domains); unpack( data.meshClass, &buffer[i] );
unpack(data.variables,&buffer[i]); i+=packsize(data.variables); i += packsize( data.meshClass );
unpack(data.variable_data,&buffer[i]); i+=packsize(data.variable_data); unpack( data.format, &buffer[i] );
i += packsize( data.format );
unpack( data.domains, &buffer[i] );
i += packsize( data.domains );
unpack( data.variables, &buffer[i] );
i += packsize( data.variables );
unpack( data.variable_data, &buffer[i] );
i += packsize( data.variable_data );
} }
@@ -132,79 +153,72 @@ namespace IO {
/**************************************************** /****************************************************
* VariableDatabase * * VariableDatabase *
****************************************************/ ****************************************************/
bool VariableDatabase::operator==(const VariableDatabase& rhs ) const bool VariableDatabase::operator==( const VariableDatabase &rhs ) const
{ {
return type==rhs.type && dim==rhs.dim && name==rhs.name; return type == rhs.type && dim == rhs.dim && name == rhs.name;
} }
bool VariableDatabase::operator!=(const VariableDatabase& rhs ) const bool VariableDatabase::operator!=( const VariableDatabase &rhs ) const
{ {
return type!=rhs.type || dim!=rhs.dim || name!=rhs.name; return type != rhs.type || dim != rhs.dim || name != rhs.name;
} }
bool VariableDatabase::operator>=(const VariableDatabase& rhs ) const bool VariableDatabase::operator>=( const VariableDatabase &rhs ) const
{ {
return operator>(rhs) || operator==(rhs); return operator>( rhs ) || operator==( rhs );
} }
bool VariableDatabase::operator<=(const VariableDatabase& rhs ) const bool VariableDatabase::operator<=( const VariableDatabase &rhs ) const { return !operator>( rhs ); }
bool VariableDatabase::operator>( const VariableDatabase &rhs ) const
{ {
return !operator>(rhs); if ( name > rhs.name )
}
bool VariableDatabase::operator>(const VariableDatabase& rhs ) const
{
if ( name>rhs.name )
return true; return true;
else if ( name<rhs.name ) else if ( name < rhs.name )
return false; return false;
if ( type>rhs.type ) if ( type > rhs.type )
return true; return true;
else if ( type<rhs.type ) else if ( type < rhs.type )
return false; return false;
if ( dim>rhs.dim ) if ( dim > rhs.dim )
return true; return true;
else if ( dim<rhs.dim ) else if ( dim < rhs.dim )
return false; return false;
return false; return false;
} }
bool VariableDatabase::operator<(const VariableDatabase& rhs ) const bool VariableDatabase::operator<( const VariableDatabase &rhs ) const
{ {
return !operator>(rhs) && operator!=(rhs); return !operator>( rhs ) && operator!=( rhs );
} }
/**************************************************** /****************************************************
* MeshDatabase * * MeshDatabase *
****************************************************/ ****************************************************/
MeshDatabase::MeshDatabase() MeshDatabase::MeshDatabase() {}
MeshDatabase::~MeshDatabase() {}
MeshDatabase::MeshDatabase( const MeshDatabase &rhs )
{ {
} name = rhs.name;
MeshDatabase::~MeshDatabase() type = rhs.type;
{ meshClass = rhs.meshClass;
} format = rhs.format;
MeshDatabase::MeshDatabase(const MeshDatabase& rhs) domains = rhs.domains;
{ variables = rhs.variables;
name = rhs.name;
type = rhs.type;
meshClass = rhs.meshClass;
format = rhs.format;
domains = rhs.domains;
variables = rhs.variables;
variable_data = rhs.variable_data; variable_data = rhs.variable_data;
} }
MeshDatabase& MeshDatabase::operator=(const MeshDatabase& rhs) MeshDatabase &MeshDatabase::operator=( const MeshDatabase &rhs )
{ {
this->name = rhs.name; this->name = rhs.name;
this->type = rhs.type; this->type = rhs.type;
this->meshClass = rhs.meshClass; this->meshClass = rhs.meshClass;
this->format = rhs.format; this->format = rhs.format;
this->domains = rhs.domains; this->domains = rhs.domains;
this->variables = rhs.variables; this->variables = rhs.variables;
this->variable_data = rhs.variable_data; this->variable_data = rhs.variable_data;
return *this; return *this;
} }
VariableDatabase MeshDatabase::getVariableDatabase( const std::string& varname ) const VariableDatabase MeshDatabase::getVariableDatabase( const std::string &varname ) const
{ {
for (size_t i=0; i<variables.size(); i++) { for ( size_t i = 0; i < variables.size(); i++ ) {
if ( variables[i].name == varname ) if ( variables[i].name == varname )
return variables[i]; return variables[i];
} }
@@ -213,217 +227,220 @@ VariableDatabase MeshDatabase::getVariableDatabase( const std::string& varname )
/**************************************************** /****************************************************
* DatabaseEntry * * DatabaseEntry *
****************************************************/ ****************************************************/
std::string DatabaseEntry::write( ) const std::string DatabaseEntry::write() const
{ {
char tmp[1000]; char tmp[1000];
sprintf(tmp,"%s; %s; %lu",name.c_str(),file.c_str(),offset); sprintf( tmp, "%s; %s; %lu", name.c_str(), file.c_str(), offset );
return std::string(tmp); return std::string( tmp );
} }
DatabaseEntry::DatabaseEntry( const char* line ) DatabaseEntry::DatabaseEntry( const char *line )
{ {
std::vector<std::string> list = splitList(line,';'); auto list = splitList( line, ';' );
name = list[0]; name = list[0];
file = list[1]; file = list[1];
offset = atol(list[2].c_str()); offset = atol( list[2].c_str() );
} }
void DatabaseEntry::read( const char* line ) void DatabaseEntry::read( const char *line )
{ {
std::vector<std::string> list = splitList(line,';'); auto list = splitList( line, ';' );
name = list[0]; name = list[0];
file = list[1]; file = list[1];
offset = atol(list[2].c_str()); offset = atol( list[2].c_str() );
} }
void DatabaseEntry::read( const std::string& line ) void DatabaseEntry::read( const std::string &line )
{ {
std::vector<std::string> list = splitList(line.c_str(),';'); auto list = splitList( line.c_str(), ';' );
name = list[0]; name = list[0];
file = list[1]; file = list[1];
offset = atol(list[2].c_str()); offset = atol( list[2].c_str() );
} }
// Gather the mesh databases from all processors // Gather the mesh databases from all processors
inline int tod( int N ) { return (N+7)/sizeof(double); } inline int tod( int N ) { return ( N + 7 ) / sizeof( double ); }
std::vector<MeshDatabase> gatherAll( const std::vector<MeshDatabase>& meshes, const Utilities::MPI& comm ) std::vector<MeshDatabase> gatherAll(
const std::vector<MeshDatabase> &meshes, const Utilities::MPI &comm )
{ {
if ( comm.getSize() == 1 ) if ( comm.getSize() == 1 )
return meshes; return meshes;
PROFILE_START("gatherAll"); PROFILE_START( "gatherAll" );
PROFILE_START("gatherAll-pack",2); PROFILE_START( "gatherAll-pack", 2 );
int size = comm.getSize(); int size = comm.getSize();
// First pack the mesh data to local buffers // First pack the mesh data to local buffers
int localsize = 0; int localsize = 0;
for (size_t i=0; i<meshes.size(); i++) for ( size_t i = 0; i < meshes.size(); i++ )
localsize += tod(packsize(meshes[i])); localsize += tod( packsize( meshes[i] ) );
auto localbuf = new double[localsize]; auto localbuf = new double[localsize];
int pos = 0; int pos = 0;
for (size_t i=0; i<meshes.size(); i++) { for ( size_t i = 0; i < meshes.size(); i++ ) {
pack( meshes[i], (char*) &localbuf[pos] ); pack( meshes[i], (char *) &localbuf[pos] );
pos += tod(packsize(meshes[i])); pos += tod( packsize( meshes[i] ) );
} }
PROFILE_STOP("gatherAll-pack",2); PROFILE_STOP( "gatherAll-pack", 2 );
// Get the number of bytes each processor will be sending/recieving // Get the number of bytes each processor will be sending/recieving
PROFILE_START("gatherAll-send1",2); PROFILE_START( "gatherAll-send1", 2 );
auto recvsize = comm.allGather( localsize ); auto recvsize = comm.allGather( localsize );
int globalsize = recvsize[0]; int globalsize = recvsize[0];
auto disp = new int[size]; auto disp = new int[size];
disp[0] = 0; disp[0] = 0;
for (int i=1; i<size; i++) { for ( int i = 1; i < size; i++ ) {
disp[i] = disp[i-1] + recvsize[i]; disp[i] = disp[i - 1] + recvsize[i];
globalsize += recvsize[i]; globalsize += recvsize[i];
} }
PROFILE_STOP("gatherAll-send1",2); PROFILE_STOP( "gatherAll-send1", 2 );
// Send/recv the global data // Send/recv the global data
PROFILE_START("gatherAll-send2",2); PROFILE_START( "gatherAll-send2", 2 );
auto globalbuf = new double[globalsize]; auto globalbuf = new double[globalsize];
comm.allGather(localbuf,localsize,globalbuf,recvsize.data(),disp,true); comm.allGather( localbuf, localsize, globalbuf, recvsize.data(), disp, true );
PROFILE_STOP("gatherAll-send2",2); PROFILE_STOP( "gatherAll-send2", 2 );
// Unpack the data // Unpack the data
PROFILE_START("gatherAll-unpack",2); PROFILE_START( "gatherAll-unpack", 2 );
std::map<std::string,MeshDatabase> data; std::map<std::string, MeshDatabase> data;
pos = 0; pos = 0;
while ( pos < globalsize ) { while ( pos < globalsize ) {
MeshDatabase tmp; MeshDatabase tmp;
unpack(tmp,(char*)&globalbuf[pos]); unpack( tmp, (char *) &globalbuf[pos] );
pos += tod(packsize(tmp)); pos += tod( packsize( tmp ) );
std::map<std::string,MeshDatabase>::iterator it = data.find(tmp.name); std::map<std::string, MeshDatabase>::iterator it = data.find( tmp.name );
if ( it==data.end() ) { if ( it == data.end() ) {
data[tmp.name] = tmp; data[tmp.name] = tmp;
} else { } else {
for (size_t i=0; i<tmp.domains.size(); i++) for ( size_t i = 0; i < tmp.domains.size(); i++ )
it->second.domains.push_back(tmp.domains[i]); it->second.domains.push_back( tmp.domains[i] );
for (size_t i=0; i<tmp.variables.size(); i++) for ( size_t i = 0; i < tmp.variables.size(); i++ )
it->second.variables.push_back(tmp.variables[i]); it->second.variables.push_back( tmp.variables[i] );
it->second.variable_data.insert(tmp.variable_data.begin(),tmp.variable_data.end()); it->second.variable_data.insert( tmp.variable_data.begin(), tmp.variable_data.end() );
} }
} }
for (auto it=data.begin(); it!=data.end(); ++it) { for ( auto it = data.begin(); it != data.end(); ++it ) {
// Get the unique variables // Get the unique variables
std::set<VariableDatabase> data2(it->second.variables.begin(),it->second.variables.end()); std::set<VariableDatabase> data2(
it->second.variables = std::vector<VariableDatabase>(data2.begin(),data2.end()); it->second.variables.begin(), it->second.variables.end() );
it->second.variables = std::vector<VariableDatabase>( data2.begin(), data2.end() );
} }
// Free temporary memory // Free temporary memory
delete [] localbuf; delete[] localbuf;
delete [] disp; delete[] disp;
delete [] globalbuf; delete[] globalbuf;
// Return the results // Return the results
std::vector<MeshDatabase> data2(data.size()); std::vector<MeshDatabase> data2( data.size() );
size_t i=0; size_t i = 0;
for (std::map<std::string,MeshDatabase>::iterator it=data.begin(); it!=data.end(); ++it, ++i) for ( std::map<std::string, MeshDatabase>::iterator it = data.begin(); it != data.end();
++it, ++i )
data2[i] = it->second; data2[i] = it->second;
PROFILE_STOP("gatherAll-unpack",2); PROFILE_STOP( "gatherAll-unpack", 2 );
PROFILE_STOP("gatherAll"); PROFILE_STOP( "gatherAll" );
return data2; return data2;
} }
//! Write the mesh databases to a file //! Write the mesh databases to a file
void write( const std::vector<MeshDatabase>& meshes, const std::string& filename ) void write( const std::vector<MeshDatabase> &meshes, const std::string &filename )
{ {
PROFILE_START("write"); PROFILE_START( "write" );
FILE *fid = fopen(filename.c_str(),"wb"); FILE *fid = fopen( filename.c_str(), "wb" );
for (size_t i=0; i<meshes.size(); i++) { for ( size_t i = 0; i < meshes.size(); i++ ) {
fprintf(fid,"%s\n",meshes[i].name.c_str()); fprintf( fid, "%s\n", meshes[i].name.c_str() );
fprintf(fid," type: %i\n",static_cast<int>(meshes[i].type)); fprintf( fid, " type: %i\n", static_cast<int>( meshes[i].type ) );
fprintf(fid," meshClass: %s\n",meshes[i].meshClass.c_str()); fprintf( fid, " meshClass: %s\n", meshes[i].meshClass.c_str() );
fprintf(fid," format: %i\n",static_cast<int>(meshes[i].format)); fprintf( fid, " format: %i\n", static_cast<int>( meshes[i].format ) );
for (size_t j=0; j<meshes[i].domains.size(); j++) for ( size_t j = 0; j < meshes[i].domains.size(); j++ )
fprintf(fid," domain: %s\n",meshes[i].domains[j].write().c_str()); fprintf( fid, " domain: %s\n", meshes[i].domains[j].write().c_str() );
fprintf(fid," variables: "); fprintf( fid, " variables: " );
for (size_t j=0; j<meshes[i].variables.size(); j++) { for ( size_t j = 0; j < meshes[i].variables.size(); j++ ) {
const VariableDatabase& var = meshes[i].variables[j]; const VariableDatabase &var = meshes[i].variables[j];
fprintf(fid,"%s|%i|%i; ",var.name.c_str(),static_cast<int>(var.type),var.dim); fprintf( fid, "%s|%i|%i; ", var.name.c_str(), static_cast<int>( var.type ), var.dim );
} }
fprintf(fid,"\n"); fprintf( fid, "\n" );
std::map<std::pair<std::string,std::string>,DatabaseEntry>::const_iterator it; std::map<std::pair<std::string, std::string>, DatabaseEntry>::const_iterator it;
for (it=meshes[i].variable_data.begin(); it!=meshes[i].variable_data.end(); ++it) { for ( it = meshes[i].variable_data.begin(); it != meshes[i].variable_data.end(); ++it ) {
const char* domain = it->first.first.c_str(); const char *domain = it->first.first.c_str();
const char* variable = it->first.second.c_str(); const char *variable = it->first.second.c_str();
fprintf(fid," variable(%s,%s): %s\n",domain,variable,it->second.write().c_str()); fprintf(
fid, " variable(%s,%s): %s\n", domain, variable, it->second.write().c_str() );
} }
} }
fclose(fid); fclose( fid );
PROFILE_STOP("write"); PROFILE_STOP( "write" );
} }
//! Read the mesh databases from a file //! Read the mesh databases from a file
std::vector<MeshDatabase> read( const std::string& filename ) std::vector<MeshDatabase> read( const std::string &filename )
{ {
std::vector<MeshDatabase> meshes; std::vector<MeshDatabase> meshes;
PROFILE_START("read"); PROFILE_START( "read" );
FILE *fid = fopen(filename.c_str(),"rb"); FILE *fid = fopen( filename.c_str(), "rb" );
if ( fid==NULL ) if ( fid == NULL )
ERROR("Error opening file"); ERROR( "Error opening file" );
char *line = new char[10000]; char *line = new char[10000];
while ( std::fgets(line,1000,fid) != NULL ) { while ( std::fgets( line, 1000, fid ) != NULL ) {
if ( line[0]<32 ) { if ( line[0] < 32 ) {
// Empty line // Empty line
continue; continue;
} else if ( line[0] != ' ' ) { } else if ( line[0] != ' ' ) {
meshes.resize(meshes.size()+1); meshes.resize( meshes.size() + 1 );
std::string name(line); std::string name( line );
name.resize(name.size()-1); name.resize( name.size() - 1 );
meshes.back().name = name; meshes.back().name = name;
} else if ( strncmp(line," format:",10)==0 ) { } else if ( strncmp( line, " format:", 10 ) == 0 ) {
meshes.back().format = static_cast<unsigned char>(atoi(&line[10])); meshes.back().format = static_cast<unsigned char>( atoi( &line[10] ) );
} else if ( strncmp(line," type:",8)==0 ) { } else if ( strncmp( line, " type:", 8 ) == 0 ) {
meshes.back().type = static_cast<MeshType>(atoi(&line[8])); meshes.back().type = static_cast<MeshType>( atoi( &line[8] ) );
} else if ( strncmp(line," meshClass:",13)==0 ) { } else if ( strncmp( line, " meshClass:", 13 ) == 0 ) {
meshes.back().meshClass = deblank(std::string(&line[13])); meshes.back().meshClass = deblank( std::string( &line[13] ) );
} else if ( strncmp(line," domain:",10)==0 ) { } else if ( strncmp( line, " domain:", 10 ) == 0 ) {
DatabaseEntry data(&line[10]); DatabaseEntry data( &line[10] );
meshes.back().domains.push_back(data); meshes.back().domains.push_back( data );
} else if ( strncmp(line," variables:",13)==0 ) { } else if ( strncmp( line, " variables:", 13 ) == 0 ) {
MeshDatabase& mesh = meshes.back(); MeshDatabase &mesh = meshes.back();
std::vector<std::string> variables = splitList(&line[13],';'); std::vector<std::string> variables = splitList( &line[13], ';' );
mesh.variables.resize(variables.size()); mesh.variables.resize( variables.size() );
for (size_t i=0; i<variables.size(); i++) { for ( size_t i = 0; i < variables.size(); i++ ) {
std::vector<std::string> tmp = splitList(variables[i].c_str(),'|'); std::vector<std::string> tmp = splitList( variables[i].c_str(), '|' );
ASSERT(tmp.size()==3); ASSERT( tmp.size() == 3 );
mesh.variables[i].name = tmp[0]; mesh.variables[i].name = tmp[0];
mesh.variables[i].type = static_cast<VariableType>(atoi(tmp[1].c_str())); mesh.variables[i].type = static_cast<VariableType>( atoi( tmp[1].c_str() ) );
mesh.variables[i].dim = atoi(tmp[2].c_str()); mesh.variables[i].dim = atoi( tmp[2].c_str() );
} }
} else if ( strncmp(line," variable(",12)==0 ) { } else if ( strncmp( line, " variable(", 12 ) == 0 ) {
size_t i1 = find(line,','); size_t i1 = find( line, ',' );
size_t i2 = find(line,':'); size_t i2 = find( line, ':' );
std::string domain = deblank(std::string(line,12,i1-12)); std::string domain = deblank( std::string( line, 12, i1 - 12 ) );
std::string variable = deblank(std::string(line,i1+1,i2-i1-2)); std::string variable = deblank( std::string( line, i1 + 1, i2 - i1 - 2 ) );
std::pair<std::string,std::string> key(domain,variable); std::pair<std::string, std::string> key( domain, variable );
DatabaseEntry data(&line[i2+1]); DatabaseEntry data( &line[i2 + 1] );
meshes.back().variable_data.insert( meshes.back().variable_data.insert(
std::pair<std::pair<std::string,std::string>,DatabaseEntry>(key,data) ); std::pair<std::pair<std::string, std::string>, DatabaseEntry>( key, data ) );
} else { } else {
ERROR("Error reading line"); ERROR( "Error reading line" );
} }
} }
fclose(fid); fclose( fid );
delete [] line; delete[] line;
PROFILE_STOP("read"); PROFILE_STOP( "read" );
return meshes; return meshes;
} }
// Return the mesh type // Return the mesh type
IO::MeshType meshType( const IO::Mesh& mesh ) IO::MeshType meshType( const IO::Mesh &mesh )
{ {
IO::MeshType type = IO::Unknown; IO::MeshType type = IO::MeshType::Unknown;
const std::string meshClass = mesh.className(); const std::string meshClass = mesh.className();
if ( meshClass=="PointList" ) { if ( meshClass == "PointList" ) {
type = IO::PointMesh; type = IO::MeshType::PointMesh;
} else if ( meshClass=="TriList" || meshClass=="TriMesh" ) { } else if ( meshClass == "TriList" || meshClass == "TriMesh" ) {
type = IO::SurfaceMesh; type = IO::MeshType::SurfaceMesh;
} else if ( meshClass=="DomainMesh" ) { } else if ( meshClass == "DomainMesh" ) {
type = IO::VolumeMesh; type = IO::MeshType::VolumeMesh;
} else { } else {
ERROR("Unknown mesh"); ERROR( "Unknown mesh" );
} }
return type; return type;
} }
} // IO namespace } // namespace IO

View File

@@ -5,10 +5,10 @@
#include "common/MPI.h" #include "common/MPI.h"
#include <iostream> #include <iostream>
#include <map>
#include <memory> #include <memory>
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include <map>
namespace IO { namespace IO {
@@ -17,74 +17,76 @@ class Mesh;
//! Enum to identify mesh type //! Enum to identify mesh type
//enum class MeshType : char { PointMesh=1, SurfaceMesh=2, VolumeMesh=3, Unknown=-1 }; // enum class MeshType : char { PointMesh=1, SurfaceMesh=2, VolumeMesh=3, Unknown=-1 };
enum MeshType { PointMesh=1, SurfaceMesh=2, VolumeMesh=3, Unknown=-1 }; enum class MeshType { PointMesh = 1, SurfaceMesh = 2, VolumeMesh = 3, Unknown = -1 };
//! Helper struct for containing offsets for the mesh info //! Helper struct for containing offsets for the mesh info
struct DatabaseEntry { struct DatabaseEntry {
std::string name; //!< Name of the entry std::string name; //!< Name of the entry
std::string file; //!< Name of the file containing the entry std::string file; //!< Name of the file containing the entry
size_t offset; //!< Offset in the file to start reading size_t offset; //!< Offset in the file to start reading
std::string write( ) const; //!< Convert the data to a string std::string write() const; //!< Convert the data to a string
void read( const char* line ); //!< Convert the string to data void read( const char *line ); //!< Convert the string to data
void read( const std::string& line ); //!< Convert the string to data void read( const std::string &line ); //!< Convert the string to data
DatabaseEntry( ) {} //!< Empty constructor DatabaseEntry() {} //!< Empty constructor
DatabaseEntry( const char* line ); //!< Convert the string to data DatabaseEntry( const char *line ); //!< Convert the string to data
~DatabaseEntry() {} //!< Destructor ~DatabaseEntry() {} //!< Destructor
}; };
//! Structure to hold the info about the variables //! Structure to hold the info about the variables
struct VariableDatabase { struct VariableDatabase {
std::string name; //!< Name of the variable std::string name; //!< Name of the variable
IO::VariableType type; //!< Variable IO::VariableType type; //!< Variable
unsigned int dim; //!< Number of points per grid point (1: scalar, 3: vector, ...) unsigned int dim; //!< Number of points per grid point (1: scalar, 3: vector, ...)
// Overload key operators // Overload key operators
bool operator==(const VariableDatabase& rhs ) const; bool operator==( const VariableDatabase &rhs ) const;
bool operator!=(const VariableDatabase& rhs ) const; bool operator!=( const VariableDatabase &rhs ) const;
bool operator>=(const VariableDatabase& rhs ) const; bool operator>=( const VariableDatabase &rhs ) const;
bool operator<=(const VariableDatabase& rhs ) const; bool operator<=( const VariableDatabase &rhs ) const;
bool operator> (const VariableDatabase& rhs ) const; bool operator>( const VariableDatabase &rhs ) const;
bool operator< (const VariableDatabase& rhs ) const; bool operator<( const VariableDatabase &rhs ) const;
}; };
//! Structure to hold the info about the meshes //! Structure to hold the info about the meshes
struct MeshDatabase { struct MeshDatabase {
typedef std::pair<std::string,std::string> variable_id; typedef std::pair<std::string, std::string> variable_id;
std::string name; //!< Name of the mesh std::string name; //!< Name of the mesh
MeshType type; //!< Mesh type MeshType type; //!< Mesh type
std::string meshClass; //!< Mesh class std::string meshClass; //!< Mesh class
unsigned char format; //!< Data format (1: old, 2: new, 3: new (single), 4: silo) unsigned char format; //!< Data format (1: old, 2: new, 3: new (single), 4: silo)
std::vector<DatabaseEntry> domains; //!< List of the domains std::vector<DatabaseEntry> domains; //!< List of the domains
std::vector<VariableDatabase> variables; //!< List of the variables std::vector<VariableDatabase> variables; //!< List of the variables
std::map<variable_id,DatabaseEntry> variable_data; //!< Data for the variables std::map<variable_id, DatabaseEntry> variable_data; //!< Data for the variables
VariableDatabase getVariableDatabase( const std::string& varname ) const; VariableDatabase getVariableDatabase( const std::string &varname ) const;
public: public:
MeshDatabase(); MeshDatabase();
~MeshDatabase(); ~MeshDatabase();
MeshDatabase(const MeshDatabase&); MeshDatabase( const MeshDatabase & );
MeshDatabase& operator=(const MeshDatabase&); MeshDatabase &operator=( const MeshDatabase & );
}; };
//! Gather the mesh databases from all processors //! Gather the mesh databases from all processors
std::vector<MeshDatabase> gatherAll( const std::vector<MeshDatabase>& meshes, const Utilities::MPI& comm ); std::vector<MeshDatabase> gatherAll(
const std::vector<MeshDatabase> &meshes, const Utilities::MPI &comm );
//! Write the mesh databases to a file //! Write the mesh databases to a file
void write( const std::vector<MeshDatabase>& meshes, const std::string& filename ); void write( const std::vector<MeshDatabase> &meshes, const std::string &filename );
//! Read the mesh databases from a file //! Read the mesh databases from a file
std::vector<MeshDatabase> read( const std::string& filename ); std::vector<MeshDatabase> read( const std::string &filename );
//! Return the mesh type //! Return the mesh type
IO::MeshType meshType( const IO::Mesh& mesh ); IO::MeshType meshType( const IO::Mesh &mesh );
} // IO namespace } // namespace IO
#endif #endif

View File

@@ -1,10 +1,10 @@
#include "IO/PIO.h" #include "IO/PIO.h"
#include "common/Utilities.h"
#include "common/MPI.h" #include "common/MPI.h"
#include "common/Utilities.h"
#include <cstring>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <cstring>
namespace IO { namespace IO {
@@ -15,19 +15,18 @@ static ParallelStreamBuffer perr_buffer;
static ParallelStreamBuffer plog_buffer; static ParallelStreamBuffer plog_buffer;
std::ostream pout(&pout_buffer); std::ostream pout( &pout_buffer );
std::ostream perr(&perr_buffer); std::ostream perr( &perr_buffer );
std::ostream plog(&plog_buffer); std::ostream plog( &plog_buffer );
/**************************************************************************** /****************************************************************************
* Functions to control logging * * Functions to control logging *
****************************************************************************/ ****************************************************************************/
std::ofstream *global_filestream=NULL; std::ofstream *global_filestream = NULL;
static void shutdownFilestream( ) static void shutdownFilestream()
{ {
if ( global_filestream!=NULL ) { if ( global_filestream != NULL ) {
global_filestream->flush(); global_filestream->flush();
global_filestream->close(); global_filestream->close();
delete global_filestream; delete global_filestream;
@@ -37,16 +36,16 @@ static void shutdownFilestream( )
void Utilities::logOnlyNodeZero( const std::string &filename ) void Utilities::logOnlyNodeZero( const std::string &filename )
{ {
int rank = 0; int rank = 0;
#ifdef USE_MPI #ifdef USE_MPI
MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_rank( MPI_COMM_WORLD, &rank );
#endif #endif
if ( rank == 0 ) if ( rank == 0 )
logAllNodes(filename,true); logAllNodes( filename, true );
} }
void Utilities::logAllNodes( const std::string &filename, bool singleStream ) void Utilities::logAllNodes( const std::string &filename, bool singleStream )
{ {
if ( singleStream ) if ( singleStream )
ERROR("Not implimented yet"); ERROR( "Not implimented yet" );
// If the filestream was open, then close it and reset streams // If the filestream was open, then close it and reset streams
shutdownFilestream(); shutdownFilestream();
@@ -55,33 +54,33 @@ void Utilities::logAllNodes( const std::string &filename, bool singleStream )
std::string full_filename = filename; std::string full_filename = filename;
if ( !singleStream ) { if ( !singleStream ) {
int rank = 0; int rank = 0;
#ifdef USE_MPI #ifdef USE_MPI
MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_rank( MPI_COMM_WORLD, &rank );
#endif #endif
char tmp[100]; char tmp[100];
sprintf(tmp,".%04i",rank); sprintf( tmp, ".%04i", rank );
full_filename += std::string(tmp); full_filename += std::string( tmp );
} }
global_filestream = new std::ofstream(full_filename.c_str()); global_filestream = new std::ofstream( full_filename.c_str() );
if ( !(*global_filestream) ) { if ( !( *global_filestream ) ) {
delete global_filestream; delete global_filestream;
global_filestream = NULL; global_filestream = NULL;
perr << "PIO: Could not open log file ``" << full_filename << "''\n"; perr << "PIO: Could not open log file ``" << full_filename << "''\n";
} else { } else {
pout_buffer.setOutputStream(global_filestream); pout_buffer.setOutputStream( global_filestream );
pout_buffer.setOutputStream(&std::cout); pout_buffer.setOutputStream( &std::cout );
perr_buffer.setOutputStream(global_filestream); perr_buffer.setOutputStream( global_filestream );
perr_buffer.setOutputStream(&std::cerr); perr_buffer.setOutputStream( &std::cerr );
plog_buffer.setOutputStream(global_filestream); plog_buffer.setOutputStream( global_filestream );
} }
} }
/**************************************************************************** /****************************************************************************
* ParallelStreamBuffer class * * ParallelStreamBuffer class *
****************************************************************************/ ****************************************************************************/
void Utilities::stopLogging( ) void Utilities::stopLogging()
{ {
pout_buffer.reset(); pout_buffer.reset();
perr_buffer.reset(); perr_buffer.reset();
@@ -93,77 +92,71 @@ void Utilities::stopLogging( )
/**************************************************************************** /****************************************************************************
* ParallelStreamBuffer class * * ParallelStreamBuffer class *
****************************************************************************/ ****************************************************************************/
ParallelStreamBuffer::ParallelStreamBuffer( ): ParallelStreamBuffer::ParallelStreamBuffer()
d_rank(0), d_size(0), d_buffer_size(0), d_buffer(NULL) : d_rank( 0 ), d_size( 0 ), d_buffer_size( 0 ), d_buffer( NULL )
{ {
} }
ParallelStreamBuffer:: ~ParallelStreamBuffer() ParallelStreamBuffer::~ParallelStreamBuffer() { delete[] d_buffer; }
{ void ParallelStreamBuffer::setOutputStream( std::ostream *stream ) { d_stream.push_back( stream ); }
delete [] d_buffer;
}
void ParallelStreamBuffer::setOutputStream( std::ostream *stream )
{
d_stream.push_back( stream );
}
int ParallelStreamBuffer::sync() int ParallelStreamBuffer::sync()
{ {
for (size_t i=0; i<d_stream.size(); i++) { for ( size_t i = 0; i < d_stream.size(); i++ ) {
std::ostream& stream = *d_stream[i]; std::ostream &stream = *d_stream[i];
stream << d_buffer; stream << d_buffer;
} }
d_size = 0; d_size = 0;
memset(d_buffer,0,d_buffer_size); memset( d_buffer, 0, d_buffer_size );
return 0; return 0;
} }
void ParallelStreamBuffer::reserve( size_t size ) void ParallelStreamBuffer::reserve( size_t size )
{ {
if ( size > d_buffer_size ) { if ( size > d_buffer_size ) {
if ( d_buffer_size==0 ) { if ( d_buffer_size == 0 ) {
d_buffer_size = 1024; d_buffer_size = 1024;
d_buffer = new char[d_buffer_size]; d_buffer = new char[d_buffer_size];
memset(d_buffer,0,d_buffer_size); memset( d_buffer, 0, d_buffer_size );
} }
while ( size > d_buffer_size ) { while ( size > d_buffer_size ) {
char *tmp = d_buffer; char *tmp = d_buffer;
d_buffer_size *= 2; d_buffer_size *= 2;
d_buffer = new char[d_buffer_size]; d_buffer = new char[d_buffer_size];
memset(d_buffer,0,d_buffer_size); memset( d_buffer, 0, d_buffer_size );
memcpy(d_buffer,tmp,d_size); memcpy( d_buffer, tmp, d_size );
delete [] tmp; delete[] tmp;
} }
} }
} }
std::streamsize ParallelStreamBuffer::xsputn( const char* text, std::streamsize n ) std::streamsize ParallelStreamBuffer::xsputn( const char *text, std::streamsize n )
{ {
reserve(d_size+n); reserve( d_size + n );
memcpy(&d_buffer[d_size],text,n); memcpy( &d_buffer[d_size], text, n );
d_size += n; d_size += n;
if ( text[n-1]==0 || text[n-1]==10 ) { sync(); } if ( text[n - 1] == 0 || text[n - 1] == 10 ) {
sync();
}
return n; return n;
} }
int ParallelStreamBuffer::overflow(int ch) int ParallelStreamBuffer::overflow( int ch )
{ {
reserve(d_size+1); reserve( d_size + 1 );
d_buffer[d_size] = ch; d_buffer[d_size] = ch;
d_size++; d_size++;
if ( ch==0 || ch==10 ) { sync(); } if ( ch == 0 || ch == 10 ) {
return std::char_traits<char>::to_int_type(ch); sync();
} }
int ParallelStreamBuffer::underflow() return std::char_traits<char>::to_int_type( ch );
{
return -1;
} }
int ParallelStreamBuffer::underflow() { return -1; }
void ParallelStreamBuffer::reset() void ParallelStreamBuffer::reset()
{ {
sync(); sync();
d_stream.clear(); d_stream.clear();
delete [] d_buffer; delete[] d_buffer;
d_buffer = NULL; d_buffer = NULL;
d_buffer_size = 0; d_buffer_size = 0;
} }
} // IO namespace } // namespace IO

View File

@@ -45,12 +45,11 @@ inline int printp( const char *format, ... );
class ParallelStreamBuffer : public std::streambuf class ParallelStreamBuffer : public std::streambuf
{ {
public: public:
/*! /*!
* Create a parallel buffer class. The object will require further * Create a parallel buffer class. The object will require further
* initialization to set up the I/O streams and prefix string. * initialization to set up the I/O streams and prefix string.
*/ */
ParallelStreamBuffer( ); ParallelStreamBuffer();
/*! /*!
* Set the output file stream (multiple output streams are supported) * Set the output file stream (multiple output streams are supported)
@@ -60,26 +59,26 @@ public:
/*! /*!
* The destructor simply deallocates any internal data * The destructor simply deallocates any internal data
* buffers. It does not modify the output streams. * buffers. It does not modify the output streams.
*/ */
virtual ~ParallelStreamBuffer(); virtual ~ParallelStreamBuffer();
/*! /*!
* Synchronize the parallel buffer (called from streambuf). * Synchronize the parallel buffer (called from streambuf).
*/ */
virtual int sync(); virtual int sync();
/** /**
* Write the specified number of characters into the output stream (called * Write the specified number of characters into the output stream (called
* from streambuf). * from streambuf).
*/ */
virtual std::streamsize xsputn(const char* text, std::streamsize n); virtual std::streamsize xsputn( const char *text, std::streamsize n );
/*! /*!
* Write an overflow character into the parallel buffer (called from * Write an overflow character into the parallel buffer (called from
* streambuf). * streambuf).
*/ */
virtual int overflow(int ch); virtual int overflow( int ch );
/*! /*!
* Read an overflow character from the parallel buffer (called from * Read an overflow character from the parallel buffer (called from
@@ -98,30 +97,30 @@ private:
size_t d_size; size_t d_size;
size_t d_buffer_size; size_t d_buffer_size;
char *d_buffer; char *d_buffer;
std::vector<std::ostream*> d_stream; std::vector<std::ostream *> d_stream;
inline void reserve( size_t size ); inline void reserve( size_t size );
}; };
namespace Utilities { namespace Utilities {
/*! /*!
* Log messages for node zero only to the specified filename. All output * Log messages for node zero only to the specified filename. All output
* to pout, perr, and plog on node zero will go to the log file. * to pout, perr, and plog on node zero will go to the log file.
*/ */
void logOnlyNodeZero( const std::string &filename ); void logOnlyNodeZero( const std::string &filename );
/*! /*!
* Log messages from all nodes. The diagnostic data for processor XXXXX * Log messages from all nodes. The diagnostic data for processor XXXXX
* will be sent to a file with the name filename.XXXXX, where filename is * will be sent to a file with the name filename.XXXXX, where filename is
* the function argument. * the function argument.
*/ */
void logAllNodes( const std::string &filename, bool singleStream=false ); void logAllNodes( const std::string &filename, bool singleStream = false );
/*! /*!
* Stop logging messages, flush buffers, and reset memory. * Stop logging messages, flush buffers, and reset memory.
*/ */
void stopLogging( ); void stopLogging();
} // namespace Utilities } // namespace Utilities

View File

@@ -3,9 +3,9 @@
#include "IO/PIO.h" #include "IO/PIO.h"
#include <cstdio>
#include <iostream> #include <iostream>
#include <stdarg.h> #include <stdarg.h>
#include <cstdio>
namespace IO { namespace IO {
@@ -14,16 +14,16 @@ namespace IO {
inline int printp( const char *format, ... ) inline int printp( const char *format, ... )
{ {
va_list ap; va_list ap;
va_start(ap,format); va_start( ap, format );
char tmp[1024]; char tmp[1024];
int n = vsprintf(tmp,format,ap); int n = vsprintf( tmp, format, ap );
va_end(ap); va_end( ap );
pout << tmp; pout << tmp;
pout.flush(); pout.flush();
return n; return n;
} }
} // IO namespace } // namespace IO
#endif #endif

View File

@@ -4,102 +4,101 @@
/******************************************************** /********************************************************
* Concrete implimentations for packing/unpacking * * Concrete implimentations for packing/unpacking *
********************************************************/ ********************************************************/
// unsigned char // unsigned char
template<> template<>
size_t packsize<unsigned char>( const unsigned char& rhs ) size_t packsize<unsigned char>( const unsigned char &rhs )
{ {
return sizeof(unsigned char); return sizeof( unsigned char );
} }
template<> template<>
void pack<unsigned char>( const unsigned char& rhs, char *buffer ) void pack<unsigned char>( const unsigned char &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(unsigned char)); memcpy( buffer, &rhs, sizeof( unsigned char ) );
} }
template<> template<>
void unpack<unsigned char>( unsigned char& data, const char *buffer ) void unpack<unsigned char>( unsigned char &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(unsigned char)); memcpy( &data, buffer, sizeof( unsigned char ) );
} }
// char // char
template<> template<>
size_t packsize<char>( const char& rhs ) size_t packsize<char>( const char &rhs )
{ {
return sizeof(char); return sizeof( char );
} }
template<> template<>
void pack<char>( const char& rhs, char *buffer ) void pack<char>( const char &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(char)); memcpy( buffer, &rhs, sizeof( char ) );
} }
template<> template<>
void unpack<char>( char& data, const char *buffer ) void unpack<char>( char &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(char)); memcpy( &data, buffer, sizeof( char ) );
} }
// int // int
template<> template<>
size_t packsize<int>( const int& rhs ) size_t packsize<int>( const int &rhs )
{ {
return sizeof(int); return sizeof( int );
} }
template<> template<>
void pack<int>( const int& rhs, char *buffer ) void pack<int>( const int &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(int)); memcpy( buffer, &rhs, sizeof( int ) );
} }
template<> template<>
void unpack<int>( int& data, const char *buffer ) void unpack<int>( int &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(int)); memcpy( &data, buffer, sizeof( int ) );
} }
// unsigned int // unsigned int
template<> template<>
size_t packsize<unsigned int>( const unsigned int& rhs ) size_t packsize<unsigned int>( const unsigned int &rhs )
{ {
return sizeof(unsigned int); return sizeof( unsigned int );
} }
template<> template<>
void pack<unsigned int>( const unsigned int& rhs, char *buffer ) void pack<unsigned int>( const unsigned int &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(int)); memcpy( buffer, &rhs, sizeof( int ) );
} }
template<> template<>
void unpack<unsigned int>( unsigned int& data, const char *buffer ) void unpack<unsigned int>( unsigned int &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(int)); memcpy( &data, buffer, sizeof( int ) );
} }
// size_t // size_t
template<> template<>
size_t packsize<size_t>( const size_t& rhs ) size_t packsize<size_t>( const size_t &rhs )
{ {
return sizeof(size_t); return sizeof( size_t );
} }
template<> template<>
void pack<size_t>( const size_t& rhs, char *buffer ) void pack<size_t>( const size_t &rhs, char *buffer )
{ {
memcpy(buffer,&rhs,sizeof(size_t)); memcpy( buffer, &rhs, sizeof( size_t ) );
} }
template<> template<>
void unpack<size_t>( size_t& data, const char *buffer ) void unpack<size_t>( size_t &data, const char *buffer )
{ {
memcpy(&data,buffer,sizeof(size_t)); memcpy( &data, buffer, sizeof( size_t ) );
} }
// std::string // std::string
template<> template<>
size_t packsize<std::string>( const std::string& rhs ) size_t packsize<std::string>( const std::string &rhs )
{ {
return rhs.size()+1; return rhs.size() + 1;
} }
template<> template<>
void pack<std::string>( const std::string& rhs, char *buffer ) void pack<std::string>( const std::string &rhs, char *buffer )
{ {
memcpy(buffer,rhs.c_str(),rhs.size()+1); memcpy( buffer, rhs.c_str(), rhs.size() + 1 );
} }
template<> template<>
void unpack<std::string>( std::string& data, const char *buffer ) void unpack<std::string>( std::string &data, const char *buffer )
{ {
data = std::string(buffer); data = std::string( buffer );
} }

View File

@@ -2,77 +2,76 @@
#ifndef included_PackData #ifndef included_PackData
#define included_PackData #define included_PackData
#include <vector>
#include <set>
#include <map> #include <map>
#include <set>
#include <vector>
//! Template function to return the buffer size required to pack a class //! Template function to return the buffer size required to pack a class
template<class TYPE> template<class TYPE>
size_t packsize( const TYPE& rhs ); size_t packsize( const TYPE &rhs );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE> template<class TYPE>
void pack( const TYPE& rhs, char *buffer ); void pack( const TYPE &rhs, char *buffer );
//! Template function to unpack a class from a buffer //! Template function to unpack a class from a buffer
template<class TYPE> template<class TYPE>
void unpack( TYPE& data, const char *buffer ); void unpack( TYPE &data, const char *buffer );
//! Template function to return the buffer size required to pack a std::vector //! Template function to return the buffer size required to pack a std::vector
template<class TYPE> template<class TYPE>
size_t packsize( const std::vector<TYPE>& rhs ); size_t packsize( const std::vector<TYPE> &rhs );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE> template<class TYPE>
void pack( const std::vector<TYPE>& rhs, char *buffer ); void pack( const std::vector<TYPE> &rhs, char *buffer );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE> template<class TYPE>
void unpack( std::vector<TYPE>& data, const char *buffer ); void unpack( std::vector<TYPE> &data, const char *buffer );
//! Template function to return the buffer size required to pack a std::pair //! Template function to return the buffer size required to pack a std::pair
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
size_t packsize( const std::pair<TYPE1,TYPE2>& rhs ); size_t packsize( const std::pair<TYPE1, TYPE2> &rhs );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void pack( const std::pair<TYPE1,TYPE2>& rhs, char *buffer ); void pack( const std::pair<TYPE1, TYPE2> &rhs, char *buffer );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void unpack( std::pair<TYPE1,TYPE2>& data, const char *buffer ); void unpack( std::pair<TYPE1, TYPE2> &data, const char *buffer );
//! Template function to return the buffer size required to pack a std::map //! Template function to return the buffer size required to pack a std::map
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
size_t packsize( const std::map<TYPE1,TYPE2>& rhs ); size_t packsize( const std::map<TYPE1, TYPE2> &rhs );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void pack( const std::map<TYPE1,TYPE2>& rhs, char *buffer ); void pack( const std::map<TYPE1, TYPE2> &rhs, char *buffer );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void unpack( std::map<TYPE1,TYPE2>& data, const char *buffer ); void unpack( std::map<TYPE1, TYPE2> &data, const char *buffer );
//! Template function to return the buffer size required to pack a std::set //! Template function to return the buffer size required to pack a std::set
template<class TYPE> template<class TYPE>
size_t packsize( const std::set<TYPE>& rhs ); size_t packsize( const std::set<TYPE> &rhs );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE> template<class TYPE>
void pack( const std::set<TYPE>& rhs, char *buffer ); void pack( const std::set<TYPE> &rhs, char *buffer );
//! Template function to pack a class to a buffer //! Template function to pack a class to a buffer
template<class TYPE> template<class TYPE>
void unpack( std::set<TYPE>& data, const char *buffer ); void unpack( std::set<TYPE> &data, const char *buffer );
#include "IO/PackData.hpp" #include "IO/PackData.hpp"
#endif #endif

View File

@@ -4,152 +4,156 @@
#include "IO/PackData.h" #include "IO/PackData.h"
#include <map>
#include <set>
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include <set>
#include <map>
/******************************************************** /********************************************************
* Default instantiations for std::vector * * Default instantiations for std::vector *
********************************************************/ ********************************************************/
template<class TYPE> template<class TYPE>
size_t packsize( const std::vector<TYPE>& rhs ) size_t packsize( const std::vector<TYPE> &rhs )
{ {
size_t bytes = sizeof(size_t); size_t bytes = sizeof( size_t );
for (size_t i=0; i<rhs.size(); i++) for ( size_t i = 0; i < rhs.size(); i++ )
bytes += packsize(rhs[i]); bytes += packsize( rhs[i] );
return bytes; return bytes;
} }
template<class TYPE> template<class TYPE>
void pack( const std::vector<TYPE>& rhs, char *buffer ) void pack( const std::vector<TYPE> &rhs, char *buffer )
{ {
size_t size = rhs.size(); size_t size = rhs.size();
memcpy(buffer,&size,sizeof(size_t)); memcpy( buffer, &size, sizeof( size_t ) );
size_t pos = sizeof(size_t); size_t pos = sizeof( size_t );
for (size_t i=0; i<rhs.size(); i++) { for ( size_t i = 0; i < rhs.size(); i++ ) {
pack(rhs[i],&buffer[pos]); pack( rhs[i], &buffer[pos] );
pos += packsize(rhs[i]); pos += packsize( rhs[i] );
} }
} }
template<class TYPE> template<class TYPE>
void unpack( std::vector<TYPE>& data, const char *buffer ) void unpack( std::vector<TYPE> &data, const char *buffer )
{ {
size_t size; size_t size;
memcpy(&size,buffer,sizeof(size_t)); memcpy( &size, buffer, sizeof( size_t ) );
data.clear(); data.clear();
data.resize(size); data.resize( size );
size_t pos = sizeof(size_t); size_t pos = sizeof( size_t );
for (size_t i=0; i<data.size(); i++) { for ( size_t i = 0; i < data.size(); i++ ) {
unpack(data[i],&buffer[pos]); unpack( data[i], &buffer[pos] );
pos += packsize(data[i]); pos += packsize( data[i] );
} }
} }
/******************************************************** /********************************************************
* Default instantiations for std::pair * * Default instantiations for std::pair *
********************************************************/ ********************************************************/
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
size_t packsize( const std::pair<TYPE1,TYPE2>& rhs ) size_t packsize( const std::pair<TYPE1, TYPE2> &rhs )
{ {
return packsize(rhs.first)+packsize(rhs.second); return packsize( rhs.first ) + packsize( rhs.second );
} }
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void pack( const std::pair<TYPE1,TYPE2>& rhs, char *buffer ) void pack( const std::pair<TYPE1, TYPE2> &rhs, char *buffer )
{ {
pack(rhs.first,buffer); pack( rhs.first, buffer );
pack(rhs.second,&buffer[packsize(rhs.first)]); pack( rhs.second, &buffer[packsize( rhs.first )] );
} }
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void unpack( std::pair<TYPE1,TYPE2>& data, const char *buffer ) void unpack( std::pair<TYPE1, TYPE2> &data, const char *buffer )
{ {
unpack(data.first,buffer); unpack( data.first, buffer );
unpack(data.second,&buffer[packsize(data.first)]); unpack( data.second, &buffer[packsize( data.first )] );
} }
/******************************************************** /********************************************************
* Default instantiations for std::map * * Default instantiations for std::map *
********************************************************/ ********************************************************/
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
size_t packsize( const std::map<TYPE1,TYPE2>& rhs ) size_t packsize( const std::map<TYPE1, TYPE2> &rhs )
{ {
size_t bytes = sizeof(size_t); size_t bytes = sizeof( size_t );
typename std::map<TYPE1,TYPE2>::const_iterator it; typename std::map<TYPE1, TYPE2>::const_iterator it;
for (it=rhs.begin(); it!=rhs.end(); ++it) { for ( it = rhs.begin(); it != rhs.end(); ++it ) {
bytes += packsize(it->first); bytes += packsize( it->first );
bytes += packsize(it->second); bytes += packsize( it->second );
} }
return bytes; return bytes;
} }
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void pack( const std::map<TYPE1,TYPE2>& rhs, char *buffer ) void pack( const std::map<TYPE1, TYPE2> &rhs, char *buffer )
{ {
size_t N = rhs.size(); size_t N = rhs.size();
pack(N,buffer); pack( N, buffer );
size_t pos = sizeof(size_t); size_t pos = sizeof( size_t );
typename std::map<TYPE1,TYPE2>::const_iterator it; typename std::map<TYPE1, TYPE2>::const_iterator it;
for (it=rhs.begin(); it!=rhs.end(); ++it) { for ( it = rhs.begin(); it != rhs.end(); ++it ) {
pack(it->first,&buffer[pos]); pos+=packsize(it->first); pack( it->first, &buffer[pos] );
pack(it->second,&buffer[pos]); pos+=packsize(it->second); pos += packsize( it->first );
pack( it->second, &buffer[pos] );
pos += packsize( it->second );
} }
} }
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
void unpack( std::map<TYPE1,TYPE2>& data, const char *buffer ) void unpack( std::map<TYPE1, TYPE2> &data, const char *buffer )
{ {
size_t N = 0; size_t N = 0;
unpack(N,buffer); unpack( N, buffer );
size_t pos = sizeof(size_t); size_t pos = sizeof( size_t );
data.clear(); data.clear();
for (size_t i=0; i<N; i++) { for ( size_t i = 0; i < N; i++ ) {
std::pair<TYPE1,TYPE2> tmp; std::pair<TYPE1, TYPE2> tmp;
unpack(tmp.first,&buffer[pos]); pos+=packsize(tmp.first); unpack( tmp.first, &buffer[pos] );
unpack(tmp.second,&buffer[pos]); pos+=packsize(tmp.second); pos += packsize( tmp.first );
data.insert(tmp); unpack( tmp.second, &buffer[pos] );
pos += packsize( tmp.second );
data.insert( tmp );
} }
} }
/******************************************************** /********************************************************
* Default instantiations for std::set * * Default instantiations for std::set *
********************************************************/ ********************************************************/
template<class TYPE> template<class TYPE>
size_t packsize( const std::set<TYPE>& rhs ) size_t packsize( const std::set<TYPE> &rhs )
{ {
size_t bytes = sizeof(size_t); size_t bytes = sizeof( size_t );
typename std::set<TYPE>::const_iterator it; typename std::set<TYPE>::const_iterator it;
for (it=rhs.begin(); it!=rhs.end(); ++it) { for ( it = rhs.begin(); it != rhs.end(); ++it ) {
bytes += packsize(*it); bytes += packsize( *it );
} }
return bytes; return bytes;
} }
template<class TYPE> template<class TYPE>
void pack( const std::set<TYPE>& rhs, char *buffer ) void pack( const std::set<TYPE> &rhs, char *buffer )
{ {
size_t N = rhs.size(); size_t N = rhs.size();
pack(N,buffer); pack( N, buffer );
size_t pos = sizeof(size_t); size_t pos = sizeof( size_t );
typename std::set<TYPE>::const_iterator it; typename std::set<TYPE>::const_iterator it;
for (it=rhs.begin(); it!=rhs.end(); ++it) { for ( it = rhs.begin(); it != rhs.end(); ++it ) {
pack(*it); pos+=packsize(*it); pack( *it );
pos += packsize( *it );
} }
} }
template<class TYPE> template<class TYPE>
void unpack( std::set<TYPE>& data, const char *buffer ) void unpack( std::set<TYPE> &data, const char *buffer )
{ {
size_t N = 0; size_t N = 0;
unpack(N,buffer); unpack( N, buffer );
size_t pos = sizeof(size_t); size_t pos = sizeof( size_t );
data.clear(); data.clear();
for (size_t i=0; i<N; i++) { for ( size_t i = 0; i < N; i++ ) {
TYPE tmp; TYPE tmp;
unpack(tmp,&buffer[pos]); pos+=packsize(tmp); unpack( tmp, &buffer[pos] );
data.insert(tmp); pos += packsize( tmp );
data.insert( tmp );
} }
} }
#endif #endif

View File

@@ -1,7 +1,7 @@
#include "IO/Reader.h" #include "IO/Reader.h"
#include "IO/IOHelpers.h"
#include "IO/Mesh.h" #include "IO/Mesh.h"
#include "IO/MeshDatabase.h" #include "IO/MeshDatabase.h"
#include "IO/IOHelpers.h"
#include "common/Utilities.h" #include "common/Utilities.h"
#ifdef USE_SILO #ifdef USE_SILO
@@ -10,92 +10,139 @@
#include <ProfilerApp.h> #include <ProfilerApp.h>
#include <cstdio>
#include <fstream>
#include <iostream> #include <iostream>
#include <map>
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include <map>
#include <cstdio>
// Inline function to read line without a return argument // Inline function to read line without a return argument
static inline void fgetl( char * str, int num, FILE * stream ) static inline void fgetl( char *str, int num, FILE *stream )
{ {
char* ptr = fgets( str, num, stream ); char *ptr = fgets( str, num, stream );
if ( 0 ) {char *temp = (char *)&ptr; temp++;} if ( 0 ) {
char *temp = (char *) &ptr;
temp++;
}
}
// Check if the file exists
bool fileExists( const std::string &filename )
{
std::ifstream ifile( filename.c_str() );
return ifile.good();
} }
// Get the path to a file // Get the path to a file
std::string IO::getPath( const std::string& filename ) std::string IO::getPath( const std::string &filename )
{ {
std::string file(filename); std::string file( filename );
size_t k1 = file.rfind(47); size_t k1 = file.rfind( 47 );
size_t k2 = file.rfind(92); size_t k2 = file.rfind( 92 );
if ( k1==std::string::npos ) { k1=0; } if ( k1 == std::string::npos ) {
if ( k2==std::string::npos ) { k2=0; } k1 = 0;
return file.substr(0,std::max(k1,k2)); }
if ( k2 == std::string::npos ) {
k2 = 0;
}
return file.substr( 0, std::max( k1, k2 ) );
} }
// List the timesteps in the given directory (dumps.LBPM) // List the timesteps in the given directory (dumps.LBPM)
std::vector<std::string> IO::readTimesteps( const std::string& path, const std::string& format ) std::vector<std::string> IO::readTimesteps( const std::string &path, const std::string &format )
{ {
// Get the name of the summary filename // Get the name of the summary filename
std::string filename = path + "/"; std::string filename = path + "/";
if ( format=="old" || format=="new" ) if ( format == "old" || format == "new" ) {
filename += "summary.LBM"; filename += "summary.LBM";
else if ( format=="silo" ) } else if ( format == "silo" ) {
filename += "LBM.visit"; filename += "LBM.visit";
else } else if ( format == "auto" ) {
bool test_old = fileExists( path + "/summary.LBM" );
bool test_silo = fileExists( path + "/LBM.visit" );
if ( test_old && test_silo ) {
ERROR( "Unable to determine format (both summary.LBM and LBM.visit exist)" );
} else if ( test_old ) {
filename += "summary.LBM";
} else if ( test_silo ) {
filename += "LBM.visit";
} else {
ERROR( "Unable to determine format (neither summary.LBM or LBM.visit exist)" );
}
} else {
ERROR( "Unknown format: " + format ); ERROR( "Unknown format: " + format );
PROFILE_START("readTimesteps"); }
PROFILE_START( "readTimesteps" );
// Read the data // Read the data
FILE *fid= fopen(filename.c_str(),"rb"); FILE *fid = fopen( filename.c_str(), "rb" );
if ( fid==NULL ) if ( fid == NULL )
ERROR("Error opening file"); ERROR( "Error opening file" );
std::vector<std::string> timesteps; std::vector<std::string> timesteps;
char buf[1000]; char buf[1000];
while (fgets(buf,sizeof(buf),fid) != NULL) { while ( fgets( buf, sizeof( buf ), fid ) != NULL ) {
std::string line(buf); std::string line( buf );
line.resize(line.size()-1); line.resize( line.size() - 1 );
auto pos = line.find( "summary.silo" ); auto pos = line.find( "summary.silo" );
if ( pos != std::string::npos ) if ( pos != std::string::npos )
line.resize(pos); line.resize( pos );
if ( line.empty() ) if ( line.empty() )
continue; continue;
timesteps.push_back(line); timesteps.push_back( line );
} }
fclose(fid); fclose( fid );
PROFILE_STOP("readTimesteps"); PROFILE_STOP( "readTimesteps" );
return timesteps; return timesteps;
return timesteps; return timesteps;
} }
// Get the maximum number of domains
int IO::maxDomains( const std::string &path, const std::string &format, const Utilities::MPI &comm )
{
int rank = comm.getRank();
int n_domains = 0;
if ( rank == 0 ) {
// Get the timesteps
auto timesteps = IO::readTimesteps( path, format );
ASSERT( !timesteps.empty() );
// Get the database for the first domain
auto db = IO::getMeshList( path, timesteps[0] );
for ( size_t i = 0; i < db.size(); i++ )
n_domains = std::max<int>( n_domains, db[i].domains.size() );
}
return comm.bcast( n_domains, 0 );
}
// Read the data for the given timestep // Read the data for the given timestep
std::vector<IO::MeshDataStruct> IO::readData( const std::string& path, const std::string& timestep, const Utilities::MPI &comm ) std::vector<IO::MeshDataStruct> IO::readData(
const std::string &path, const std::string &timestep, int rank )
{ {
// Get the mesh databases // Get the mesh databases
auto db = IO::getMeshList( path, timestep ); auto db = IO::getMeshList( path, timestep );
// Create the data // Create the data
std::vector<IO::MeshDataStruct> data( db .size() ); std::vector<IO::MeshDataStruct> data( db.size() );
for ( size_t i=0; i<data.size(); i++ ) { for ( size_t i = 0; i < data.size(); i++ ) {
ASSERT( (int) db [i].domains.size() == comm.getSize() );
int domain = comm.getRank();
data[i].precision = IO::DataType::Double; data[i].precision = IO::DataType::Double;
data[i].meshName = db [i].name; data[i].meshName = db[i].name;
data[i].mesh = getMesh( path, timestep, db [i], domain ); data[i].mesh = getMesh( path, timestep, db[i], rank );
data[i].vars.resize( db[i].variables.size() ); data[i].vars.resize( db[i].variables.size() );
for ( size_t j=0; j<db[i].variables.size(); j++ ) for ( size_t j = 0; j < db[i].variables.size(); j++ )
data[i].vars[j] = getVariable( path, timestep, db[i], domain, db[i].variables[j].name ); data[i].vars[j] = getVariable( path, timestep, db[i], rank, db[i].variables[j].name );
data[i].check(); INSIST( data[i].check(), "Failed check of " + data[i].meshName );
} }
return data; return data;
} }
// Read the list of variables for the given timestep // Read the list of variables for the given timestep
std::vector<IO::MeshDatabase> IO::getMeshList( const std::string& path, const std::string& timestep ) std::vector<IO::MeshDatabase> IO::getMeshList(
const std::string &path, const std::string &timestep )
{ {
std::string filename = path + "/" + timestep + "/LBM.summary"; std::string filename = path + "/" + timestep + "/LBM.summary";
return IO::read( filename ); return IO::read( filename );
@@ -103,270 +150,271 @@ std::vector<IO::MeshDatabase> IO::getMeshList( const std::string& path, const st
// Read the given mesh domain // Read the given mesh domain
std::shared_ptr<IO::Mesh> IO::getMesh( const std::string& path, const std::string& timestep, std::shared_ptr<IO::Mesh> IO::getMesh( const std::string &path, const std::string &timestep,
const IO::MeshDatabase& meshDatabase, int domain ) const IO::MeshDatabase &meshDatabase, int domain )
{ {
PROFILE_START("getMesh"); PROFILE_START( "getMesh" );
std::shared_ptr<IO::Mesh> mesh; std::shared_ptr<IO::Mesh> mesh;
if ( meshDatabase.format==1 ) { if ( meshDatabase.format == 1 ) {
// Old format (binary doubles) // Old format (binary doubles)
std::string filename = path + "/" + timestep + "/" + meshDatabase.domains[domain].file; std::string filename = path + "/" + timestep + "/" + meshDatabase.domains[domain].file;
FILE *fid = fopen(filename.c_str(),"rb"); FILE *fid = fopen( filename.c_str(), "rb" );
INSIST(fid!=NULL,"Error opening file"); INSIST( fid != NULL, "Error opening file" );
fseek( fid, 0, SEEK_END ); fseek( fid, 0, SEEK_END );
size_t bytes = ftell(fid); size_t bytes = ftell( fid );
size_t N_max = bytes/sizeof(double)+1000; size_t N_max = bytes / sizeof( double ) + 1000;
double *data = new double[N_max]; double *data = new double[N_max];
fseek(fid,0,SEEK_SET); fseek( fid, 0, SEEK_SET );
size_t count = fread(data,sizeof(double),N_max,fid); size_t count = fread( data, sizeof( double ), N_max, fid );
fclose(fid); fclose( fid );
if ( count%3 != 0 ) if ( count % 3 != 0 )
ERROR("Error reading file"); ERROR( "Error reading file" );
if ( meshDatabase.type==IO::PointMesh ) { if ( meshDatabase.type == IO::MeshType::PointMesh ) {
size_t N = count/3; size_t N = count / 3;
std::shared_ptr<PointList> pointlist( new PointList(N) ); std::shared_ptr<PointList> pointlist( new PointList( N ) );
std::vector<Point>& P = pointlist->points; std::vector<Point> &P = pointlist->points;
for (size_t i=0; i<N; i++) { for ( size_t i = 0; i < N; i++ ) {
P[i].x = data[3*i+0]; P[i].x = data[3 * i + 0];
P[i].y = data[3*i+1]; P[i].y = data[3 * i + 1];
P[i].z = data[3*i+2]; P[i].z = data[3 * i + 2];
} }
mesh = pointlist; mesh = pointlist;
} else if ( meshDatabase.type==IO::SurfaceMesh ) { } else if ( meshDatabase.type == IO::MeshType::SurfaceMesh ) {
if ( count%9 != 0 ) if ( count % 9 != 0 )
ERROR("Error reading file (2)"); ERROR( "Error reading file (2)" );
size_t N_tri = count/9; size_t N_tri = count / 9;
std::shared_ptr<TriList> trilist( new TriList(N_tri) ); std::shared_ptr<TriList> trilist( new TriList( N_tri ) );
std::vector<Point>& A = trilist->A; std::vector<Point> &A = trilist->A;
std::vector<Point>& B = trilist->B; std::vector<Point> &B = trilist->B;
std::vector<Point>& C = trilist->C; std::vector<Point> &C = trilist->C;
for (size_t i=0; i<N_tri; i++) { for ( size_t i = 0; i < N_tri; i++ ) {
A[i].x = data[9*i+0]; A[i].x = data[9 * i + 0];
A[i].y = data[9*i+1]; A[i].y = data[9 * i + 1];
A[i].z = data[9*i+2]; A[i].z = data[9 * i + 2];
B[i].x = data[9*i+3]; B[i].x = data[9 * i + 3];
B[i].y = data[9*i+4]; B[i].y = data[9 * i + 4];
B[i].z = data[9*i+5]; B[i].z = data[9 * i + 5];
C[i].x = data[9*i+6]; C[i].x = data[9 * i + 6];
C[i].y = data[9*i+7]; C[i].y = data[9 * i + 7];
C[i].z = data[9*i+8]; C[i].z = data[9 * i + 8];
} }
mesh = trilist; mesh = trilist;
} else if ( meshDatabase.type==IO::VolumeMesh ) { } else if ( meshDatabase.type == IO::MeshType::VolumeMesh ) {
// this was never supported in the old format // this was never supported in the old format
mesh = std::shared_ptr<DomainMesh>( new DomainMesh() ); mesh = std::shared_ptr<DomainMesh>( new DomainMesh() );
} else { } else {
ERROR("Unknown mesh type"); ERROR( "Unknown mesh type" );
} }
delete [] data; delete[] data;
} else if ( meshDatabase.format==2 ) { } else if ( meshDatabase.format == 2 ) {
const DatabaseEntry& database = meshDatabase.domains[domain]; const DatabaseEntry &database = meshDatabase.domains[domain];
std::string filename = path + "/" + timestep + "/" + database.file; std::string filename = path + "/" + timestep + "/" + database.file;
FILE *fid = fopen(filename.c_str(),"rb"); FILE *fid = fopen( filename.c_str(), "rb" );
fseek(fid,database.offset,SEEK_SET); fseek( fid, database.offset, SEEK_SET );
char line[1000]; char line[1000];
fgetl(line,1000,fid); fgetl( line, 1000, fid );
size_t i1 = find(line,':'); size_t i1 = find( line, ':' );
size_t i2 = find(&line[i1+1],':')+i1+1; size_t i2 = find( &line[i1 + 1], ':' ) + i1 + 1;
size_t bytes = atol(&line[i2+1]); size_t bytes = atol( &line[i2 + 1] );
char *data = new char[bytes]; char *data = new char[bytes];
size_t count = fread(data,1,bytes,fid); size_t count = fread( data, 1, bytes, fid );
fclose(fid); fclose( fid );
ASSERT(count==bytes); ASSERT( count == bytes );
if ( meshDatabase.meshClass=="PointList" ) { if ( meshDatabase.meshClass == "PointList" ) {
mesh.reset( new IO::PointList() ); mesh.reset( new IO::PointList() );
} else if ( meshDatabase.meshClass=="TriMesh" ) { } else if ( meshDatabase.meshClass == "TriMesh" ) {
mesh.reset( new IO::TriMesh() ); mesh.reset( new IO::TriMesh() );
} else if ( meshDatabase.meshClass=="TriList" ) { } else if ( meshDatabase.meshClass == "TriList" ) {
mesh.reset( new IO::TriList() ); mesh.reset( new IO::TriList() );
} else if ( meshDatabase.meshClass=="DomainMesh" ) { } else if ( meshDatabase.meshClass == "DomainMesh" ) {
mesh.reset( new IO::DomainMesh() ); mesh.reset( new IO::DomainMesh() );
} else { } else {
ERROR("Unknown mesh class"); ERROR( "Unknown mesh class" );
} }
mesh->unpack( std::pair<size_t,void*>(bytes,data) ); mesh->unpack( std::pair<size_t, void *>( bytes, data ) );
delete [] data; delete[] data;
} else if ( meshDatabase.format==4 ) { } else if ( meshDatabase.format == 4 ) {
// Reading a silo file // Reading a silo file
#ifdef USE_SILO #ifdef USE_SILO
const DatabaseEntry& database = meshDatabase.domains[domain]; const DatabaseEntry &database = meshDatabase.domains[domain];
std::string filename = path + "/" + timestep + "/" + database.file; std::string filename = path + "/" + timestep + "/" + database.file;
auto fid = silo::open( filename, silo::READ ); auto fid = silo::open( filename, silo::READ );
if ( meshDatabase.meshClass=="PointList" ) { if ( meshDatabase.meshClass == "PointList" ) {
Array<double> coords = silo::readPointMesh<double>( fid, database.name ); Array<double> coords = silo::readPointMesh<double>( fid, database.name );
ASSERT(coords.size(1)==3); ASSERT( coords.size( 1 ) == 3 );
std::shared_ptr<IO::PointList> mesh2( new IO::PointList( coords.size(0) ) ); std::shared_ptr<IO::PointList> mesh2( new IO::PointList( coords.size( 0 ) ) );
for (size_t i=0; i<coords.size(1); i++) { for ( size_t i = 0; i < coords.size( 1 ); i++ ) {
mesh2->points[i].x = coords(i,0); mesh2->points[i].x = coords( i, 0 );
mesh2->points[i].y = coords(i,1); mesh2->points[i].y = coords( i, 1 );
mesh2->points[i].z = coords(i,2); mesh2->points[i].z = coords( i, 2 );
} }
mesh = mesh2; mesh = mesh2;
} else if ( meshDatabase.meshClass=="TriMesh" || meshDatabase.meshClass=="TriList" ) { } else if ( meshDatabase.meshClass == "TriMesh" || meshDatabase.meshClass == "TriList" ) {
Array<double> coords; Array<double> coords;
Array<int> tri; Array<int> tri;
silo::readTriMesh( fid, database.name, coords, tri ); silo::readTriMesh( fid, database.name, coords, tri );
ASSERT( tri.size(1)==3 && coords.size(1)==3 ); ASSERT( tri.size( 1 ) == 3 && coords.size( 1 ) == 3 );
int N_tri = tri.size(0); int N_tri = tri.size( 0 );
int N_point = coords.size(0); int N_point = coords.size( 0 );
std::shared_ptr<IO::TriMesh> mesh2( new IO::TriMesh( N_tri, N_point ) ); std::shared_ptr<IO::TriMesh> mesh2( new IO::TriMesh( N_tri, N_point ) );
for (int i=0; i<N_point; i++) { for ( int i = 0; i < N_point; i++ ) {
mesh2->vertices->points[i].x = coords(i,0); mesh2->vertices->points[i].x = coords( i, 0 );
mesh2->vertices->points[i].y = coords(i,1); mesh2->vertices->points[i].y = coords( i, 1 );
mesh2->vertices->points[i].z = coords(i,2); mesh2->vertices->points[i].z = coords( i, 2 );
} }
for (int i=0; i<N_tri; i++) { for ( int i = 0; i < N_tri; i++ ) {
mesh2->A[i] = tri(i,0); mesh2->A[i] = tri( i, 0 );
mesh2->B[i] = tri(i,1); mesh2->B[i] = tri( i, 1 );
mesh2->C[i] = tri(i,2); mesh2->C[i] = tri( i, 2 );
} }
if ( meshDatabase.meshClass=="TriMesh" ) { if ( meshDatabase.meshClass == "TriMesh" ) {
mesh = mesh2; mesh = mesh2;
} else if ( meshDatabase.meshClass=="TriList" ) { } else if ( meshDatabase.meshClass == "TriList" ) {
auto trilist = IO::getTriList( std::dynamic_pointer_cast<IO::Mesh>( mesh2 ) ); auto trilist = IO::getTriList( std::dynamic_pointer_cast<IO::Mesh>( mesh2 ) );
mesh = trilist; mesh = trilist;
} }
} else if ( meshDatabase.meshClass=="DomainMesh" ) { } else if ( meshDatabase.meshClass == "DomainMesh" ) {
std::vector<double> range; std::vector<double> range;
std::vector<int> N; std::vector<int> N;
silo::readUniformMesh( fid, database.name, range, N ); silo::readUniformMesh( fid, database.name, range, N );
auto rankinfo = silo::read<int>( fid, database.name+"_rankinfo" ); auto rankinfo = silo::read<int>( fid, database.name + "_rankinfo" );
RankInfoStruct rank_data( rankinfo[0], rankinfo[1], rankinfo[2], rankinfo[3] ); RankInfoStruct rank_data( rankinfo[0], rankinfo[1], rankinfo[2], rankinfo[3] );
mesh.reset( new IO::DomainMesh( rank_data, N[0], N[1], N[2], range[1]-range[0], range[3]-range[2], range[5]-range[4] ) ); mesh.reset( new IO::DomainMesh( rank_data, N[0], N[1], N[2], range[1] - range[0],
range[3] - range[2], range[5] - range[4] ) );
} else { } else {
ERROR("Unknown mesh class"); ERROR( "Unknown mesh class" );
} }
silo::close( fid ); silo::close( fid );
#else #else
ERROR("Build without silo support"); ERROR( "Build without silo support" );
#endif #endif
} else { } else {
ERROR("Unknown format"); ERROR( "Unknown format" );
} }
PROFILE_STOP("getMesh"); PROFILE_STOP( "getMesh" );
return mesh; return mesh;
} }
// Read the given variable for the given mesh domain // Read the given variable for the given mesh domain
std::shared_ptr<IO::Variable> IO::getVariable( const std::string& path, const std::string& timestep, std::shared_ptr<IO::Variable> IO::getVariable( const std::string &path, const std::string &timestep,
const MeshDatabase& meshDatabase, int domain, const std::string& variable ) const MeshDatabase &meshDatabase, int domain, const std::string &variable )
{ {
std::pair<std::string,std::string> key(meshDatabase.domains[domain].name,variable); std::pair<std::string, std::string> key( meshDatabase.domains[domain].name, variable );
std::map<std::pair<std::string,std::string>,DatabaseEntry>::const_iterator it; std::map<std::pair<std::string, std::string>, DatabaseEntry>::const_iterator it;
it = meshDatabase.variable_data.find(key); it = meshDatabase.variable_data.find( key );
if ( it==meshDatabase.variable_data.end() ) if ( it == meshDatabase.variable_data.end() )
return std::shared_ptr<IO::Variable>(); return std::shared_ptr<IO::Variable>();
std::shared_ptr<IO::Variable> var; std::shared_ptr<IO::Variable> var;
if ( meshDatabase.format == 2 ) { if ( meshDatabase.format == 2 ) {
const DatabaseEntry& database = it->second; const DatabaseEntry &database = it->second;
std::string filename = path + "/" + timestep + "/" + database.file; std::string filename = path + "/" + timestep + "/" + database.file;
FILE *fid = fopen(filename.c_str(),"rb"); FILE *fid = fopen( filename.c_str(), "rb" );
fseek(fid,database.offset,SEEK_SET); fseek( fid, database.offset, SEEK_SET );
char line[1000]; char line[1000];
fgetl(line,1000,fid); fgetl( line, 1000, fid );
size_t i1 = find(line,':'); size_t i1 = find( line, ':' );
size_t i2 = find(&line[i1+1],':')+i1+1; size_t i2 = find( &line[i1 + 1], ':' ) + i1 + 1;
std::vector<std::string> values = splitList(&line[i2+1],','); std::vector<std::string> values = splitList( &line[i2 + 1], ',' );
ASSERT(values.size()==5); ASSERT( values.size() == 5 );
int dim = atoi(values[0].c_str()); int dim = atoi( values[0].c_str() );
int type = atoi(values[1].c_str()); int type = atoi( values[1].c_str() );
size_t N = atol(values[2].c_str()); size_t N = atol( values[2].c_str() );
size_t bytes = atol(values[3].c_str()); size_t bytes = atol( values[3].c_str() );
std::string precision = values[4]; std::string precision = values[4];
var = std::shared_ptr<IO::Variable>( new IO::Variable() ); var = std::shared_ptr<IO::Variable>( new IO::Variable() );
var->dim = dim; var->dim = dim;
var->type = static_cast<IO::VariableType>(type); var->type = static_cast<IO::VariableType>( type );
var->name = variable; var->name = variable;
var->data.resize(N*dim); var->data.resize( N, dim );
if ( precision=="double" ) { if ( precision == "double" ) {
size_t count = fread(var->data.data(),sizeof(double),N*dim,fid); size_t count = fread( var->data.data(), sizeof( double ), N * dim, fid );
ASSERT(count*sizeof(double)==bytes); ASSERT( count * sizeof( double ) == bytes );
} else { } else {
ERROR("Format not implimented"); ERROR( "Format not implimented" );
} }
fclose(fid); fclose( fid );
} else if ( meshDatabase.format == 4 ) { } else if ( meshDatabase.format == 4 ) {
// Reading a silo file // Reading a silo file
#ifdef USE_SILO #ifdef USE_SILO
const auto& database = meshDatabase.domains[domain]; const auto &database = meshDatabase.domains[domain];
auto variableDatabase = meshDatabase.getVariableDatabase( variable ); auto variableDatabase = meshDatabase.getVariableDatabase( variable );
std::string filename = path + "/" + timestep + "/" + database.file; std::string filename = path + "/" + timestep + "/" + database.file;
auto fid = silo::open( filename, silo::READ ); auto fid = silo::open( filename, silo::READ );
var.reset( new Variable( variableDatabase.dim, variableDatabase.type, variable ) ); var.reset( new Variable( variableDatabase.dim, variableDatabase.type, variable ) );
if ( meshDatabase.meshClass=="PointList" ) { if ( meshDatabase.meshClass == "PointList" ) {
var->data = silo::readPointMeshVariable<double>( fid, variable ); var->data = silo::readPointMeshVariable<double>( fid, variable );
} else if ( meshDatabase.meshClass=="TriMesh" || meshDatabase.meshClass=="TriList" ) { } else if ( meshDatabase.meshClass == "TriMesh" || meshDatabase.meshClass == "TriList" ) {
var->data = silo::readTriMeshVariable<double>( fid, variable ); var->data = silo::readTriMeshVariable<double>( fid, variable );
} else if ( meshDatabase.meshClass=="DomainMesh" ) { } else if ( meshDatabase.meshClass == "DomainMesh" ) {
var->data = silo::readUniformMeshVariable<double>( fid, variable ); var->data = silo::readUniformMeshVariable<double>( fid, variable );
} else { } else {
ERROR("Unknown mesh class"); ERROR( "Unknown mesh class" );
} }
silo::close( fid ); silo::close( fid );
#else #else
ERROR("Build without silo support"); ERROR( "Build without silo support" );
#endif #endif
} else { } else {
ERROR("Unknown format"); ERROR( "Unknown format" );
} }
return var; return var;
} }
/**************************************************** /****************************************************
* Reformat the variable to match the mesh * * Reformat the variable to match the mesh *
****************************************************/ ****************************************************/
void IO::reformatVariable( const IO::Mesh& mesh, IO::Variable& var ) void IO::reformatVariable( const IO::Mesh &mesh, IO::Variable &var )
{ {
if ( mesh.className() == "DomainMesh" ) { if ( mesh.className() == "DomainMesh" ) {
const IO::DomainMesh& mesh2 = dynamic_cast<const IO::DomainMesh&>( mesh ); const IO::DomainMesh &mesh2 = dynamic_cast<const IO::DomainMesh &>( mesh );
if ( var.type == VariableType::NodeVariable ) { if ( var.type == VariableType::NodeVariable ) {
size_t N2 = var.data.length() / ((mesh2.nx+1)*(mesh2.ny+1)*(mesh2.nz+1)); size_t N2 =
ASSERT( (mesh2.nx+1)*(mesh2.ny+1)*(mesh2.nz+1)*N2 == var.data.length() ); var.data.length() / ( ( mesh2.nx + 1 ) * ( mesh2.ny + 1 ) * ( mesh2.nz + 1 ) );
var.data.reshape( { (size_t) mesh2.nx+1, (size_t) mesh2.ny+1, (size_t) mesh2.nz+1, N2 } ); ASSERT(
( mesh2.nx + 1 ) * ( mesh2.ny + 1 ) * ( mesh2.nz + 1 ) * N2 == var.data.length() );
var.data.reshape(
{ (size_t) mesh2.nx + 1, (size_t) mesh2.ny + 1, (size_t) mesh2.nz + 1, N2 } );
} else if ( var.type == VariableType::EdgeVariable ) { } else if ( var.type == VariableType::EdgeVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var.type == VariableType::SurfaceVariable ) { } else if ( var.type == VariableType::SurfaceVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var.type == VariableType::VolumeVariable ) { } else if ( var.type == VariableType::VolumeVariable ) {
size_t N2 = var.data.length() / (mesh2.nx*mesh2.ny*mesh2.nz); size_t N2 = var.data.length() / ( mesh2.nx * mesh2.ny * mesh2.nz );
ASSERT( mesh2.nx*mesh2.ny*mesh2.nz*N2 == var.data.length() ); ASSERT( mesh2.nx * mesh2.ny * mesh2.nz * N2 == var.data.length() );
var.data.reshape( { (size_t) mesh2.nx, (size_t) mesh2.ny, (size_t) mesh2.nz, N2 } ); var.data.reshape( { (size_t) mesh2.nx, (size_t) mesh2.ny, (size_t) mesh2.nz, N2 } );
} else { } else {
ERROR("Invalid variable type"); ERROR( "Invalid variable type" );
} }
} else if ( mesh.className() == "PointList" ) { } else if ( mesh.className() == "PointList" ) {
const IO::PointList& mesh2 = dynamic_cast<const IO::PointList&>( mesh ); const IO::PointList &mesh2 = dynamic_cast<const IO::PointList &>( mesh );
size_t N = mesh2.points.size(); size_t N = mesh2.points.size();
size_t N_var = var.data.length()/N; size_t N_var = var.data.length() / N;
ASSERT( N*N_var == var.data.length() ); ASSERT( N * N_var == var.data.length() );
var.data.reshape( { N, N_var } ); var.data.reshape( { N, N_var } );
} else if ( mesh.className()=="TriMesh" || mesh.className() == "TriList" ) { } else if ( mesh.className() == "TriMesh" || mesh.className() == "TriList" ) {
std::shared_ptr<Mesh> mesh_ptr( const_cast<Mesh*>(&mesh), []( void* ) {} ); std::shared_ptr<Mesh> mesh_ptr( const_cast<Mesh *>( &mesh ), []( void * ) {} );
std::shared_ptr<TriMesh> mesh2 = getTriMesh( mesh_ptr ); std::shared_ptr<TriMesh> mesh2 = getTriMesh( mesh_ptr );
if ( var.type == VariableType::NodeVariable ) { if ( var.type == VariableType::NodeVariable ) {
size_t N = mesh2->vertices->points.size(); size_t N = mesh2->vertices->points.size();
size_t N_var = var.data.length()/N; size_t N_var = var.data.length() / N;
ASSERT( N*N_var == var.data.length() ); ASSERT( N * N_var == var.data.length() );
var.data.reshape( { N, N_var } ); var.data.reshape( { N, N_var } );
} else if ( var.type == VariableType::EdgeVariable ) { } else if ( var.type == VariableType::EdgeVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var.type == VariableType::SurfaceVariable ) { } else if ( var.type == VariableType::SurfaceVariable ) {
ERROR("Not finished"); ERROR( "Not finished" );
} else if ( var.type == VariableType::VolumeVariable ) { } else if ( var.type == VariableType::VolumeVariable ) {
size_t N = mesh2->A.size(); size_t N = mesh2->A.size();
size_t N_var = var.data.length()/N; size_t N_var = var.data.length() / N;
ASSERT( N*N_var == var.data.length() ); ASSERT( N * N_var == var.data.length() );
var.data.reshape( { N, N_var } ); var.data.reshape( { N, N_var } );
} else { } else {
ERROR("Invalid variable type"); ERROR( "Invalid variable type" );
} }
} else { } else {
ERROR("Unknown mesh type"); ERROR( "Unknown mesh type" );
} }
} }

View File

@@ -14,7 +14,24 @@ namespace IO {
//! Get the path to a file //! Get the path to a file
std::string getPath( const std::string& filename ); std::string getPath( const std::string &filename );
/*!
* @brief Get the maximum number of domains written
* @details This function reads the summary files to determine the maximum
* number of domains in the output.
* @param[in] path The path to use for reading
* @param[in] format The data format to use:
* old - Old mesh format (provided for backward compatibility)
* new - New format, 1 file/process
* silo - Silo
* auto - Auto-determin the format
* @param[in] comm Optional comm to use to reduce IO load by
* reading on rank 0 and then communicating the result
*/
int maxDomains( const std::string &path, const std::string &format = "auto",
const Utilities::MPI &comm = MPI_COMM_SELF );
/*! /*!
@@ -22,31 +39,34 @@ std::string getPath( const std::string& filename );
* @details This function reads the timestep list from the summary file. * @details This function reads the timestep list from the summary file.
* @param[in] path The path to use for reading * @param[in] path The path to use for reading
* @param[in] format The data format to use: * @param[in] format The data format to use:
* old - Old mesh format (provided for backward compatibility) * old - Old mesh format (provided for backward compatibility)
* new - New format, 1 file/process * new - New format, 1 file/process
* silo - Silo * silo - Silo
* @return append Append any existing data (default is false) * auto - Auto-determin the format
* @return append Append any existing data (default is false)
*/ */
std::vector<std::string> readTimesteps( const std::string& path, const std::string& format ); std::vector<std::string> readTimesteps(
const std::string &path, const std::string &format = "auto" );
/*! /*!
* @brief Read the data for the timestep * @brief Read the data for the timestep
* @details This function reads the mesh and variable data provided for the given timestep. * @details This function reads the mesh and variable data provided for the given timestep.
* Note: this function requires that the number of ranks of the comm match the number of ranks in the meshes
* @param[in] path The path to use for reading * @param[in] path The path to use for reading
* @param[in] timestep The timestep iteration * @param[in] timestep The timestep iteration
* @param[in] domain The desired domain to read
*/ */
std::vector<IO::MeshDataStruct> readData( const std::string& path, const std::string& timestep, const Utilities::MPI &comm = MPI_COMM_WORLD ); std::vector<IO::MeshDataStruct> readData(
const std::string &path, const std::string &timestep, int domain );
//! Read the list of mesh databases for the given timestep //! Read the list of mesh databases for the given timestep
std::vector<IO::MeshDatabase> getMeshList( const std::string& path, const std::string& timestep ); std::vector<IO::MeshDatabase> getMeshList( const std::string &path, const std::string &timestep );
//! Read the given mesh domain //! Read the given mesh domain
std::shared_ptr<IO::Mesh> getMesh( const std::string& path, const std::string& timestep, std::shared_ptr<IO::Mesh> getMesh( const std::string &path, const std::string &timestep,
const MeshDatabase& meshDatabase, int domain ); const MeshDatabase &meshDatabase, int domain );
/*! /*!
@@ -59,8 +79,8 @@ std::shared_ptr<IO::Mesh> getMesh( const std::string& path, const std::string& t
* @param[in] variable The variable name to read * @param[in] variable The variable name to read
* @return Returns the variable data as a linear array * @return Returns the variable data as a linear array
*/ */
std::shared_ptr<IO::Variable> getVariable( const std::string& path, const std::string& timestep, std::shared_ptr<IO::Variable> getVariable( const std::string &path, const std::string &timestep,
const MeshDatabase& meshDatabase, int domain, const std::string& variable ); const MeshDatabase &meshDatabase, int domain, const std::string &variable );
/*! /*!
@@ -69,9 +89,9 @@ std::shared_ptr<IO::Variable> getVariable( const std::string& path, const std::s
* @param[in] mesh The underlying mesh * @param[in] mesh The underlying mesh
* @param[in/out] variable The variable name to read * @param[in/out] variable The variable name to read
*/ */
void reformatVariable( const IO::Mesh& mesh, IO::Variable& var ); void reformatVariable( const IO::Mesh &mesh, IO::Variable &var );
} // IO namespace } // namespace IO
#endif #endif

View File

@@ -1,28 +1,69 @@
#include "IO/Writer.h" #include "IO/Writer.h"
#include "IO/MeshDatabase.h"
#include "IO/IOHelpers.h" #include "IO/IOHelpers.h"
#include "IO/MeshDatabase.h"
#include "IO/silo.h" #include "IO/silo.h"
#include "common/MPI.h" #include "common/MPI.h"
#include "common/Utilities.h" #include "common/Utilities.h"
#include <sys/stat.h>
#include <algorithm> #include <algorithm>
#include <vector>
#include <set>
#include <memory> #include <memory>
#include <set>
#include <sys/stat.h>
#include <vector>
enum class Format { OLD, NEW, SILO, UNKNOWN }; enum class Format { OLD, NEW, SILO, UNKNOWN };
/****************************************************
* Recursively create the subdirectory *
****************************************************/
static void recursiveMkdir( const std::string &path, mode_t mode )
{
// Iterate through the root directories until we create the desired path
for ( size_t pos = 0; pos < path.size(); ) {
// slide backwards in string until next slash found
pos++;
for ( ; pos < path.size(); pos++ ) {
if ( path[pos] == '/' || path[pos] == 92 )
break;
}
// Create the temporary path
auto path2 = path.substr( 0, pos );
// Check if the temporary path exists
struct stat status;
int result = stat( path2.data(), &status );
if ( result == 0 ) {
// if there is a part of the path that already exists make sure it is really a directory
if ( !S_ISDIR( status.st_mode ) ) {
ERROR(
"Error in recursiveMkdir...\n"
" Cannot create directories in path = " +
path +
"\n because some intermediate item in path exists and is NOT a directory" );
}
continue;
}
// Create the directory and test the result
result = mkdir( path2.data(), mode );
if ( result != 0 ) {
// Maybe another rank created the directory, check
int result = stat( path2.data(), &status );
if ( result != 0 && !S_ISDIR( status.st_mode ) )
ERROR( "Error in Utilities::recursiveMkdir...\n"
" Cannot create directory = " +
path2 );
}
}
}
/**************************************************** /****************************************************
* Initialize the writer * * Initialize the writer *
****************************************************/ ****************************************************/
static std::string global_IO_path; static std::string global_IO_path;
static Format global_IO_format = Format::UNKNOWN; static Format global_IO_format = Format::UNKNOWN;
void IO::initialize( const std::string& path, const std::string& format, bool append ) void IO::initialize( const std::string &path, const std::string &format, bool append )
{ {
if ( path.empty() ) if ( path.empty() )
global_IO_path = "."; global_IO_path = ".";
@@ -35,161 +76,170 @@ void IO::initialize( const std::string& path, const std::string& format, bool ap
else if ( format == "silo" ) else if ( format == "silo" )
global_IO_format = Format::SILO; global_IO_format = Format::SILO;
else else
ERROR("Unknown format"); ERROR( "Unknown format" );
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank(); int rank = Utilities::MPI( MPI_COMM_WORLD ).getRank();
if ( !append && rank==0 ) { if ( !append && rank == 0 ) {
mkdir(path.c_str(),S_IRWXU|S_IRGRP); recursiveMkdir( path, S_IRWXU | S_IRGRP );
std::string filename; std::string filename;
if ( global_IO_format==Format::OLD || global_IO_format==Format::NEW ) if ( global_IO_format == Format::OLD || global_IO_format == Format::NEW )
filename = global_IO_path + "/summary.LBM"; filename = global_IO_path + "/summary.LBM";
else if ( global_IO_format==Format::SILO ) else if ( global_IO_format == Format::SILO )
filename = global_IO_path + "/LBM.visit"; filename = global_IO_path + "/LBM.visit";
else else
ERROR("Unknown format"); ERROR( "Unknown format" );
auto fid = fopen(filename.c_str(),"wb"); auto fid = fopen( filename.c_str(), "wb" );
fclose(fid); fclose( fid );
} }
} }
// Write the mesh data in the original format // Write the mesh data in the original format
static std::vector<IO::MeshDatabase> writeMeshesOrigFormat( const std::vector<IO::MeshDataStruct>& meshData, const std::string& path ) static std::vector<IO::MeshDatabase> writeMeshesOrigFormat(
const std::vector<IO::MeshDataStruct> &meshData, const std::string &path, int rank )
{ {
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank();
std::vector<IO::MeshDatabase> meshes_written; std::vector<IO::MeshDatabase> meshes_written;
for (size_t i=0; i<meshData.size(); i++) { for ( size_t i = 0; i < meshData.size(); i++ ) {
char domainname[100], filename[100], fullpath[200]; char domainname[100], filename[100], fullpath[200];
sprintf(domainname,"%05i",rank); sprintf( domainname, "%05i", rank );
sprintf(filename,"%s.%05i",meshData[i].meshName.c_str(),rank); sprintf( filename, "%s.%05i", meshData[i].meshName.c_str(), rank );
sprintf(fullpath,"%s/%s",path.c_str(),filename); sprintf( fullpath, "%s/%s", path.c_str(), filename );
FILE *fid = fopen(fullpath,"wb"); FILE *fid = fopen( fullpath, "wb" );
INSIST(fid!=NULL,std::string("Error opening file: ")+fullpath); INSIST( fid != NULL, std::string( "Error opening file: " ) + fullpath );
std::shared_ptr<IO::Mesh> mesh = meshData[i].mesh; std::shared_ptr<IO::Mesh> mesh = meshData[i].mesh;
IO::MeshDatabase mesh_entry; IO::MeshDatabase mesh_entry;
mesh_entry.name = meshData[i].meshName; mesh_entry.name = meshData[i].meshName;
mesh_entry.type = meshType(*mesh); mesh_entry.type = meshType( *mesh );
mesh_entry.meshClass = meshData[i].mesh->className(); mesh_entry.meshClass = meshData[i].mesh->className();
mesh_entry.format = 1; mesh_entry.format = 1;
IO::DatabaseEntry domain; IO::DatabaseEntry domain;
domain.name = domainname; domain.name = domainname;
domain.file = filename; domain.file = filename;
domain.offset = 0; domain.offset = 0;
mesh_entry.domains.push_back(domain); mesh_entry.domains.push_back( domain );
if ( !meshData[i].vars.empty() ) { if ( !meshData[i].vars.empty() ) {
printf("Warning: variables are not supported with this format (original)\n"); printf( "Warning: variables are not supported with this format (original)\n" );
//for (size_t j=0; j<meshData[i].vars.size(); j++) // for (size_t j=0; j<meshData[i].vars.size(); j++)
// mesh_entry.variables.push_back( meshData[i].vars[j]->name ); // mesh_entry.variables.push_back( meshData[i].vars[j]->name );
} }
const std::string meshClass = mesh->className(); const std::string meshClass = mesh->className();
if ( meshClass=="PointList" ) { if ( meshClass == "PointList" ) {
// List of points // List of points
std::shared_ptr<IO::PointList> pointlist = std::dynamic_pointer_cast<IO::PointList>(mesh); std::shared_ptr<IO::PointList> pointlist =
const std::vector<Point>& P = pointlist->points; std::dynamic_pointer_cast<IO::PointList>( mesh );
for (size_t i=0; i<P.size(); i++) { const std::vector<Point> &P = pointlist->points;
for ( size_t i = 0; i < P.size(); i++ ) {
double x[3]; double x[3];
x[0] = P[i].x; x[1] = P[i].y; x[2] = P[i].z; x[0] = P[i].x;
fwrite(x,sizeof(double),3,fid); x[1] = P[i].y;
x[2] = P[i].z;
fwrite( x, sizeof( double ), 3, fid );
} }
} else if ( meshClass=="TriList" || meshClass=="TriMesh" ) { } else if ( meshClass == "TriList" || meshClass == "TriMesh" ) {
// Triangle mesh // Triangle mesh
std::shared_ptr<IO::TriList> trilist = IO::getTriList(mesh); std::shared_ptr<IO::TriList> trilist = IO::getTriList( mesh );
const std::vector<Point>& A = trilist->A; const std::vector<Point> &A = trilist->A;
const std::vector<Point>& B = trilist->B; const std::vector<Point> &B = trilist->B;
const std::vector<Point>& C = trilist->C; const std::vector<Point> &C = trilist->C;
for (size_t i=0; i<A.size(); i++) { for ( size_t i = 0; i < A.size(); i++ ) {
double tri[9]; double tri[9];
tri[0] = A[i].x; tri[1] = A[i].y; tri[2] = A[i].z; tri[0] = A[i].x;
tri[3] = B[i].x; tri[4] = B[i].y; tri[5] = B[i].z; tri[1] = A[i].y;
tri[6] = C[i].x; tri[7] = C[i].y; tri[8] = C[i].z; tri[2] = A[i].z;
fwrite(tri,sizeof(double),9,fid); tri[3] = B[i].x;
tri[4] = B[i].y;
tri[5] = B[i].z;
tri[6] = C[i].x;
tri[7] = C[i].y;
tri[8] = C[i].z;
fwrite( tri, sizeof( double ), 9, fid );
} }
} else if ( meshClass=="DomainMesh" ) { } else if ( meshClass == "DomainMesh" ) {
// This format was never supported with the old format // This format was never supported with the old format
} else { } else {
ERROR("Unknown mesh"); ERROR( "Unknown mesh" );
} }
fclose(fid); fclose( fid );
std::sort( mesh_entry.variables.begin(), mesh_entry.variables.end() ); std::sort( mesh_entry.variables.begin(), mesh_entry.variables.end() );
mesh_entry.variables.erase( std::unique( mesh_entry.variables.begin(), mesh_entry.variables.end() ), mesh_entry.variables.end() ); mesh_entry.variables.erase(
meshes_written.push_back(mesh_entry); std::unique( mesh_entry.variables.begin(), mesh_entry.variables.end() ),
mesh_entry.variables.end() );
meshes_written.push_back( mesh_entry );
} }
return meshes_written; return meshes_written;
} }
// Create the database entry for the mesh data // Create the database entry for the mesh data
static IO::MeshDatabase getDatabase( const std::string& filename, const IO::MeshDataStruct& mesh, int format ) static IO::MeshDatabase getDatabase(
const std::string &filename, const IO::MeshDataStruct &mesh, int format, int rank )
{ {
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank();
char domainname[100]; char domainname[100];
sprintf(domainname,"%s_%05i",mesh.meshName.c_str(),rank); sprintf( domainname, "%s_%05i", mesh.meshName.c_str(), rank );
// Create the MeshDatabase // Create the MeshDatabase
IO::MeshDatabase database; IO::MeshDatabase database;
database.name = mesh.meshName; database.name = mesh.meshName;
database.type = meshType(*(mesh.mesh)); database.type = meshType( *( mesh.mesh ) );
database.meshClass = mesh.mesh->className(); database.meshClass = mesh.mesh->className();
database.format = format; database.format = format;
// Write the mesh // Write the mesh
IO::DatabaseEntry domain; IO::DatabaseEntry domain;
domain.name = domainname; domain.name = domainname;
domain.file = filename; domain.file = filename;
domain.offset = -1; domain.offset = -1;
database.domains.push_back(domain); database.domains.push_back( domain );
// Write the variables // Write the variables
for (size_t i=0; i<mesh.vars.size(); i++) { for ( size_t i = 0; i < mesh.vars.size(); i++ ) {
// Add basic variable info // Add basic variable info
IO::VariableDatabase info; IO::VariableDatabase info;
info.name = mesh.vars[i]->name; info.name = mesh.vars[i]->name;
info.type = mesh.vars[i]->type; info.type = mesh.vars[i]->type;
info.dim = mesh.vars[i]->dim; info.dim = mesh.vars[i]->dim;
database.variables.push_back(info); database.variables.push_back( info );
// Add domain variable info // Add domain variable info
IO::DatabaseEntry variable; IO::DatabaseEntry variable;
variable.name = mesh.vars[i]->name; variable.name = mesh.vars[i]->name;
variable.file = filename; variable.file = filename;
variable.offset = -1; variable.offset = -1;
std::pair<std::string,std::string> key(domain.name,mesh.vars[i]->name); std::pair<std::string, std::string> key( domain.name, mesh.vars[i]->name );
database.variable_data.insert( database.variable_data.insert(
std::pair<std::pair<std::string,std::string>,IO::DatabaseEntry>(key,variable) ); std::pair<std::pair<std::string, std::string>, IO::DatabaseEntry>( key, variable ) );
} }
return database; return database;
} }
// Write a mesh (and variables) to a file // Write a mesh (and variables) to a file
static IO::MeshDatabase write_domain( FILE *fid, const std::string& filename, static IO::MeshDatabase write_domain(
const IO::MeshDataStruct& mesh, int format ) FILE *fid, const std::string &filename, const IO::MeshDataStruct &mesh, int format, int rank )
{ {
const int level = 0; const int level = 0;
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank();
// Create the MeshDatabase // Create the MeshDatabase
IO::MeshDatabase database = getDatabase( filename, mesh, format ); IO::MeshDatabase database = getDatabase( filename, mesh, format, rank );
// Write the mesh // Write the mesh
IO::DatabaseEntry& domain = database.domains[0]; IO::DatabaseEntry &domain = database.domains[0];
domain.offset = ftell(fid); domain.offset = ftell( fid );
std::pair<size_t,void*> data = mesh.mesh->pack(level); std::pair<size_t, void *> data = mesh.mesh->pack( level );
fprintf(fid,"Mesh: %s-%05i: %lu\n",mesh.meshName.c_str(),rank,data.first); fprintf( fid, "Mesh: %s-%05i: %lu\n", mesh.meshName.c_str(), rank, data.first );
fwrite(data.second,1,data.first,fid); fwrite( data.second, 1, data.first, fid );
fprintf(fid,"\n"); fprintf( fid, "\n" );
delete [] (char*) data.second; delete[]( char * ) data.second;
// Write the variables // Write the variables
for (size_t i=0; i<mesh.vars.size(); i++) { for ( size_t i = 0; i < mesh.vars.size(); i++ ) {
std::pair<std::string,std::string> key(domain.name,mesh.vars[i]->name); std::pair<std::string, std::string> key( domain.name, mesh.vars[i]->name );
IO::DatabaseEntry& variable = database.variable_data[key]; IO::DatabaseEntry &variable = database.variable_data[key];
variable.offset = ftell(fid); variable.offset = ftell( fid );
int dim = mesh.vars[i]->dim; int dim = mesh.vars[i]->dim;
int type = static_cast<int>(mesh.vars[i]->type); int type = static_cast<int>( mesh.vars[i]->type );
size_t N = mesh.vars[i]->data.length(); size_t N = mesh.vars[i]->data.length();
if ( type == static_cast<int>(IO::VariableType::NullVariable) ) { if ( type == static_cast<int>( IO::VariableType::NullVariable ) ) {
ERROR("Variable type not set"); ERROR( "Variable type not set" );
} }
size_t N_mesh = mesh.mesh->numberPointsVar(mesh.vars[i]->type); size_t N_mesh = mesh.mesh->numberPointsVar( mesh.vars[i]->type );
ASSERT(N==dim*N_mesh); ASSERT( N == dim * N_mesh );
fprintf(fid,"Var: %s-%05i-%s: %i, %i, %lu, %lu, double\n", fprintf( fid, "Var: %s-%05i-%s: %i, %i, %lu, %lu, double\n", database.name.c_str(), rank,
database.name.c_str(), rank, variable.name.c_str(), variable.name.c_str(), dim, type, N_mesh, N * sizeof( double ) );
dim, type, N_mesh, N*sizeof(double) ); fwrite( mesh.vars[i]->data.data(), sizeof( double ), N, fid );
fwrite(mesh.vars[i]->data.data(),sizeof(double),N,fid); fprintf( fid, "\n" );
fprintf(fid,"\n");
} }
return database; return database;
} }
@@ -198,11 +248,12 @@ static IO::MeshDatabase write_domain( FILE *fid, const std::string& filename,
#ifdef USE_SILO #ifdef USE_SILO
// Write a PointList mesh (and variables) to a file // Write a PointList mesh (and variables) to a file
template<class TYPE> template<class TYPE>
static void writeSiloPointMesh( DBfile *fid, const IO::PointList& mesh, const std::string& meshname ) static void writeSiloPointMesh(
DBfile *fid, const IO::PointList &mesh, const std::string &meshname )
{ {
const auto& points = mesh.getPoints(); const auto &points = mesh.getPoints();
std::vector<TYPE> x(points.size()), y(points.size()), z(points.size()); std::vector<TYPE> x( points.size() ), y( points.size() ), z( points.size() );
for (size_t i=0; i<x.size(); i++) { for ( size_t i = 0; i < x.size(); i++ ) {
x[i] = points[i].x; x[i] = points[i].x;
y[i] = points[i].y; y[i] = points[i].y;
z[i] = points[i].z; z[i] = points[i].z;
@@ -210,28 +261,29 @@ static void writeSiloPointMesh( DBfile *fid, const IO::PointList& mesh, const st
const TYPE *coords[] = { x.data(), y.data(), z.data() }; const TYPE *coords[] = { x.data(), y.data(), z.data() };
silo::writePointMesh<TYPE>( fid, meshname, 3, points.size(), coords ); silo::writePointMesh<TYPE>( fid, meshname, 3, points.size(), coords );
} }
static void writeSiloPointList( DBfile *fid, const IO::MeshDataStruct& meshData, IO::MeshDatabase database ) static void writeSiloPointList(
DBfile *fid, const IO::MeshDataStruct &meshData, IO::MeshDatabase database )
{ {
const IO::PointList& mesh = dynamic_cast<IO::PointList&>( *meshData.mesh ); const IO::PointList &mesh = dynamic_cast<IO::PointList &>( *meshData.mesh );
const std::string meshname = database.domains[0].name; const std::string meshname = database.domains[0].name;
if ( meshData.precision == IO::DataType::Double ) { if ( meshData.precision == IO::DataType::Double ) {
writeSiloPointMesh<double>( fid, mesh, meshname ); writeSiloPointMesh<double>( fid, mesh, meshname );
} else if ( meshData.precision == IO::DataType::Float ) { } else if ( meshData.precision == IO::DataType::Float ) {
writeSiloPointMesh<float>( fid, mesh, meshname ); writeSiloPointMesh<float>( fid, mesh, meshname );
} else { } else {
ERROR("Unsupported format"); ERROR( "Unsupported format" );
} }
const auto& points = mesh.getPoints(); const auto &points = mesh.getPoints();
std::vector<double> x(points.size()), y(points.size()), z(points.size()); std::vector<double> x( points.size() ), y( points.size() ), z( points.size() );
for (size_t i=0; i<x.size(); i++) { for ( size_t i = 0; i < x.size(); i++ ) {
x[i] = points[i].x; x[i] = points[i].x;
y[i] = points[i].y; y[i] = points[i].y;
z[i] = points[i].z; z[i] = points[i].z;
} }
const double *coords[] = { x.data(), y.data(), z.data() }; const double *coords[] = { x.data(), y.data(), z.data() };
silo::writePointMesh( fid, meshname, 3, points.size(), coords ); silo::writePointMesh( fid, meshname, 3, points.size(), coords );
for (size_t i=0; i<meshData.vars.size(); i++) { for ( size_t i = 0; i < meshData.vars.size(); i++ ) {
const IO::Variable& var = *meshData.vars[i]; const IO::Variable &var = *meshData.vars[i];
if ( var.precision == IO::DataType::Double ) { if ( var.precision == IO::DataType::Double ) {
silo::writePointMeshVariable( fid, meshname, var.name, var.data ); silo::writePointMeshVariable( fid, meshname, var.name, var.data );
} else if ( var.precision == IO::DataType::Float ) { } else if ( var.precision == IO::DataType::Float ) {
@@ -243,27 +295,27 @@ static void writeSiloPointList( DBfile *fid, const IO::MeshDataStruct& meshData,
data2.copy( var.data ); data2.copy( var.data );
silo::writePointMeshVariable( fid, meshname, var.name, data2 ); silo::writePointMeshVariable( fid, meshname, var.name, data2 );
} else { } else {
ERROR("Unsupported format"); ERROR( "Unsupported format" );
} }
} }
} }
// Write a TriMesh mesh (and variables) to a file // Write a TriMesh mesh (and variables) to a file
template<class TYPE> template<class TYPE>
static void writeSiloTriMesh( DBfile *fid, const IO::TriMesh& mesh, const std::string& meshname ) static void writeSiloTriMesh( DBfile *fid, const IO::TriMesh &mesh, const std::string &meshname )
{ {
const auto& points = mesh.vertices->getPoints(); const auto &points = mesh.vertices->getPoints();
std::vector<TYPE> x(points.size()), y(points.size()), z(points.size()); std::vector<TYPE> x( points.size() ), y( points.size() ), z( points.size() );
for (size_t i=0; i<x.size(); i++) { for ( size_t i = 0; i < x.size(); i++ ) {
x[i] = points[i].x; x[i] = points[i].x;
y[i] = points[i].y; y[i] = points[i].y;
z[i] = points[i].z; z[i] = points[i].z;
} }
const TYPE *coords[] = { x.data(), y.data(), z.data() }; const TYPE *coords[] = { x.data(), y.data(), z.data() };
const int *tri[] = { mesh.A.data(), mesh.B.data(), mesh.C.data() }; const int *tri[] = { mesh.A.data(), mesh.B.data(), mesh.C.data() };
silo::writeTriMesh<TYPE>( fid, meshname, 3, 2, points.size(), coords, mesh.A.size(), tri ); silo::writeTriMesh<TYPE>( fid, meshname, 3, 2, points.size(), coords, mesh.A.size(), tri );
} }
static void writeSiloTriMesh2( DBfile *fid, const IO::MeshDataStruct& meshData, static void writeSiloTriMesh2( DBfile *fid, const IO::MeshDataStruct &meshData,
const IO::TriMesh& mesh, IO::MeshDatabase database ) const IO::TriMesh &mesh, IO::MeshDatabase database )
{ {
const std::string meshname = database.domains[0].name; const std::string meshname = database.domains[0].name;
if ( meshData.precision == IO::DataType::Double ) { if ( meshData.precision == IO::DataType::Double ) {
@@ -271,11 +323,11 @@ static void writeSiloTriMesh2( DBfile *fid, const IO::MeshDataStruct& meshData,
} else if ( meshData.precision == IO::DataType::Float ) { } else if ( meshData.precision == IO::DataType::Float ) {
writeSiloTriMesh<float>( fid, mesh, meshname ); writeSiloTriMesh<float>( fid, mesh, meshname );
} else { } else {
ERROR("Unsupported format"); ERROR( "Unsupported format" );
} }
for (size_t i=0; i<meshData.vars.size(); i++) { for ( size_t i = 0; i < meshData.vars.size(); i++ ) {
const IO::Variable& var = *meshData.vars[i]; const IO::Variable &var = *meshData.vars[i];
auto type = static_cast<silo::VariableType>( var.type ); auto type = static_cast<silo::VariableType>( var.type );
if ( var.precision == IO::DataType::Double ) { if ( var.precision == IO::DataType::Double ) {
silo::writeTriMeshVariable( fid, 3, meshname, var.name, var.data, type ); silo::writeTriMeshVariable( fid, 3, meshname, var.name, var.data, type );
} else if ( var.precision == IO::DataType::Float ) { } else if ( var.precision == IO::DataType::Float ) {
@@ -287,35 +339,40 @@ static void writeSiloTriMesh2( DBfile *fid, const IO::MeshDataStruct& meshData,
data2.copy( var.data ); data2.copy( var.data );
silo::writeTriMeshVariable( fid, 3, meshname, var.name, data2, type ); silo::writeTriMeshVariable( fid, 3, meshname, var.name, data2, type );
} else { } else {
ERROR("Unsupported format"); ERROR( "Unsupported format" );
} }
} }
} }
static void writeSiloTriMesh( DBfile *fid, const IO::MeshDataStruct& meshData, IO::MeshDatabase database ) static void writeSiloTriMesh(
DBfile *fid, const IO::MeshDataStruct &meshData, IO::MeshDatabase database )
{ {
const IO::TriMesh& mesh = dynamic_cast<IO::TriMesh&>( *meshData.mesh ); const IO::TriMesh &mesh = dynamic_cast<IO::TriMesh &>( *meshData.mesh );
writeSiloTriMesh2( fid, meshData, mesh, database ); writeSiloTriMesh2( fid, meshData, mesh, database );
} }
static void writeSiloTriList( DBfile *fid, const IO::MeshDataStruct& meshData, IO::MeshDatabase database ) static void writeSiloTriList(
DBfile *fid, const IO::MeshDataStruct &meshData, IO::MeshDatabase database )
{ {
auto mesh = getTriMesh( meshData.mesh ); auto mesh = getTriMesh( meshData.mesh );
writeSiloTriMesh2( fid, meshData, *mesh, database ); writeSiloTriMesh2( fid, meshData, *mesh, database );
} }
// Write a DomainMesh mesh (and variables) to a file // Write a DomainMesh mesh (and variables) to a file
static void writeSiloDomainMesh( DBfile *fid, const IO::MeshDataStruct& meshData, IO::MeshDatabase database ) static void writeSiloDomainMesh(
DBfile *fid, const IO::MeshDataStruct &meshData, IO::MeshDatabase database )
{ {
const IO::DomainMesh& mesh = dynamic_cast<IO::DomainMesh&>( *meshData.mesh ); const IO::DomainMesh &mesh = dynamic_cast<IO::DomainMesh &>( *meshData.mesh );
RankInfoStruct info( mesh.rank, mesh.nprocx, mesh.nprocy, mesh.nprocz ); RankInfoStruct info( mesh.rank, mesh.nprocx, mesh.nprocy, mesh.nprocz );
std::array<double,6> range = { info.ix*mesh.Lx/info.nx, (info.ix+1)*mesh.Lx/info.nx, std::array<double, 6> range = { info.ix * mesh.Lx / info.nx,
info.jy*mesh.Ly/info.ny, (info.jy+1)*mesh.Ly/info.ny, ( info.ix + 1 ) * mesh.Lx / info.nx, info.jy * mesh.Ly / info.ny,
info.kz*mesh.Lz/info.nz, (info.kz+1)*mesh.Lz/info.nz }; ( info.jy + 1 ) * mesh.Ly / info.ny, info.kz * mesh.Lz / info.nz,
std::array<int,3> N = { mesh.nx, mesh.ny, mesh.nz }; ( info.kz + 1 ) * mesh.Lz / info.nz };
auto meshname = database.domains[0].name; std::array<int, 3> N = { mesh.nx, mesh.ny, mesh.nz };
auto meshname = database.domains[0].name;
silo::writeUniformMesh<3>( fid, meshname, range, N ); silo::writeUniformMesh<3>( fid, meshname, range, N );
silo::write<int>( fid, meshname+"_rankinfo", { mesh.rank, mesh.nprocx, mesh.nprocy, mesh.nprocz } ); silo::write<int>(
for (size_t i=0; i<meshData.vars.size(); i++) { fid, meshname + "_rankinfo", { mesh.rank, mesh.nprocx, mesh.nprocy, mesh.nprocz } );
const auto& var = *meshData.vars[i]; for ( size_t i = 0; i < meshData.vars.size(); i++ ) {
auto type = static_cast<silo::VariableType>( var.type ); const auto &var = *meshData.vars[i];
auto type = static_cast<silo::VariableType>( var.type );
if ( var.precision == IO::DataType::Double ) { if ( var.precision == IO::DataType::Double ) {
silo::writeUniformMeshVariable<3>( fid, meshname, N, var.name, var.data, type ); silo::writeUniformMeshVariable<3>( fid, meshname, N, var.name, var.data, type );
} else if ( var.precision == IO::DataType::Float ) { } else if ( var.precision == IO::DataType::Float ) {
@@ -327,65 +384,66 @@ static void writeSiloDomainMesh( DBfile *fid, const IO::MeshDataStruct& meshData
data2.copy( var.data ); data2.copy( var.data );
silo::writeUniformMeshVariable<3>( fid, meshname, N, var.name, data2, type ); silo::writeUniformMeshVariable<3>( fid, meshname, N, var.name, data2, type );
} else { } else {
ERROR("Unsupported format"); ERROR( "Unsupported format" );
} }
} }
} }
// Write a mesh (and variables) to a file // Write a mesh (and variables) to a file
static IO::MeshDatabase write_domain_silo( DBfile *fid, const std::string& filename, static IO::MeshDatabase write_domain_silo(
const IO::MeshDataStruct& mesh, int format ) DBfile *fid, const std::string &filename, const IO::MeshDataStruct &mesh, int format, int rank )
{ {
// Create the MeshDatabase // Create the MeshDatabase
auto database = getDatabase( filename, mesh, format ); auto database = getDatabase( filename, mesh, format, rank );
if ( database.meshClass=="PointList" ) { if ( database.meshClass == "PointList" ) {
writeSiloPointList( fid, mesh, database ); writeSiloPointList( fid, mesh, database );
} else if ( database.meshClass=="TriMesh" ) { } else if ( database.meshClass == "TriMesh" ) {
writeSiloTriMesh( fid, mesh, database ); writeSiloTriMesh( fid, mesh, database );
} else if ( database.meshClass=="TriList" ) { } else if ( database.meshClass == "TriList" ) {
writeSiloTriList( fid, mesh, database ); writeSiloTriList( fid, mesh, database );
} else if ( database.meshClass=="DomainMesh" ) { } else if ( database.meshClass == "DomainMesh" ) {
writeSiloDomainMesh( fid, mesh, database ); writeSiloDomainMesh( fid, mesh, database );
} else { } else {
ERROR("Unknown mesh class"); ERROR( "Unknown mesh class" );
} }
return database; return database;
} }
// Write the summary file for silo // Write the summary file for silo
std::pair<int,int> getSiloMeshType( const std::string& meshClass ) std::pair<int, int> getSiloMeshType( const std::string &meshClass )
{ {
int meshType = 0; int meshType = 0;
int varType = 0; int varType = 0;
if ( meshClass=="PointList" ) { if ( meshClass == "PointList" ) {
meshType = DB_POINTMESH; meshType = DB_POINTMESH;
varType = DB_POINTVAR; varType = DB_POINTVAR;
} else if ( meshClass=="TriMesh" ) { } else if ( meshClass == "TriMesh" ) {
meshType = DB_UCDMESH; meshType = DB_UCDMESH;
varType = DB_UCDVAR; varType = DB_UCDVAR;
} else if ( meshClass=="TriList" ) { } else if ( meshClass == "TriList" ) {
meshType = DB_UCDMESH; meshType = DB_UCDMESH;
varType = DB_UCDVAR; varType = DB_UCDVAR;
} else if ( meshClass=="DomainMesh" ) { } else if ( meshClass == "DomainMesh" ) {
meshType = DB_QUAD_RECT; meshType = DB_QUAD_RECT;
varType = DB_QUADVAR; varType = DB_QUADVAR;
} else { } else {
ERROR("Unknown mesh class"); ERROR( "Unknown mesh class" );
} }
return std::make_pair( meshType, varType ); return std::make_pair( meshType, varType );
} }
void writeSiloSummary( const std::vector<IO::MeshDatabase>& meshes_written, const std::string& filename ) void writeSiloSummary(
const std::vector<IO::MeshDatabase> &meshes_written, const std::string &filename )
{ {
auto fid = silo::open( filename, silo::CREATE ); auto fid = silo::open( filename, silo::CREATE );
for ( const auto& data : meshes_written ) { for ( const auto &data : meshes_written ) {
auto type = getSiloMeshType( data.meshClass ); auto type = getSiloMeshType( data.meshClass );
std::vector<int> meshTypes( data.domains.size(), type.first ); std::vector<int> meshTypes( data.domains.size(), type.first );
std::vector<int> varTypes( data.domains.size(), type.second ); std::vector<int> varTypes( data.domains.size(), type.second );
std::vector<std::string> meshNames; std::vector<std::string> meshNames;
for ( const auto& tmp : data.domains ) for ( const auto &tmp : data.domains )
meshNames.push_back( tmp.file + ":" + tmp.name ); meshNames.push_back( tmp.file + ":" + tmp.name );
silo::writeMultiMesh( fid, data.name, meshNames, meshTypes ); silo::writeMultiMesh( fid, data.name, meshNames, meshTypes );
for (const auto& variable : data.variables ) { for ( const auto &variable : data.variables ) {
std::vector<std::string> varnames; std::vector<std::string> varnames;
for ( const auto& tmp : data.domains ) for ( const auto &tmp : data.domains )
varnames.push_back( tmp.file + ":" + variable.name ); varnames.push_back( tmp.file + ":" + variable.name );
silo::writeMultiVar( fid, variable.name, varnames, varTypes ); silo::writeMultiVar( fid, variable.name, varnames, varTypes );
} }
@@ -397,112 +455,110 @@ void writeSiloSummary( const std::vector<IO::MeshDatabase>& meshes_written, cons
// Write the mesh data in the new format // Write the mesh data in the new format
static std::vector<IO::MeshDatabase> writeMeshesNewFormat( static std::vector<IO::MeshDatabase> writeMeshesNewFormat(
const std::vector<IO::MeshDataStruct>& meshData, const std::string& path, int format ) const std::vector<IO::MeshDataStruct> &meshData, const std::string &path, int format, int rank )
{ {
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank();
std::vector<IO::MeshDatabase> meshes_written; std::vector<IO::MeshDatabase> meshes_written;
char filename[100], fullpath[200]; char filename[100], fullpath[200];
sprintf(filename,"%05i",rank); sprintf( filename, "%05i", rank );
sprintf(fullpath,"%s/%s",path.c_str(),filename); sprintf( fullpath, "%s/%s", path.c_str(), filename );
FILE *fid = fopen(fullpath,"wb"); FILE *fid = fopen( fullpath, "wb" );
for (size_t i=0; i<meshData.size(); i++) { for ( size_t i = 0; i < meshData.size(); i++ ) {
std::shared_ptr<IO::Mesh> mesh = meshData[i].mesh; std::shared_ptr<IO::Mesh> mesh = meshData[i].mesh;
meshes_written.push_back( write_domain(fid,filename,meshData[i],format) ); meshes_written.push_back( write_domain( fid, filename, meshData[i], format, rank ) );
} }
fclose(fid); fclose( fid );
return meshes_written; return meshes_written;
} }
// Write the mesh data to silo // Write the mesh data to silo
static std::vector<IO::MeshDatabase> writeMeshesSilo( static std::vector<IO::MeshDatabase> writeMeshesSilo(
const std::vector<IO::MeshDataStruct>& meshData, const std::string& path, int format ) const std::vector<IO::MeshDataStruct> &meshData, const std::string &path, int format, int rank )
{ {
#ifdef USE_SILO #ifdef USE_SILO
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank();
std::vector<IO::MeshDatabase> meshes_written; std::vector<IO::MeshDatabase> meshes_written;
char filename[100], fullpath[200]; char filename[100], fullpath[200];
sprintf(filename,"%05i.silo",rank); sprintf( filename, "%05i.silo", rank );
sprintf(fullpath,"%s/%s",path.c_str(),filename); sprintf( fullpath, "%s/%s", path.c_str(), filename );
auto fid = silo::open( fullpath, silo::CREATE ); auto fid = silo::open( fullpath, silo::CREATE );
for (size_t i=0; i<meshData.size(); i++) { for ( size_t i = 0; i < meshData.size(); i++ ) {
auto mesh = meshData[i].mesh; auto mesh = meshData[i].mesh;
meshes_written.push_back( write_domain_silo(fid,filename,meshData[i],format) ); meshes_written.push_back( write_domain_silo( fid, filename, meshData[i], format, rank ) );
} }
silo::close( fid ); silo::close( fid );
return meshes_written; return meshes_written;
#else #else
ERROR("Application built without silo support"); NULL_USE( meshData );
NULL_USE( path );
NULL_USE( format );
NULL_USE( rank );
ERROR( "Application built without silo support" );
return std::vector<IO::MeshDatabase>(); return std::vector<IO::MeshDatabase>();
#endif #endif
} }
/**************************************************** /****************************************************
* Write the mesh data * * Write the mesh data *
****************************************************/ ****************************************************/
void IO::writeData( const std::string& subdir, const std::vector<IO::MeshDataStruct>& meshData, const Utilities::MPI& comm ) void IO::writeData( const std::string &subdir, const std::vector<IO::MeshDataStruct> &meshData,
const Utilities::MPI &comm )
{ {
if ( global_IO_path.empty() ) if ( global_IO_path.empty() )
IO::initialize( ); IO::initialize();
PROFILE_START("writeData"); PROFILE_START( "writeData" );
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank(); int rank = Utilities::MPI( MPI_COMM_WORLD ).getRank();
// Check the meshData before writing // Check the meshData before writing
for ( const auto& data : meshData ) { for ( const auto &data : meshData ) {
if ( !data.check() ) if ( !data.check() )
ERROR("Error in meshData"); ERROR( "Error in meshData" );
} }
// Create the output directory // Create the output directory
std::string path = global_IO_path + "/" + subdir; std::string path = global_IO_path + "/" + subdir;
if ( rank == 0 ) { recursiveMkdir( path, S_IRWXU | S_IRGRP );
mkdir(path.c_str(),S_IRWXU|S_IRGRP);
}
comm.barrier();
// Write the mesh files // Write the mesh files
std::vector<IO::MeshDatabase> meshes_written; std::vector<IO::MeshDatabase> meshes_written;
if ( global_IO_format == Format::OLD ) { if ( global_IO_format == Format::OLD ) {
// Write the original triangle format // Write the original triangle format
meshes_written = writeMeshesOrigFormat( meshData, path ); meshes_written = writeMeshesOrigFormat( meshData, path, rank );
} else if ( global_IO_format == Format::NEW ) { } else if ( global_IO_format == Format::NEW ) {
// Write the new format (double precision) // Write the new format (double precision)
meshes_written = writeMeshesNewFormat( meshData, path, 2 ); meshes_written = writeMeshesNewFormat( meshData, path, 2, rank );
} else if ( global_IO_format == Format::SILO ) { } else if ( global_IO_format == Format::SILO ) {
// Write silo // Write silo
meshes_written = writeMeshesSilo( meshData, path, 4 ); meshes_written = writeMeshesSilo( meshData, path, 4, rank );
} else { } else {
ERROR("Unknown format"); ERROR( "Unknown format" );
} }
// Gather a complete list of files on rank 0 // Gather a complete list of files on rank 0
meshes_written = gatherAll(meshes_written,comm); meshes_written = gatherAll( meshes_written, comm );
// Write the summary files // Write the summary files
if ( rank == 0 ) { if ( rank == 0 ) {
// Write the summary file for the current timestep // Write the summary file for the current timestep
char filename[200]; char filename[200];
sprintf(filename,"%s/LBM.summary",path.c_str()); sprintf( filename, "%s/LBM.summary", path.c_str() );
write(meshes_written,filename); write( meshes_written, filename );
// Write summary silo file if needed // Write summary silo file if needed
#ifdef USE_SILO #ifdef USE_SILO
if ( global_IO_format == Format::SILO ) { if ( global_IO_format == Format::SILO ) {
sprintf(filename,"%s/summary.silo",path.c_str()); sprintf( filename, "%s/summary.silo", path.c_str() );
writeSiloSummary(meshes_written,filename); writeSiloSummary( meshes_written, filename );
} }
#endif #endif
// Add the timestep to the global summary file // Add the timestep to the global summary file
if ( global_IO_format == Format::OLD || global_IO_format == Format::NEW ) { if ( global_IO_format == Format::OLD || global_IO_format == Format::NEW ) {
auto filename = global_IO_path+"/summary.LBM"; auto filename = global_IO_path + "/summary.LBM";
FILE *fid = fopen(filename.c_str(),"ab"); FILE *fid = fopen( filename.c_str(), "ab" );
fprintf(fid,"%s/\n",subdir.c_str()); fprintf( fid, "%s/\n", subdir.c_str() );
fclose(fid); fclose( fid );
} else if ( global_IO_format == Format::SILO ) { } else if ( global_IO_format == Format::SILO ) {
auto filename = global_IO_path+"/LBM.visit"; auto filename = global_IO_path + "/LBM.visit";
FILE *fid = fopen(filename.c_str(),"ab"); FILE *fid = fopen( filename.c_str(), "ab" );
fprintf(fid,"%s/summary.silo\n",subdir.c_str()); fprintf( fid, "%s/summary.silo\n", subdir.c_str() );
fclose(fid); fclose( fid );
} else { } else {
ERROR("Unknown format"); ERROR( "Unknown format" );
} }
} }
PROFILE_STOP("writeData"); PROFILE_STOP( "writeData" );
} }

View File

@@ -14,17 +14,18 @@ namespace IO {
/*! /*!
* @brief Initialize the writer * @brief Initialize the writer
* @details This function initializes the writer to the given path. All subsequent * @details This function initializes the writer to the given path.
* writes will occur in this directory. If this is not called, then it will default * All subsequent writes will occur in this directory.
* to the current path. * If this is not called, then it will default to the current path.
* @param[in] path The path to use for writes * @param[in] path The path to use for writes
* @param[in] format The data format to use: * @param[in] format The data format to use:
* old - Old mesh format (provided for backward compatibility, cannot write variables) * old - Old mesh format
* new - New format, 1 file/process * (provided for backward compatibility, cannot write variables)
* silo - Silo * new - New format, 1 file/process silo - Silo
* @param[in] append Append any existing data (default is false) * @param[in] append Append any existing data (default is false)
*/ */
void initialize( const std::string& path="", const std::string& format="silo", bool append=false ); void initialize(
const std::string &path = "", const std::string &format = "silo", bool append = false );
/*! /*!
@@ -34,7 +35,8 @@ void initialize( const std::string& path="", const std::string& format="silo", b
* @param[in] meshData The data to write * @param[in] meshData The data to write
* @param[in] comm The comm to use for writing (usually MPI_COMM_WORLD or a dup thereof) * @param[in] comm The comm to use for writing (usually MPI_COMM_WORLD or a dup thereof)
*/ */
void writeData( const std::string& subdir, const std::vector<IO::MeshDataStruct>& meshData, const Utilities::MPI& comm ); void writeData( const std::string &subdir, const std::vector<IO::MeshDataStruct> &meshData,
const Utilities::MPI &comm );
/*! /*!
@@ -44,14 +46,15 @@ void writeData( const std::string& subdir, const std::vector<IO::MeshDataStruct>
* @param[in] meshData The data to write * @param[in] meshData The data to write
* @param[in] comm The comm to use for writing (usually MPI_COMM_WORLD or a dup thereof) * @param[in] comm The comm to use for writing (usually MPI_COMM_WORLD or a dup thereof)
*/ */
inline void writeData( int timestep, const std::vector<IO::MeshDataStruct>& meshData, const Utilities::MPI& comm ) inline void writeData(
int timestep, const std::vector<IO::MeshDataStruct> &meshData, const Utilities::MPI &comm )
{ {
char subdir[100]; char subdir[100];
sprintf(subdir,"vis%03i",timestep); sprintf( subdir, "vis%03i", timestep );
writeData( subdir, meshData, comm ); writeData( subdir, meshData, comm );
} }
} // IO namespace } // namespace IO
#endif #endif

View File

@@ -1,6 +1,6 @@
#include "IO/netcdf.h" #include "IO/netcdf.h"
#include "common/Utilities.h"
#include "common/MPI.h" #include "common/MPI.h"
#include "common/Utilities.h"
#include "ProfilerApp.h" #include "ProfilerApp.h"
@@ -12,14 +12,14 @@
#include <netcdf_par.h> #include <netcdf_par.h>
#define CHECK_NC_ERR( ERR ) \ #define CHECK_NC_ERR( ERR ) \
do { \ do { \
if ( ERR != NC_NOERR ) { \ if ( ERR != NC_NOERR ) { \
std::string msg = "Error calling netcdf routine: "; \ std::string msg = "Error calling netcdf routine: "; \
msg += nc_strerror( ERR ); \ msg += nc_strerror( ERR ); \
ERROR( msg ); \ ERROR( msg ); \
} \ } \
} while (0) } while ( 0 )
namespace netcdf { namespace netcdf {
@@ -50,43 +50,64 @@ static inline VariableType convertType( nc_type type )
else if ( type == NC_DOUBLE ) else if ( type == NC_DOUBLE )
type2 = DOUBLE; type2 = DOUBLE;
else else
ERROR("Unknown type"); ERROR( "Unknown type" );
return type2; return type2;
} }
// Get nc_type from the template // Get nc_type from the template
template<class T> inline nc_type getType(); template<class T>
template<> inline nc_type getType<char>() { return NC_CHAR; } inline nc_type getType();
template<> inline nc_type getType<short>() { return NC_SHORT; } template<>
template<> inline nc_type getType<int>() { return NC_INT; } inline nc_type getType<char>()
template<> inline nc_type getType<float>() { return NC_FLOAT; } {
template<> inline nc_type getType<double>() { return NC_DOUBLE; } return NC_CHAR;
}
template<>
inline nc_type getType<short>()
{
return NC_SHORT;
}
template<>
inline nc_type getType<int>()
{
return NC_INT;
}
template<>
inline nc_type getType<float>()
{
return NC_FLOAT;
}
template<>
inline nc_type getType<double>()
{
return NC_DOUBLE;
}
// Function to reverse an array // Function to reverse an array
template<class TYPE> template<class TYPE>
inline std::vector<TYPE> reverse( const std::vector<TYPE>& x ) inline std::vector<TYPE> reverse( const std::vector<TYPE> &x )
{ {
std::vector<TYPE> y(x.size()); std::vector<TYPE> y( x.size() );
for (size_t i=0; i<x.size(); i++) for ( size_t i = 0; i < x.size(); i++ )
y[i] = x[x.size()-i-1]; y[i] = x[x.size() - i - 1];
return y; return y;
} }
// Function to reverse an array // Function to reverse an array
template<class TYPE1, class TYPE2> template<class TYPE1, class TYPE2>
inline std::vector<TYPE2> convert( const std::vector<TYPE1>& x ) inline std::vector<TYPE2> convert( const std::vector<TYPE1> &x )
{ {
std::vector<TYPE2> y(x.size()); std::vector<TYPE2> y( x.size() );
for (size_t i=0; i<x.size(); i++) for ( size_t i = 0; i < x.size(); i++ )
y[i] = static_cast<TYPE2>(x[i]); y[i] = static_cast<TYPE2>( x[i] );
return y; return y;
} }
/**************************************************** /****************************************************
* Convert the VariableType to a string * * Convert the VariableType to a string *
****************************************************/ ****************************************************/
std::string VariableTypeName( VariableType type ) std::string VariableTypeName( VariableType type )
{ {
if ( type == BYTE ) if ( type == BYTE )
@@ -114,9 +135,9 @@ std::string VariableTypeName( VariableType type )
/**************************************************** /****************************************************
* Open/close a file * * Open/close a file *
****************************************************/ ****************************************************/
int open( const std::string& filename, FileMode mode, const Utilities::MPI& comm ) int open( const std::string &filename, FileMode mode, const Utilities::MPI &comm )
{ {
int fid = 0; int fid = 0;
if ( comm.isNull() ) { if ( comm.isNull() ) {
@@ -127,23 +148,26 @@ int open( const std::string& filename, FileMode mode, const Utilities::MPI& comm
int err = nc_open( filename.c_str(), NC_WRITE, &fid ); int err = nc_open( filename.c_str(), NC_WRITE, &fid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} else if ( mode == CREATE ) { } else if ( mode == CREATE ) {
int err = nc_create( filename.c_str(), NC_SHARE|NC_64BIT_OFFSET, &fid ); int err = nc_create( filename.c_str(), NC_SHARE | NC_64BIT_OFFSET, &fid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} else { } else {
ERROR("Unknown file mode"); ERROR( "Unknown file mode" );
} }
} else { } else {
if ( mode == READ ) { if ( mode == READ ) {
int err = nc_open_par( filename.c_str(), NC_MPIPOSIX, comm.getCommunicator(), MPI_INFO_NULL, &fid ); int err = nc_open_par(
filename.c_str(), NC_MPIPOSIX, comm.getCommunicator(), MPI_INFO_NULL, &fid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} else if ( mode == WRITE ) { } else if ( mode == WRITE ) {
int err = nc_open_par( filename.c_str(), NC_WRITE|NC_MPIPOSIX, comm.getCommunicator(), MPI_INFO_NULL, &fid ); int err = nc_open_par( filename.c_str(), NC_WRITE | NC_MPIPOSIX, comm.getCommunicator(),
MPI_INFO_NULL, &fid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} else if ( mode == CREATE ) { } else if ( mode == CREATE ) {
int err = nc_create_par( filename.c_str(), NC_NETCDF4|NC_MPIIO, comm.getCommunicator(), MPI_INFO_NULL, &fid ); int err = nc_create_par( filename.c_str(), NC_NETCDF4 | NC_MPIIO,
comm.getCommunicator(), MPI_INFO_NULL, &fid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} else { } else {
ERROR("Unknown file mode"); ERROR( "Unknown file mode" );
} }
} }
return fid; return fid;
@@ -152,42 +176,42 @@ void close( int fid )
{ {
int err = nc_close( fid ); int err = nc_close( fid );
if ( err != NC_NOERR ) if ( err != NC_NOERR )
ERROR("Error closing file"); ERROR( "Error closing file" );
} }
/**************************************************** /****************************************************
* Query basic properties * * Query basic properties *
****************************************************/ ****************************************************/
static std::vector<size_t> getDimVar( int fid, int varid ) static std::vector<size_t> getDimVar( int fid, int varid )
{ {
int ndim = 0; int ndim = 0;
int err = nc_inq_varndims( fid, varid, &ndim ); int err = nc_inq_varndims( fid, varid, &ndim );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
std::vector<size_t> dims(ndim,0); std::vector<size_t> dims( ndim, 0 );
int dimid[64] = {-1}; int dimid[64] = { -1 };
err = nc_inq_vardimid( fid, varid, dimid ); err = nc_inq_vardimid( fid, varid, dimid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
for (int i=0; i<ndim; i++) { for ( int i = 0; i < ndim; i++ ) {
err = nc_inq_dimlen( fid, dimid[i], &dims[i] ); err = nc_inq_dimlen( fid, dimid[i], &dims[i] );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} }
return dims; return dims;
} }
static int getVarID( int fid, const std::string& var ) static int getVarID( int fid, const std::string &var )
{ {
int id = -1; int id = -1;
int err = nc_inq_varid( fid, var.c_str(), &id ); int err = nc_inq_varid( fid, var.c_str(), &id );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
return id; return id;
} }
std::vector<size_t> getVarDim( int fid, const std::string& var ) std::vector<size_t> getVarDim( int fid, const std::string &var )
{ {
return getDimVar( fid, getVarID( fid, var ) ); return getDimVar( fid, getVarID( fid, var ) );
} }
std::vector<size_t> getAttDim( int fid, const std::string& att ) std::vector<size_t> getAttDim( int fid, const std::string &att )
{ {
std::vector<size_t> dim(1,0); std::vector<size_t> dim( 1, 0 );
int err = nc_inq_attlen( fid, NC_GLOBAL, att.c_str(), dim.data() ); int err = nc_inq_attlen( fid, NC_GLOBAL, att.c_str(), dim.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
return dim; return dim;
@@ -197,9 +221,9 @@ std::vector<std::string> getVarNames( int fid )
int nvar; int nvar;
int err = nc_inq( fid, NULL, &nvar, NULL, NULL ); int err = nc_inq( fid, NULL, &nvar, NULL, NULL );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
std::vector<std::string> vars(nvar); std::vector<std::string> vars( nvar );
for (int i=0; i<nvar; i++) { for ( int i = 0; i < nvar; i++ ) {
char name[NC_MAX_NAME+1]; char name[NC_MAX_NAME + 1];
err = nc_inq_varname( fid, i, name ); err = nc_inq_varname( fid, i, name );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
vars[i] = name; vars[i] = name;
@@ -211,238 +235,243 @@ std::vector<std::string> getAttNames( int fid )
int natt; int natt;
int err = nc_inq( fid, NULL, NULL, &natt, NULL ); int err = nc_inq( fid, NULL, NULL, &natt, NULL );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
std::vector<std::string> att(natt); std::vector<std::string> att( natt );
for (int i=0; i<natt; i++) { for ( int i = 0; i < natt; i++ ) {
char name[NC_MAX_NAME+1]; char name[NC_MAX_NAME + 1];
err = nc_inq_attname( fid, NC_GLOBAL, i, name ); err = nc_inq_attname( fid, NC_GLOBAL, i, name );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
att[i] = name; att[i] = name;
} }
return att; return att;
} }
VariableType getVarType( int fid, const std::string& var ) VariableType getVarType( int fid, const std::string &var )
{ {
int varid = -1; int varid = -1;
int err = nc_inq_varid( fid, var.c_str(), &varid ); int err = nc_inq_varid( fid, var.c_str(), &varid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
nc_type type=0; nc_type type = 0;
err = nc_inq_vartype( fid, varid, &type ); err = nc_inq_vartype( fid, varid, &type );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
return convertType(type); return convertType( type );
} }
VariableType getAttType( int fid, const std::string& att ) VariableType getAttType( int fid, const std::string &att )
{ {
nc_type type=0; nc_type type = 0;
int err = nc_inq_atttype( fid, NC_GLOBAL, att.c_str(), &type ); int err = nc_inq_atttype( fid, NC_GLOBAL, att.c_str(), &type );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
return convertType(type); return convertType( type );
} }
/**************************************************** /****************************************************
* Read a variable * * Read a variable *
****************************************************/ ****************************************************/
template<> template<>
Array<unsigned short> getVar<unsigned short>( int fid, const std::string& var ) Array<unsigned short> getVar<unsigned short>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<unsigned short>"); PROFILE_START( "getVar<unsigned short>" );
Array<unsigned short> x( reverse(getVarDim(fid,var)) ); Array<unsigned short> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_ushort( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_ushort( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<unsigned short>"); PROFILE_STOP( "getVar<unsigned short>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<short> getVar<short>( int fid, const std::string& var ) Array<short> getVar<short>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<short>"); PROFILE_START( "getVar<short>" );
Array<short> x( reverse(getVarDim(fid,var)) ); Array<short> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_short( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_short( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<short>"); PROFILE_STOP( "getVar<short>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<unsigned int> getVar<unsigned int>( int fid, const std::string& var ) Array<unsigned int> getVar<unsigned int>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<unsigned int>"); PROFILE_START( "getVar<unsigned int>" );
Array<unsigned int> x( reverse(getVarDim(fid,var)) ); Array<unsigned int> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_uint( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_uint( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<unsigned int>"); PROFILE_STOP( "getVar<unsigned int>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<int> getVar<int>( int fid, const std::string& var ) Array<int> getVar<int>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<int>"); PROFILE_START( "getVar<int>" );
Array<int> x( reverse(getVarDim(fid,var)) ); Array<int> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_int( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_int( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<int>"); PROFILE_STOP( "getVar<int>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<float> getVar<float>( int fid, const std::string& var ) Array<float> getVar<float>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<float>"); PROFILE_START( "getVar<float>" );
Array<float> x( reverse(getVarDim(fid,var)) ); Array<float> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_float( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_float( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<float>"); PROFILE_STOP( "getVar<float>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<double> getVar<double>( int fid, const std::string& var ) Array<double> getVar<double>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<double>"); PROFILE_START( "getVar<double>" );
Array<double> x( reverse(getVarDim(fid,var)) ); Array<double> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_double( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_double( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<double>"); PROFILE_STOP( "getVar<double>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<char> getVar<char>( int fid, const std::string& var ) Array<char> getVar<char>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<char>"); PROFILE_START( "getVar<char>" );
Array<char> x( reverse(getVarDim(fid,var)) ); Array<char> x( reverse( getVarDim( fid, var ) ) );
int err = nc_get_var_text( fid, getVarID(fid,var), x.data() ); int err = nc_get_var_text( fid, getVarID( fid, var ), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<char>"); PROFILE_STOP( "getVar<char>" );
return x.reverseDim(); return x.reverseDim();
} }
template<> template<>
Array<std::string> getVar<std::string>( int fid, const std::string& var ) Array<std::string> getVar<std::string>( int fid, const std::string &var )
{ {
PROFILE_START("getVar<std::string>"); PROFILE_START( "getVar<std::string>" );
Array<char> tmp = getVar<char>( fid, var ); Array<char> tmp = getVar<char>( fid, var );
std::vector<size_t> dim = {tmp.size(0), tmp.size(1), tmp.size(2) }; std::vector<size_t> dim = { tmp.size( 0 ), tmp.size( 1 ), tmp.size( 2 ) };
if ( dim.size() == 1 ) if ( dim.size() == 1 )
dim[0] = 1; dim[0] = 1;
else else
dim.erase( dim.begin() ); dim.erase( dim.begin() );
Array<std::string> text(dim); Array<std::string> text( dim );
for (size_t i=0; i<text.length(); i++) for ( size_t i = 0; i < text.length(); i++ )
text(i) = &(tmp(0,i)); text( i ) = &( tmp( 0, i ) );
PROFILE_STOP("getVar<std::string>"); PROFILE_STOP( "getVar<std::string>" );
return text; return text;
} }
static inline void get_stride_args( const std::vector<int>& start, static inline void get_stride_args( const std::vector<int> &start, const std::vector<int> &count,
const std::vector<int>& count, const std::vector<int>& stride, const std::vector<int> &stride, size_t *startp, size_t *countp, ptrdiff_t *stridep )
size_t *startp, size_t *countp, ptrdiff_t *stridep )
{ {
for (size_t i=0; i<start.size(); i++) for ( size_t i = 0; i < start.size(); i++ )
startp[i] = start[i]; startp[i] = start[i];
for (size_t i=0; i<count.size(); i++) for ( size_t i = 0; i < count.size(); i++ )
countp[i] = count[i]; countp[i] = count[i];
for (size_t i=0; i<stride.size(); i++) for ( size_t i = 0; i < stride.size(); i++ )
stridep[i] = stride[i]; stridep[i] = stride[i];
} }
template<class TYPE> template<class TYPE>
int nc_get_vars_TYPE( int fid, int varid, const size_t start[], int nc_get_vars_TYPE( int fid, int varid, const size_t start[], const size_t count[],
const size_t count[], const ptrdiff_t stride[], TYPE *ptr ); const ptrdiff_t stride[], TYPE *ptr );
template<> template<>
int nc_get_vars_TYPE<short>( int fid, int varid, const size_t start[], int nc_get_vars_TYPE<short>( int fid, int varid, const size_t start[], const size_t count[],
const size_t count[], const ptrdiff_t stride[], short *ptr ) const ptrdiff_t stride[], short *ptr )
{ {
return nc_get_vars_short( fid, varid, start, count, stride, ptr ); return nc_get_vars_short( fid, varid, start, count, stride, ptr );
} }
template<> template<>
int nc_get_vars_TYPE<int>( int fid, int varid, const size_t start[], int nc_get_vars_TYPE<int>( int fid, int varid, const size_t start[], const size_t count[],
const size_t count[], const ptrdiff_t stride[], int *ptr ) const ptrdiff_t stride[], int *ptr )
{ {
return nc_get_vars_int( fid, varid, start, count, stride, ptr ); return nc_get_vars_int( fid, varid, start, count, stride, ptr );
} }
template<> template<>
int nc_get_vars_TYPE<float>( int fid, int varid, const size_t start[], int nc_get_vars_TYPE<float>( int fid, int varid, const size_t start[], const size_t count[],
const size_t count[], const ptrdiff_t stride[], float *ptr ) const ptrdiff_t stride[], float *ptr )
{ {
return nc_get_vars_float( fid, varid, start, count, stride, ptr ); return nc_get_vars_float( fid, varid, start, count, stride, ptr );
} }
template<> template<>
int nc_get_vars_TYPE<double>( int fid, int varid, const size_t start[], int nc_get_vars_TYPE<double>( int fid, int varid, const size_t start[], const size_t count[],
const size_t count[], const ptrdiff_t stride[], double *ptr ) const ptrdiff_t stride[], double *ptr )
{ {
return nc_get_vars_double( fid, varid, start, count, stride, ptr ); return nc_get_vars_double( fid, varid, start, count, stride, ptr );
} }
template<class TYPE> template<class TYPE>
Array<TYPE> getVar( int fid, const std::string& var, const std::vector<int>& start, Array<TYPE> getVar( int fid, const std::string &var, const std::vector<int> &start,
const std::vector<int>& count, const std::vector<int>& stride ) const std::vector<int> &count, const std::vector<int> &stride )
{ {
PROFILE_START("getVar<> (strided)"); PROFILE_START( "getVar<> (strided)" );
std::vector<size_t> var_size = getVarDim( fid, var ); std::vector<size_t> var_size = getVarDim( fid, var );
for (int d=0; d<(int)var_size.size(); d++) { for ( int d = 0; d < (int) var_size.size(); d++ ) {
if ( start[d]<0 || start[d]+stride[d]*(count[d]-1)>(int)var_size[d] ) { if ( start[d] < 0 || start[d] + stride[d] * ( count[d] - 1 ) > (int) var_size[d] ) {
int rank = Utilities::MPI(MPI_COMM_WORLD).getRank(); int rank = Utilities::MPI( MPI_COMM_WORLD ).getRank();
char tmp[1000]; char tmp[1000];
sprintf(tmp,"%i: Range exceeded array dimension:\n" sprintf( tmp,
"%i: Range exceeded array dimension:\n"
" start[%i]=%i, count[%i]=%i, stride[%i]=%i, var_size[%i]=%i", " start[%i]=%i, count[%i]=%i, stride[%i]=%i, var_size[%i]=%i",
rank,d,start[d],d,count[d],d,stride[d],d,(int)var_size[d]); rank, d, start[d], d, count[d], d, stride[d], d, (int) var_size[d] );
ERROR(tmp); ERROR( tmp );
} }
} }
Array<TYPE> x( reverse(convert<int,size_t>(count)) ); Array<TYPE> x( reverse( convert<int, size_t>( count ) ) );
size_t startp[10], countp[10]; size_t startp[10], countp[10];
ptrdiff_t stridep[10]; ptrdiff_t stridep[10];
get_stride_args( start, count, stride, startp, countp, stridep ); get_stride_args( start, count, stride, startp, countp, stridep );
int err = nc_get_vars_TYPE<TYPE>( fid, getVarID(fid,var), startp, countp, stridep, x.data() ); int err =
nc_get_vars_TYPE<TYPE>( fid, getVarID( fid, var ), startp, countp, stridep, x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getVar<> (strided)"); PROFILE_STOP( "getVar<> (strided)" );
return x.reverseDim(); return x.reverseDim();
} }
template Array<short> getVar<short>( int, const std::string&, const std::vector<int>&, const std::vector<int>&, const std::vector<int>& ); template Array<short> getVar<short>( int, const std::string &, const std::vector<int> &,
template Array<int> getVar<int>( int, const std::string&, const std::vector<int>&, const std::vector<int>&, const std::vector<int>& ); const std::vector<int> &, const std::vector<int> & );
template Array<float> getVar<float>( int, const std::string&, const std::vector<int>&, const std::vector<int>&, const std::vector<int>& ); template Array<int> getVar<int>( int, const std::string &, const std::vector<int> &,
template Array<double> getVar<double>( int, const std::string&, const std::vector<int>&, const std::vector<int>&, const std::vector<int>& ); const std::vector<int> &, const std::vector<int> & );
template Array<float> getVar<float>( int, const std::string &, const std::vector<int> &,
const std::vector<int> &, const std::vector<int> & );
template Array<double> getVar<double>( int, const std::string &, const std::vector<int> &,
const std::vector<int> &, const std::vector<int> & );
/**************************************************** /****************************************************
* Read an attribute * * Read an attribute *
****************************************************/ ****************************************************/
template<> template<>
Array<double> getAtt<double>( int fid, const std::string& att ) Array<double> getAtt<double>( int fid, const std::string &att )
{ {
PROFILE_START("getAtt<double>"); PROFILE_START( "getAtt<double>" );
Array<double> x( getAttDim(fid,att) ); Array<double> x( getAttDim( fid, att ) );
int err = nc_get_att_double( fid, NC_GLOBAL, att.c_str(), x.data() ); int err = nc_get_att_double( fid, NC_GLOBAL, att.c_str(), x.data() );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
PROFILE_STOP("getAtt<double>"); PROFILE_STOP( "getAtt<double>" );
return x; return x;
} }
template<> template<>
Array<std::string> getAtt<std::string>( int fid, const std::string& att ) Array<std::string> getAtt<std::string>( int fid, const std::string &att )
{ {
PROFILE_START("getAtt<std::string>"); PROFILE_START( "getAtt<std::string>" );
char *tmp = new char[getAttDim(fid,att)[0]]; char *tmp = new char[getAttDim( fid, att )[0]];
Array<std::string> x(1); Array<std::string> x( 1 );
x(0) = tmp; x( 0 ) = tmp;
delete [] tmp; delete[] tmp;
PROFILE_STOP("getAtt<std::string>"); PROFILE_STOP( "getAtt<std::string>" );
return x; return x;
} }
/**************************************************** /****************************************************
* Write an array to a file * * Write an array to a file *
****************************************************/ ****************************************************/
std::vector<int> defDim( int fid, const std::vector<std::string>& names, const std::vector<int>& dims ) std::vector<int> defDim(
int fid, const std::vector<std::string> &names, const std::vector<int> &dims )
{ {
std::vector<int> dimid(names.size(),0); std::vector<int> dimid( names.size(), 0 );
for (size_t i=0; i<names.size(); i++) { for ( size_t i = 0; i < names.size(); i++ ) {
int err = nc_def_dim( fid, names[i].c_str(), dims[i], &dimid[i]); int err = nc_def_dim( fid, names[i].c_str(), dims[i], &dimid[i] );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
} }
return dimid; return dimid;
} }
template<class TYPE> template<class TYPE>
void write( int fid, const std::string& var, const std::vector<int>& dimids, void write( int fid, const std::string &var, const std::vector<int> &dimids,
const Array<TYPE>& data, const RankInfoStruct& info ) const Array<TYPE> &data, const RankInfoStruct &info )
{ {
// Define the variable // Define the variable
int varid = 0; int varid = 0;
int err = nc_def_var( fid, var.c_str(), getType<TYPE>(), data.ndim(), dimids.data(), &varid ); int err = nc_def_var( fid, var.c_str(), getType<TYPE>(), data.ndim(), dimids.data(), &varid );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
// exit define mode // exit define mode
err = nc_enddef( fid ); err = nc_enddef( fid );
@@ -451,22 +480,24 @@ void write( int fid, const std::string& var, const std::vector<int>& dimids,
err = nc_var_par_access( fid, varid, NC_INDEPENDENT ); err = nc_var_par_access( fid, varid, NC_INDEPENDENT );
CHECK_NC_ERR( err ); CHECK_NC_ERR( err );
// parallel write: each process writes its subarray to the file // parallel write: each process writes its subarray to the file
auto x = data.reverseDim(); auto x = data.reverseDim();
std::vector<size_t> count = { data.size(0), data.size(1), data.size(2) }; std::vector<size_t> count = { data.size( 0 ), data.size( 1 ), data.size( 2 ) };
std::vector<size_t> start = { info.ix*data.size(0), info.jy*data.size(1), info.kz*data.size(2) }; std::vector<size_t> start = { info.ix * data.size( 0 ), info.jy * data.size( 1 ),
info.kz * data.size( 2 ) };
nc_put_vara( fid, varid, start.data(), count.data(), x.data() ); nc_put_vara( fid, varid, start.data(), count.data(), x.data() );
} }
template void write<short>( int fid, const std::string& var, const std::vector<int>& dimids, const Array<short>& data, const RankInfoStruct& info ); template void write<short>( int fid, const std::string &var, const std::vector<int> &dimids,
template void write<int>( int fid, const std::string& var, const std::vector<int>& dimids, const Array<int>& data, const RankInfoStruct& info ); const Array<short> &data, const RankInfoStruct &info );
template void write<float>( int fid, const std::string& var, const std::vector<int>& dimids, const Array<float>& data, const RankInfoStruct& info ); template void write<int>( int fid, const std::string &var, const std::vector<int> &dimids,
template void write<double>( int fid, const std::string& var, const std::vector<int>& dimids, const Array<double>& data, const RankInfoStruct& info ); const Array<int> &data, const RankInfoStruct &info );
template void write<float>( int fid, const std::string &var, const std::vector<int> &dimids,
const Array<float> &data, const RankInfoStruct &info );
template void write<double>( int fid, const std::string &var, const std::vector<int> &dimids,
const Array<double> &data, const RankInfoStruct &info );
}; // namespace netcdf
}; // netcdf namespace
#else #else
#endif #endif

View File

@@ -5,9 +5,8 @@
#include <vector> #include <vector>
#include "common/Array.h" #include "common/Array.h"
#include "common/MPI.h"
#include "common/Communication.h" #include "common/Communication.h"
#include "common/MPI.h"
namespace netcdf { namespace netcdf {
@@ -31,15 +30,15 @@ std::string VariableTypeName( VariableType type );
* @param filename File to open * @param filename File to open
* @param mode Open the file for reading or writing * @param mode Open the file for reading or writing
* @param comm MPI communicator to use (MPI_COMM_WORLD: don't use parallel netcdf) * @param comm MPI communicator to use (MPI_COMM_WORLD: don't use parallel netcdf)
*/ */
int open( const std::string& filename, FileMode mode, const Utilities::MPI& comm=MPI_COMM_NULL ); int open( const std::string &filename, FileMode mode, const Utilities::MPI &comm = MPI_COMM_NULL );
/*! /*!
* @brief Close netcdf file * @brief Close netcdf file
* @details This function closes a netcdf file * @details This function closes a netcdf file
* @param fid Handle to the open file * @param fid Handle to the open file
*/ */
void close( int fid ); void close( int fid );
@@ -47,7 +46,7 @@ void close( int fid );
* @brief Read the variable names * @brief Read the variable names
* @details This function reads a list of the variable names in the file * @details This function reads a list of the variable names in the file
* @param fid Handle to the open file * @param fid Handle to the open file
*/ */
std::vector<std::string> getVarNames( int fid ); std::vector<std::string> getVarNames( int fid );
@@ -55,7 +54,7 @@ std::vector<std::string> getVarNames( int fid );
* @brief Read the attribute names * @brief Read the attribute names
* @details This function reads a list of the attribute names in the file * @details This function reads a list of the attribute names in the file
* @param fid Handle to the open file * @param fid Handle to the open file
*/ */
std::vector<std::string> getAttNames( int fid ); std::vector<std::string> getAttNames( int fid );
@@ -64,8 +63,8 @@ std::vector<std::string> getAttNames( int fid );
* @details This function returns the type for a variable * @details This function returns the type for a variable
* @param fid Handle to the open file * @param fid Handle to the open file
* @param var Variable to read * @param var Variable to read
*/ */
VariableType getVarType( int fid, const std::string& var ); VariableType getVarType( int fid, const std::string &var );
/*! /*!
@@ -73,8 +72,8 @@ VariableType getVarType( int fid, const std::string& var );
* @details This function returns the type for an attribute * @details This function returns the type for an attribute
* @param fid Handle to the open file * @param fid Handle to the open file
* @param att Attribute to read * @param att Attribute to read
*/ */
VariableType getAttType( int fid, const std::string& att ); VariableType getAttType( int fid, const std::string &att );
/*! /*!
@@ -82,8 +81,8 @@ VariableType getAttType( int fid, const std::string& att );
* @details This function returns the die for a variable * @details This function returns the die for a variable
* @param fid Handle to the open file * @param fid Handle to the open file
* @param var Variable to read * @param var Variable to read
*/ */
std::vector<size_t> getVarDim( int fid, const std::string& var ); std::vector<size_t> getVarDim( int fid, const std::string &var );
/*! /*!
@@ -91,9 +90,9 @@ std::vector<size_t> getVarDim( int fid, const std::string& var );
* @details This function reads a variable with the given name from the file * @details This function reads a variable with the given name from the file
* @param fid Handle to the open file * @param fid Handle to the open file
* @param var Variable to read * @param var Variable to read
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> getVar( int fid, const std::string& var ); Array<TYPE> getVar( int fid, const std::string &var );
/*! /*!
@@ -104,10 +103,10 @@ Array<TYPE> getVar( int fid, const std::string& var );
* @param start Starting corner for the read * @param start Starting corner for the read
* @param count Number of elements to read * @param count Number of elements to read
* @param stride Stride size for the read * @param stride Stride size for the read
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> getVar( int fid, const std::string& var, const std::vector<int>& start, Array<TYPE> getVar( int fid, const std::string &var, const std::vector<int> &start,
const std::vector<int>& count, const std::vector<int>& stride ); const std::vector<int> &count, const std::vector<int> &stride );
/*! /*!
@@ -115,27 +114,29 @@ Array<TYPE> getVar( int fid, const std::string& var, const std::vector<int>& sta
* @details This function reads an attribute with the given name from the file * @details This function reads an attribute with the given name from the file
* @param fid Handle to the open file * @param fid Handle to the open file
* @param att Attribute to read * @param att Attribute to read
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> getAtt( int fid, const std::string& att ); Array<TYPE> getAtt( int fid, const std::string &att );
/*! /*!
* @brief Write the dimensions * @brief Write the dimensions
* @details This function writes the grid dimensions to netcdf. * @details This function writes the grid dimensions to netcdf.
* @param fid Handle to the open file * @param fid Handle to the open file
*/ */
std::vector<int> defDim( int fid, const std::vector<std::string>& names, const std::vector<int>& dims ); std::vector<int> defDim(
int fid, const std::vector<std::string> &names, const std::vector<int> &dims );
/*! /*!
* @brief Write a variable * @brief Write a variable
* @details This function writes a variable to netcdf. * @details This function writes a variable to netcdf.
* @param fid Handle to the open file * @param fid Handle to the open file
*/ */
template<class TYPE> template<class TYPE>
void write( int fid, const std::string& var, const std::vector<int>& dimids, const Array<TYPE>& data, const RankInfoStruct& rank_info ); void write( int fid, const std::string &var, const std::vector<int> &dimids,
const Array<TYPE> &data, const RankInfoStruct &rank_info );
}; // netcdf namespace }; // namespace netcdf
#endif #endif

View File

@@ -1,6 +1,6 @@
#include "IO/silo.h" #include "IO/silo.h"
#include "common/Utilities.h"
#include "common/MPI.h" #include "common/MPI.h"
#include "common/Utilities.h"
#include "ProfilerApp.h" #include "ProfilerApp.h"
@@ -10,14 +10,13 @@
#include <silo.h> #include <silo.h>
namespace silo { namespace silo {
/**************************************************** /****************************************************
* Open/close a file * * Open/close a file *
****************************************************/ ****************************************************/
DBfile* open( const std::string& filename, FileMode mode ) DBfile *open( const std::string &filename, FileMode mode )
{ {
DBfile *fid = nullptr; DBfile *fid = nullptr;
if ( mode == CREATE ) { if ( mode == CREATE ) {
@@ -29,18 +28,15 @@ DBfile* open( const std::string& filename, FileMode mode )
} }
return fid; return fid;
} }
void close( DBfile* fid ) void close( DBfile *fid ) { DBClose( fid ); }
{
DBClose( fid );
}
/**************************************************** /****************************************************
* Helper functions * * Helper functions *
****************************************************/ ****************************************************/
VariableDataType varDataType( DBfile *fid, const std::string& name ) VariableDataType varDataType( DBfile *fid, const std::string &name )
{ {
auto type = DBGetVarType( fid, name.c_str() ); auto type = DBGetVarType( fid, name.c_str() );
VariableDataType type2 = VariableDataType::UNKNOWN; VariableDataType type2 = VariableDataType::UNKNOWN;
if ( type == DB_DOUBLE ) if ( type == DB_DOUBLE )
type2 = VariableDataType::DOUBLE; type2 = VariableDataType::DOUBLE;
@@ -53,58 +49,57 @@ VariableDataType varDataType( DBfile *fid, const std::string& name )
/**************************************************** /****************************************************
* Write/read a uniform mesh to silo * * Write/read a uniform mesh to silo *
****************************************************/ ****************************************************/
void readUniformMesh( DBfile* fid, const std::string& meshname, void readUniformMesh(
std::vector<double>& range, std::vector<int>& N ) DBfile *fid, const std::string &meshname, std::vector<double> &range, std::vector<int> &N )
{ {
DBquadmesh* mesh = DBGetQuadmesh( fid, meshname.c_str() ); DBquadmesh *mesh = DBGetQuadmesh( fid, meshname.c_str() );
int ndim = mesh->ndims; int ndim = mesh->ndims;
range.resize(2*ndim); range.resize( 2 * ndim );
N.resize(ndim); N.resize( ndim );
for (int d=0; d<ndim; d++) { for ( int d = 0; d < ndim; d++ ) {
N[d] = mesh->dims[d]-1; N[d] = mesh->dims[d] - 1;
range[2*d+0] = mesh->min_extents[d]; range[2 * d + 0] = mesh->min_extents[d];
range[2*d+1] = mesh->max_extents[d]; range[2 * d + 1] = mesh->max_extents[d];
} }
DBFreeQuadmesh( mesh ); DBFreeQuadmesh( mesh );
} }
/**************************************************** /****************************************************
* Write a multimesh * * Write a multimesh *
****************************************************/ ****************************************************/
void writeMultiMesh( DBfile* fid, const std::string& meshname, void writeMultiMesh( DBfile *fid, const std::string &meshname,
const std::vector<std::string>& meshNames, const std::vector<std::string> &meshNames, const std::vector<int> &meshTypes )
const std::vector<int>& meshTypes )
{ {
std::vector<char*> meshnames(meshNames.size()); std::vector<char *> meshnames( meshNames.size() );
for ( size_t i = 0; i < meshNames.size(); ++i ) for ( size_t i = 0; i < meshNames.size(); ++i )
meshnames[i] = (char *) meshNames[i].c_str(); meshnames[i] = (char *) meshNames[i].c_str();
std::string tree_name = meshname + "_tree"; std::string tree_name = meshname + "_tree";
DBoptlist *optList = DBMakeOptlist( 1 ); DBoptlist *optList = DBMakeOptlist( 1 );
DBAddOption( optList, DBOPT_MRGTREE_NAME, (char *) tree_name.c_str() ); DBAddOption( optList, DBOPT_MRGTREE_NAME, (char *) tree_name.c_str() );
DBPutMultimesh( fid, meshname.c_str(), meshNames.size(), meshnames.data(), (int*) meshTypes.data(), nullptr ); DBPutMultimesh( fid, meshname.c_str(), meshNames.size(), meshnames.data(),
(int *) meshTypes.data(), nullptr );
DBFreeOptlist( optList ); DBFreeOptlist( optList );
} }
/**************************************************** /****************************************************
* Write a multivariable * * Write a multivariable *
****************************************************/ ****************************************************/
void writeMultiVar( DBfile* fid, const std::string& varname, void writeMultiVar( DBfile *fid, const std::string &varname,
const std::vector<std::string>& varNames, const std::vector<std::string> &varNames, const std::vector<int> &varTypes )
const std::vector<int>& varTypes )
{ {
std::vector<char*> varnames(varNames.size(),nullptr); std::vector<char *> varnames( varNames.size(), nullptr );
for (size_t j=0; j<varNames.size(); j++) for ( size_t j = 0; j < varNames.size(); j++ )
varnames[j] = const_cast<char*>(varNames[j].c_str()); varnames[j] = const_cast<char *>( varNames[j].c_str() );
DBPutMultivar( fid, varname.c_str(), varNames.size(), varnames.data(), (int*) varTypes.data(), nullptr ); DBPutMultivar(
fid, varname.c_str(), varNames.size(), varnames.data(), (int *) varTypes.data(), nullptr );
} }
}; // namespace silo
}; // silo namespace
#else #else

119
IO/silo.h
View File

@@ -1,29 +1,34 @@
#ifndef SILO_INTERFACE #ifndef SILO_INTERFACE
#define SILO_INTERFACE #define SILO_INTERFACE
#include <array>
#include <string> #include <string>
#include <vector> #include <vector>
#include <array>
#include "common/Array.h" #include "common/Array.h"
#include "common/MPI.h"
#include "common/Communication.h" #include "common/Communication.h"
#include "common/MPI.h"
#ifdef USE_SILO #ifdef USE_SILO
#include <silo.h> #include <silo.h>
#else #else
typedef int DBfile; typedef int DBfile;
#endif #endif
namespace silo { namespace silo {
enum FileMode { READ, WRITE, CREATE }; enum FileMode { READ, WRITE, CREATE };
enum class VariableType : int { NodeVariable=1, EdgeVariable=2, SurfaceVariable=2, VolumeVariable=3, NullVariable=0 }; enum class VariableType : int {
NodeVariable = 1,
EdgeVariable = 2,
SurfaceVariable = 2,
VolumeVariable = 3,
NullVariable = 0
};
enum class VariableDataType { DOUBLE, FLOAT, INT, UNKNOWN }; enum class VariableDataType { DOUBLE, FLOAT, INT, UNKNOWN };
@@ -34,16 +39,16 @@ enum class VariableDataType { DOUBLE, FLOAT, INT, UNKNOWN };
* @param[in] filename File to open * @param[in] filename File to open
* @param[in] mode Open the file for reading or writing * @param[in] mode Open the file for reading or writing
* @return This function returns a handle to the file * @return This function returns a handle to the file
*/ */
DBfile* open( const std::string& filename, FileMode mode ); DBfile *open( const std::string &filename, FileMode mode );
/*! /*!
* @brief Close silo file * @brief Close silo file
* @details This function closes a silo file * @details This function closes a silo file
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
*/ */
void close( DBfile* fid ); void close( DBfile *fid );
/*! /*!
@@ -51,8 +56,8 @@ void close( DBfile* fid );
* @details This function returns the type of variable data * @details This function returns the type of variable data
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] name Name of variable * @param[in] name Name of variable
*/ */
VariableDataType varDataType( DBfile *dbfile, const std::string& name ); VariableDataType varDataType( DBfile *dbfile, const std::string &name );
/*! /*!
@@ -61,9 +66,9 @@ VariableDataType varDataType( DBfile *dbfile, const std::string& name );
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] varname Variable name * @param[in] varname Variable name
* @param[in] data Data to write * @param[in] data Data to write
*/ */
template<class TYPE> template<class TYPE>
void write( DBfile* fid, const std::string& varname, const std::vector<TYPE>& data ); void write( DBfile *fid, const std::string &varname, const std::vector<TYPE> &data );
/*! /*!
@@ -72,9 +77,9 @@ void write( DBfile* fid, const std::string& varname, const std::vector<TYPE>& da
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] varname Variable name * @param[in] varname Variable name
* @return Data read * @return Data read
*/ */
template<class TYPE> template<class TYPE>
std::vector<TYPE> read( DBfile* fid, const std::string& varname ); std::vector<TYPE> read( DBfile *fid, const std::string &varname );
/*! /*!
@@ -84,10 +89,10 @@ std::vector<TYPE> read( DBfile* fid, const std::string& varname );
* @param[in] meshname Mesh name * @param[in] meshname Mesh name
* @param[in] range Range of mesh { xmin, xmax, ymin, ymax, zmin, zmax } * @param[in] range Range of mesh { xmin, xmax, ymin, ymax, zmin, zmax }
* @param[in] N Number of cells in each direction * @param[in] N Number of cells in each direction
*/ */
template<int NDIM> template<int NDIM>
void writeUniformMesh( DBfile* fid, const std::string& meshname, void writeUniformMesh( DBfile *fid, const std::string &meshname,
const std::array<double,2*NDIM>& range, const std::array<int,NDIM>& N ); const std::array<double, 2 * NDIM> &range, const std::array<int, NDIM> &N );
/*! /*!
@@ -97,9 +102,9 @@ void writeUniformMesh( DBfile* fid, const std::string& meshname,
* @param[in] meshname Mesh name * @param[in] meshname Mesh name
* @param[out] range Range of mesh { xmin, xmax, ymin, ymax, zmin, zmax } * @param[out] range Range of mesh { xmin, xmax, ymin, ymax, zmin, zmax }
* @param[out] N Number of cells in each direction * @param[out] N Number of cells in each direction
*/ */
void readUniformMesh( DBfile* fid, const std::string& meshname, void readUniformMesh(
std::vector<double>& range, std::vector<int>& N ); DBfile *fid, const std::string &meshname, std::vector<double> &range, std::vector<int> &N );
/*! /*!
@@ -111,10 +116,11 @@ void readUniformMesh( DBfile* fid, const std::string& meshname,
* @param[in] varname Variable name * @param[in] varname Variable name
* @param[in] data Variable data * @param[in] data Variable data
* @param[in] type Variable type * @param[in] type Variable type
*/ */
template< int NDIM, class TYPE > template<int NDIM, class TYPE>
void writeUniformMeshVariable( DBfile* fid, const std::string& meshname, const std::array<int,NDIM>& N, void writeUniformMeshVariable( DBfile *fid, const std::string &meshname,
const std::string& varname, const Array<TYPE>& data, VariableType type ); const std::array<int, NDIM> &N, const std::string &varname, const Array<TYPE> &data,
VariableType type );
/*! /*!
@@ -123,9 +129,9 @@ void writeUniformMeshVariable( DBfile* fid, const std::string& meshname, const s
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] varname Variable name * @param[in] varname Variable name
* @return Variable data * @return Variable data
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> readUniformMeshVariable( DBfile* fid, const std::string& varname ); Array<TYPE> readUniformMeshVariable( DBfile *fid, const std::string &varname );
/*! /*!
@@ -136,10 +142,10 @@ Array<TYPE> readUniformMeshVariable( DBfile* fid, const std::string& varname );
* @param[in] ndim Number of dimensions * @param[in] ndim Number of dimensions
* @param[in] N Number of points * @param[in] N Number of points
* @param[in] coords Coordinates of the points * @param[in] coords Coordinates of the points
*/ */
template<class TYPE> template<class TYPE>
void writePointMesh( DBfile* fid, const std::string& meshname, void writePointMesh(
int ndim, int N, const TYPE *coords[] ); DBfile *fid, const std::string &meshname, int ndim, int N, const TYPE *coords[] );
/*! /*!
@@ -148,9 +154,9 @@ void writePointMesh( DBfile* fid, const std::string& meshname,
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] meshname Mesh name * @param[in] meshname Mesh name
* @return Returns the coordinates as a N x ndim array * @return Returns the coordinates as a N x ndim array
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> readPointMesh( DBfile* fid, const std::string& meshname ); Array<TYPE> readPointMesh( DBfile *fid, const std::string &meshname );
/*! /*!
@@ -160,10 +166,10 @@ Array<TYPE> readPointMesh( DBfile* fid, const std::string& meshname );
* @param[in] meshname Mesh name * @param[in] meshname Mesh name
* @param[in] varname Variable name * @param[in] varname Variable name
* @param[in] data Variable data * @param[in] data Variable data
*/ */
template<class TYPE> template<class TYPE>
void writePointMeshVariable( DBfile* fid, const std::string& meshname, void writePointMeshVariable(
const std::string& varname, const Array<TYPE>& data ); DBfile *fid, const std::string &meshname, const std::string &varname, const Array<TYPE> &data );
/*! /*!
@@ -172,9 +178,9 @@ void writePointMeshVariable( DBfile* fid, const std::string& meshname,
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] varname Variable name * @param[in] varname Variable name
* @return Variable data * @return Variable data
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> readPointMeshVariable( DBfile* fid, const std::string& varname ); Array<TYPE> readPointMeshVariable( DBfile *fid, const std::string &varname );
/*! /*!
@@ -188,10 +194,10 @@ Array<TYPE> readPointMeshVariable( DBfile* fid, const std::string& varname );
* @param[in] coords Coordinates of the points * @param[in] coords Coordinates of the points
* @param[in] N_tri Number of triangles * @param[in] N_tri Number of triangles
* @param[in] tri Coordinates of the points * @param[in] tri Coordinates of the points
*/ */
template<class TYPE> template<class TYPE>
void writeTriMesh( DBfile* fid, const std::string& meshname, void writeTriMesh( DBfile *fid, const std::string &meshname, int ndim, int ndim_tri, int N,
int ndim, int ndim_tri, int N, const TYPE *coords[], int N_tri, const int *tri[] ); const TYPE *coords[], int N_tri, const int *tri[] );
/*! /*!
@@ -201,9 +207,9 @@ void writeTriMesh( DBfile* fid, const std::string& meshname,
* @param[in] meshname Mesh name * @param[in] meshname Mesh name
* @param[in] coords Coordinates of the points * @param[in] coords Coordinates of the points
* @param[in] tri Coordinates of the points * @param[in] tri Coordinates of the points
*/ */
template<class TYPE> template<class TYPE>
void readTriMesh( DBfile* fid, const std::string& meshname, Array<TYPE>& coords, Array<int>& tri ); void readTriMesh( DBfile *fid, const std::string &meshname, Array<TYPE> &coords, Array<int> &tri );
/*! /*!
@@ -215,10 +221,10 @@ void readTriMesh( DBfile* fid, const std::string& meshname, Array<TYPE>& coords,
* @param[in] varname Variable name * @param[in] varname Variable name
* @param[in] data Variable data * @param[in] data Variable data
* @param[in] type Variable type * @param[in] type Variable type
*/ */
template<class TYPE> template<class TYPE>
void writeTriMeshVariable( DBfile* fid, int ndim, const std::string& meshname, void writeTriMeshVariable( DBfile *fid, int ndim, const std::string &meshname,
const std::string& varname, const Array<TYPE>& data, VariableType type ); const std::string &varname, const Array<TYPE> &data, VariableType type );
/*! /*!
@@ -227,9 +233,9 @@ void writeTriMeshVariable( DBfile* fid, int ndim, const std::string& meshname,
* @param[in] fid Handle to the open file * @param[in] fid Handle to the open file
* @param[in] varname Variable name * @param[in] varname Variable name
* @return Variable data * @return Variable data
*/ */
template<class TYPE> template<class TYPE>
Array<TYPE> readTriMeshVariable( DBfile* fid, const std::string& varname ); Array<TYPE> readTriMeshVariable( DBfile *fid, const std::string &varname );
/*! /*!
@@ -239,10 +245,9 @@ Array<TYPE> readTriMeshVariable( DBfile* fid, const std::string& varname );
* @param[in] meshname Mesh name * @param[in] meshname Mesh name
* @param[in] subMeshNames Names of the sub meshes in the form "filename:meshname" * @param[in] subMeshNames Names of the sub meshes in the form "filename:meshname"
* @param[in] subMeshTypes Type of each submesh * @param[in] subMeshTypes Type of each submesh
*/ */
void writeMultiMesh( DBfile* fid, const std::string& meshname, void writeMultiMesh( DBfile *fid, const std::string &meshname,
const std::vector<std::string>& subMeshNames, const std::vector<std::string> &subMeshNames, const std::vector<int> &subMeshTypes );
const std::vector<int>& subMeshTypes );
/*! /*!
@@ -255,14 +260,12 @@ void writeMultiMesh( DBfile* fid, const std::string& meshname,
* @param[in] subVarTypes Type of each submesh * @param[in] subVarTypes Type of each submesh
* @param[in] ndim Dimension of variable (used to determine suffix) * @param[in] ndim Dimension of variable (used to determine suffix)
* @param[in] nvar Number of subvariables (used to determine suffix) * @param[in] nvar Number of subvariables (used to determine suffix)
*/ */
void writeMultiVar( DBfile* fid, const std::string& varname, void writeMultiVar( DBfile *fid, const std::string &varname,
const std::vector<std::string>& subVarNames, const std::vector<std::string> &subVarNames, const std::vector<int> &subVarTypes );
const std::vector<int>& subVarTypes );
}; // silo namespace }; // namespace silo
#endif #endif
#include "IO/silo.hpp" #include "IO/silo.hpp"

View File

@@ -35,7 +35,7 @@ ADD_LBPM_EXECUTABLE( GenerateSphereTest )
#ADD_LBPM_EXECUTABLE( BlobAnalysis ) #ADD_LBPM_EXECUTABLE( BlobAnalysis )
#ADD_LBPM_EXECUTABLE( BlobIdentify ) #ADD_LBPM_EXECUTABLE( BlobIdentify )
#ADD_LBPM_EXECUTABLE( BlobIdentifyParallel ) #ADD_LBPM_EXECUTABLE( BlobIdentifyParallel )
#ADD_LBPM_EXECUTABLE( convertIO ) ADD_LBPM_EXECUTABLE( convertIO )
#ADD_LBPM_EXECUTABLE( DataAggregator ) #ADD_LBPM_EXECUTABLE( DataAggregator )
#ADD_LBPM_EXECUTABLE( BlobAnalyzeParallel )( #ADD_LBPM_EXECUTABLE( BlobAnalyzeParallel )(
ADD_LBPM_EXECUTABLE( lbpm_minkowski_scalar ) ADD_LBPM_EXECUTABLE( lbpm_minkowski_scalar )

View File

@@ -159,7 +159,7 @@ void testWriter( const std::string& format, std::vector<IO::MeshDataStruct>& mes
// Test the simple read interface // Test the simple read interface
bool pass = true; bool pass = true;
for ( const auto& timestep : timesteps ) { for ( const auto& timestep : timesteps ) {
auto data = IO::readData( path, timestep ); auto data = IO::readData( path, timestep, comm.getRank() );
pass = pass && data.size() == meshData.size(); pass = pass && data.size() == meshData.size();
for ( size_t i=0; i<data.size(); i++ ) { for ( size_t i=0; i<data.size(); i++ ) {
pass = pass && checkMesh( meshData, format, data[i].mesh ); pass = pass && checkMesh( meshData, format, data[i].mesh );

View File

@@ -5,8 +5,7 @@
#include <stdexcept> #include <stdexcept>
#include <fstream> #include <fstream>
#include "common/MPI_Helpers.h" #include "common/MPI.h"
#include "common/Communication.h"
#include "common/Utilities.h" #include "common/Utilities.h"
#include "IO/Mesh.h" #include "IO/Mesh.h"
#include "IO/Reader.h" #include "IO/Reader.h"
@@ -16,74 +15,56 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// Initialize MPI // Initialize MPI
Utilities::startup( argc, argv ); Utilities::startup( argc, argv );
Utilities::MPI comm( MPI_COMM_WORLD ); Utilities::setErrorHandlers();
int rank = comm.getRank(); PROFILE_ENABLE(2);
int nprocs = comm.getSize(); PROFILE_ENABLE_TRACE();
Utilities::setErrorHandlers(); PROFILE_START("Main");
PROFILE_ENABLE(2);
PROFILE_ENABLE_TRACE();
PROFILE_START("Main");
{ // Limit scope
// Get inputs { // Limit scope
if ( argc != 3 ) {
std::cerr << "Error calling convertIO:\n";
std::cerr << " convertIO input_file format\n";
return -1;
}
std::string filename = argv[1];
std::string format = argv[2];
std::string path = IO::getPath( filename );
// Read the timesteps Utilities::MPI comm( MPI_COMM_WORLD );
auto timesteps = IO::readTimesteps( filename, "old" ); // Get inputs
if ( argc != 5 ) {
// Loop through the timesteps, reading/writing the data std::cerr << "Error calling convertIO:\n";
IO::initialize( "", format, false ); std::cerr << " convertIO <input_path> <input_format> <output_path> <output_format>\n";
for ( auto timestep : timesteps ) { return -1;
// Read the list of MeshDatabase
auto databases = IO::getMeshList( path, timestep );
// Build the MeshDataStruct
std::vector<IO::MeshDataStruct> meshData(databases.size());
// Loop through the database
int i = 0;
PROFILE_START("Read");
for ( const auto& database : databases ) {
// Read the appropriate mesh domain
ASSERT( (int) database.domains.size() == nprocs );
meshData[i].meshName = database.name;
meshData[i].mesh = IO::getMesh( path, timestep, database, rank );
// Read the variables
for ( auto var : database.variables ) {
auto varData = IO::getVariable( path, timestep, database, rank, var.name );
IO::reformatVariable( *meshData[i].mesh, *varData );
meshData[i].vars.push_back( varData );
}
i++;
} }
MPI_Barrier(comm); std::string path_in = argv[1];
PROFILE_STOP("Read"); std::string format_in = argv[2];
std::string path_out = argv[3];
std::string format_out = argv[4];
// Save the mesh data to a new file // Check that we have enough ranks to load and write the data
PROFILE_START("Write"); // This is really only a bottleneck for the writer
IO::writeData( timestep, meshData, MPI_COMM_WORLD ); int N_domains = IO::maxDomains( path_in, format_in, comm );
MPI_Barrier(comm); ASSERT( comm.getSize() == N_domains );
PROFILE_STOP("Write");
}
} // Limit scope // Read the timesteps
PROFILE_STOP("Main"); auto timesteps = IO::readTimesteps( path_in, format_in );
PROFILE_SAVE("convertData",true);
comm.barrier(); // Loop through the timesteps, reading/writing the data
Utilities::shutdown(); IO::initialize( path_out, format_out, false );
return 0; for ( auto timestep : timesteps ) {
// Set the domain to read (needs to be the current rank for the writer to be valid)
int domain = comm.getRank();
// Get the maximum number of domains for the
auto data = IO::readData( path_in, timestep, domain );
// Save the mesh data to a new file
IO::writeData( timestep, data, comm );
}
} // Limit scope
// shutdown
PROFILE_STOP("Main");
PROFILE_SAVE("convertData",true);
Utilities::shutdown();
return 0;
} }