2013-09-03 14:46:57 -04:00
|
|
|
// Created by James McClure
|
|
|
|
|
// Copyright 2008-2013
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <time.h>
|
2014-02-01 10:33:03 -05:00
|
|
|
#include <exception> // std::exception
|
|
|
|
|
#include <stdexcept>
|
2014-06-25 20:49:37 -04:00
|
|
|
#include <mpi.h>
|
2014-02-21 15:08:49 -05:00
|
|
|
#include "common/Utilities.h"
|
2014-02-01 10:33:03 -05:00
|
|
|
|
2013-09-03 14:46:57 -04:00
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
2014-06-25 16:35:53 -04:00
|
|
|
struct Domain{
|
|
|
|
|
|
|
|
|
|
Domain(int nx, int ny, int nz, int rnk, int npx, int npy, int npz,
|
|
|
|
|
double lx, double ly, double lz){
|
2014-06-25 16:45:42 -04:00
|
|
|
Nx = nx+2; Ny = ny+2; Nz = nz+2;
|
2014-06-25 16:35:53 -04:00
|
|
|
Lx = lx, Ly = ly, Lz = lz;
|
|
|
|
|
rank = rnk;
|
|
|
|
|
nprocx=npx; nprocy=npy; nprocz=npz;
|
|
|
|
|
N = Nx*Ny*Nz;
|
2014-06-25 20:38:43 -04:00
|
|
|
id = new char [N];
|
2014-06-25 16:35:53 -04:00
|
|
|
Blobs.New(Nx,Ny,Nz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Basic domain information
|
|
|
|
|
int Nx,Ny,Nz,N;
|
|
|
|
|
int iproc,jproc,kproc;
|
|
|
|
|
int nprocx,nprocy,nprocz;
|
|
|
|
|
double Lx,Ly,Lz;
|
|
|
|
|
int rank;
|
|
|
|
|
//**********************************
|
|
|
|
|
// 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;
|
|
|
|
|
//**********************************
|
2014-06-25 20:36:35 -04:00
|
|
|
//......................................................................................
|
|
|
|
|
// Get the actual D3Q19 communication counts (based on location of solid phase)
|
|
|
|
|
// Discrete velocity set symmetry implies the sendcount = recvcount
|
2014-06-25 20:44:04 -04:00
|
|
|
//......................................................................................
|
2014-06-25 20:36:35 -04:00
|
|
|
int sendCount_x, sendCount_y, sendCount_z, sendCount_X, sendCount_Y, sendCount_Z;
|
|
|
|
|
int sendCount_xy, sendCount_yz, sendCount_xz, sendCount_Xy, sendCount_Yz, sendCount_xZ;
|
|
|
|
|
int sendCount_xY, sendCount_yZ, sendCount_Xz, sendCount_XY, sendCount_YZ, sendCount_XZ;
|
|
|
|
|
//......................................................................................
|
|
|
|
|
int *sendList_x, *sendList_y, *sendList_z, *sendList_X, *sendList_Y, *sendList_Z;
|
|
|
|
|
int *sendList_xy, *sendList_yz, *sendList_xz, *sendList_Xy, *sendList_Yz, *sendList_xZ;
|
|
|
|
|
int *sendList_xY, *sendList_yZ, *sendList_Xz, *sendList_XY, *sendList_YZ, *sendList_XZ;
|
|
|
|
|
//......................................................................................
|
2014-06-25 20:44:04 -04:00
|
|
|
int *sendBuf_x, *sendBuf_y, *sendBuf_z, *sendBuf_X, *sendBuf_Y, *sendBuf_Z;
|
|
|
|
|
int *sendBuf_xy, *sendBuf_yz, *sendBuf_xz, *sendBuf_Xy, *sendBuf_Yz, *sendBuf_xZ;
|
|
|
|
|
int *sendBuf_xY, *sendBuf_yZ, *sendBuf_Xz, *sendBuf_XY, *sendBuf_YZ, *sendBuf_XZ;
|
2014-06-25 20:49:37 -04:00
|
|
|
//......................................................................................
|
|
|
|
|
int recvCount_x, recvCount_y, recvCount_z, recvCount_X, recvCount_Y, recvCount_Z;
|
|
|
|
|
int recvCount_xy, recvCount_yz, recvCount_xz, recvCount_Xy, recvCount_Yz, recvCount_xZ;
|
|
|
|
|
int recvCount_xY, recvCount_yZ, recvCount_Xz, recvCount_XY, recvCount_YZ, recvCount_XZ;
|
|
|
|
|
//......................................................................................
|
|
|
|
|
int *recvBuf_x, *recvBuf_y, *recvBuf_z, *recvBuf_X, *recvBuf_Y, *recvBuf_Z;
|
|
|
|
|
int *recvBuf_xy, *recvBuf_yz, *recvBuf_xz, *recvBuf_Xy, *recvBuf_Yz, *recvBuf_xZ;
|
|
|
|
|
int *recvBuf_xY, *recvBuf_yZ, *recvBuf_Xz, *recvBuf_XY, *recvBuf_YZ, *recvBuf_XZ;
|
2014-06-25 20:44:04 -04:00
|
|
|
//......................................................................................
|
2014-06-25 16:35:53 -04:00
|
|
|
|
|
|
|
|
// Solid indicator function
|
2014-06-25 20:36:35 -04:00
|
|
|
char *id;
|
2014-06-25 16:35:53 -04:00
|
|
|
// Blob information
|
|
|
|
|
IntArray Blobs;
|
|
|
|
|
|
2014-06-25 20:36:35 -04:00
|
|
|
void InitializeRanks();
|
|
|
|
|
void CommInit();
|
2014-06-25 16:35:53 -04:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
int getRankForBlock( int i, int j, int k )
|
|
|
|
|
{
|
|
|
|
|
int i2 = (i+nprocx)%nprocx;
|
|
|
|
|
int j2 = (j+nprocy)%nprocy;
|
|
|
|
|
int k2 = (k+nprocz)%nprocz;
|
|
|
|
|
return i2 + j2*nprocx + k2*nprocx*nprocy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2014-06-25 20:36:35 -04:00
|
|
|
void Domain::InitializeRanks()
|
|
|
|
|
{
|
|
|
|
|
// map the rank to the block index
|
|
|
|
|
iproc = rank%nprocx;
|
|
|
|
|
jproc = (rank/nprocx)%nprocy;
|
|
|
|
|
kproc = rank/(nprocx*nprocy);
|
|
|
|
|
|
|
|
|
|
// set up the neighbor ranks
|
|
|
|
|
int i = iproc;
|
|
|
|
|
int j = jproc;
|
|
|
|
|
int k = kproc;
|
|
|
|
|
rank_X = getRankForBlock(i+1,j,k);
|
|
|
|
|
rank_x = getRankForBlock(i-1,j,k);
|
|
|
|
|
rank_Y = getRankForBlock(i,j+1,k);
|
|
|
|
|
rank_y = getRankForBlock(i,j-1,k);
|
|
|
|
|
rank_Z = getRankForBlock(i,j,k+1);
|
|
|
|
|
rank_z = getRankForBlock(i,j,k-1);
|
|
|
|
|
rank_XY = getRankForBlock(i+1,j+1,k);
|
|
|
|
|
rank_xy = getRankForBlock(i-1,j-1,k);
|
|
|
|
|
rank_Xy = getRankForBlock(i+1,j-1,k);
|
|
|
|
|
rank_xY = getRankForBlock(i-1,j+1,k);
|
|
|
|
|
rank_XZ = getRankForBlock(i+1,j,k+1);
|
|
|
|
|
rank_xz = getRankForBlock(i-1,j,k-1);
|
|
|
|
|
rank_Xz = getRankForBlock(i+1,j,k-1);
|
|
|
|
|
rank_xZ = getRankForBlock(i-1,j,k+1);
|
|
|
|
|
rank_YZ = getRankForBlock(i,j+1,k+1);
|
|
|
|
|
rank_yz = getRankForBlock(i,j-1,k-1);
|
|
|
|
|
rank_Yz = getRankForBlock(i,j+1,k-1);
|
|
|
|
|
rank_yZ = getRankForBlock(i,j-1,k+1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Domain::CommInit(){
|
|
|
|
|
int i,j,k,n;
|
|
|
|
|
sendCount_x = sendCount_y = sendCount_z = sendCount_X = sendCount_Y = sendCount_Z = 0;
|
|
|
|
|
sendCount_xy = sendCount_yz = sendCount_xz = sendCount_Xy = sendCount_Yz = sendCount_xZ = 0;
|
|
|
|
|
sendCount_xY = sendCount_yZ = sendCount_Xz = sendCount_XY = sendCount_YZ = sendCount_XZ = 0;
|
|
|
|
|
//......................................................................................
|
|
|
|
|
for (k=0; k<Nz; k++){
|
|
|
|
|
for (j=0; j<Ny; j++){
|
|
|
|
|
for (i=0; i<Nx; i++){
|
|
|
|
|
// Check the phase ID
|
|
|
|
|
if (id[k*Nx*Ny+j*Nx+i] != 0){
|
|
|
|
|
// Counts for the six faces
|
|
|
|
|
if (i==1) sendCount_x++;
|
|
|
|
|
if (j==1) sendCount_y++;
|
|
|
|
|
if (k==1) sendCount_z++;
|
|
|
|
|
if (i==Nx-2) sendCount_X++;
|
|
|
|
|
if (j==Ny-2) sendCount_Y++;
|
|
|
|
|
if (k==Nz-2) sendCount_Z++;
|
|
|
|
|
// Counts for the twelve edges
|
|
|
|
|
if (i==1 && j==1) sendCount_xy++;
|
|
|
|
|
if (i==1 && j==Ny-2) sendCount_xY++;
|
|
|
|
|
if (i==Nx-2 && j==1) sendCount_Xy++;
|
|
|
|
|
if (i==Nx-2 && j==Ny-2) sendCount_XY++;
|
|
|
|
|
|
|
|
|
|
if (i==1 && k==1) sendCount_xz++;
|
|
|
|
|
if (i==1 && k==Nz-2) sendCount_xZ++;
|
|
|
|
|
if (i==Nx-2 && k==1) sendCount_Xz++;
|
|
|
|
|
if (i==Nx-2 && k==Nz-2) sendCount_XZ++;
|
|
|
|
|
|
|
|
|
|
if (j==1 && k==1) sendCount_yz++;
|
|
|
|
|
if (j==1 && k==Nz-2) sendCount_yZ++;
|
|
|
|
|
if (j==Ny-2 && k==1) sendCount_Yz++;
|
|
|
|
|
if (j==Ny-2 && k==Nz-2) sendCount_YZ++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-25 20:44:04 -04:00
|
|
|
// allocate send lists
|
2014-06-25 20:36:35 -04:00
|
|
|
sendList_x = new int [sendCount_x];
|
|
|
|
|
sendList_y = new int [sendCount_y];
|
|
|
|
|
sendList_z = new int [sendCount_z];
|
|
|
|
|
sendList_X = new int [sendCount_X];
|
|
|
|
|
sendList_Y = new int [sendCount_Y];
|
|
|
|
|
sendList_Z = new int [sendCount_Z];
|
|
|
|
|
sendList_xy = new int [sendCount_xy];
|
|
|
|
|
sendList_yz = new int [sendCount_yz];
|
|
|
|
|
sendList_xz = new int [sendCount_xz];
|
|
|
|
|
sendList_Xy = new int [sendCount_Xy];
|
|
|
|
|
sendList_Yz = new int [sendCount_Yz];
|
|
|
|
|
sendList_xZ = new int [sendCount_xZ];
|
|
|
|
|
sendList_xY = new int [sendCount_xY];
|
|
|
|
|
sendList_yZ = new int [sendCount_yZ];
|
|
|
|
|
sendList_Xz = new int [sendCount_Xz];
|
|
|
|
|
sendList_XY = new int [sendCount_XY];
|
|
|
|
|
sendList_YZ = new int [sendCount_YZ];
|
|
|
|
|
sendList_XZ = new int [sendCount_XZ];
|
|
|
|
|
// Populate the send list
|
|
|
|
|
sendCount_x = sendCount_y = sendCount_z = sendCount_X = sendCount_Y = sendCount_Z = 0;
|
|
|
|
|
sendCount_xy = sendCount_yz = sendCount_xz = sendCount_Xy = sendCount_Yz = sendCount_xZ = 0;
|
|
|
|
|
sendCount_xY = sendCount_yZ = sendCount_Xz = sendCount_XY = sendCount_YZ = sendCount_XZ = 0;
|
|
|
|
|
for (k=0; k<Nz; k++){
|
|
|
|
|
for (j=0; j<Ny; j++){
|
|
|
|
|
for (i=0; i<Nx; i++){
|
|
|
|
|
// Local value to send
|
|
|
|
|
n = k*Nx*Ny+j*Nx+i;
|
|
|
|
|
if (id[n] != 0){
|
|
|
|
|
// Counts for the six faces
|
|
|
|
|
if (i==1) sendList_x[sendCount_x++]=n;
|
|
|
|
|
if (j==1) sendList_y[sendCount_y++]=n;
|
|
|
|
|
if (k==1) sendList_z[sendCount_z++]=n;
|
|
|
|
|
if (i==Nx-2) sendList_X[sendCount_X++]=n;
|
|
|
|
|
if (j==Ny-2) sendList_Y[sendCount_Y++]=n;
|
|
|
|
|
if (k==Nz-2) sendList_Z[sendCount_Z++]=n;
|
|
|
|
|
// Counts for the twelve edges
|
|
|
|
|
if (i==1 && j==1) sendList_xy[sendCount_xy++]=n;
|
|
|
|
|
if (i==1 && j==Ny-2) sendList_xY[sendCount_xY++]=n;
|
|
|
|
|
if (i==Nx-2 && j==1) sendList_Xy[sendCount_Xy++]=n;
|
|
|
|
|
if (i==Nx-2 && j==Ny-2) sendList_XY[sendCount_XY++]=n;
|
|
|
|
|
|
|
|
|
|
if (i==1 && k==1) sendList_xz[sendCount_xz++]=n;
|
|
|
|
|
if (i==1 && k==Nz-2) sendList_xZ[sendCount_xZ++]=n;
|
|
|
|
|
if (i==Nx-2 && k==1) sendList_Xz[sendCount_Xz++]=n;
|
|
|
|
|
if (i==Nx-2 && k==Nz-2) sendList_XZ[sendCount_XZ++]=n;
|
|
|
|
|
|
|
|
|
|
if (j==1 && k==1) sendList_yz[sendCount_yz++]=n;
|
|
|
|
|
if (j==1 && k==Nz-2) sendList_yZ[sendCount_yZ++]=n;
|
|
|
|
|
if (j==Ny-2 && k==1) sendList_Yz[sendCount_Yz++]=n;
|
|
|
|
|
if (j==Ny-2 && k==Nz-2) sendList_YZ[sendCount_YZ++]=n;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-25 20:44:04 -04:00
|
|
|
// allocate send buffers
|
|
|
|
|
sendBuf_x = new int [sendCount_x];
|
|
|
|
|
sendBuf_y = new int [sendCount_y];
|
|
|
|
|
sendBuf_z = new int [sendCount_z];
|
|
|
|
|
sendBuf_X = new int [sendCount_X];
|
|
|
|
|
sendBuf_Y = new int [sendCount_Y];
|
|
|
|
|
sendBuf_Z = new int [sendCount_Z];
|
|
|
|
|
sendBuf_xy = new int [sendCount_xy];
|
|
|
|
|
sendBuf_yz = new int [sendCount_yz];
|
|
|
|
|
sendBuf_xz = new int [sendCount_xz];
|
|
|
|
|
sendBuf_Xy = new int [sendCount_Xy];
|
|
|
|
|
sendBuf_Yz = new int [sendCount_Yz];
|
|
|
|
|
sendBuf_xZ = new int [sendCount_xZ];
|
|
|
|
|
sendBuf_xY = new int [sendCount_xY];
|
|
|
|
|
sendBuf_yZ = new int [sendCount_yZ];
|
|
|
|
|
sendBuf_Xz = new int [sendCount_Xz];
|
|
|
|
|
sendBuf_XY = new int [sendCount_XY];
|
|
|
|
|
sendBuf_YZ = new int [sendCount_YZ];
|
|
|
|
|
sendBuf_XZ = new int [sendCount_XZ];
|
2014-06-25 20:36:35 -04:00
|
|
|
}
|
|
|
|
|
|
2013-09-03 14:46:57 -04:00
|
|
|
inline void ReadSpherePacking(int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad)
|
|
|
|
|
{
|
|
|
|
|
// Read in the full sphere pack
|
|
|
|
|
//...... READ IN THE SPHERES...................................
|
|
|
|
|
cout << "Reading the packing file..." << endl;
|
2014-02-01 10:33:03 -05:00
|
|
|
FILE *fid = fopen("pack.out","rb");
|
2014-02-21 15:36:05 -05:00
|
|
|
INSIST(fid!=NULL,"Error opening pack.out");
|
2013-09-03 14:46:57 -04:00
|
|
|
//.........Trash the header lines..........
|
2014-02-01 10:33:03 -05:00
|
|
|
char * line = new char[100];
|
|
|
|
|
fgets(line, 100, fid);
|
|
|
|
|
fgets(line, 100, fid);
|
|
|
|
|
fgets(line, 100, fid);
|
|
|
|
|
fgets(line, 100, fid);
|
|
|
|
|
fgets(line, 100, fid);
|
2013-09-03 14:46:57 -04:00
|
|
|
//........read the spheres..................
|
2014-02-01 10:33:03 -05:00
|
|
|
// We will read until a blank like or end-of-file is reached
|
|
|
|
|
int count = 0;
|
|
|
|
|
while ( !feof(fid) && fgets(line,100,fid)>0 ) {
|
|
|
|
|
char* line2 = line;
|
|
|
|
|
List_cx[count] = strtod(line2,&line2);
|
|
|
|
|
List_cy[count] = strtod(line2,&line2);
|
|
|
|
|
List_cz[count] = strtod(line2,&line2);
|
|
|
|
|
List_rad[count] = strtod(line2,&line2);
|
2013-09-03 14:46:57 -04:00
|
|
|
count++;
|
|
|
|
|
}
|
2014-02-24 12:35:31 -05:00
|
|
|
cout << "Number of spheres extracted is: " << count << endl;
|
2014-02-21 15:36:05 -05:00
|
|
|
INSIST( count==nspheres, "Specified number of spheres is probably incorrect!" );
|
2013-09-03 14:46:57 -04:00
|
|
|
// .............................................................
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void AssignLocalSolidID(char *ID, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad,
|
|
|
|
|
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
|
|
|
|
|
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz)
|
|
|
|
|
{
|
|
|
|
|
// Use sphere lists to determine which nodes are in porespace
|
|
|
|
|
// Write out binary file for nodes
|
|
|
|
|
char value;
|
|
|
|
|
int N = Nx*Ny*Nz; // Domain size, including the halo
|
|
|
|
|
double hx,hy,hz;
|
|
|
|
|
double x,y,z;
|
|
|
|
|
double cx,cy,cz,r;
|
|
|
|
|
int imin,imax,jmin,jmax,kmin,kmax;
|
|
|
|
|
int p,i,j,k,n;
|
|
|
|
|
//............................................
|
|
|
|
|
double min_x,min_y,min_z;
|
|
|
|
|
// double max_x,max_y,max_z;
|
|
|
|
|
//............................................
|
|
|
|
|
// Lattice spacing for the entire domain
|
|
|
|
|
// It should generally be true that hx=hy=hz
|
|
|
|
|
// Otherwise, you will end up with ellipsoids
|
|
|
|
|
hx = Lx/(Nx*nprocx-1);
|
|
|
|
|
hy = Ly/(Ny*nprocy-1);
|
|
|
|
|
hz = Lz/(Nz*nprocz-1);
|
|
|
|
|
//............................................
|
|
|
|
|
// Get maximum and minimum for this domain
|
|
|
|
|
// Halo is included !
|
|
|
|
|
min_x = double(iproc*Nx-1)*hx;
|
|
|
|
|
min_y = double(jproc*Ny-1)*hy;
|
|
|
|
|
min_z = double(kproc*Nz-1)*hz;
|
|
|
|
|
// max_x = ((iproc+1)*Nx+1)*hx;
|
|
|
|
|
// max_y = ((jproc+1)*Ny+1)*hy;
|
|
|
|
|
// max_z = ((kproc+1)*Nz+1)*hz;
|
|
|
|
|
//............................................
|
|
|
|
|
|
|
|
|
|
//............................................
|
|
|
|
|
// Pre-initialize local ID
|
|
|
|
|
for (n=0;n<N;n++){
|
|
|
|
|
ID[n]=1;
|
|
|
|
|
}
|
|
|
|
|
//............................................
|
|
|
|
|
|
|
|
|
|
//............................................
|
|
|
|
|
// .........Loop over the spheres.............
|
|
|
|
|
for (p=0;p<nspheres;p++){
|
|
|
|
|
// Get the sphere from the list, map to local min
|
|
|
|
|
cx = List_cx[p] - min_x;
|
|
|
|
|
cy = List_cy[p] - min_y;
|
|
|
|
|
cz = List_cz[p] - min_z;
|
|
|
|
|
r = List_rad[p];
|
|
|
|
|
// Check if
|
|
|
|
|
// Range for this sphere in global indexing
|
|
|
|
|
imin = int ((cx-r)/hx)-1;
|
|
|
|
|
imax = int ((cx+r)/hx)+1;
|
|
|
|
|
jmin = int ((cy-r)/hy)-1;
|
|
|
|
|
jmax = int ((cy+r)/hy)+1;
|
|
|
|
|
kmin = int ((cz-r)/hz)-1;
|
|
|
|
|
kmax = int ((cz+r)/hz)+1;
|
|
|
|
|
// Obviously we have to do something at the edges
|
|
|
|
|
if (imin<0) imin = 0;
|
|
|
|
|
if (imin>Nx) imin = Nx;
|
|
|
|
|
if (imax<0) imax = 0;
|
|
|
|
|
if (imax>Nx) imax = Nx;
|
|
|
|
|
if (jmin<0) jmin = 0;
|
|
|
|
|
if (jmin>Ny) jmin = Ny;
|
|
|
|
|
if (jmax<0) jmax = 0;
|
|
|
|
|
if (jmax>Ny) jmax = Ny;
|
|
|
|
|
if (kmin<0) kmin = 0;
|
|
|
|
|
if (kmin>Nz) kmin = Nz;
|
|
|
|
|
if (kmax<0) kmax = 0;
|
|
|
|
|
if (kmax>Nz) kmax = Nz;
|
|
|
|
|
// Loop over the domain for this sphere (may be null)
|
|
|
|
|
for (i=imin;i<imax;i++){
|
|
|
|
|
for (j=jmin;j<jmax;j++){
|
|
|
|
|
for (k=kmin;k<kmax;k++){
|
|
|
|
|
// Initialize ID value to 'fluid (=1)'
|
|
|
|
|
x = i*hx;
|
|
|
|
|
y = j*hy;
|
|
|
|
|
z = k*hz;
|
|
|
|
|
value = 1;
|
|
|
|
|
// if inside sphere, set to zero
|
|
|
|
|
if ( (cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z) < r*r){
|
|
|
|
|
value=0;
|
|
|
|
|
}
|
|
|
|
|
// get the position in the list
|
|
|
|
|
n = k*Nx*Ny+j*Nx+i;
|
|
|
|
|
if ( ID[n] != 0 ){
|
|
|
|
|
ID[n] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-08 22:29:21 -04:00
|
|
|
inline void SignedDistance(double *Distance, int nspheres, double *List_cx, double *List_cy, double *List_cz, double *List_rad,
|
|
|
|
|
double Lx, double Ly, double Lz, int Nx, int Ny, int Nz,
|
|
|
|
|
int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz)
|
|
|
|
|
{
|
|
|
|
|
// Use sphere lists to determine which nodes are in porespace
|
|
|
|
|
// Write out binary file for nodes
|
|
|
|
|
int N = Nx*Ny*Nz; // Domain size, including the halo
|
|
|
|
|
double hx,hy,hz;
|
|
|
|
|
double x,y,z;
|
|
|
|
|
double cx,cy,cz,r;
|
|
|
|
|
int imin,imax,jmin,jmax,kmin,kmax;
|
|
|
|
|
int p,i,j,k,n;
|
|
|
|
|
//............................................
|
|
|
|
|
double min_x,min_y,min_z;
|
|
|
|
|
double distance;
|
|
|
|
|
//............................................
|
|
|
|
|
// Lattice spacing for the entire domain
|
|
|
|
|
// It should generally be true that hx=hy=hz
|
|
|
|
|
// Otherwise, you will end up with ellipsoids
|
|
|
|
|
hx = Lx/((Nx-2)*nprocx-1);
|
|
|
|
|
hy = Ly/((Ny-2)*nprocy-1);
|
|
|
|
|
hz = Lz/((Nz-2)*nprocz-1);
|
|
|
|
|
//............................................
|
|
|
|
|
// Get maximum and minimum for this domain
|
|
|
|
|
// Halo is included !
|
|
|
|
|
min_x = double(iproc*(Nx-2)-1)*hx;
|
|
|
|
|
min_y = double(jproc*(Ny-2)-1)*hy;
|
|
|
|
|
min_z = double(kproc*(Nz-2)-1)*hz;
|
|
|
|
|
//............................................
|
|
|
|
|
|
|
|
|
|
//............................................
|
|
|
|
|
// Pre-initialize Distance
|
|
|
|
|
for (n=0;n<N;n++){
|
|
|
|
|
Distance[n]=100.0;
|
|
|
|
|
}
|
|
|
|
|
//............................................
|
|
|
|
|
|
|
|
|
|
//............................................
|
|
|
|
|
// .........Loop over the spheres.............
|
|
|
|
|
for (p=0;p<nspheres;p++){
|
|
|
|
|
// Get the sphere from the list, map to local min
|
|
|
|
|
cx = List_cx[p] - min_x;
|
|
|
|
|
cy = List_cy[p] - min_y;
|
|
|
|
|
cz = List_cz[p] - min_z;
|
|
|
|
|
r = List_rad[p];
|
|
|
|
|
// Check if
|
|
|
|
|
// Range for this sphere in global indexing
|
|
|
|
|
imin = int ((cx-r)/hx);
|
|
|
|
|
imax = int ((cx+r)/hx)+2;
|
|
|
|
|
jmin = int ((cy-r)/hy);
|
|
|
|
|
jmax = int ((cy+r)/hy)+2;
|
|
|
|
|
kmin = int ((cz-r)/hz);
|
|
|
|
|
kmax = int ((cz+r)/hz)+2;
|
|
|
|
|
// Obviously we have to do something at the edges
|
|
|
|
|
if (imin<0) imin = 0;
|
|
|
|
|
if (imin>Nx) imin = Nx;
|
|
|
|
|
if (imax<0) imax = 0;
|
|
|
|
|
if (imax>Nx) imax = Nx;
|
|
|
|
|
if (jmin<0) jmin = 0;
|
|
|
|
|
if (jmin>Ny) jmin = Ny;
|
|
|
|
|
if (jmax<0) jmax = 0;
|
|
|
|
|
if (jmax>Ny) jmax = Ny;
|
|
|
|
|
if (kmin<0) kmin = 0;
|
|
|
|
|
if (kmin>Nz) kmin = Nz;
|
|
|
|
|
if (kmax<0) kmax = 0;
|
|
|
|
|
if (kmax>Nz) kmax = Nz;
|
|
|
|
|
// Loop over the domain for this sphere (may be null)
|
|
|
|
|
for (i=imin;i<imax;i++){
|
|
|
|
|
for (j=jmin;j<jmax;j++){
|
|
|
|
|
for (k=kmin;k<kmax;k++){
|
|
|
|
|
// x,y,z is distance in physical units
|
|
|
|
|
x = i*hx;
|
|
|
|
|
y = j*hy;
|
|
|
|
|
z = k*hz;
|
|
|
|
|
// if inside sphere, set to zero
|
|
|
|
|
// get the position in the list
|
|
|
|
|
n = k*Nx*Ny+j*Nx+i;
|
|
|
|
|
// Compute the distance
|
|
|
|
|
distance = sqrt((cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z)) - r;
|
|
|
|
|
// Assign the minimum distance
|
|
|
|
|
if (distance < Distance[n]) Distance[n] = distance;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Map the distance to lattice units
|
|
|
|
|
for (n=0; n<N; n++) Distance[n] = Distance[n]/hx;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-03 14:46:57 -04:00
|
|
|
inline void GenerateResidual(char *ID, int Nx, int Ny, int Nz, double Saturation)
|
|
|
|
|
{
|
|
|
|
|
//.......................................................................
|
|
|
|
|
int i,j,k,n,Number,N;
|
|
|
|
|
int x,y,z,ii,jj,kk;
|
|
|
|
|
int sizeX,sizeY,sizeZ;
|
|
|
|
|
int *SizeX, *SizeY, *SizeZ;
|
|
|
|
|
|
2014-06-02 17:06:34 -04:00
|
|
|
#ifdef NORANDOM
|
2013-09-03 14:46:57 -04:00
|
|
|
srand(10009);
|
2014-06-02 17:06:34 -04:00
|
|
|
#else
|
|
|
|
|
srand(time(NULL));
|
|
|
|
|
#endif
|
2013-09-03 14:46:57 -04:00
|
|
|
// float bin;
|
|
|
|
|
//.......................................................................
|
|
|
|
|
N = Nx*Ny*Nz;
|
|
|
|
|
|
2014-05-11 10:14:38 -04:00
|
|
|
int bin, binCount;
|
2014-05-11 08:23:16 -04:00
|
|
|
ifstream Dist("BlobSize.in");
|
|
|
|
|
Dist >> binCount;
|
2014-05-21 20:51:42 -04:00
|
|
|
// printf("Number of blob sizes: %i \n",binCount);
|
2013-09-03 14:46:57 -04:00
|
|
|
SizeX = new int [binCount];
|
|
|
|
|
SizeY = new int [binCount];
|
|
|
|
|
SizeZ = new int [binCount];
|
2014-05-11 10:14:38 -04:00
|
|
|
for (bin=0; bin<binCount; bin++){
|
2013-09-03 14:46:57 -04:00
|
|
|
Dist >> SizeX[bin];
|
|
|
|
|
Dist >> SizeY[bin];
|
|
|
|
|
Dist >> SizeZ[bin];
|
2014-05-21 20:51:42 -04:00
|
|
|
// printf("Blob %i dimension: %i x %i x %i \n",bin, SizeX[bin], SizeY[bin], SizeZ[bin]);
|
2013-09-03 14:46:57 -04:00
|
|
|
}
|
|
|
|
|
Dist.close();
|
2014-05-11 08:23:16 -04:00
|
|
|
//.......................................................................
|
2013-09-03 14:46:57 -04:00
|
|
|
// cout << "Generating blocks... " << endl;
|
|
|
|
|
// Count for the total number of oil nodes
|
|
|
|
|
int count = 0;
|
|
|
|
|
// Count the total number of non-solid nodes
|
|
|
|
|
int total = 0;
|
|
|
|
|
for (i=0;i<N;i++){
|
|
|
|
|
if (ID[i] != 0) total++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float sat = 0.f;
|
|
|
|
|
Number = 0; // number of features
|
|
|
|
|
while (sat < Saturation){
|
|
|
|
|
Number++;
|
|
|
|
|
// Randomly generate a point in the domain
|
|
|
|
|
x = Nx*float(rand())/float(RAND_MAX);
|
|
|
|
|
y = Ny*float(rand())/float(RAND_MAX);
|
|
|
|
|
z = Nz*float(rand())/float(RAND_MAX);
|
|
|
|
|
|
2014-05-11 10:14:38 -04:00
|
|
|
bin = int(floor(binCount*float(rand())/float(RAND_MAX)));
|
|
|
|
|
sizeX = SizeX[bin];
|
|
|
|
|
sizeY = SizeY[bin];
|
|
|
|
|
sizeZ = SizeZ[bin];
|
2013-09-03 14:46:57 -04:00
|
|
|
|
|
|
|
|
// cout << "Sampling from bin no. " << floor(bin) << endl;
|
|
|
|
|
// cout << "Feature size is: " << sizeX << "x" << sizeY << "x" << sizeZ << endl;
|
|
|
|
|
|
|
|
|
|
for (k=z;k<z+sizeZ;k++){
|
|
|
|
|
for (j=y;j<y+sizeY;j++){
|
|
|
|
|
for (i=x;i<x+sizeX;i++){
|
|
|
|
|
// Identify nodes in the domain (periodic BC)
|
|
|
|
|
ii = i;
|
|
|
|
|
jj = j;
|
|
|
|
|
kk = k;
|
|
|
|
|
if (ii < 1) ii+=(Nx-2);
|
|
|
|
|
if (jj < 1) jj+=(Ny-2);
|
|
|
|
|
if (kk < 1) kk+=(Nz-2);
|
|
|
|
|
if (!(ii < Nx-1)) ii-=(Nx-2);
|
|
|
|
|
if (!(jj < Ny-1)) jj-=(Ny-2);
|
|
|
|
|
if (!(kk < Nz-1)) kk-=(Nz-2);
|
|
|
|
|
|
|
|
|
|
n = kk*Nx*Ny+jj*Nx+ii;
|
|
|
|
|
|
2014-03-23 09:43:37 -04:00
|
|
|
if (ID[n] == 2){
|
|
|
|
|
ID[n] = 1;
|
2013-09-03 14:46:57 -04:00
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sat = float(count)/total;
|
|
|
|
|
}
|
|
|
|
|
//.......................................................................
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-03 17:47:57 -04:00
|
|
|
inline void FlipID(char *ID, int N)
|
|
|
|
|
{
|
|
|
|
|
for (int n=0; n<N; n++){
|
2014-06-17 15:16:46 -04:00
|
|
|
if (ID[n] == 1) ID[n] = 2;
|
2014-06-03 17:47:57 -04:00
|
|
|
else if (ID[n] == 2) ID[n] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-02 17:06:34 -04:00
|
|
|
|
2013-09-03 14:46:57 -04:00
|
|
|
inline void WriteLocalSolidID(char *FILENAME, char *ID, int N)
|
|
|
|
|
{
|
|
|
|
|
char value;
|
|
|
|
|
ofstream File(FILENAME,ios::binary);
|
|
|
|
|
for (int n=0; n<N; n++){
|
|
|
|
|
value = ID[n];
|
|
|
|
|
File.write((char*) &value, sizeof(value));
|
|
|
|
|
}
|
|
|
|
|
File.close();
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-08 22:29:21 -04:00
|
|
|
inline void WriteLocalSolidDistance(char *FILENAME, double *Distance, int N)
|
|
|
|
|
{
|
|
|
|
|
double value;
|
|
|
|
|
ofstream File(FILENAME,ios::binary);
|
|
|
|
|
for (int n=0; n<N; n++){
|
|
|
|
|
value = Distance[n];
|
|
|
|
|
File.write((char*) &value, sizeof(value));
|
|
|
|
|
}
|
|
|
|
|
File.close();
|
|
|
|
|
}
|
2013-11-19 00:57:48 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void WriteCheckpoint(char *FILENAME, double *cDen, double *cDistEven, double *cDistOdd, int N)
|
|
|
|
|
{
|
|
|
|
|
int q,n;
|
|
|
|
|
double value;
|
|
|
|
|
ofstream File(FILENAME,ios::binary);
|
|
|
|
|
for (n=0; n<N; n++){
|
|
|
|
|
// Write the two density values
|
|
|
|
|
value = cDen[2*n];
|
|
|
|
|
File.write((char*) &value, sizeof(value));
|
|
|
|
|
value = cDen[2*n+1];
|
|
|
|
|
File.write((char*) &value, sizeof(value));
|
|
|
|
|
// Write the even distributions
|
|
|
|
|
for (q=0; q<10; q++){
|
|
|
|
|
value = cDistEven[q*N+n];
|
|
|
|
|
File.write((char*) &value, sizeof(value));
|
|
|
|
|
}
|
|
|
|
|
// Write the odd distributions
|
|
|
|
|
for (q=0; q<9; q++){
|
|
|
|
|
value = cDistOdd[q*N+n];
|
|
|
|
|
File.write((char*) &value, sizeof(value));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
File.close();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void ReadCheckpoint(char *FILENAME, double *cDen, double *cDistEven, double *cDistOdd, int N)
|
|
|
|
|
{
|
|
|
|
|
int q,n;
|
|
|
|
|
double value;
|
|
|
|
|
ifstream File(FILENAME,ios::binary);
|
|
|
|
|
for (n=0; n<N; n++){
|
|
|
|
|
// Write the two density values
|
|
|
|
|
File.read((char*) &value, sizeof(value));
|
|
|
|
|
cDen[2*n] = value;
|
|
|
|
|
// if (n== 66276) printf("Density a = %f \n",value);
|
|
|
|
|
File.read((char*) &value, sizeof(value));
|
|
|
|
|
cDen[2*n+1] = value;
|
|
|
|
|
// if (n== 66276) printf("Density b = %f \n",value);
|
|
|
|
|
// Read the even distributions
|
|
|
|
|
for (q=0; q<10; q++){
|
|
|
|
|
File.read((char*) &value, sizeof(value));
|
|
|
|
|
cDistEven[q*N+n] = value;
|
|
|
|
|
// if (n== 66276) printf("dist even %i = %f \n",q,value);
|
|
|
|
|
}
|
|
|
|
|
// Read the odd distributions
|
|
|
|
|
for (q=0; q<9; q++){
|
|
|
|
|
File.read((char*) &value, sizeof(value));
|
|
|
|
|
cDistOdd[q*N+n] = value;
|
|
|
|
|
// if (n== 66276) printf("dist even %i = %f \n",q,value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
File.close();
|
|
|
|
|
}
|
2014-01-27 11:43:24 -05:00
|
|
|
|
|
|
|
|
inline void ReadBinaryFile(char *FILENAME, double *Data, int N)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
double value;
|
|
|
|
|
ifstream File(FILENAME,ios::binary);
|
|
|
|
|
for (n=0; n<N; n++){
|
|
|
|
|
// Write the two density values
|
|
|
|
|
File.read((char*) &value, sizeof(value));
|
|
|
|
|
Data[n] = value;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
File.close();
|
|
|
|
|
}
|
|
|
|
|
|