diff --git a/IO/Reader.cpp b/IO/Reader.cpp index c9595a8b..dedb9b82 100644 --- a/IO/Reader.cpp +++ b/IO/Reader.cpp @@ -44,7 +44,6 @@ std::vector IO::readTimesteps( const std::string& filename ) FILE *fid= fopen(filename.c_str(),"rb"); if ( fid==NULL ) ERROR("Error opening file"); - auto pos = std::min(filename.find_last_of(47),filename.find_last_of(90)); std::vector timesteps; char buf[1000]; while (fgets(buf,sizeof(buf),fid) != NULL) { @@ -160,7 +159,6 @@ std::shared_ptr IO::getMesh( const std::string& path, const std::strin #ifdef USE_SILO const DatabaseEntry& database = meshDatabase.domains[domain]; std::string filename = path + "/" + timestep + "/" + database.file; - int rank = std::stoi(database.file.substr(0,database.file.find(".silo")).c_str()); auto fid = silo::open( filename, silo::READ ); if ( meshDatabase.meshClass=="PointList" ) { Array coords = silo::readPointMesh( fid, database.name ); @@ -262,7 +260,6 @@ std::shared_ptr IO::getVariable( const std::string& path, const st const auto& database = meshDatabase.domains[domain]; auto variableDatabase = meshDatabase.getVariableDatabase( variable ); std::string filename = path + "/" + timestep + "/" + database.file; - int rank = std::stoi(database.file.substr(0,database.file.find(".silo")).c_str()); auto fid = silo::open( filename, silo::READ ); var.reset( new Variable( variableDatabase.dim, variableDatabase.type, variable ) ); if ( meshDatabase.meshClass=="PointList" ) { diff --git a/IO/silo.hpp b/IO/silo.hpp index d1ecee0c..312f32d8 100644 --- a/IO/silo.hpp +++ b/IO/silo.hpp @@ -322,9 +322,7 @@ void readTriMesh( DBfile* fid, const std::string& meshname, Array& coords, } auto zones = mesh->zones; int N_zones = zones->nzones; - int ndim_zones = zones->ndims; ASSERT( zones->nshapes==1 ); - int shape_type = zones->shapetype[0]; int shapesize = zones->shapesize[0]; tri.resize(N_zones,shapesize); for (int i=0; i &d, double dx, double dy, double dz ) -{ - auto s = d.size(); - bool test[3] = { false, false, false }; - // Check x-direction - Vec v1, v2; - for (size_t k=1; k -void CalcDist( Array &Distance, const Array &ID, const Domain &Dm, const std::array& periodic ) +void CalcDist( Array &Distance, const Array &ID, const Domain &Dm, + const std::array& periodic, const std::array& dx ) { ASSERT( Distance.size() == ID.size() ); std::array n = { Dm.Nx-2, Dm.Ny-2, Dm.Nz-2 }; @@ -64,15 +16,121 @@ void CalcDist( Array &Distance, const Array &ID, const Domain &Dm, c for (size_t i=0; i &d, const Array &ID0, const Domain &Dm, const std::array& periodic ) + + +/****************************************************************** +* Vector-based distance calculation * +* Initialize cells adjacent to boundaries * +******************************************************************/ +static void calcVecInitialize( Array &d, const Array &ID, double dx, double dy, double dz ) +{ + d.fill( Vec( 1e50, 1e50, 1e50 ) ); + const double dx0 = 0.5*dx; + const double dy0 = 0.5*dy; + const double dz0 = 0.5*dz; + //const double dxy0 = 0.25*sqrt( dx*dx + dy*dy ); + //const double dxz0 = 0.25*sqrt( dx*dx + dz*dz ); + //const double dyz0 = 0.25*sqrt( dy*dy + dz*dz ); + //const double dxyz0 = sqrt( dx*dx + dy*dy + dz*dz ); + int Nx = d.size(0); + int Ny = d.size(1); + int Nz = d.size(2); + for (int k=1; k &d, double dx, double dy, double dz ) +{ + double err = 0; + int Nx = d.size(0); + int Ny = d.size(1); + int Nz = d.size(2); + // Propagate (+,+,+) + for (int k=1; k=0; k--) { + for (int j=Ny-2; j>=0; j--) { + for (int i=Nx-2; i>=0; i--) { + auto vx = d(i+1,j,k); + auto vy = d(i,j+1,k); + auto vz = d(i,j,k+1); + vx.x -= dx; + vy.y -= dy; + vz.z -= dz; + auto v = std::min( std::min(vx,vy), vz ); + double d1 = v.norm2(); + double d2 = d(i,j,k).norm2(); + if ( d1 < d2 ) { + d(i,j,k) = v; + err = std::max( err, sqrt(d2)-sqrt(d1) ); + } + } + } + } + return err; +} + + +/****************************************************************** +* Vector-based distance calculation * +******************************************************************/ +void CalcVecDist( Array &d, const Array &ID0, const Domain &Dm, + const std::array& periodic, const std::array& dx ) { - const double dx = 1.0; - const double dy = 1.0; - const double dz = 1.0; std::array N = { Dm.Nx, Dm.Ny, Dm.Nz }; std::array n = { Dm.Nx-2, Dm.Ny-2, Dm.Nz-2 }; // Create ID with ghosts @@ -102,112 +160,30 @@ void CalcVecDist( Array &d, const Array &ID0, const Domain &Dm, const fillDataID.fill( ID ); // Create communicator for distance fillHalo fillData( Dm.Comm, Dm.rank_info, n, {1,1,1}, 50, 1, {true,false,false}, periodic ); - // Initialize the vector distance - d.fill( Vec( 1e50, 1e50, 1e50 ) ); - const double dx0 = 0.5*dx; - const double dy0 = 0.5*dy; - const double dz0 = 0.5*dz; - //const double dxy0 = 0.25*sqrt( dx*dx + dy*dy ); - //const double dxz0 = 0.25*sqrt( dx*dx + dz*dz ); - //const double dyz0 = 0.25*sqrt( dy*dy + dz*dz ); - //const double dxyz0 = sqrt( dx*dx + dy*dy + dz*dz ); - for (int k=1; ktol; it++) { + err = calcVecUpdateInterior( d, dx[0], dx[1], dx[2] ); } - int N_it = Dm.nprocx() + Dm.nprocy() + Dm.nprocz() + 3; + // Calculate the global distances + int N_it = Dm.nprocx() + Dm.nprocy() + Dm.nprocz() + 100; for ( int it=0; it=0; i--) { - auto v1 = d(i,j,k); - auto v2 = d(i+1,j,k); - v2.x -= dx; - if ( v2 < v1 ) - d(i,j,k) = v2; - } - } - } - // Propagate +/- y-direction - for (int k=0; k=0; j--) { - auto v1 = d(i,j,k); - auto v2 = d(i,j+1,k); - v2.y -= dy; - if ( v2 < v1 ) - d(i,j,k) = v2; - } - } - } - // Propagate +/- z-direction - for (int j=0; j=0; k--) { - auto v1 = d(i,j,k); - auto v2 = d(i,j,k+1); - v2.z -= dz; - if ( v2 < v1 ) - d(i,j,k) = v2; - } - } - } + // Update ghosts fillData.fill( d ); - bool test = checkUpdate( d, dx, dy, dz ); - test = sumReduce( Dm.Comm, test ); - if ( !test ) + // Update distance + double err = calcVecUpdateInterior( d, dx[0], dx[1], dx[2] ); + // Check if we are finished + err = maxReduce( Dm.Comm, err ); + if ( err < tol ) break; } } -template void CalcDist( Array&, const Array&, const Domain&, const std::array& ); -template void CalcDist( Array&, const Array&, const Domain&, const std::array& ); + + +// Explicit instantiations +template void CalcDist( Array&, const Array&, const Domain&, const std::array&, const std::array& ); +template void CalcDist( Array&, const Array&, const Domain&, const std::array&, const std::array& ); diff --git a/analysis/distance.h b/analysis/distance.h index b1bb9af5..b84a93f8 100644 --- a/analysis/distance.h +++ b/analysis/distance.h @@ -11,6 +11,7 @@ struct Vec { inline Vec(): x(0), y(0), z(0) {} inline Vec( double x_, double y_, double z_ ): x(x_), y(y_), z(z_) {} inline double norm() const { return sqrt(x*x+y*y+z*z); } + inline double norm2() const { return x*x+y*y+z*z; } }; inline bool operator<(const Vec& l, const Vec& r){ return l.x*l.x+l.y*l.y+l.z*l.z < r.x*r.x+r.y*r.y+r.z*r.z; } @@ -24,7 +25,8 @@ inline bool operator<(const Vec& l, const Vec& r){ return l.x*l.x+l.y*l.y+l.z*l. * @param[in] periodic Directions that are periodic */ template -void CalcDist( Array &Distance, const Array &ID, const Domain &Dm, const std::array& periodic = {true,true,true} ); +void CalcDist( Array &Distance, const Array &ID, const Domain &Dm, + const std::array& periodic = {true,true,true}, const std::array& dx = {1,1,1} ); /*! * @brief Calculate the distance using a simple method @@ -34,7 +36,7 @@ void CalcDist( Array &Distance, const Array &ID, const Domain &Dm, c * @param[in] Dm Domain information * @param[in] periodic Directions that are periodic */ -void CalcVecDist( Array &Distance, const Array &ID, const Domain &Dm, const std::array& periodic ); - +void CalcVecDist( Array &Distance, const Array &ID, const Domain &Dm, + const std::array& periodic = {true,true,true}, const std::array& dx = {1,1,1} ); #endif diff --git a/common/MPI_Helpers.h b/common/MPI_Helpers.h index 5a02397c..0cae743b 100644 --- a/common/MPI_Helpers.h +++ b/common/MPI_Helpers.h @@ -170,6 +170,12 @@ void unpack( std::set& data, const char *buffer ); // Helper functions +inline double sumReduce( MPI_Comm comm, double x ) +{ + double y = 0; + MPI_Allreduce(&x,&y,1,MPI_DOUBLE,MPI_SUM,comm); + return y; +} inline float sumReduce( MPI_Comm comm, float x ) { float y = 0; @@ -199,12 +205,24 @@ inline std::vector sumReduce( MPI_Comm comm, const std::vector& x ) MPI_Allreduce(x.data(),y.data(),x.size(),MPI_INT,MPI_SUM,comm); return y; } +inline double maxReduce( MPI_Comm comm, double x ) +{ + double y = 0; + MPI_Allreduce(&x,&y,1,MPI_DOUBLE,MPI_MAX,comm); + return y; +} inline float maxReduce( MPI_Comm comm, float x ) { float y = 0; MPI_Allreduce(&x,&y,1,MPI_FLOAT,MPI_MAX,comm); return y; } +inline int maxReduce( MPI_Comm comm, int x ) +{ + int y = 0; + MPI_Allreduce(&x,&y,1,MPI_INT,MPI_MAX,comm); + return y; +} #endif diff --git a/tests/TestSegDist.cpp b/tests/TestSegDist.cpp index f2b8b631..5866101d 100644 --- a/tests/TestSegDist.cpp +++ b/tests/TestSegDist.cpp @@ -17,11 +17,18 @@ std::shared_ptr loadInputs( int nprocs ) { - INSIST(nprocs==8, "TestSegDist: Number of MPI processes must be equal to 8"); + std::vector nproc; + if ( nprocs == 1 ) { + nproc = { 1, 1, 1 }; + } else if ( nprocs == 8 ) { + nproc = { 2, 2, 2 }; + } else { + ERROR("TestSegDist: Unsupported number of processors"); + } auto db = std::make_shared( ); db->putScalar( "BC", 0 ); - db->putVector( "nproc", { 2, 2, 2 } ); - db->putVector( "n", { 100, 100, 100 } ); + db->putVector( "nproc", nproc ); + db->putVector( "n", { 200, 200, 200 } ); db->putScalar( "nspheres", 0 ); db->putVector( "L", { 1, 1, 1 } ); return db; @@ -63,35 +70,30 @@ int main(int argc, char **argv) int ny = Ny+2; int nz = Nz+2; - double BubbleRadius = 0.3*nx; - // Initialize the bubble - double Cx = 1.0*nx; - double Cy = 1.0*ny; - double Cz = 1.0*nz; + double BubbleRadius = 0.15*Nx*Dm.nprocx(); + double Cx = 0.40*Nx*Dm.nprocx(); + double Cy = 0.45*Nx*Dm.nprocy(); + double Cz = 0.50*Nx*Dm.nprocy(); DoubleArray TrueDist(nx,ny,nz); Array id(nx,ny,nz); id.fill(0); - for (int k=1;k ID0(id.size());