2015-06-24 19:45:48 -04:00
|
|
|
// Unit test to test mass conservation for D3Q7 mass transport LBE
|
2015-06-24 19:48:13 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <exception>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
2015-08-21 16:56:43 -04:00
|
|
|
#include "common/ScaLBL.h"
|
|
|
|
|
#include "common/Communication.h"
|
2018-02-10 20:13:57 -05:00
|
|
|
#include "analysis/TwoPhase.h"
|
2015-06-24 19:48:13 -04:00
|
|
|
#include "common/MPI_Helpers.h"
|
2015-06-24 19:45:48 -04:00
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
//*****************************************
|
|
|
|
|
// ***** MPI STUFF ****************
|
|
|
|
|
//*****************************************
|
|
|
|
|
// Initialize MPI
|
|
|
|
|
int rank,nprocs;
|
|
|
|
|
MPI_Init(&argc,&argv);
|
2015-09-04 13:06:36 -04:00
|
|
|
MPI_Comm comm = MPI_COMM_WORLD;
|
|
|
|
|
MPI_Comm_rank(comm,&rank);
|
|
|
|
|
MPI_Comm_size(comm,&nprocs);
|
2015-06-24 19:45:48 -04:00
|
|
|
// parallel domain size (# of sub-domains)
|
|
|
|
|
int nprocx,nprocy,nprocz;
|
|
|
|
|
int iproc,jproc,kproc;
|
|
|
|
|
int sendtag,recvtag;
|
|
|
|
|
//*****************************************
|
|
|
|
|
// MPI ranks for all 18 neighbors
|
|
|
|
|
//**********************************
|
|
|
|
|
int rank_x,rank_y,rank_z,rank_X,rank_Y,rank_Z;
|
|
|
|
|
int rank_xy,rank_XY,rank_xY,rank_Xy;
|
|
|
|
|
int rank_xz,rank_XZ,rank_xZ,rank_Xz;
|
|
|
|
|
int rank_yz,rank_YZ,rank_yZ,rank_Yz;
|
|
|
|
|
//**********************************
|
|
|
|
|
MPI_Request req1[18],req2[18];
|
|
|
|
|
MPI_Status stat1[18],stat2[18];
|
|
|
|
|
|
|
|
|
|
if (rank == 0){
|
|
|
|
|
printf("********************************************************\n");
|
|
|
|
|
printf("Running Unit Test for D3Q7 Mass Conservation \n");
|
|
|
|
|
printf("********************************************************\n");
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-24 19:49:46 -04:00
|
|
|
double das=0.0;
|
|
|
|
|
double dbs=1.0;
|
|
|
|
|
double beta=0.95;
|
|
|
|
|
bool pBC=false;
|
|
|
|
|
int i,j,k,n;
|
2015-06-24 19:45:48 -04:00
|
|
|
int Nx,Ny,Nz,N;
|
|
|
|
|
Nx=Nz=Ny=100;
|
|
|
|
|
N = Nx*Ny*Nz;
|
|
|
|
|
int dist_mem_size = N*sizeof(double);
|
|
|
|
|
|
2015-06-25 09:52:10 -04:00
|
|
|
double *DenOriginal, *DenFinal;
|
|
|
|
|
DenOriginal = new double [2*N];
|
|
|
|
|
DenFinal = new double [2*N];
|
|
|
|
|
|
|
|
|
|
double *Vel;
|
|
|
|
|
Vel = new double [3*N];
|
2015-06-24 19:45:48 -04:00
|
|
|
char *id;
|
|
|
|
|
id = new char [N];
|
2015-06-25 09:52:10 -04:00
|
|
|
|
2015-06-24 19:45:48 -04:00
|
|
|
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;
|
|
|
|
|
if (k<10) id[n] = 0;
|
|
|
|
|
else if (k>80) id[n] = 0;
|
2015-06-25 09:52:10 -04:00
|
|
|
else if (i<50){
|
|
|
|
|
id[n]=1;
|
|
|
|
|
Vel[n]=0.1;
|
|
|
|
|
Vel[N+n]=0.1;
|
|
|
|
|
Vel[2*N+n]=0.1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
id[n]=2;
|
|
|
|
|
Vel[n]=0.1;
|
|
|
|
|
Vel[N+n]=0.1;
|
|
|
|
|
Vel[2*N+n]=0.1;
|
|
|
|
|
}
|
2015-06-24 19:45:48 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 09:52:10 -04:00
|
|
|
|
2015-06-24 19:45:48 -04:00
|
|
|
|
|
|
|
|
//......................device distributions.................................
|
|
|
|
|
double *A_even,*A_odd,*B_even,*B_odd;
|
|
|
|
|
//...........................................................................
|
2016-11-24 11:26:51 -05:00
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &A_even, 4*dist_mem_size); // Allocate device memory
|
|
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &A_odd, 3*dist_mem_size); // Allocate device memory
|
|
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &B_even, 4*dist_mem_size); // Allocate device memory
|
|
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &B_odd, 3*dist_mem_size); // Allocate device memory
|
2015-06-24 19:45:48 -04:00
|
|
|
//...........................................................................
|
2015-06-25 09:52:10 -04:00
|
|
|
double *Phi,*Den;
|
2015-06-24 19:45:48 -04:00
|
|
|
double *ColorGrad, *Velocity;
|
|
|
|
|
//...........................................................................
|
2016-11-24 11:26:51 -05:00
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &Phi, dist_mem_size);
|
|
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &Velocity, 3*dist_mem_size);
|
|
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &ColorGrad, 3*dist_mem_size);
|
|
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &Den, 2*dist_mem_size);
|
2015-06-24 19:45:48 -04:00
|
|
|
//...........device phase ID.................................................
|
|
|
|
|
if (rank==0) printf ("Copying phase ID to device \n");
|
|
|
|
|
char *ID;
|
2016-11-24 11:26:51 -05:00
|
|
|
ScaLBL_AllocateDeviceMemory((void **) &ID, N); // Allocate device memory
|
2015-06-24 19:45:48 -04:00
|
|
|
// Copy to the device
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_CopyToDevice(ID, id, N);
|
|
|
|
|
ScaLBL_CopyToDevice(Velocity, Vel, 3*N*sizeof(double));
|
2015-06-24 19:45:48 -04:00
|
|
|
//...........................................................................
|
|
|
|
|
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_Color_Init(ID, Den, Phi, das, dbs, Nx, Ny, Nz);
|
|
|
|
|
ScaLBL_CopyToHost(DenOriginal,Den,2*N*sizeof(double));
|
2015-06-24 19:45:48 -04:00
|
|
|
|
|
|
|
|
//......................................................................
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_D3Q7_Init(ID, A_even, A_odd, &Den[0], Nx, Ny, Nz);
|
|
|
|
|
ScaLBL_D3Q7_Init(ID, B_even, B_odd, &Den[N], Nx, Ny, Nz);
|
|
|
|
|
ScaLBL_ComputePhaseField(ID, Phi, Den, N);
|
|
|
|
|
ScaLBL_D3Q19_ColorGradient(ID,Phi,ColorGrad,Nx,Ny,Nz);
|
2015-06-25 10:01:16 -04:00
|
|
|
//..................................................................................
|
|
|
|
|
|
2015-06-24 19:45:48 -04:00
|
|
|
//*************************************************************************
|
|
|
|
|
// Carry out the density streaming step for mass transport
|
|
|
|
|
//*************************************************************************
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_D3Q7_ColorCollideMass(ID, A_even, A_odd, B_even, B_odd, Den, Phi,
|
2015-06-24 19:45:48 -04:00
|
|
|
ColorGrad, Velocity, beta, N, pBC);
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
//..................................................................................
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_D3Q7_Density(ID, A_even, A_odd, &Den[0], Nx, Ny, Nz);
|
|
|
|
|
ScaLBL_D3Q7_Density(ID, B_even, B_odd, &Den[N], Nx, Ny, Nz);
|
2015-06-24 19:45:48 -04:00
|
|
|
//..................................................................................
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_ComputePhaseField(ID, Phi, Den, N);
|
|
|
|
|
ScaLBL_D3Q19_ColorGradient(ID,Phi,ColorGrad,Nx,Ny,Nz);
|
2015-06-25 10:01:16 -04:00
|
|
|
//..................................................................................
|
2015-06-24 19:45:48 -04:00
|
|
|
|
|
|
|
|
// Compare and make sure mass is conserved at every lattice site
|
|
|
|
|
bool CleanCheck = true;
|
|
|
|
|
double original,final;
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_CopyToHost(DenFinal,Den,2*N*sizeof(double));
|
2015-06-24 19:45:48 -04:00
|
|
|
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;
|
|
|
|
|
if (fabs(DenFinal[n] - DenOriginal[n]) > 1e-15){
|
|
|
|
|
final = DenFinal[n];
|
|
|
|
|
original = DenOriginal[n];
|
2015-06-24 19:53:19 -04:00
|
|
|
if (id[n] == 0) printf("Solid phase! \n");
|
|
|
|
|
if (id[n] == 1) printf("Wetting phase! \n");
|
|
|
|
|
if (id[n] == 2) printf("Non-wetting phase! \n");
|
2015-06-24 19:55:24 -04:00
|
|
|
printf("Mass not conserved: WP density, site=%i,%i,%i, original = %f, final = %f \n",i,j,k,original,final);
|
2015-06-24 19:45:48 -04:00
|
|
|
CleanCheck=false;
|
|
|
|
|
}
|
|
|
|
|
if (fabs(DenFinal[N+n] - DenOriginal[N+n]) > 1e-15){
|
2015-06-24 19:55:24 -04:00
|
|
|
if (id[n] == 0) printf("Solid phase! \n");
|
|
|
|
|
if (id[n] == 1) printf("Wetting phase! \n");
|
|
|
|
|
if (id[n] == 2) printf("Non-wetting phase! \n");
|
2015-06-24 19:45:48 -04:00
|
|
|
final = DenFinal[N+n];
|
|
|
|
|
original = DenOriginal[N+n];
|
2015-06-24 19:55:24 -04:00
|
|
|
printf("Mass not conserved: NWP density, site=%i,%i,%i, original = %f, final = %f \n",i,j,k,original,final);
|
2015-06-24 19:45:48 -04:00
|
|
|
CleanCheck=false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-06-27 09:17:51 -04:00
|
|
|
if (rank==0) printf("Checking that the correct velocity is retained \n");
|
2015-06-27 09:15:32 -04:00
|
|
|
// Swap convention is observed -- velocity is negative
|
2015-06-27 09:04:36 -04:00
|
|
|
double *Aeven,*Aodd,*Beven,*Bodd;
|
|
|
|
|
Aeven = new double[4*N];
|
|
|
|
|
Aodd = new double[3*N];
|
|
|
|
|
Beven = new double[4*N];
|
2015-06-27 09:13:25 -04:00
|
|
|
Bodd = new double[3*N];
|
2016-11-23 16:16:48 -05:00
|
|
|
ScaLBL_CopyToHost(Aeven,A_even,4*dist_mem_size);
|
|
|
|
|
ScaLBL_CopyToHost(Aodd,A_odd,3*dist_mem_size);
|
|
|
|
|
ScaLBL_CopyToHost(Beven,B_even,4*dist_mem_size);
|
|
|
|
|
ScaLBL_CopyToHost(Bodd,B_odd,3*dist_mem_size);
|
2015-06-27 09:04:36 -04:00
|
|
|
double rho,ux,uy,uz;
|
|
|
|
|
for (k=0;k<Nz;k++){
|
|
|
|
|
for (j=0;j<Ny;j++){
|
|
|
|
|
for (i=0;i<Nx;i++){
|
|
|
|
|
rho = ux = uy = uz = 0.0;
|
|
|
|
|
n = k*Nx*Ny + j*Nx + i;
|
|
|
|
|
if (id[n] != 0){
|
|
|
|
|
rho = Aeven[n]+Aeven[N+n]+Aeven[2*N+n]+Aeven[3*N+n]+Aodd[n]+Aodd[N+n]+Aodd[2*N+n]+
|
|
|
|
|
Beven[n]+Beven[N+n]+Beven[2*N+n]+Beven[3*N+n]+Bodd[n]+Bodd[N+n]+Bodd[2*N+n];
|
|
|
|
|
ux = Aeven[N+n] - Aodd[n] + Beven[N+n] - Bodd[n];
|
|
|
|
|
uy = Aeven[2*N+n] - Aodd[N+n] + Beven[2*N+n] - Bodd[N+n];
|
|
|
|
|
uz = Aeven[3*N+n] - Aodd[2*N+n] + Beven[3*N+n] - Bodd[2*N+n];
|
2015-06-27 09:15:32 -04:00
|
|
|
if ( fabs(0.1+ux / rho) > 1e-13 ){
|
2015-06-27 09:04:36 -04:00
|
|
|
if (id[n] == 1) printf("Wetting phase! \n");
|
|
|
|
|
if (id[n] == 2) printf("Non-wetting phase! \n");
|
|
|
|
|
final = ux/rho;
|
|
|
|
|
printf("Momentum (x) not conserved, site=%i,%i,%i, final = %f \n",i,j,k,final);
|
|
|
|
|
CleanCheck=false;
|
|
|
|
|
}
|
2015-06-27 09:15:32 -04:00
|
|
|
if ( fabs(0.1+uy / rho) > 1e-13 ){
|
2015-06-27 09:13:25 -04:00
|
|
|
if (id[n] == 1) printf("Wetting phase! \n");
|
|
|
|
|
if (id[n] == 2) printf("Non-wetting phase! \n");
|
|
|
|
|
final = uy/rho;
|
|
|
|
|
printf("Momentum (y) not conserved, site=%i,%i,%i, final = %f \n",i,j,k,final);
|
|
|
|
|
CleanCheck=false;
|
|
|
|
|
}
|
2015-06-27 09:15:32 -04:00
|
|
|
if ( fabs(0.1+uz / rho) > 1e-13 ){
|
2015-06-27 09:13:25 -04:00
|
|
|
if (id[n] == 1) printf("Wetting phase! \n");
|
|
|
|
|
if (id[n] == 2) printf("Non-wetting phase! \n");
|
|
|
|
|
final = uz/rho;
|
|
|
|
|
printf("Momentum (z) not conserved, site=%i,%i,%i, final = %f \n",i,j,k,final);
|
|
|
|
|
CleanCheck=false;
|
|
|
|
|
}
|
2015-06-27 09:04:36 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 10:05:20 -04:00
|
|
|
if (CleanCheck){
|
|
|
|
|
if (rank==0) printf("Test passed: mass conservation for D3Q7 \n");
|
|
|
|
|
}
|
2015-06-27 09:17:51 -04:00
|
|
|
else {
|
|
|
|
|
if (rank==0) printf("Test failed!: mass conservation for D3Q7 \n");
|
|
|
|
|
|
|
|
|
|
}
|
2015-06-24 19:45:48 -04:00
|
|
|
|
|
|
|
|
// ****************************************************
|
2015-09-04 13:06:36 -04:00
|
|
|
MPI_Barrier(comm);
|
2015-06-24 19:45:48 -04:00
|
|
|
MPI_Finalize();
|
|
|
|
|
// ****************************************************
|
2015-06-27 09:04:36 -04:00
|
|
|
}
|