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;
|
||||
timestep=-1;
|
||||
timestep_previous=-1;
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 (M.db->keyExists( "FlowAdaptor" )){
|
||||
auto flow_db = M.db->getDatabase( "FlowAdaptor" );
|
||||
MASS_FRACTION_CHANGE = flow_db->getWithDefault<double>( "mass_fraction_factor", 0.0005);
|
||||
}
|
||||
int Np = M.Np;
|
||||
double dA, dB, phi;
|
||||
double vx,vy,vz;
|
||||
double vax,vay,vaz;
|
||||
double vbx,vby,vbz;
|
||||
double vax_global,vay_global,vaz_global;
|
||||
double vbx_global,vby_global,vbz_global;
|
||||
if (rank==0) printf(" new saturation: %f (%f / %f) \n", Count / PoreCount, Count, PoreCount);
|
||||
ScaLBL_CopyToDevice(M.Phi, PhaseLabel, Nx*Ny*Nz*sizeof(double));
|
||||
M.Dm->Comm.barrier();
|
||||
|
||||
ScaLBL_D3Q19_Init(M.fq, M.Np);
|
||||
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, 0, M.ScaLBL_Comm->LastExterior(), M.Np);
|
||||
ScaLBL_PhaseField_Init(M.dvcMap, M.Phi, M.Den, M.Aq, M.Bq, M.ScaLBL_Comm->FirstInterior(), M.ScaLBL_Comm->LastInterior(), M.Np);
|
||||
M.Dm->Comm.barrier();
|
||||
|
||||
ScaLBL_CopyToHost(M.Averages->Phi.data(),M.Phi,Nx*Ny*Nz*sizeof(double));
|
||||
|
||||
double mass_a, mass_b, mass_a_global, mass_b_global;
|
||||
|
||||
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];
|
||||
double saturation = Count/PoreCount;
|
||||
return saturation;
|
||||
}
|
||||
|
||||
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 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 FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
||||
|
||||
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++){
|
||||
double MASS_FRACTION_CHANGE = 0.0005;
|
||||
if (M.db->keyExists( "FlowAdaptor" )){
|
||||
auto flow_db = M.db->getDatabase( "FlowAdaptor" );
|
||||
MASS_FRACTION_CHANGE = flow_db->getWithDefault<double>( "mass_fraction_factor", 0.0005);
|
||||
}
|
||||
int Np = M.Np;
|
||||
double dA, dB, phi;
|
||||
double vx,vy,vz;
|
||||
double vax,vay,vaz;
|
||||
double vbx,vby,vbz;
|
||||
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 *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);
|
||||
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];
|
||||
vx = Vel_x[n];
|
||||
vy = Vel_y[n];
|
||||
@ -2221,10 +2230,10 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
||||
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
|
||||
double value;
|
||||
char LocalRankFilename[40];
|
||||
@ -2241,13 +2250,13 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FILE *AFILE;
|
||||
sprintf(LocalRankFilename,"dA.%05i.raw",M.rank);
|
||||
AFILE = fopen(LocalRankFilename,"wb");
|
||||
fwrite(regdata.data(),8,N,AFILE);
|
||||
fclose(AFILE);
|
||||
|
||||
|
||||
regdata.fill(0.f);
|
||||
for (int k=0; k<Nz; k++){
|
||||
for (int j=0; j<Ny; j++){
|
||||
@ -2265,14 +2274,14 @@ double FlowAdaptor::UpdateFractionalFlow(ScaLBL_ColorModel &M){
|
||||
BFILE = fopen(LocalRankFilename,"wb");
|
||||
fwrite(regdata.data(),8,N,BFILE);
|
||||
fclose(BFILE);
|
||||
*/
|
||||
*/
|
||||
|
||||
// Need to initialize Aq, Bq, Den, Phi directly
|
||||
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
|
||||
ScaLBL_CopyToDevice(M.Aq, Aq_tmp, 7*Np*sizeof(double));
|
||||
ScaLBL_CopyToDevice(M.Bq, Bq_tmp, 7*Np*sizeof(double));
|
||||
// Need to initialize Aq, Bq, Den, Phi directly
|
||||
//ScaLBL_CopyToDevice(Phi,phase.data(),7*Np*sizeof(double));
|
||||
ScaLBL_CopyToDevice(M.Aq, Aq_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){
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
double *ColorGrad;
|
||||
double *Velocity;
|
||||
double *Pressure;
|
||||
|
||||
void AssignComponentLabels(double *phase);
|
||||
|
||||
private:
|
||||
Utilities::MPI comm;
|
||||
@ -85,7 +87,6 @@ private:
|
||||
|
||||
//int rank,nprocs;
|
||||
void LoadParams(std::shared_ptr<Database> db0);
|
||||
void AssignComponentLabels(double *phase);
|
||||
double ImageInit(std::string filename);
|
||||
double MorphInit(const double beta, const double morph_delta);
|
||||
double SeedPhaseField(const double seed_water_in_oil);
|
||||
@ -97,6 +98,7 @@ public:
|
||||
FlowAdaptor(ScaLBL_ColorModel &M);
|
||||
~FlowAdaptor();
|
||||
double MoveInterface(ScaLBL_ColorModel &M);
|
||||
double ImageInit(ScaLBL_ColorModel &M, std::string Filename);
|
||||
double UpdateFractionalFlow(ScaLBL_ColorModel &M);
|
||||
void Flatten(ScaLBL_ColorModel &M);
|
||||
DoubleArray phi;
|
||||
|
@ -22,114 +22,138 @@
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// Initialize
|
||||
Utilities::startup( argc, argv );
|
||||
// Initialize
|
||||
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 );
|
||||
int rank = comm.getRank();
|
||||
int nprocs = comm.getSize();
|
||||
std::string SimulationMode = "production";
|
||||
// Load the input database
|
||||
auto db = std::make_shared<Database>( argv[1] );
|
||||
if (argc > 2) {
|
||||
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;
|
||||
Utilities::MPI comm( MPI_COMM_WORLD );
|
||||
int rank = comm.getRank();
|
||||
int nprocs = comm.getSize();
|
||||
std::string SimulationMode = "production";
|
||||
// Load the input database
|
||||
auto db = std::make_shared<Database>( argv[1] );
|
||||
if (argc > 2) {
|
||||
SimulationMode = "development";
|
||||
}
|
||||
if (rank==0) printf(" ********************************************************************* \n");
|
||||
if (rank==0) printf(" Updated fractional flow with saturation change = %f \n", SaturationChange);
|
||||
if (rank==0) printf(" ********************************************************************* \n");
|
||||
|
||||
if ( rank == 0 ) {
|
||||
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 */
|
||||
/* skip_time = 0;
|
||||
// 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;
|
||||
|
||||
/* 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;
|
||||
while (skip_time < SKIP_TIMESTEPS){
|
||||
timestep += ANALYSIS_INTERVAL;
|
||||
@ -137,24 +161,24 @@ int main( int argc, char **argv )
|
||||
Adapt.MoveInterface(ColorModel);
|
||||
skip_time += ANALYSIS_INTERVAL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
//ColorModel.WriteDebug();
|
||||
}
|
||||
*/
|
||||
}
|
||||
//ColorModel.WriteDebug();
|
||||
}
|
||||
|
||||
else
|
||||
ColorModel.Run();
|
||||
else
|
||||
ColorModel.Run();
|
||||
|
||||
PROFILE_STOP( "Main" );
|
||||
auto file = db->getWithDefault<std::string>( "TimerFile", "lbpm_color_simulator" );
|
||||
auto level = db->getWithDefault<int>( "TimerLevel", 1 );
|
||||
NULL_USE(level);
|
||||
PROFILE_SAVE( file, level );
|
||||
// ****************************************************
|
||||
PROFILE_STOP( "Main" );
|
||||
auto file = db->getWithDefault<std::string>( "TimerFile", "lbpm_color_simulator" );
|
||||
auto level = db->getWithDefault<int>( "TimerLevel", 1 );
|
||||
NULL_USE(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();
|
||||
return 0;
|
||||
Utilities::shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user