This commit is contained in:
James E McClure 2015-06-04 09:47:24 -04:00
commit 5dfd3f0fe3
8 changed files with 362 additions and 57 deletions

View File

@ -34,6 +34,7 @@ struct Domain{
BlobLabel.resize(Nx,Ny,Nz); BlobLabel.resize(Nx,Ny,Nz);
BlobGraph.resize(18,MAX_BLOB_COUNT,MAX_BLOB_COUNT); BlobGraph.resize(18,MAX_BLOB_COUNT,MAX_BLOB_COUNT);
BoundaryCondition = BC; BoundaryCondition = BC;
rank_info=RankInfoStruct(rank,nprocx,nprocy,nprocz);
} }
~Domain(); ~Domain();
@ -44,6 +45,7 @@ struct Domain{
double Lx,Ly,Lz,Volume; double Lx,Ly,Lz,Volume;
int rank; int rank;
int BoundaryCondition; int BoundaryCondition;
RankInfoStruct rank_info;
MPI_Group Group; // Group of processors associated with this domain MPI_Group Group; // Group of processors associated with this domain
MPI_Comm Comm; // MPI Communicator for this domain MPI_Comm Comm; // MPI Communicator for this domain
@ -775,6 +777,142 @@ void Domain::BlobComm(MPI_Comm Communicator){
UnpackBlobData(recvList_YZ, recvCount_YZ ,recvBuf_YZ, BlobLabelData); UnpackBlobData(recvList_YZ, recvCount_YZ ,recvBuf_YZ, BlobLabelData);
//...................................................................................... //......................................................................................
} }
inline void SSO(DoubleArray &Distance, char *ID, Domain &Dm, int timesteps){
/*
* This routine converts the data in the Distance array to a signed distance
* by solving the equation df/dt = sign(1-|grad f|), where Distance provides
* the values of f on the mesh associated with domain Dm
* It has been tested with segmented data initialized to values [-1,1]
* and will converge toward the signed distance to the surface bounding the associated phases
*/
int Q=26;
int q,i,j,k,n;
double dt=0.1;
int in,jn,kn,nn;
double Dqx,Dqy,Dqz,Dx,Dy,Dz,W;
double nx,ny,nz,Cqx,Cqy,Cqz,sign,norm;
const static int D3Q27[26][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1},
{1,1,0},{-1,-1,0},{1,-1,0},{-1,1,0},{1,0,1},{-1,0,-1},{1,0,-1},{-1,0,1},
{0,1,1},{0,-1,-1},{0,1,-1},{0,-1,1},{1,1,1},{-1,-1,-1},{1,1,-1},{-1,-1,1},
{-1,1,-1},{1,-1,1},{1,-1,-1},{-1,1,1}};
double weights[26];
// Compute the weights from the finite differences
for (q=0; q<Q; q++){
weights[q] = sqrt(1.0*(D3Q27[q][0]*D3Q27[q][0]) + 1.0*(D3Q27[q][1]*D3Q27[q][1]) + 1.0*(D3Q27[q][2]*D3Q27[q][2]));
}
int xdim,ydim,zdim;
xdim=Dm.Nx-2;
ydim=Dm.Ny-2;
zdim=Dm.Nz-2;
fillHalo<double> fillData(Dm.rank_info,xdim,ydim,zdim,1,1,1,0,1);
int count = 0;
while (count < timesteps){
// Communicate the halo of values
fillData.fill(Distance);
// Execute the next timestep
for (k=1;k<Dm.Nz-1;k++){
for (j=1;j<Dm.Ny-1;j++){
for (i=1;i<Dm.Nx-1;i++){
n = k*Dm.Nx*Dm.Ny+j*Dm.Nx+i;
sign = Distance(i,j,k) / fabs(Distance(i,j,k));
/*
if (!(i+1<Nx)) nx=0.5*Distance(i,j,k);
else nx=0.5*Distance(i+1,j,k);;
if (!(j+1<Ny)) ny=0.5*Distance(i,j,k);
else ny=0.5*Distance(i,j+1,k);
if (!(k+1<Nz)) nz=0.5*Distance(i,j,k);
else nz=0.5*Distance(i,j,k+1);
if (i<1) nx-=0.5*Distance(i,j,k);
else nx-=0.5*Distance(i-1,j,k);
if (j<1) ny-=0.5*Distance(i,j,k);
else ny-=0.5*Distance(i,j-1,k);
if (k<1) nz-=0.5*Distance(i,j,k);
else nz-=0.5*Distance(i,j,k-1);
*/
//............Compute the Gradient...................................
nx = 0.5*(Distance(i+1,j,k) - Distance(i-1,j,k));
ny = 0.5*(Distance(i,j+1,k) - Distance(i,j-1,k));
nz = 0.5*(Distance(i,j,k+1) - Distance(i,j,k-1));
W = 0.0; Dx = Dy = Dz = 0.0;
// Ignore any values that have distances less than a lattice unit
// since sometimes the positions may be guessed more accurately from
// another source (such as a simulation)
// also ignore places where the gradient is zero since this will not
// result in any local change to Distance
if (nx*nx+ny*ny+nz*nz > 0.0 && !(Distance(i,j,k)*Distance(i,j,k) < 1.0) ){
for (q=0; q<26; q++){
Cqx = 1.0*D3Q27[q][0];
Cqy = 1.0*D3Q27[q][1];
Cqz = 1.0*D3Q27[q][2];
// get the associated neighbor
in = i + D3Q27[q][0];
jn = j + D3Q27[q][1];
kn = k + D3Q27[q][2];
// make sure the neighbor is in the domain (periodic BC)
/* if (in < 0 ) in +=Nx;
* don't need this in parallel since MPI handles the halos
if (jn < 0 ) jn +=Ny;
if (kn < 0 ) kn +=Nz;
if (!(in < Nx) ) in -=Nx;
if (!(jn < Ny) ) jn -=Ny;
if (!(kn < Nz) ) kn -=Nz;
// symmetric boundary
if (in < 0 ) in = i;
if (jn < 0 ) jn = j;
if (kn < 0 ) kn = k;
if (!(in < Nx) ) in = i;
if (!(jn < Ny) ) jn = k;
if (!(kn < Nz) ) kn = k;
*/
// Compute the gradient using upwind finite differences
Dqx = weights[q]*(Distance(i,j,k) - Distance(in,jn,kn))*Cqx;
Dqy = weights[q]*(Distance(i,j,k) - Distance(in,jn,kn))*Cqy;
Dqz = weights[q]*(Distance(i,j,k) - Distance(in,jn,kn))*Cqz;
// Only include upwind derivatives
if (sign*(nx*Cqx + ny*Cqy + nz*Cqz) < 0.0 ){
Dx += Dqx;
Dy += Dqy;
Dz += Dqz;
W += weights[q];
}
}
// Normalize by the weight to get the approximation to the gradient
Dx /= W;
Dy /= W;
Dz /= W;
norm = sqrt(Dx*Dx+Dy*Dy+Dz*Dz);
}
else{
norm = 0.0;
}
Distance(i,j,k) += dt*sign*(1.0 - norm);
// Disallow any change in phase
if (Distance(i,j,k)*2.0*(ID[n]-1.0) < 0) Distance(i,j,k) = -Distance(i,j,k);
}
}
}
count++;
}
}
inline void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad) inline void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad)
{ {

View File

@ -550,7 +550,7 @@ void TwoPhase::ComputeLocalBlob(){
int i,j,k,n,label; int i,j,k,n,label;
double vF,vS; double vF,vS;
vF = 0.0; vS= -1.0; vF = 0.0; vS= -1.0;
const RankInfoStruct rank_info(Dm.rank,Dm.nprocx,Dm.nprocy,Dm.nprocz); // const RankInfoStruct rank_info(Dm.rank,Dm.nprocx,Dm.nprocy,Dm.nprocz);
int cube[8][3] = {{0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}}; int cube[8][3] = {{0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}};
// get the maximum label locally -- then compute number of global blobs // get the maximum label locally -- then compute number of global blobs
@ -563,7 +563,7 @@ void TwoPhase::ComputeLocalBlob(){
nblobs_global+=1; nblobs_global+=1;
if (Dm.rank==0) printf("Number of blobs is %i \n",nblobs_global); if (Dm.rank==0) printf("Number of blobs is %i \n",nblobs_global);
nblobs_global = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,rank_info, nblobs_global = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,Dm.rank_info,
Phase,SDs,vF,vS,BlobLabel); Phase,SDs,vF,vS,BlobLabel);
if (Dm.rank==0) printf("Number of blobs is %i \n",nblobs_global); if (Dm.rank==0) printf("Number of blobs is %i \n",nblobs_global);

View File

@ -7,7 +7,9 @@
#include <math.h> #include <math.h>
#include "common/Communication.h" #include "common/Communication.h"
#include "analysis/analysis.h" #include "analysis/analysis.h"
#ifdef PROFILE
#include "ProfilerApp.h" #include "ProfilerApp.h"
#endif
#include "TwoPhase.h" #include "TwoPhase.h"
//#include "Domain.h" //#include "Domain.h"
@ -98,10 +100,12 @@ int main(int argc, char **argv)
MPI_Init(&argc,&argv); MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs); MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
#ifdef PROFILE
PROFILE_ENABLE(0); PROFILE_ENABLE(0);
PROFILE_DISABLE_TRACE(); PROFILE_DISABLE_TRACE();
PROFILE_SYNCHRONIZE(); PROFILE_SYNCHRONIZE();
PROFILE_START("main"); PROFILE_START("main");
#endif
if ( rank==0 ) { if ( rank==0 ) {
printf("-----------------------------------------------------------\n"); printf("-----------------------------------------------------------\n");
@ -147,7 +151,7 @@ int main(int argc, char **argv)
int BC=0; int BC=0;
// Get the rank info // Get the rank info
Domain Dm(nx,ny,nz,rank,nprocx,nprocy,nprocz,Lx,Ly,Lz,BC); Domain Dm(nx,ny,nz,rank,nprocx,nprocy,nprocz,Lx,Ly,Lz,BC);
const RankInfoStruct rank_info(rank,nprocx,nprocy,nprocz); // const RankInfoStruct rank_info(rank,nprocx,nprocy,nprocz);
TwoPhase Averages(Dm); TwoPhase Averages(Dm);
int N = (nx+2)*(ny+2)*(nz+2); int N = (nx+2)*(ny+2)*(nz+2);
@ -157,6 +161,7 @@ int main(int argc, char **argv)
readRankData( rank, nx+2, ny+2, nz+2, Phase, SignDist ); readRankData( rank, nx+2, ny+2, nz+2, Phase, SignDist );
// Communication the halos // Communication the halos
const RankInfoStruct rank_info(rank,nprocx,nprocy,nprocz);
fillHalo<double> fillData(rank_info,nx,ny,nz,1,1,1,0,1); fillHalo<double> fillData(rank_info,nx,ny,nz,1,1,1,0,1);
fillData.fill(Phase); fillData.fill(Phase);
fillData.fill(SignDist); fillData.fill(SignDist);
@ -166,7 +171,7 @@ int main(int argc, char **argv)
double vF=0.0; double vF=0.0;
double vS=0.0; double vS=0.0;
IntArray GlobalBlobID; IntArray GlobalBlobID;
int nblobs = ComputeGlobalBlobIDs(nx,ny,nz,rank_info, int nblobs = ComputeGlobalBlobIDs(nx,ny,nz,Dm.rank_info,
Phase,SignDist,vF,vS,GlobalBlobID); Phase,SignDist,vF,vS,GlobalBlobID);
if ( rank==0 ) { printf("Identified %i blobs\n",nblobs); } if ( rank==0 ) { printf("Identified %i blobs\n",nblobs); }
@ -191,9 +196,6 @@ int main(int argc, char **argv)
//......................................................................... //.........................................................................
// Populate the arrays needed to perform averaging // Populate the arrays needed to perform averaging
if (rank==0) printf("Populate arrays \n"); if (rank==0) printf("Populate arrays \n");
// Compute porosity
double porosity,sum,sum_global;
sum=0.0;
for (int k=0; k<nz+2; k++){ for (int k=0; k<nz+2; k++){
for (int j=0; j<ny+2; j++){ for (int j=0; j<ny+2; j++){
for (int i=0; i<nx+2; i++){ for (int i=0; i<nx+2; i++){
@ -237,6 +239,20 @@ int main(int argc, char **argv)
Averages.Vel_x(i,j,k)=vx; Averages.Vel_x(i,j,k)=vx;
Averages.Vel_y(i,j,k)=vy; Averages.Vel_y(i,j,k)=vy;
Averages.Vel_z(i,j,k)=vz; Averages.Vel_z(i,j,k)=vz;
}
}
}
delete [] DistEven;
delete [] DistOdd;
// Compute porosity
double porosity,sum,sum_global;
sum=0.0;
for (int k=1; k<nz+1; k++){
for (int j=1; j<ny+1; j++){
for (int i=1; i<nx+1; i++){
int n = k*(nx+2)*(ny+2)+j*(nx+2)+i;
if (Averages.SDs(i,j,k) > 0.0){ if (Averages.SDs(i,j,k) > 0.0){
Dm.id[n]=1; Dm.id[n]=1;
sum += 1.0; sum += 1.0;
@ -245,9 +261,6 @@ int main(int argc, char **argv)
} }
} }
} }
delete [] DistEven;
delete [] DistOdd;
MPI_Allreduce(&sum,&sum_global,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); MPI_Allreduce(&sum,&sum_global,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
porosity = sum_global/Dm.Volume; porosity = sum_global/Dm.Volume;
if (rank==0) printf("Porosity = %f \n",porosity); if (rank==0) printf("Porosity = %f \n",porosity);
@ -366,9 +379,10 @@ int main(int argc, char **argv)
/*FILE *BLOBS = fopen("Blobs.dat","wb"); /*FILE *BLOBS = fopen("Blobs.dat","wb");
fwrite(GlobalBlobID.get(),4,Nx*Ny*Nz,BLOBS); fwrite(GlobalBlobID.get(),4,Nx*Ny*Nz,BLOBS);
fclose(BLOBS);*/ fclose(BLOBS);*/
#ifdef PROFILE
PROFILE_STOP("main"); PROFILE_STOP("main");
PROFILE_SAVE("BlobIdentifyParallel",false); PROFILE_SAVE("BlobIdentifyParallel",false);
#endif
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize(); MPI_Finalize();
return 0; return 0;

View File

@ -8,8 +8,9 @@
#include "common/pmmc.h" #include "common/pmmc.h"
#include "common/Communication.h" #include "common/Communication.h"
#include "analysis/analysis.h" #include "analysis/analysis.h"
#ifdef PROFILE
#include "ProfilerApp.h" #include "ProfilerApp.h"
#endif
//#include "Domain.h" //#include "Domain.h"
@ -50,10 +51,12 @@ int main(int argc, char **argv)
MPI_Init(&argc,&argv); MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs); MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
#ifdef PROFILE
PROFILE_ENABLE(0); PROFILE_ENABLE(0);
PROFILE_DISABLE_TRACE(); PROFILE_DISABLE_TRACE();
PROFILE_SYNCHRONIZE(); PROFILE_SYNCHRONIZE();
PROFILE_START("main"); PROFILE_START("main");
#endif
if ( rank==0 ) { if ( rank==0 ) {
printf("-----------------------------------------------------------\n"); printf("-----------------------------------------------------------\n");
@ -121,9 +124,10 @@ int main(int argc, char **argv)
/*FILE *BLOBS = fopen("Blobs.dat","wb"); /*FILE *BLOBS = fopen("Blobs.dat","wb");
fwrite(GlobalBlobID.get(),4,Nx*Ny*Nz,BLOBS); fwrite(GlobalBlobID.get(),4,Nx*Ny*Nz,BLOBS);
fclose(BLOBS);*/ fclose(BLOBS);*/
#ifdef PROFILE
PROFILE_STOP("main"); PROFILE_STOP("main");
PROFILE_SAVE("BlobIdentifyParallel",false); PROFILE_SAVE("BlobIdentifyParallel",false);
#endif
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize(); MPI_Finalize();
return 0; return 0;

View File

@ -22,6 +22,7 @@ ADD_LBPM_TEST( TestSphereCurvature )
ADD_LBPM_TEST( TestContactAngle ) ADD_LBPM_TEST( TestContactAngle )
ADD_LBPM_TEST_1_2_4( TestTwoPhase ) ADD_LBPM_TEST_1_2_4( TestTwoPhase )
ADD_LBPM_TEST_PARALLEL( TestTwoPhase 8 ) ADD_LBPM_TEST_PARALLEL( TestTwoPhase 8 )
ADD_LBPM_TEST_PARALLEL( TestSegDist 8 )
ADD_LBPM_TEST_1_2_4( testCommunication ) ADD_LBPM_TEST_1_2_4( testCommunication )
ADD_LBPM_TEST_1_2_4( testUtilities ) ADD_LBPM_TEST_1_2_4( testUtilities )
ADD_LBPM_TEST( TestWriter ) ADD_LBPM_TEST( TestWriter )

View File

@ -11,13 +11,13 @@
#include <fstream> #include <fstream>
#include <Array.h> #include <Array.h>
inline void SSO(DoubleArray &Distance, IntArray &ID, int timesteps){ inline void SSO(DoubleArray &Distance, char *ID, int timesteps){
int Q=26; int Q=26;
int q,i,j,k; int q,i,j,k,n;
int Nx = ID.m; int Nx = Distance.m;
int Ny = ID.n; int Ny = Distance.n;
int Nz = ID.o; int Nz = Distance.o;
const static int D3Q27[26][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}, const static int D3Q27[26][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1},
{1,1,0},{-1,-1,0},{1,-1,0},{-1,1,0},{1,0,1},{-1,0,-1},{1,0,-1},{-1,0,1}, {1,1,0},{-1,-1,0},{1,-1,0},{-1,1,0},{1,0,1},{-1,0,-1},{1,0,-1},{-1,0,1},
{0,1,1},{0,-1,-1},{0,1,-1},{0,-1,1},{1,1,1},{-1,-1,-1},{1,1,-1},{-1,-1,1}, {0,1,1},{0,-1,-1},{0,1,-1},{0,-1,1},{1,1,1},{-1,-1,-1},{1,1,-1},{-1,-1,1},
@ -30,40 +30,58 @@ inline void SSO(DoubleArray &Distance, IntArray &ID, int timesteps){
} }
// Initialize the Distance from ID // Initialize the Distance from ID
for (i=0; i<Nx*Ny*Nz; i++) Distance.data[i] = -0.5; // for (i=0; i<Nx*Ny*Nz; i++) Distance.data[i] = -0.5;
for (k=1;k<Nz-1;k++){ for (k=0;k<Nz;k++){
for (j=1;j<Ny-1;j++){ for (j=0;j<Ny;j++){
for (i=1;i<Nx-1;i++){ for (i=0;i<Nx;i++){
n=k*Nx*Ny+j*Nx+i;
// Initialize distance to +/- 1 // Initialize distance to +/- 1
Distance(i,j,k) = 1.0*ID(i,j,k)-0.5; Distance(i,j,k) = 1.0*ID[n]-0.5;
} }
} }
} }
int count = 0; int count = 0;
double dt=1.0; double dt=0.1;
int n,in,jn,kn,nn; int in,jn,kn,nn;
double Dqx,Dqy,Dqz,Dx,Dy,Dz,W; double Dqx,Dqy,Dqz,Dx,Dy,Dz,W;
double nx,ny,nz,Cqx,Cqy,Cqz,sign,norm; double nx,ny,nz,Cqx,Cqy,Cqz,sign,norm;
double f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18; double f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18;
printf("Number of timesteps is %i \n",timesteps);
printf("Mesh is %i,%i,%i \n",Nx,Ny,Nz);
while (count < timesteps){ while (count < timesteps){
for (k=1;k<Nz-1;k++){ printf("count=%i \n",count);
for (j=1;j<Ny-1;j++){ for (k=0;k<Nz;k++){
for (i=1;i<Nx-1;i++){ for (j=0;j<Ny;j++){
for (i=0;i<Nx;i++){
n = k*Nx*Ny + j*Nx + i; n = k*Nx*Ny + j*Nx + i;
sign = Distance.data[n] / fabs(Distance.data[n]); sign = Distance.data[n] / fabs(Distance.data[n]);
//............Compute the Gradient................................... //............Compute the Gradient...................................
nx = 0.5*(Distance(i+1,j,k) - Distance(i-1,j,k)); if (!(i+1<Nx)) nx=0.5*Distance(i,j,k);
ny = 0.5*(Distance(i,j+1,k) - Distance(i,j-1,k)); else nx=0.5*Distance(i+1,j,k);;
nz = 0.5*(Distance(i,j,k+1) - Distance(i,j,k-1)); if (!(j+1<Ny)) ny=0.5*Distance(i,j,k);
else ny=0.5*Distance(i,j+1,k);
if (!(k+1<Nz)) nz=0.5*Distance(i,j,k);
else nz=0.5*Distance(i,j,k+1);
if (i<1) nx-=0.5*Distance(i,j,k);
else nx-=0.5*Distance(i-1,j,k);
if (j<1) ny-=0.5*Distance(i,j,k);
else ny-=0.5*Distance(i,j-1,k);
if (k<1) nz-=0.5*Distance(i,j,k);
else nz-=0.5*Distance(i,j,k-1);
// nx = 0.5*(Distance(i+1,j,k) - Distance(i-1,j,k));
// ny = 0.5*(Distance(i,j+1,k) - Distance(i,j-1,k));
// nz = 0.5*(Distance(i,j,k+1) - Distance(i,j,k-1));
W = 0.0; Dx = Dy = Dz = 0.0; W = 0.0; Dx = Dy = Dz = 0.0;
if (nx*nx+ny*ny+nz*nz > 0.0){ if (nx*nx+ny*ny+nz*nz > 0.0){
for (q=0; q<27; q++){ for (q=0; q<26; q++){
Cqx = 1.0*D3Q27[q][0]; Cqx = 1.0*D3Q27[q][0];
Cqy = 1.0*D3Q27[q][1]; Cqy = 1.0*D3Q27[q][1];
Cqz = 1.0*D3Q27[q][2]; Cqz = 1.0*D3Q27[q][2];
@ -72,12 +90,19 @@ inline void SSO(DoubleArray &Distance, IntArray &ID, int timesteps){
jn = j + D3Q27[q][1]; jn = j + D3Q27[q][1];
kn = k + D3Q27[q][2]; kn = k + D3Q27[q][2];
// make sure the neighbor is in the domain (periodic BC) // make sure the neighbor is in the domain (periodic BC)
if (in < 0 ) in +=Nx; /* if (in < 0 ) in +=Nx;
if (jn < 0 ) jn +=Ny; if (jn < 0 ) jn +=Ny;
if (kn < 0 ) kn +=Nz; if (kn < 0 ) kn +=Nz;
if (!(in < Nx) ) in -=Nx; if (!(in < Nx) ) in -=Nx;
if (!(jn < Ny) ) jn -=Ny; if (!(jn < Ny) ) jn -=Ny;
if (!(kn < Nz) ) kn -=Nz; if (!(kn < Nz) ) kn -=Nz;
*/ // symmetric boundary
if (in < 0 ) in = i;
if (jn < 0 ) jn = j;
if (kn < 0 ) kn = k;
if (!(in < Nx) ) in = i;
if (!(jn < Ny) ) jn = k;
if (!(kn < Nz) ) kn = k;
// 1-D index // 1-D index
nn = kn*Nx*Ny + jn*Nx + in; nn = kn*Nx*Ny + jn*Nx + in;
@ -103,20 +128,18 @@ inline void SSO(DoubleArray &Distance, IntArray &ID, int timesteps){
norm = sqrt(Dx*Dx+Dy*Dy+Dz*Dz); norm = sqrt(Dx*Dx+Dy*Dy+Dz*Dz);
} }
else{ else{
norm = 0.7; norm = 0.0;
} }
Distance.data[n] += dt*sign*(1.0 - norm); Distance.data[n] += dt*sign*(1.0 - norm);
// Disallow any change in phase position // Disallow any change in phase
if (Distance.data[n]*ID.data[n] < 0) Distance.data[n] = -Distance.data[n]; if (Distance.data[n]*2.0*(ID[n]-1.0) < 0) Distance.data[n] = -Distance.data[n];
} }
} }
} }
count++; count++;
} }
} }
int main(){ int main(){
@ -137,27 +160,30 @@ int main(){
double fxy,fXy,fxY,fXY,fxz,fXz,fxZ,fXZ,fyz,fYz,fyZ,fYZ; double fxy,fXy,fxY,fXY,fxz,fXz,fxZ,fXZ,fyz,fYz,fyZ,fYZ;
double nx,ny,nz; double nx,ny,nz;
int ip,im,jp,jm,kp,km; int ip,im,jp,jm,kp,km;
int count = 0; int count = 0;
double sign; double sign;
double dt=0.01; double dt=1.0;
printf("Nx=%i, Ny=%i, Nz= %i, \n",Nx,Ny,Nz); printf("Nx=%i, Ny=%i, Nz= %i, \n",Nx,Ny,Nz);
short int *id; char *id;
#ifdef READMEDIA #ifdef READMEDIA
Nx = 347; Nx = 347;
Ny = 347; Ny = 347;
Nz = 235; Nz = 235;
Nx = 512;
Ny = 512;
Nz = 512;
N = Nx*Ny*Nz; N = Nx*Ny*Nz;
id = new short int [N]; id = new char [N];
FILE *INPUT = fopen("Solid.dat",'rb');
fread(id,4,N*,Ny*Nz,INPUT) FILE *INPUT = fopen("Solid.dat","rb");
fread(id,1,Nx*Ny*Nz,INPUT);
fclose(INPUT); fclose(INPUT);
#else #else
id = new short int [N]; id = new char [N];
double BubbleRadius = 5; double BubbleRadius = 5;
// Initialize the bubble // Initialize the bubble
for (k=0;k<Nz;k++){ for (k=0;k<Nz;k++){
@ -176,6 +202,21 @@ int main(){
} }
#endif #endif
DoubleArray Distance(Nx,Ny,Nz);
// Initialize the signed distance function
for (k=0;k<Nz;k++){
for (j=0;j<Ny;j++){
for (i=0;i<Nx;i++){
n=k*Nx*Ny+j*Nx+i;
// Initialize distance to +/- 1
Distance(i,j,k) = 2.0*ID[n]-1.0;
}
}
}
printf("Initialized! Converting to Signed Distance function \n");
SSO(Distance,id,20);
/* double *f,*f_old,*f_new; /* double *f,*f_old,*f_new;
f = new double[N]; f = new double[N];
f_old = new double[N]; f_old = new double[N];
@ -184,9 +225,11 @@ int main(){
for (int n=0; n<N; n++) Distance.data[n] = 0.5*(id[n]-1); for (int n=0; n<N; n++) Distance.data[n] = 0.5*(id[n]-1);
for (int n=0; n<N; n++) f_old[n] = Distance.data[n]; for (int n=0; n<N; n++) f_old[n] = Distance.data[n];
for (int n=0; n<N; n++) f_new[n] = Distance.data[n]; for (int n=0; n<N; n++) f_new[n] = Distance.data[n];
for (int n=0; n<N; n++) f[n] = Distance.data[n];
count=0; count=0;
while (count < 10000 && dt > 1.0e-6){ dt=1.0;
while (count < 10 && dt > 1.0e-6){
err = 0.0; err = 0.0;
for (k=0;k<Nz;k++){ for (k=0;k<Nz;k++){
@ -306,7 +349,7 @@ int main(){
f_y = 0.5*(f[k*Nx*Ny + jp*Nx + i] - f[k*Nx*Ny + jm*Nx + i]); f_y = 0.5*(f[k*Nx*Ny + jp*Nx + i] - f[k*Nx*Ny + jm*Nx + i]);
f_z = 0.5*(f[kp*Nx*Ny + j*Nx + i] - f[km*Nx*Ny + j*Nx + i]); f_z = 0.5*(f[kp*Nx*Ny + j*Nx + i] - f[km*Nx*Ny + j*Nx + i]);
if (id[n] > 0){ if (id[n] < 0){
if ( nx > 0.0) f_x = fxp; if ( nx > 0.0) f_x = fxp;
else f_x = fxm; else f_x = fxm;
if ( ny > 0.0) f_y = fyp; if ( ny > 0.0) f_y = fyp;
@ -348,8 +391,8 @@ int main(){
count++; count++;
} }
*/ */
FILE *DIST; FILE *DIST;
DIST = fopen("SignDist","wb"); DIST = fopen("SignDist","wb");
fwrite(Distance.data,8,N,DIST); fwrite(Distance.data,8,N,DIST);

106
tests/TestSegDist.cpp Normal file
View File

@ -0,0 +1,106 @@
// Compute the signed distance from a digitized image
// Two phases are present
// Phase 1 has value -1
// Phase 2 has value 1
// this code uses the segmented image to generate the signed distance
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <fstream>
#include <Array.h>
#include <Domain.h>
int main(int argc, char **argv)
{
// Initialize MPI
int rank, nprocs;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
int i,j,k,n,nn;
int iproc,jproc,kproc;
int nx,ny,nz;
int Nx, Ny, Nz, N;
int nprocx, nprocy, nprocz, nspheres;
double Lx, Ly, Lz;
Nx = Ny = Nz = 50;
nx = ny = nz = 50;
N = Nx*Ny*Nz;
nprocx=nprocy=nprocz=2;
Lx = Ly = Lz = 1.0;
int BC=0;
if (nprocs != 8){
ERROR("TestSegDist: Number of MPI processes must be equal to 8");
}
if (nprocx !=2 || nprocz !=2 || nprocy !=2 ){
ERROR("TestSegDist: MPI process grid must be 2x2x2");
}
// Get the rank info
Domain Dm(nx,ny,nz,rank,nprocx,nprocy,nprocz,Lx,Ly,Lz,BC);
Dm.CommInit(MPI_COMM_WORLD);
nx+=2; ny+=2; nz+=2;
N = nx*ny*nz;
int count = 0;
char *id;
id = new char [N];
double BubbleRadius = 25;
// Initialize the bubble
int x,y,z;
for (k=1;k<nz-1;k++){
for (j=1;j<ny-1;j++){
for (i=1;i<nx-1;i++){
x = (nx-2)*Dm.iproc+i;
y = (ny-2)*Dm.jproc+j;
z = (nz-2)*Dm.kproc+k;
n = k*nx*ny+j*nx+i;
// Initialize phase positions
if ((x-nx+1)*(x-nx+1)+(y-ny+1)*(y-ny+1)+(z-nz+1)*(z-nz+1) < BubbleRadius*BubbleRadius){
id[n] = 0;
}
else{
id[n]=1;
}
}
}
}
DoubleArray Distance(nx,ny,nz);
// Initialize the signed distance function
for (k=0;k<nz;k++){
for (j=0;j<ny;j++){
for (i=0;i<nx;i++){
n=k*nx*ny+j*nx+i;
// Initialize distance to +/- 1
Distance(i,j,k) = 2.0*id[n]-1.0;
}
}
}
if (rank==0) printf("Nx = %i \n",(int)Distance.size(0));
if (rank==0) printf("Ny = %i \n",(int)Distance.size(1));
if (rank==0) printf("Nz = %i \n",(int)Distance.size(2));
printf("Initialized! Converting to Signed Distance function \n");
SSO(Distance,id,Dm,10);
char LocalRankFilename[40];
sprintf(LocalRankFilename,"Dist.%05i",rank);
FILE *DIST = fopen(LocalRankFilename,"wb");
fwrite(Distance.get(),8,Distance.length(),DIST);
fclose(DIST);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}

View File

@ -106,7 +106,6 @@ int main(int argc, char **argv)
Averages.PrintAll(timestep); Averages.PrintAll(timestep);
//.................................................................... //....................................................................
if (rank==0){ if (rank==0){
FILE *PHASE; FILE *PHASE;
PHASE = fopen("Phase.00000","wb"); PHASE = fopen("Phase.00000","wb");