diff --git a/IO/IOHelpers.h b/IO/IOHelpers.h new file mode 100644 index 00000000..2e9b06e0 --- /dev/null +++ b/IO/IOHelpers.h @@ -0,0 +1,64 @@ +#ifndef IO_HELPERS_INC +#define IO_HELPERS_INC + +#include +#include + +namespace IO { + + +// Find a character in a line +inline size_t find( const char *line, char token ) +{ + size_t i=0; + while ( 1 ) { + if ( line[i]==token || line[i]<32 || line[i]==0 ) + break; + ++i; + } + return i; +} + + +// Remove preceeding/trailing whitespace +inline std::string deblank( const std::string& str ) +{ + size_t i1 = str.size(); + size_t i2 = 0; + for (size_t i=0; i=32 ) { + i1 = std::min(i1,i); + i2 = std::max(i2,i); + } + } + return str.substr(i1,i2-i1+1); +} + + +// Split a list by the given token +inline std::vector splitList( const char *line, const char token ) +{ + std::vector list; + size_t i1 = 0; + size_t i2 = 0; + while ( 1 ) { + if ( line[i2]==token || line[i2]<32 ) { + std::string tmp(&line[i1],i2-i1); + tmp = deblank(tmp); + if ( !tmp.empty() ) + list.push_back(tmp); + i1 = i2+1; + } + if ( line[i2]==0 ) + break; + i2++; + } + return list; +} + + + +}; + +#endif + diff --git a/IO/Mesh.h b/IO/Mesh.h index 449a052f..f44ed081 100644 --- a/IO/Mesh.h +++ b/IO/Mesh.h @@ -122,12 +122,14 @@ public: struct Variable { public: - //! Internal variables - int dim; - std::string name; - std::vector data; + enum class VariableType : unsigned char { NodeVariable=1, EdgeVariable=2, SurfaceVariable=2, VolumeVariable=3, Null=0 }; + // Internal variables + unsigned int dim; //!< Number of points per grid point (1: scalar, 3: vector, ...) + VariableType type; //!< Variable type + std::string name; //!< Variable name + std::vector data; //!< Variable data //! Empty constructor - Variable() {} + Variable(): type(VariableType::Null) {} //! Destructor virtual ~Variable() {} protected: diff --git a/IO/MeshDatabase.cpp b/IO/MeshDatabase.cpp index 4a7fa6c6..be583309 100644 --- a/IO/MeshDatabase.cpp +++ b/IO/MeshDatabase.cpp @@ -1,5 +1,6 @@ #include "IO/MeshDatabase.h" #include "IO/Mesh.h" +#include "IO/IOHelpers.h" #include "common/Utilities.h" #include @@ -11,21 +12,6 @@ namespace IO { -// Remove preceeding/trailing whitespace -inline std::string deblank( const std::string& str ) -{ - size_t i1 = str.size(); - size_t i2 = 0; - for (size_t i=0; i=32 ) { - i1 = std::min(i1,i); - i2 = std::max(i2,i); - } - } - return str.substr(i1,i2-i1+1); -} - - /**************************************************** * Pack/unpack data from a buffer * @@ -281,40 +267,6 @@ MeshDatabase& MeshDatabase::operator=(const MeshDatabase& rhs) } -/**************************************************** -* Split a line into pieces * -****************************************************/ -static inline size_t find( const char *line, char key ) -{ - size_t i=0; - while ( 1 ) { - if ( line[i]==key || line[i]<32 || line[i]==0 ) - break; - ++i; - } - return i; -} -static inline std::vector splitList( const char *line ) -{ - std::vector list; - size_t i1 = 0; - size_t i2 = 0; - while ( 1 ) { - if ( line[i2]==';' || line[i2]<32 ) { - std::string tmp(&line[i1],i2-i1); - tmp = deblank(tmp); - if ( !tmp.empty() ) - list.push_back(tmp); - i1 = i2+1; - } - if ( line[i2]==0 ) - break; - i2++; - } - return list; -} - - /**************************************************** * DatabaseEntry * ****************************************************/ @@ -326,21 +278,21 @@ std::string DatabaseEntry::write( ) const } DatabaseEntry::DatabaseEntry( const char* line ) { - std::vector list = splitList(line); + std::vector list = splitList(line,';'); name = list[0]; file = list[1]; offset = atol(list[2].c_str()); } void DatabaseEntry::read( const char* line ) { - std::vector list = splitList(line); + std::vector list = splitList(line,';'); name = list[0]; file = list[1]; offset = atol(list[2].c_str()); } void DatabaseEntry::read( const std::string& line ) { - std::vector list = splitList(line.c_str()); + std::vector list = splitList(line.c_str(),';'); name = list[0]; file = list[1]; offset = atol(list[2].c_str()); @@ -454,8 +406,8 @@ std::vector read( const std::string& filename ) FILE *fid = fopen(filename.c_str(),"rb"); if ( fid==NULL ) ERROR("Error opening file"); - char *line = new char[0x100000]; - while ( std::fgets(line,0x100000,fid) != NULL ) { + char *line = new char[10000]; + while ( std::fgets(line,1000,fid) != NULL ) { if ( line[0]<32 ) { // Empty line continue; @@ -474,12 +426,12 @@ std::vector read( const std::string& filename ) DatabaseEntry data(&line[10]); meshes.back().domains.push_back(data); } else if ( strncmp(line," variables:",13)==0 ) { - meshes.back().variables = splitList(&line[13]); + meshes.back().variables = splitList(&line[13],';'); } else if ( strncmp(line," variable(",12)==0 ) { size_t i1 = find(line,','); size_t i2 = find(line,':'); - std::string domain = deblank(std::string(line,13,i1-13)); - std::string variable = deblank(std::string(line,i1+1,i2-i1)); + std::string domain = deblank(std::string(line,12,i1-12)); + std::string variable = deblank(std::string(line,i1+1,i2-i1-2)); std::pair key(domain,variable); DatabaseEntry data(&line[i2+1]); meshes.back().variable_data.insert( diff --git a/IO/Reader.cpp b/IO/Reader.cpp index 9ac1c5a7..ad5229eb 100644 --- a/IO/Reader.cpp +++ b/IO/Reader.cpp @@ -1,6 +1,7 @@ #include "IO/Reader.h" #include "IO/Mesh.h" #include "IO/MeshDatabase.h" +#include "IO/IOHelpers.h" #include "common/Utilities.h" #include @@ -8,34 +9,7 @@ #include #include #include - - -// Helper function -static inline size_t find( const char *line, char key ) -{ - size_t i=0; - while ( 1 ) { - if ( line[i]==key || line[i]<32 || line[i]==0 ) - break; - ++i; - } - return i; -} - - -// Remove preceeding/trailing whitespace -inline std::string deblank( const std::string& str ) -{ - size_t i1 = str.size(); - size_t i2 = 0; - for (size_t i=0; i=32 ) { - i1 = std::min(i1,i); - i2 = std::max(i2,i); - } - } - return str.substr(i1,i2-i1+1); -} +#include @@ -129,13 +103,14 @@ std::shared_ptr IO::getMesh( const std::string& path, const std::strin FILE *fid = fopen(filename.c_str(),"rb"); fseek(fid,database.offset,SEEK_SET); char line[1000]; - std::fgets(line,0x100000,fid); + std::fgets(line,1000,fid); size_t i1 = find(line,':'); size_t i2 = find(&line[i1+1],':')+i1+1; size_t bytes = atol(&line[i2+1]); char *data = new char[bytes]; size_t count = fread(data,1,bytes,fid); fclose(fid); + ASSERT(count==bytes); if ( meshDatabase.meshClass=="PointList" ) { mesh.reset( new IO::PointList() ); } else if ( meshDatabase.meshClass=="TriMesh" ) { @@ -159,7 +134,43 @@ std::shared_ptr IO::getMesh( const std::string& path, const std::strin std::shared_ptr IO::getVariable( const std::string& path, const std::string& timestep, const MeshDatabase& meshDatabase, int domain, const std::string& variable ) { - return std::shared_ptr(); + std::pair key(meshDatabase.domains[domain].name,variable); + std::map,DatabaseEntry>::const_iterator it; + it = meshDatabase.variable_data.find(key); + if ( it==meshDatabase.variable_data.end() ) + return std::shared_ptr(); + const DatabaseEntry& database = it->second; + std::string filename = path + "/" + timestep + "/" + database.file; + FILE *fid = fopen(filename.c_str(),"rb"); + fseek(fid,database.offset,SEEK_SET); + char line[1000]; + std::fgets(line,1000,fid); + size_t i1 = find(line,':'); + size_t i2 = find(&line[i1+1],':')+i1+1; + std::vector values = splitList(&line[i2+1],','); + ASSERT(values.size()==5); + int dim = atoi(values[0].c_str()); + int type = atoi(values[1].c_str()); + size_t N = atol(values[2].c_str()); + size_t bytes = atol(values[3].c_str()); + std::string precision = values[4]; + char *data = new char[bytes]; + size_t count = fread(data,1,bytes,fid); + fclose(fid); + ASSERT(count==bytes); + std::shared_ptr var( new IO::Variable() ); + var->dim = dim; + var->type = static_cast(type); + var->name = variable; + var->data.resize(N); + double *var_data = var->data.data(); + if ( precision=="double" ) { + memcpy(var_data,data,bytes); + } else { + ERROR("Format not implimented"); + } + delete [] data; + return var; } diff --git a/IO/Writer.cpp b/IO/Writer.cpp index 4a70b53e..86317a09 100644 --- a/IO/Writer.cpp +++ b/IO/Writer.cpp @@ -1,5 +1,6 @@ #include "IO/Writer.h" #include "IO/MeshDatabase.h" +#include "IO/IOHelpers.h" #include "common/Utilities.h" #include "mpi.h" @@ -37,8 +38,8 @@ static std::vector writeMeshesOrigFormat( const std::vectorname ); + //for (size_t j=0; jname ); } if ( std::dynamic_pointer_cast(mesh)!=NULL ) { // List of points @@ -110,10 +111,12 @@ static IO::MeshDatabase write_domain( FILE *fid, const std::string& filename, database.variable_data.insert( std::pair,IO::DatabaseEntry>(key,variable) ); int dim = mesh.vars[i]->dim; + int type = static_cast(mesh.vars[i]->type); size_t N = mesh.vars[i]->data.size(); const void* data = N==0 ? 0:&mesh.vars[i]->data[0]; - fprintf(fid,"Var: %s-%05i-%s: %i, %lu, %lu, double\n", - database.name.c_str(),rank,variable.name.c_str(),dim,N,dim*N*sizeof(double)); + fprintf(fid,"Var: %s-%05i-%s: %i, %i, %lu, %lu, double\n", + database.name.c_str(), rank, variable.name.c_str(), + dim, type, N, dim*N*sizeof(double) ); fwrite(data,sizeof(double),dim*N,fid); fprintf(fid,"\n"); } diff --git a/tests/TestWriter.cpp b/tests/TestWriter.cpp index 33173e8d..f8ef98f5 100644 --- a/tests/TestWriter.cpp +++ b/tests/TestWriter.cpp @@ -16,9 +16,13 @@ inline bool approx_equal( const Point& A, const Point& B ) { - double tol = 1e-8*(A.x*A.x+A.y*A.y+A.z*A.z); + double tol = 1e-8*sqrt(A.x*A.x+A.y*A.y+A.z*A.z); return fabs(A.x-B.x)<=tol && fabs(A.y-B.y)<=tol && fabs(A.z-B.z)<=tol; } +inline bool approx_equal( const double& A, const double& B ) +{ + return fabs(A-B)<=1e-8*fabs(A+B); +} inline double distance( const Point& p ) @@ -83,6 +87,8 @@ int main(int argc, char **argv) dist_trimesh->dim = 1; dist_set1->name = "Distance"; dist_trimesh->name = "Distance"; + dist_set1->type = IO::Variable::VariableType::NodeVariable; + dist_trimesh->type = IO::Variable::VariableType::NodeVariable; dist_set1->data.resize( N_points ); for (int i=0; idata[i] = distance(set1->points[i]); @@ -196,10 +202,36 @@ int main(int argc, char **argv) continue; } // For each domain, load the variables and check their data + if ( i==0 ) + continue; // Format 1 does not support variables for (size_t j=0; j var = IO::getVariable(".",timesteps[i],list[j],k,list[i].variables[v]); + const IO::MeshDataStruct* mesh0 = NULL; + for (size_t k=0; k variable = + IO::getVariable(".",timesteps[i],list[j],k,list[j].variables[v]); + const IO::Variable& var1 = *mesh0->vars[v]; + const IO::Variable& var2 = *variable; + pass = var1.name == var2.name; + pass = pass && var1.dim == var2.dim; + pass = pass && var1.type == var2.type; + pass = pass && var1.data.size() == var2.data.size(); + if ( pass ) { + for (size_t m=0; mAddExpression(&expr); } + // Add the variables + } DebugStream::Stream1() << " Finished" << std::endl;