add image sequence to FlowAdaptor
This commit is contained in:
parent
fddd7ae261
commit
7072ede5a4
@ -1981,188 +1981,197 @@ FlowAdaptor::FlowAdaptor(ScaLBL_ColorModel &M){
|
|||||||
Nz = M.Dm->Nz;
|
Nz = M.Dm->Nz;
|
||||||
timestep=-1;
|
timestep=-1;
|
||||||
timestep_previous=-1;
|
timestep_previous=-1;
|
||||||
|
|
||||||
phi.resize(Nx,Ny,Nz); phi.fill(0); // phase indicator field
|
phi.resize(Nx,Ny,Nz); phi.fill(0); // phase indicator field
|
||||||
phi_t.resize(Nx,Ny,Nz); phi_t.fill(0); // time derivative for the phase indicator field
|
phi_t.resize(Nx,Ny,Nz); phi_t.fill(0); // time derivative for the phase indicator field
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowAdaptor::~FlowAdaptor(){
|
FlowAdaptor::~FlowAdaptor(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
double FlowAdaptor::ImageInit(ScaLBL_ColorModel &M, std::string Filename){
|
||||||
|
int rank = M.rank;
|
||||||
|
int Nx = M.Nx; int Ny = M.Ny; int Nz = M.Nz;
|
||||||
|
if (rank==0) printf("Re-initializing fluids from file: %s \n", Filename.c_str());
|
||||||
|
M.Mask->Decomp(Filename);
|
||||||
|
for (int i=0; i<Nx*Ny*Nz; i++) M.id[i] = M.Mask->id[i]; // save what was read
|
||||||
|
for (int i=0; i<Nx*Ny*Nz; i++) M.Dm->id[i] = M.Mask->id[i]; // save what was read
|
||||||
|
|
||||||
|
double *PhaseLabel;
|
||||||
|
PhaseLabel = new double[Nx*Ny*Nz];
|
||||||
|
M.AssignComponentLabels(PhaseLabel);
|
||||||
|
|
||||||
|
double Count = 0.0;
|
||||||
|
double PoreCount = 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++){
|
||||||
|
if (M.id[Nx*Ny*k+Nx*j+i] == 2){
|
||||||
|
PoreCount++;
|
||||||
|
Count++;
|
||||||
|
}
|
||||||
|
else if (M.id[Nx*Ny*k+Nx*j+i] == 1){
|
||||||
|
PoreCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Count=M.Dm->Comm.sumReduce( Count);
|
||||||
|
PoreCount=M.Dm->Comm.sumReduce( PoreCount);
|
||||||
|
|
||||||
double MASS_FRACTION_CHANGE = 0.0005;
|
if (rank==0) printf(" new saturation: %f (%f / %f) \n", Count / PoreCount, Count, PoreCount);
|
||||||
if (M.db->keyExists( "FlowAdaptor" )){
|
ScaLBL_CopyToDevice(M.Phi, PhaseLabel, Nx*Ny*Nz*sizeof(double));
|
||||||
auto flow_db = M.db->getDatabase( "FlowAdaptor" );
|
M.Dm->Comm.barrier();
|
||||||
MASS_FRACTION_CHANGE = flow_db->getWithDefault<double>( "mass_fraction_factor", 0.0005);
|
|
||||||
}
|
ScaLBL_D3Q19_Init(M.fq, M.Np);
|
||||||
int Np = M.Np;
|
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0, M.ScaLBL_Comm->LastExterior(), M.Np);
|
||||||
double dA, dB, phi;
|
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, M.ScaLBL_Comm->FirstInterior(), M.ScaLBL_Comm->LastInterior(), M.Np);
|
||||||
double vx,vy,vz;
|
M.Dm->Comm.barrier();
|
||||||
double vax,vay,vaz;
|
|
||||||
double vbx,vby,vbz;
|
ScaLBL_CopyToHost(M.Averages->Phi.data(),M.Phi,Nx*Ny*Nz*sizeof(double));
|
||||||
double vax_global,vay_global,vaz_global;
|
|
||||||
double vbx_global,vby_global,vbz_global;
|
|
||||||
|
|
||||||
double mass_a, mass_b, mass_a_global, mass_b_global;
|
double saturation = Count/PoreCount;
|
||||||
|
return saturation;
|
||||||
double *Aq_tmp, *Bq_tmp;
|
}
|
||||||
double *Vel_x, *Vel_y, *Vel_z, *Phase;
|
|
||||||
|
|
||||||
Aq_tmp = new double [7*Np];
|
|
||||||
Bq_tmp = new double [7*Np];
|
|
||||||
Phase = new double [Np];
|
|
||||||
Vel_x = new double [Np];
|
|
||||||
Vel_y = new double [Np];
|
|
||||||
Vel_z = new double [Np];
|
|
||||||
|
|
||||||
ScaLBL_CopyToHost(Aq_tmp, M.Aq, 7*Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToHost(Bq_tmp, M.Bq, 7*Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToHost(Vel_x, &M.Velocity[0], Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToHost(Vel_y, &M.Velocity[Np], Np*sizeof(double));
|
|
||||||
ScaLBL_CopyToHost(Vel_z, &M.Velocity[2*Np], Np*sizeof(double));
|
|
||||||
|
|
||||||
/* DEBUG STRUCTURES */
|
|
||||||
int Nx = M.Nx; int Ny = M.Ny; int Nz = M.Nz;
|
|
||||||
//int N = Nx*Ny*Nz;
|
|
||||||
//double * DebugMassA, *DebugMassB;
|
|
||||||
//DebugMassA = new double[Np];
|
|
||||||
//DebugMassB = new double[Np];
|
|
||||||
|
|
||||||
/* compute the total momentum */
|
|
||||||
vax = vay = vaz = 0.0;
|
|
||||||
vbx = vby = vbz = 0.0;
|
|
||||||
mass_a = mass_b = 0.0;
|
|
||||||
|
|
||||||
double maxSpeed = 0.0;
|
|
||||||
double localMaxSpeed = 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=M.Map(i,j,k);
|
|
||||||
double distance = M.Averages->SDs(i,j,k);
|
|
||||||
if (!(n<0) ){
|
|
||||||
dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
|
|
||||||
dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
|
|
||||||
phi = (dA - dB) / (dA + dB);
|
|
||||||
Phase[n] = phi;
|
|
||||||
mass_a += dA;
|
|
||||||
mass_b += dB;
|
|
||||||
if (phi > 0.0){
|
|
||||||
vax += Vel_x[n];
|
|
||||||
vay += Vel_y[n];
|
|
||||||
vaz += Vel_z[n];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vbx += Vel_x[n];
|
|
||||||
vby += Vel_y[n];
|
|
||||||
vbz += Vel_z[n];
|
|
||||||
}
|
|
||||||
double speed = sqrt(vax*vax + vay*vay + vaz*vaz + vbx*vbx + vby*vby + vbz*vbz);
|
|
||||||
if (distance > 3.0 && speed > localMaxSpeed){
|
|
||||||
localMaxSpeed = speed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maxSpeed = M.Dm->Comm.maxReduce(localMaxSpeed);
|
|
||||||
/* for (int n=0; n < M.ScaLBL_Comm->LastExterior(); n++){
|
|
||||||
dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
|
|
||||||
dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
|
|
||||||
phi = (dA - dB) / (dA + dB);
|
|
||||||
Phase[n] = phi;
|
|
||||||
mass_a += dA;
|
|
||||||
mass_b += dB;
|
|
||||||
if (phi > 0.0){
|
|
||||||
vax += Vel_x[n];
|
|
||||||
vay += Vel_y[n];
|
|
||||||
vaz += Vel_z[n];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vbx += Vel_x[n];
|
|
||||||
vby += Vel_y[n];
|
|
||||||
vbz += Vel_z[n];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int n=M.ScaLBL_Comm->FirstInterior(); n < M.ScaLBL_Comm->LastInterior(); n++){
|
|
||||||
dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
|
|
||||||
dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
|
|
||||||
phi = (dA - dB) / (dA + dB);
|
|
||||||
Phase[n] = phi;
|
|
||||||
mass_a += dA;
|
|
||||||
mass_b += dB;
|
|
||||||
if (phi > 0.0){
|
|
||||||
vax += Vel_x[n];
|
|
||||||
vay += Vel_y[n];
|
|
||||||
vaz += Vel_z[n];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vbx += Vel_x[n];
|
|
||||||
vby += Vel_y[n];
|
|
||||||
vbz += Vel_z[n];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
mass_a_global = M.Dm->Comm.sumReduce(mass_a);
|
|
||||||
mass_b_global = M.Dm->Comm.sumReduce(mass_b);
|
|
||||||
vax_global = M.Dm->Comm.sumReduce(vax);
|
|
||||||
vay_global = M.Dm->Comm.sumReduce(vay);
|
|
||||||
vaz_global = M.Dm->Comm.sumReduce(vaz);
|
|
||||||
vbx_global = M.Dm->Comm.sumReduce(vbx);
|
|
||||||
vby_global = M.Dm->Comm.sumReduce(vby);
|
|
||||||
vbz_global = M.Dm->Comm.sumReduce(vbz);
|
|
||||||
|
|
||||||
double total_momentum_A = sqrt(vax_global*vax_global+vay_global*vay_global+vaz_global*vaz_global);
|
double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
||||||
double total_momentum_B = sqrt(vbx_global*vbx_global+vby_global*vby_global+vbz_global*vbz_global);
|
|
||||||
/* compute the total mass change */
|
|
||||||
double TOTAL_MASS_CHANGE = MASS_FRACTION_CHANGE*(mass_a_global + mass_b_global);
|
|
||||||
if (fabs(TOTAL_MASS_CHANGE) > 0.1*mass_a_global )
|
|
||||||
TOTAL_MASS_CHANGE = 0.1*mass_a_global;
|
|
||||||
if (fabs(TOTAL_MASS_CHANGE) > 0.1*mass_b_global )
|
|
||||||
TOTAL_MASS_CHANGE = 0.1*mass_b_global;
|
|
||||||
|
|
||||||
double LOCAL_MASS_CHANGE = 0.0;
|
double MASS_FRACTION_CHANGE = 0.0005;
|
||||||
for (int k=1; k<Nz-1; k++){
|
if (M.db->keyExists( "FlowAdaptor" )){
|
||||||
for (int j=1; j<Ny-1; j++){
|
auto flow_db = M.db->getDatabase( "FlowAdaptor" );
|
||||||
for (int i=1; i<Nx-1; i++){
|
MASS_FRACTION_CHANGE = flow_db->getWithDefault<double>( "mass_fraction_factor", 0.0005);
|
||||||
int n=M.Map(i,j,k);
|
}
|
||||||
if (!(n<0)){
|
int Np = M.Np;
|
||||||
phi = Phase[n];
|
double dA, dB, phi;
|
||||||
vx = Vel_x[n];
|
double vx,vy,vz;
|
||||||
vy = Vel_y[n];
|
double vax,vay,vaz;
|
||||||
vz = Vel_z[n];
|
double vbx,vby,vbz;
|
||||||
double local_momentum = sqrt(vx*vx+vy*vy+vz*vz);
|
double vax_global,vay_global,vaz_global;
|
||||||
/* impose ceiling for spurious currents */
|
double vbx_global,vby_global,vbz_global;
|
||||||
if (local_momentum > maxSpeed) local_momentum = maxSpeed;
|
|
||||||
if (phi > 0.0){
|
double mass_a, mass_b, mass_a_global, mass_b_global;
|
||||||
LOCAL_MASS_CHANGE = TOTAL_MASS_CHANGE*local_momentum/total_momentum_A;
|
|
||||||
Aq_tmp[n] -= 0.3333333333333333*LOCAL_MASS_CHANGE;
|
double *Aq_tmp, *Bq_tmp;
|
||||||
Aq_tmp[n+Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
double *Vel_x, *Vel_y, *Vel_z, *Phase;
|
||||||
Aq_tmp[n+2*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
|
||||||
Aq_tmp[n+3*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
Aq_tmp = new double [7*Np];
|
||||||
Aq_tmp[n+4*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
Bq_tmp = new double [7*Np];
|
||||||
Aq_tmp[n+5*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
Phase = new double [Np];
|
||||||
Aq_tmp[n+6*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
Vel_x = new double [Np];
|
||||||
//DebugMassA[n] = (-1.0)*LOCAL_MASS_CHANGE;
|
Vel_y = new double [Np];
|
||||||
}
|
Vel_z = new double [Np];
|
||||||
else{
|
|
||||||
LOCAL_MASS_CHANGE = TOTAL_MASS_CHANGE*local_momentum/total_momentum_B;
|
ScaLBL_CopyToHost(Aq_tmp, M.Aq, 7*Np*sizeof(double));
|
||||||
Bq_tmp[n] += 0.3333333333333333*LOCAL_MASS_CHANGE;
|
ScaLBL_CopyToHost(Bq_tmp, M.Bq, 7*Np*sizeof(double));
|
||||||
Bq_tmp[n+Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
ScaLBL_CopyToHost(Vel_x, &M.Velocity[0], Np*sizeof(double));
|
||||||
Bq_tmp[n+2*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
ScaLBL_CopyToHost(Vel_y, &M.Velocity[Np], Np*sizeof(double));
|
||||||
Bq_tmp[n+3*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
ScaLBL_CopyToHost(Vel_z, &M.Velocity[2*Np], Np*sizeof(double));
|
||||||
Bq_tmp[n+4*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
|
||||||
Bq_tmp[n+5*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
/* DEBUG STRUCTURES */
|
||||||
Bq_tmp[n+6*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
int Nx = M.Nx; int Ny = M.Ny; int Nz = M.Nz;
|
||||||
//DebugMassB[n] = LOCAL_MASS_CHANGE;
|
//int N = Nx*Ny*Nz;
|
||||||
}
|
//double * DebugMassA, *DebugMassB;
|
||||||
}
|
//DebugMassA = new double[Np];
|
||||||
}
|
//DebugMassB = new double[Np];
|
||||||
}
|
|
||||||
}
|
/* compute the total momentum */
|
||||||
/* for (int n=0; n < M.ScaLBL_Comm->LastExterior(); n++){
|
vax = vay = vaz = 0.0;
|
||||||
|
vbx = vby = vbz = 0.0;
|
||||||
|
mass_a = mass_b = 0.0;
|
||||||
|
double maxSpeed = 0.0;
|
||||||
|
double localMaxSpeed = 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=M.Map(i,j,k);
|
||||||
|
double distance = M.Averages->SDs(i,j,k);
|
||||||
|
if (!(n<0) ){
|
||||||
|
dA = Aq_tmp[n] + Aq_tmp[n+Np] + Aq_tmp[n+2*Np] + Aq_tmp[n+3*Np] + Aq_tmp[n+4*Np] + Aq_tmp[n+5*Np] + Aq_tmp[n+6*Np];
|
||||||
|
dB = Bq_tmp[n] + Bq_tmp[n+Np] + Bq_tmp[n+2*Np] + Bq_tmp[n+3*Np] + Bq_tmp[n+4*Np] + Bq_tmp[n+5*Np] + Bq_tmp[n+6*Np];
|
||||||
|
phi = (dA - dB) / (dA + dB);
|
||||||
|
Phase[n] = phi;
|
||||||
|
mass_a += dA;
|
||||||
|
mass_b += dB;
|
||||||
|
if (phi > 0.0){
|
||||||
|
vax += Vel_x[n];
|
||||||
|
vay += Vel_y[n];
|
||||||
|
vaz += Vel_z[n];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vbx += Vel_x[n];
|
||||||
|
vby += Vel_y[n];
|
||||||
|
vbz += Vel_z[n];
|
||||||
|
}
|
||||||
|
double speed = sqrt(vax*vax + vay*vay + vaz*vaz + vbx*vbx + vby*vby + vbz*vbz);
|
||||||
|
if (distance > 3.0 && speed > localMaxSpeed){
|
||||||
|
localMaxSpeed = speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
maxSpeed = M.Dm->Comm.maxReduce(localMaxSpeed);
|
||||||
|
mass_a_global = M.Dm->Comm.sumReduce(mass_a);
|
||||||
|
mass_b_global = M.Dm->Comm.sumReduce(mass_b);
|
||||||
|
vax_global = M.Dm->Comm.sumReduce(vax);
|
||||||
|
vay_global = M.Dm->Comm.sumReduce(vay);
|
||||||
|
vaz_global = M.Dm->Comm.sumReduce(vaz);
|
||||||
|
vbx_global = M.Dm->Comm.sumReduce(vbx);
|
||||||
|
vby_global = M.Dm->Comm.sumReduce(vby);
|
||||||
|
vbz_global = M.Dm->Comm.sumReduce(vbz);
|
||||||
|
|
||||||
|
double total_momentum_A = sqrt(vax_global*vax_global+vay_global*vay_global+vaz_global*vaz_global);
|
||||||
|
double total_momentum_B = sqrt(vbx_global*vbx_global+vby_global*vby_global+vbz_global*vbz_global);
|
||||||
|
/* compute the total mass change */
|
||||||
|
double TOTAL_MASS_CHANGE = MASS_FRACTION_CHANGE*(mass_a_global + mass_b_global);
|
||||||
|
if (fabs(TOTAL_MASS_CHANGE) > 0.1*mass_a_global )
|
||||||
|
TOTAL_MASS_CHANGE = 0.1*mass_a_global;
|
||||||
|
if (fabs(TOTAL_MASS_CHANGE) > 0.1*mass_b_global )
|
||||||
|
TOTAL_MASS_CHANGE = 0.1*mass_b_global;
|
||||||
|
|
||||||
|
double LOCAL_MASS_CHANGE = 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=M.Map(i,j,k);
|
||||||
|
if (!(n<0)){
|
||||||
|
phi = Phase[n];
|
||||||
|
vx = Vel_x[n];
|
||||||
|
vy = Vel_y[n];
|
||||||
|
vz = Vel_z[n];
|
||||||
|
double local_momentum = sqrt(vx*vx+vy*vy+vz*vz);
|
||||||
|
/* impose ceiling for spurious currents */
|
||||||
|
if (local_momentum > maxSpeed) local_momentum = maxSpeed;
|
||||||
|
if (phi > 0.0){
|
||||||
|
LOCAL_MASS_CHANGE = TOTAL_MASS_CHANGE*local_momentum/total_momentum_A;
|
||||||
|
Aq_tmp[n] -= 0.3333333333333333*LOCAL_MASS_CHANGE;
|
||||||
|
Aq_tmp[n+Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Aq_tmp[n+2*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Aq_tmp[n+3*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Aq_tmp[n+4*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Aq_tmp[n+5*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Aq_tmp[n+6*Np] -= 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
//DebugMassA[n] = (-1.0)*LOCAL_MASS_CHANGE;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
LOCAL_MASS_CHANGE = TOTAL_MASS_CHANGE*local_momentum/total_momentum_B;
|
||||||
|
Bq_tmp[n] += 0.3333333333333333*LOCAL_MASS_CHANGE;
|
||||||
|
Bq_tmp[n+Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Bq_tmp[n+2*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Bq_tmp[n+3*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Bq_tmp[n+4*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Bq_tmp[n+5*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
Bq_tmp[n+6*Np] += 0.1111111111111111*LOCAL_MASS_CHANGE;
|
||||||
|
//DebugMassB[n] = LOCAL_MASS_CHANGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* for (int n=0; n < M.ScaLBL_Comm->LastExterior(); n++){
|
||||||
phi = Phase[n];
|
phi = Phase[n];
|
||||||
vx = Vel_x[n];
|
vx = Vel_x[n];
|
||||||
vy = Vel_y[n];
|
vy = Vel_y[n];
|
||||||
@ -2221,10 +2230,10 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
|||||||
DebugMassB[n] = LOCAL_MASS_CHANGE;
|
DebugMassB[n] = LOCAL_MASS_CHANGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (M.rank == 0) printf("Update Fractional Flow: change mass of fluid B by %f \n",TOTAL_MASS_CHANGE/mass_b_global);
|
if (M.rank == 0) printf("Update Fractional Flow: change mass of fluid B by %f \n",TOTAL_MASS_CHANGE/mass_b_global);
|
||||||
|
|
||||||
/* Print out debugging info with mass update
|
/* Print out debugging info with mass update
|
||||||
// initialize the array
|
// initialize the array
|
||||||
double value;
|
double value;
|
||||||
char LocalRankFilename[40];
|
char LocalRankFilename[40];
|
||||||
@ -2241,13 +2250,13 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *AFILE;
|
FILE *AFILE;
|
||||||
sprintf(LocalRankFilename,"dA.%05i.raw",M.rank);
|
sprintf(LocalRankFilename,"dA.%05i.raw",M.rank);
|
||||||
AFILE = fopen(LocalRankFilename,"wb");
|
AFILE = fopen(LocalRankFilename,"wb");
|
||||||
fwrite(regdata.data(),8,N,AFILE);
|
fwrite(regdata.data(),8,N,AFILE);
|
||||||
fclose(AFILE);
|
fclose(AFILE);
|
||||||
|
|
||||||
regdata.fill(0.f);
|
regdata.fill(0.f);
|
||||||
for (int k=0; k<Nz; k++){
|
for (int k=0; k<Nz; k++){
|
||||||
for (int j=0; j<Ny; j++){
|
for (int j=0; j<Ny; j++){
|
||||||
@ -2265,14 +2274,14 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
|||||||
BFILE = fopen(LocalRankFilename,"wb");
|
BFILE = fopen(LocalRankFilename,"wb");
|
||||||
fwrite(regdata.data(),8,N,BFILE);
|
fwrite(regdata.data(),8,N,BFILE);
|
||||||
fclose(BFILE);
|
fclose(BFILE);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Need to initialize Aq, Bq, Den, Phi directly
|
// Need to initialize Aq, Bq, Den, Phi directly
|
||||||
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
|
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
|
||||||
ScaLBL_CopyToDevice(M.Aq, Aq_tmp, 7*Np*sizeof(double));
|
ScaLBL_CopyToDevice(M.Aq, Aq_tmp, 7*Np*sizeof(double));
|
||||||
ScaLBL_CopyToDevice(M.Bq, Bq_tmp, 7*Np*sizeof(double));
|
ScaLBL_CopyToDevice(M.Bq, Bq_tmp, 7*Np*sizeof(double));
|
||||||
|
|
||||||
return(TOTAL_MASS_CHANGE);
|
return(TOTAL_MASS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlowAdaptor::Flatten(ScaLBL_ColorModel &M){
|
void FlowAdaptor::Flatten(ScaLBL_ColorModel &M){
|
||||||
|
@ -72,6 +72,8 @@ public:
|
|||||||
double *ColorGrad;
|
double *ColorGrad;
|
||||||
double *Velocity;
|
double *Velocity;
|
||||||
double *Pressure;
|
double *Pressure;
|
||||||
|
|
||||||
|
void AssignComponentLabels(double *phase);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utilities::MPI comm;
|
Utilities::MPI comm;
|
||||||
@ -85,7 +87,6 @@ private:
|
|||||||
|
|
||||||
//int rank,nprocs;
|
//int rank,nprocs;
|
||||||
void LoadParams(std::shared_ptr<Database> db0);
|
void LoadParams(std::shared_ptr<Database> db0);
|
||||||
void AssignComponentLabels(double *phase);
|
|
||||||
double ImageInit(std::string filename);
|
double ImageInit(std::string filename);
|
||||||
double MorphInit(const double beta, const double morph_delta);
|
double MorphInit(const double beta, const double morph_delta);
|
||||||
double SeedPhaseField(const double seed_water_in_oil);
|
double SeedPhaseField(const double seed_water_in_oil);
|
||||||
@ -97,6 +98,7 @@ public:
|
|||||||
FlowAdaptor(ScaLBL_ColorModel &M);
|
FlowAdaptor(ScaLBL_ColorModel &M);
|
||||||
~FlowAdaptor();
|
~FlowAdaptor();
|
||||||
double MoveInterface(ScaLBL_ColorModel &M);
|
double MoveInterface(ScaLBL_ColorModel &M);
|
||||||
|
double ImageInit(ScaLBL_ColorModel &M, std::string Filename);
|
||||||
double UpdateFractionalFlow(ScaLBL_ColorModel &M);
|
double UpdateFractionalFlow(ScaLBL_ColorModel &M);
|
||||||
void Flatten(ScaLBL_ColorModel &M);
|
void Flatten(ScaLBL_ColorModel &M);
|
||||||
DoubleArray phi;
|
DoubleArray phi;
|
||||||
|
@ -22,114 +22,138 @@
|
|||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
Utilities::startup( argc, argv );
|
Utilities::startup( argc, argv );
|
||||||
|
|
||||||
{ // Limit scope so variables that contain communicators will free before MPI_Finialize
|
{ // Limit scope so variables that contain communicators will free before MPI_Finialize
|
||||||
|
|
||||||
Utilities::MPI comm( MPI_COMM_WORLD );
|
Utilities::MPI comm( MPI_COMM_WORLD );
|
||||||
int rank = comm.getRank();
|
int rank = comm.getRank();
|
||||||
int nprocs = comm.getSize();
|
int nprocs = comm.getSize();
|
||||||
std::string SimulationMode = "production";
|
std::string SimulationMode = "production";
|
||||||
// Load the input database
|
// Load the input database
|
||||||
auto db = std::make_shared<Database>( argv[1] );
|
auto db = std::make_shared<Database>( argv[1] );
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
SimulationMode = "development";
|
SimulationMode = "development";
|
||||||
}
|
|
||||||
|
|
||||||
if ( rank == 0 ) {
|
|
||||||
printf( "********************************************************\n" );
|
|
||||||
printf( "Running Color LBM \n" );
|
|
||||||
printf( "********************************************************\n" );
|
|
||||||
if (SimulationMode == "development")
|
|
||||||
printf("**** DEVELOPMENT MODE ENABLED *************\n");
|
|
||||||
}
|
|
||||||
// Initialize compute device
|
|
||||||
int device = ScaLBL_SetDevice( rank );
|
|
||||||
NULL_USE( device );
|
|
||||||
ScaLBL_DeviceBarrier();
|
|
||||||
comm.barrier();
|
|
||||||
|
|
||||||
PROFILE_ENABLE( 1 );
|
|
||||||
// PROFILE_ENABLE_TRACE();
|
|
||||||
// PROFILE_ENABLE_MEMORY();
|
|
||||||
PROFILE_SYNCHRONIZE();
|
|
||||||
PROFILE_START( "Main" );
|
|
||||||
Utilities::setErrorHandlers();
|
|
||||||
|
|
||||||
auto filename = argv[1];
|
|
||||||
ScaLBL_ColorModel ColorModel( rank, nprocs, comm );
|
|
||||||
ColorModel.ReadParams( filename );
|
|
||||||
ColorModel.SetDomain();
|
|
||||||
ColorModel.ReadInput();
|
|
||||||
ColorModel.Create(); // creating the model will create data structure to match the pore
|
|
||||||
// structure and allocate variables
|
|
||||||
ColorModel.Initialize(); // initializing the model will set initial conditions for variables
|
|
||||||
|
|
||||||
if (SimulationMode == "development"){
|
|
||||||
double MLUPS=0.0;
|
|
||||||
int timestep = 0;
|
|
||||||
bool ContinueSimulation = true;
|
|
||||||
int ANALYSIS_INTERVAL = ColorModel.timestepMax;
|
|
||||||
/* flow adaptor keys to control */
|
|
||||||
int SKIP_TIMESTEPS = 0;
|
|
||||||
int MAX_STEADY_TIME = 1000000;
|
|
||||||
double ENDPOINT_THRESHOLD = 0.1;
|
|
||||||
double FRACTIONAL_FLOW_INCREMENT = 0.05;
|
|
||||||
if (ColorModel.db->keyExists( "FlowAdaptor" )){
|
|
||||||
auto flow_db = ColorModel.db->getDatabase( "FlowAdaptor" );
|
|
||||||
MAX_STEADY_TIME = flow_db->getWithDefault<int>( "max_steady_timesteps", 1000000 );
|
|
||||||
SKIP_TIMESTEPS = flow_db->getWithDefault<int>( "skip_timesteps", 100000 );
|
|
||||||
FRACTIONAL_FLOW_INCREMENT = flow_db->getWithDefault<double>( "fractional_flow_increment", 0.05);
|
|
||||||
ENDPOINT_THRESHOLD = flow_db->getWithDefault<double>( "endpoint_threshold", 0.1);
|
|
||||||
}
|
|
||||||
if (ColorModel.analysis_db->keyExists( "analysis_interval" )){
|
|
||||||
ANALYSIS_INTERVAL = ColorModel.analysis_db->getScalar<int>( "analysis_interval" );
|
|
||||||
}
|
|
||||||
/* Launch the simulation */
|
|
||||||
FlowAdaptor Adapt(ColorModel);
|
|
||||||
runAnalysis analysis(ColorModel);
|
|
||||||
while (ContinueSimulation){
|
|
||||||
/* this will run steady points */
|
|
||||||
timestep += MAX_STEADY_TIME;
|
|
||||||
MLUPS = ColorModel.Run(timestep);
|
|
||||||
if (rank==0) printf("Lattice update rate (per MPI process)= %f MLUPS \n", MLUPS);
|
|
||||||
if (ColorModel.timestep > ColorModel.timestepMax){
|
|
||||||
ContinueSimulation = false;
|
|
||||||
}
|
|
||||||
/* update the fractional flow by adding mass */
|
|
||||||
int skip_time = 0;
|
|
||||||
timestep = ColorModel.timestep;
|
|
||||||
double SaturationChange = 0.0;
|
|
||||||
double volB = ColorModel.Averages->gwb.V;
|
|
||||||
double volA = ColorModel.Averages->gnb.V;
|
|
||||||
double initialSaturation = volB/(volA + volB);
|
|
||||||
|
|
||||||
double vA_x = ColorModel.Averages->gnb.Px/ColorModel.Averages->gnb.M;
|
|
||||||
double vA_y = ColorModel.Averages->gnb.Py/ColorModel.Averages->gnb.M;
|
|
||||||
double vA_z = ColorModel.Averages->gnb.Pz/ColorModel.Averages->gnb.M;
|
|
||||||
double vB_x = ColorModel.Averages->gwb.Px/ColorModel.Averages->gwb.M;
|
|
||||||
double vB_y = ColorModel.Averages->gwb.Py/ColorModel.Averages->gwb.M;
|
|
||||||
double vB_z = ColorModel.Averages->gwb.Pz/ColorModel.Averages->gwb.M;
|
|
||||||
double speedA = sqrt(vA_x*vA_x + vA_y*vA_y + vA_z*vA_z);
|
|
||||||
double speedB = sqrt(vB_x*vB_x + vB_y*vB_y + vB_z*vB_z);
|
|
||||||
if (volA*speedA < ENDPOINT_THRESHOLD*volB*speedB) ContinueSimulation = false;
|
|
||||||
if (ContinueSimulation){
|
|
||||||
while (skip_time < SKIP_TIMESTEPS && fabs(SaturationChange) < fabs(FRACTIONAL_FLOW_INCREMENT) ){
|
|
||||||
timestep += ANALYSIS_INTERVAL;
|
|
||||||
Adapt.UpdateFractionalFlow(ColorModel);
|
|
||||||
MLUPS = ColorModel.Run(timestep);
|
|
||||||
double volB = ColorModel.Averages->gwb.V;
|
|
||||||
double volA = ColorModel.Averages->gnb.V;
|
|
||||||
SaturationChange = volB/(volA + volB) - initialSaturation;
|
|
||||||
skip_time += ANALYSIS_INTERVAL;
|
|
||||||
}
|
}
|
||||||
if (rank==0) printf(" ********************************************************************* \n");
|
|
||||||
if (rank==0) printf(" Updated fractional flow with saturation change = %f \n", SaturationChange);
|
if ( rank == 0 ) {
|
||||||
if (rank==0) printf(" ********************************************************************* \n");
|
printf( "********************************************************\n" );
|
||||||
|
printf( "Running Color LBM \n" );
|
||||||
|
printf( "********************************************************\n" );
|
||||||
|
if (SimulationMode == "development")
|
||||||
|
printf("**** DEVELOPMENT MODE ENABLED *************\n");
|
||||||
}
|
}
|
||||||
/* apply timestep skipping algorithm to accelerate steady-state */
|
// Initialize compute device
|
||||||
/* skip_time = 0;
|
int device = ScaLBL_SetDevice( rank );
|
||||||
|
NULL_USE( device );
|
||||||
|
ScaLBL_DeviceBarrier();
|
||||||
|
comm.barrier();
|
||||||
|
|
||||||
|
PROFILE_ENABLE( 1 );
|
||||||
|
// PROFILE_ENABLE_TRACE();
|
||||||
|
// PROFILE_ENABLE_MEMORY();
|
||||||
|
PROFILE_SYNCHRONIZE();
|
||||||
|
PROFILE_START( "Main" );
|
||||||
|
Utilities::setErrorHandlers();
|
||||||
|
|
||||||
|
auto filename = argv[1];
|
||||||
|
ScaLBL_ColorModel ColorModel( rank, nprocs, comm );
|
||||||
|
ColorModel.ReadParams( filename );
|
||||||
|
ColorModel.SetDomain();
|
||||||
|
ColorModel.ReadInput();
|
||||||
|
ColorModel.Create(); // creating the model will create data structure to match the pore
|
||||||
|
// structure and allocate variables
|
||||||
|
ColorModel.Initialize(); // initializing the model will set initial conditions for variables
|
||||||
|
|
||||||
|
|
||||||
|
if (SimulationMode == "development"){
|
||||||
|
double MLUPS=0.0;
|
||||||
|
int timestep = 0;
|
||||||
|
bool ContinueSimulation = true;
|
||||||
|
|
||||||
|
/* Variables for simulation protocols */
|
||||||
|
auto PROTOCOL = ColorModel.color_db->getWithDefault<std::string>( "protocol", "none" );
|
||||||
|
/* image sequence protocol */
|
||||||
|
int IMAGE_INDEX = 0;
|
||||||
|
int IMAGE_COUNT = 0;
|
||||||
|
std::vector<std::string> ImageList;
|
||||||
|
/* flow adaptor keys to control behavior */
|
||||||
|
int SKIP_TIMESTEPS = 0;
|
||||||
|
int MAX_STEADY_TIME = 1000000;
|
||||||
|
double ENDPOINT_THRESHOLD = 0.1;
|
||||||
|
double FRACTIONAL_FLOW_INCREMENT = 0.05;
|
||||||
|
if (ColorModel.db->keyExists( "FlowAdaptor" )){
|
||||||
|
auto flow_db = ColorModel.db->getDatabase( "FlowAdaptor" );
|
||||||
|
MAX_STEADY_TIME = flow_db->getWithDefault<int>( "max_steady_timesteps", 1000000 );
|
||||||
|
SKIP_TIMESTEPS = flow_db->getWithDefault<int>( "skip_timesteps", 100000 );
|
||||||
|
FRACTIONAL_FLOW_INCREMENT = flow_db->getWithDefault<double>( "fractional_flow_increment", 0.05);
|
||||||
|
ENDPOINT_THRESHOLD = flow_db->getWithDefault<double>( "endpoint_threshold", 0.1);
|
||||||
|
}
|
||||||
|
/* analysis keys*/
|
||||||
|
int ANALYSIS_INTERVAL = ColorModel.timestepMax;
|
||||||
|
if (ColorModel.analysis_db->keyExists( "analysis_interval" )){
|
||||||
|
ANALYSIS_INTERVAL = ColorModel.analysis_db->getScalar<int>( "analysis_interval" );
|
||||||
|
}
|
||||||
|
/* Launch the simulation */
|
||||||
|
FlowAdaptor Adapt(ColorModel);
|
||||||
|
runAnalysis analysis(ColorModel);
|
||||||
|
while (ContinueSimulation){
|
||||||
|
/* this will run steady points */
|
||||||
|
timestep += MAX_STEADY_TIME;
|
||||||
|
MLUPS = ColorModel.Run(timestep);
|
||||||
|
if (rank==0) printf("Lattice update rate (per MPI process)= %f MLUPS \n", MLUPS);
|
||||||
|
if (ColorModel.timestep > ColorModel.timestepMax){
|
||||||
|
ContinueSimulation = false;
|
||||||
|
}
|
||||||
|
/* update the fluid configuration with the flow adapter */
|
||||||
|
int skip_time = 0;
|
||||||
|
timestep = ColorModel.timestep;
|
||||||
|
double SaturationChange = 0.0;
|
||||||
|
double volB = ColorModel.Averages->gwb.V;
|
||||||
|
double volA = ColorModel.Averages->gnb.V;
|
||||||
|
double initialSaturation = volB/(volA + volB);
|
||||||
|
double vA_x = ColorModel.Averages->gnb.Px/ColorModel.Averages->gnb.M;
|
||||||
|
double vA_y = ColorModel.Averages->gnb.Py/ColorModel.Averages->gnb.M;
|
||||||
|
double vA_z = ColorModel.Averages->gnb.Pz/ColorModel.Averages->gnb.M;
|
||||||
|
double vB_x = ColorModel.Averages->gwb.Px/ColorModel.Averages->gwb.M;
|
||||||
|
double vB_y = ColorModel.Averages->gwb.Py/ColorModel.Averages->gwb.M;
|
||||||
|
double vB_z = ColorModel.Averages->gwb.Pz/ColorModel.Averages->gwb.M;
|
||||||
|
double speedA = sqrt(vA_x*vA_x + vA_y*vA_y + vA_z*vA_z);
|
||||||
|
double speedB = sqrt(vB_x*vB_x + vB_y*vB_y + vB_z*vB_z);
|
||||||
|
if (volA*speedA < ENDPOINT_THRESHOLD*volB*speedB) ContinueSimulation = false;
|
||||||
|
if (ContinueSimulation){
|
||||||
|
while (skip_time < SKIP_TIMESTEPS && fabs(SaturationChange) < fabs(FRACTIONAL_FLOW_INCREMENT) ){
|
||||||
|
timestep += ANALYSIS_INTERVAL;
|
||||||
|
if (PROTOCOL == "fractional flow") {
|
||||||
|
Adapt.UpdateFractionalFlow(ColorModel);
|
||||||
|
}
|
||||||
|
else if (PROTOCOL == "image sequence"){
|
||||||
|
// Use image sequence
|
||||||
|
IMAGE_INDEX++;
|
||||||
|
if (IMAGE_INDEX < IMAGE_COUNT){
|
||||||
|
std::string next_image = ImageList[IMAGE_INDEX];
|
||||||
|
if (rank==0) printf("***Loading next image in sequence (%i) ***\n",IMAGE_INDEX);
|
||||||
|
ColorModel.color_db->putScalar<int>("image_index",IMAGE_INDEX);
|
||||||
|
Adapt.ImageInit(ColorModel, next_image);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (rank==0) printf("Finished simulating image sequence \n");
|
||||||
|
ColorModel.timestep = ColorModel.timestepMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MLUPS = ColorModel.Run(timestep);
|
||||||
|
double volB = ColorModel.Averages->gwb.V;
|
||||||
|
double volA = ColorModel.Averages->gnb.V;
|
||||||
|
SaturationChange = volB/(volA + volB) - initialSaturation;
|
||||||
|
skip_time += ANALYSIS_INTERVAL;
|
||||||
|
}
|
||||||
|
if (rank==0) printf(" ********************************************************************* \n");
|
||||||
|
if (rank==0) printf(" Updated fractional flow with saturation change = %f \n", SaturationChange);
|
||||||
|
if (rank==0) printf(" ********************************************************************* \n");
|
||||||
|
}
|
||||||
|
/* apply timestep skipping algorithm to accelerate steady-state */
|
||||||
|
/* skip_time = 0;
|
||||||
timestep = ColorModel.timestep;
|
timestep = ColorModel.timestep;
|
||||||
while (skip_time < SKIP_TIMESTEPS){
|
while (skip_time < SKIP_TIMESTEPS){
|
||||||
timestep += ANALYSIS_INTERVAL;
|
timestep += ANALYSIS_INTERVAL;
|
||||||
@ -137,24 +161,24 @@ int main( int argc, char **argv )
|
|||||||
Adapt.MoveInterface(ColorModel);
|
Adapt.MoveInterface(ColorModel);
|
||||||
skip_time += ANALYSIS_INTERVAL;
|
skip_time += ANALYSIS_INTERVAL;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
//ColorModel.WriteDebug();
|
//ColorModel.WriteDebug();
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
ColorModel.Run();
|
ColorModel.Run();
|
||||||
|
|
||||||
PROFILE_STOP( "Main" );
|
PROFILE_STOP( "Main" );
|
||||||
auto file = db->getWithDefault<std::string>( "TimerFile", "lbpm_color_simulator" );
|
auto file = db->getWithDefault<std::string>( "TimerFile", "lbpm_color_simulator" );
|
||||||
auto level = db->getWithDefault<int>( "TimerLevel", 1 );
|
auto level = db->getWithDefault<int>( "TimerLevel", 1 );
|
||||||
NULL_USE(level);
|
NULL_USE(level);
|
||||||
PROFILE_SAVE( file, level );
|
PROFILE_SAVE( file, level );
|
||||||
// ****************************************************
|
// ****************************************************
|
||||||
|
|
||||||
|
|
||||||
} // Limit scope so variables that contain communicators will free before MPI_Finialize
|
} // Limit scope so variables that contain communicators will free before MPI_Finialize
|
||||||
|
|
||||||
Utilities::shutdown();
|
Utilities::shutdown();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user