#include #include #include #include #include #include #include "shared_ptr.h" #include "common/UnitTest.h" #include "common/Utilities.h" #include "common/MPI_Helpers.h" #include "IO/MeshDatabase.h" #include "IO/Reader.h" #include "IO/Writer.h" inline bool approx_equal( const Point& A, const Point& B ) { 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 ) { return sqrt(p.x*p.x+p.y*p.y+p.z*p.z); } int main(int argc, char **argv) { int rank,nprocs; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&nprocs); Utilities::setAbortBehavior(true,true,false); Utilities::setErrorHandlers(); UnitTest ut; // Create some points const int N_points = 8; const int N_tri = 12; double x[8] = { 0, 1, 0, 1, 0, 1, 0, 1 }; double y[8] = { 0, 0, 1, 1, 0, 0, 1, 1 }; double z[8] = { 0, 0, 0, 0, 1, 1, 1, 1 }; int tri[N_tri][3] = { {0,1,3}, {0,3,2}, {4,5,7}, {4,7,6}, // z faces {0,1,4}, {1,4,5}, {2,3,6}, {3,6,7}, // y faces {0,2,4}, {2,4,6}, {1,3,5}, {3,5,7} // x faces }; // Create the meshes std::shared_ptr set1( new IO::PointList(N_points) ); for (int i=0; ipoints[i].x = x[i]; set1->points[i].y = y[i]; set1->points[i].z = z[i]; } std::shared_ptr trimesh( new IO::TriMesh(N_tri,set1) ); for (int i=0; iA[i] = tri[i][0]; trimesh->B[i] = tri[i][1]; trimesh->C[i] = tri[i][2]; } std::shared_ptr trilist( new IO::TriList(*trimesh) ); for (int i=0; iA[i],A) || !approx_equal(trilist->B[i],B) || !approx_equal(trilist->C[i],C) ) { printf("Failed to create trilist\n"); return -1; } } RankInfoStruct rank_data( rank, nprocs, 1, 1 ); std::shared_ptr domain( new IO::DomainMesh(rank_data,6,7,8,1.0,1.0,1.0) ); // Create the variables std::shared_ptr dist_set1( new IO::Variable() ); std::shared_ptr dist_list( new IO::Variable() ); std::shared_ptr domain_var( new IO::Variable() ); dist_set1->dim = 1; dist_list->dim = 1; domain_var->dim = 1; dist_set1->name = "Distance"; dist_list->name = "Distance"; domain_var->name = "Distance"; dist_set1->type = IO::NodeVariable; dist_list->type = IO::NodeVariable; domain_var->type = IO::VolumeVariable; dist_set1->data.resize( N_points ); for (int i=0; idata(i) = distance(set1->points[i]); dist_list->data.resize( 3, N_tri ); for (int i=0; idata(0,i) = distance(trilist->A[i]); dist_list->data(1,i) = distance(trilist->B[i]); dist_list->data(2,i) = distance(trilist->C[i]); } domain_var->data.resize(domain->nx,domain->ny,domain->nz); for (int i=0; inx; i++) { for (int j=0; jny; j++) { for (int k=0; knz; k++) { domain_var->data(i,j,k) = distance(Point(i,j,k)); } } } // Create the MeshDataStruct std::vector meshData(4); meshData[0].meshName = "pointmesh"; meshData[0].mesh = set1; meshData[0].vars.push_back(dist_set1); meshData[1].meshName = "trimesh"; meshData[1].mesh = trimesh; meshData[1].vars.push_back(dist_set1); meshData[2].meshName = "trilist"; meshData[2].mesh = trilist; meshData[2].vars.push_back(dist_list); meshData[3].meshName = "domain"; meshData[3].mesh = domain; meshData[3].vars.push_back(domain_var); // Write the data std::vector format(2,0); format[0] = 2; format[1] = 1; IO::writeData( 0, meshData, format[0] ); IO::writeData( 3, meshData, format[1] ); MPI_Barrier(MPI_COMM_WORLD); // Get a list of the timesteps std::vector timesteps = IO::readTimesteps("summary.LBM"); if ( timesteps.size()==2 ) ut.passes("Corrent number of timesteps"); else ut.failure("Incorrent number of timesteps"); // Check the mesh lists for (size_t i=0; i list = IO::getMeshList(".",timesteps[i]); if ( list.size()==meshData.size() ) ut.passes("Corrent number of meshes found"); else ut.failure("Incorrent number of meshes found"); // Check the number of domains for each mesh bool pass = true; for (size_t j=0; j mesh = IO::getMesh(".",timesteps[i],list[j],k); if ( mesh.get()==NULL ) { printf("Failed to load %s\n",list[j].name.c_str()); pass = false; break; } if ( list[j].name=="pointmesh" ) { // Check the pointmesh std::shared_ptr pmesh = IO::getPointList(mesh); if ( pmesh.get()==NULL ) { pass = false; break; } if ( pmesh->points.size()!=N_points ) { pass = false; break; } } if ( list[j].name=="trimesh" || list[j].name=="trilist" ) { // Check the trimesh/trilist std::shared_ptr mesh1 = IO::getTriMesh(mesh); std::shared_ptr mesh2 = IO::getTriList(mesh); if ( mesh1.get()==NULL || mesh2.get()==NULL ) { pass = false; break; } if ( mesh1->A.size()!=N_tri || mesh1->B.size()!=N_tri || mesh1->C.size()!=N_tri || mesh2->A.size()!=N_tri || mesh2->B.size()!=N_tri || mesh2->C.size()!=N_tri ) { pass = false; break; } const std::vector& P1 = mesh1->vertices->points; const std::vector& A1 = mesh1->A; const std::vector& B1 = mesh1->B; const std::vector& C1 = mesh1->C; const std::vector& A2 = mesh2->A; const std::vector& B2 = mesh2->B; const std::vector& C2 = mesh2->C; const std::vector& A = trilist->A; const std::vector& B = trilist->B; const std::vector& C = trilist->C; for (size_t i=0; i2 ) { // Check the domain mesh const IO::DomainMesh& mesh1 = *std::dynamic_pointer_cast(mesh); if ( mesh1.nprocx!=domain->nprocx || mesh1.nprocy!=domain->nprocy || mesh1.nprocz!=domain->nprocz ) pass = false; if ( mesh1.nx!=domain->nx || mesh1.ny!=domain->ny || mesh1.nz!=domain->nz ) pass = false; if ( mesh1.Lx!=domain->Lx || mesh1.Ly!=domain->Ly || mesh1.Lz!=domain->Lz ) pass = false; } } } if ( pass ) { ut.passes("Meshes loaded correctly"); } else { ut.failure("Meshes did not load correctly"); continue; } // For each domain, load the variables and check their data if ( format[i]==1 ) continue; // Format 1 does not support variables for (size_t j=0; j variable = IO::getVariable(".",timesteps[i],list[j],k,list[j].variables[v].name); 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.length() == var2.data.length(); if ( pass ) { for (size_t m=0; m