enable different types of solid BC for Poisson solver; to be built and tested

This commit is contained in:
Rex Zhe Li
2021-12-02 23:32:57 +11:00
parent e6fa7d4065
commit 7d525e999b
5 changed files with 80 additions and 43 deletions

View File

@@ -1356,6 +1356,14 @@ void ScaLBL_Communicator::SolidNeumannD3Q7(double *fq, double *BoundaryValue){
ScaLBL_Solid_Neumann_D3Q7(fq,BoundaryValue,bb_dist,bb_interactions,n_bb_d3q7); ScaLBL_Solid_Neumann_D3Q7(fq,BoundaryValue,bb_dist,bb_interactions,n_bb_d3q7);
} }
void ScaLBL_Communicator::SolidDirichletAndNeumannD3Q7(double *fq, double *BoundaryValue, int *BoundaryLabel){
// fq is a D3Q7 distribution
// BoundaryValues is a list of values to assign at bounce-back solid sites
// BoundaryLabel: is a list of integer labels indicating the type of BCs
// 1-> Dirichlet BC; 2-> Neumann BC.
ScaLBL_Solid_DirichletAndNeumann_D3Q7(fq,BoundaryValue,BoundaryLabel,bb_dist,bb_interactions,n_bb_d3q7);
}
void ScaLBL_Communicator::SolidSlippingVelocityBCD3Q19(double *fq, double *zeta_potential, double *ElectricField, double *SolidGrad, void ScaLBL_Communicator::SolidSlippingVelocityBCD3Q19(double *fq, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epsilon_LB, double tau, double rho0, double den_scale,double h, double time_conv){ double epsilon_LB, double tau, double rho0, double den_scale,double h, double time_conv){
// fq is a D3Q19 distribution // fq is a D3Q19 distribution

View File

@@ -593,6 +593,8 @@ extern "C" void ScaLBL_Solid_Dirichlet_D3Q7(double *dist,double *BoundaryValue,i
extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist,double *BoundaryValue,int *BounceBackDist_list,int *BounceBackSolid_list,int N); extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist,double *BoundaryValue,int *BounceBackDist_list,int *BounceBackSolid_list,int N);
extern "C" void ScaLBL_Solid_DirichletAndNeumann_D3Q7(double *dist,double *BoundaryValue,int *BoundaryLabel,int *BounceBackDist_list,int *BounceBackSolid_list,int N);
extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta_potential, double *ElectricField, double *SolidGrad, extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epsilon_LB, double tau, double rho0,double den_scale, double h, double time_conv, double epsilon_LB, double tau, double rho0,double den_scale, double h, double time_conv,
int *BounceBackDist_list, int *BounceBackSolid_list, int *FluidBoundary_list, int *BounceBackDist_list, int *BounceBackSolid_list, int *FluidBoundary_list,
@@ -700,6 +702,7 @@ public:
void SetupBounceBackList(IntArray &Map, signed char *id, int Np, bool SlippingVelBC=false); void SetupBounceBackList(IntArray &Map, signed char *id, int Np, bool SlippingVelBC=false);
void SolidDirichletD3Q7(double *fq, double *BoundaryValue); void SolidDirichletD3Q7(double *fq, double *BoundaryValue);
void SolidNeumannD3Q7(double *fq, double *BoundaryValue); void SolidNeumannD3Q7(double *fq, double *BoundaryValue);
void SolidDirichletAndNeumannD3Q7(double *fq, double *BoundaryValue, int *BoundaryLabel);
void SolidSlippingVelocityBCD3Q19(double *fq, double *zeta_potential, double *ElectricField, double *SolidGrad, void SolidSlippingVelocityBCD3Q19(double *fq, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epslion_LB, double tau, double rho0, double den_scale,double h, double time_conv); double epslion_LB, double tau, double rho0, double den_scale,double h, double time_conv);

View File

@@ -30,6 +30,26 @@ extern "C" void ScaLBL_Solid_Neumann_D3Q7(double *dist,double *BoundaryValue,int
} }
} }
extern "C" void ScaLBL_Solid_DirichletAndNeumann_D3Q7(double *dist,double *BoundaryValue,int* BoundaryLabel,int *BounceBackDist_list,int *BounceBackSolid_list,int N){
int idx;
int iq,ib;
double value_b,value_b_label,value_q;
for (idx=0; idx<N; idx++){
iq = BounceBackDist_list[idx];
ib = BounceBackSolid_list[idx];
value_b = BoundaryValue[ib];//get boundary value from a solid site
value_b_label = BoundaryLabel[ib];//get boundary label (i.e. type of BC) from a solid site
value_q = dist[iq];
if (value_b_label==1){//Dirichlet BC
dist[iq] = -1.0*value_q + value_b*0.25;//NOTE 0.25 is the speed of sound for D3Q7 lattice
}
if (value_b_label==2){//Neumann BC
dist[iq] = value_q + value_b;
}
}
}
extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta_potential, double *ElectricField, double *SolidGrad, extern "C" void ScaLBL_Solid_SlippingVelocityBC_D3Q19(double *dist, double *zeta_potential, double *ElectricField, double *SolidGrad,
double epsilon_LB, double tau, double rho0,double den_scale, double h, double time_conv, double epsilon_LB, double tau, double rho0,double den_scale, double h, double time_conv,
int *BounceBackDist_list, int *BounceBackSolid_list, int *FluidBoundary_list, int *BounceBackDist_list, int *BounceBackSolid_list, int *FluidBoundary_list,

View File

@@ -17,7 +17,7 @@ ScaLBL_Poisson::ScaLBL_Poisson(int RANK, int NP, const Utilities::MPI& COMM):
rank(RANK), TIMELOG(nullptr), nprocs(NP),timestep(0),timestepMax(0),tau(0),k2_inv(0),tolerance(0),h(0), rank(RANK), TIMELOG(nullptr), nprocs(NP),timestep(0),timestepMax(0),tau(0),k2_inv(0),tolerance(0),h(0),
epsilon0(0),epsilon0_LB(0),epsilonR(0),epsilon_LB(0),Vin(0),Vout(0),Nx(0),Ny(0),Nz(0),N(0),Np(0),analysis_interval(0), epsilon0(0),epsilon0_LB(0),epsilonR(0),epsilon_LB(0),Vin(0),Vout(0),Nx(0),Ny(0),Nz(0),N(0),Np(0),analysis_interval(0),
chargeDen_dummy(0),WriteLog(0),nprocx(0),nprocy(0),nprocz(0), chargeDen_dummy(0),WriteLog(0),nprocx(0),nprocy(0),nprocz(0),
BoundaryConditionInlet(0),BoundaryConditionOutlet(0),BoundaryConditionSolid(0),Lx(0),Ly(0),Lz(0), BoundaryConditionInlet(0),BoundaryConditionOutlet(0),BoundaryConditionSolidList(0),Lx(0),Ly(0),Lz(0),
Vin0(0),freqIn(0),t0_In(0),Vin_Type(0),Vout0(0),freqOut(0),t0_Out(0),Vout_Type(0), Vin0(0),freqIn(0),t0_In(0),Vin_Type(0),Vout0(0),freqOut(0),t0_Out(0),Vout_Type(0),
TestPeriodic(0),TestPeriodicTime(0),TestPeriodicTimeConv(0),TestPeriodicSaveInterval(0), TestPeriodic(0),TestPeriodicTime(0),TestPeriodicTimeConv(0),TestPeriodicSaveInterval(0),
comm(COMM) comm(COMM)
@@ -94,9 +94,12 @@ void ScaLBL_Poisson::ReadParams(string filename){
} }
// Read solid boundary condition specific to Poisson equation // Read solid boundary condition specific to Poisson equation
BoundaryConditionSolid = 1; // BC_solid=1: Dirichlet-type surfacen potential
if (electric_db->keyExists( "BC_Solid" )){ // BC_solid=2: Neumann-type surfacen charge density
BoundaryConditionSolid = electric_db->getScalar<int>( "BC_Solid" ); BoundaryConditionSolidList.push_back(1);
if (electric_db->keyExists( "BC_SolidList" )){
BoundaryConditionSolidList.clear();
BoundaryConditionSolidList = electric_db->getVector<int>( "BC_SolidList" );
} }
// Read boundary condition for electric potential // Read boundary condition for electric potential
// BC = 0: normal periodic BC // BC = 0: normal periodic BC
@@ -133,19 +136,8 @@ void ScaLBL_Poisson::ReadParams(string filename){
else{ else{
if (rank==0) printf("LB-Poisson Solver: tolerance_method=%s cannot be identified!\n",tolerance_method.c_str()); if (rank==0) printf("LB-Poisson Solver: tolerance_method=%s cannot be identified!\n",tolerance_method.c_str());
} }
switch (BoundaryConditionSolid){
case 1:
if (rank==0) printf("LB-Poisson Solver: solid boundary: Dirichlet-type surfacen potential is assigned\n");
break;
case 2:
if (rank==0) printf("LB-Poisson Solver: solid boundary: Neumann-type surfacen charge density is assigned\n");
break;
default:
if (rank==0) printf("LB-Poisson Solver: solid boundary: Dirichlet-type surfacen potential is assigned\n");
break;
}
} }
void ScaLBL_Poisson::SetDomain(){ void ScaLBL_Poisson::SetDomain(){
Dm = std::shared_ptr<Domain>(new Domain(domain_db,comm)); // full domain for analysis Dm = std::shared_ptr<Domain>(new Domain(domain_db,comm)); // full domain for analysis
Mask = std::shared_ptr<Domain>(new Domain(domain_db,comm)); // mask domain removes immobile phases Mask = std::shared_ptr<Domain>(new Domain(domain_db,comm)); // mask domain removes immobile phases
@@ -243,17 +235,18 @@ void ScaLBL_Poisson::ReadInput(){
if (rank == 0) cout << " Domain set." << endl; if (rank == 0) cout << " Domain set." << endl;
} }
void ScaLBL_Poisson::AssignSolidBoundary(double *poisson_solid) void ScaLBL_Poisson::AssignSolidBoundary(double *poisson_solid, int *poisson_solid_BClabel)
{ {
signed char VALUE=0; signed char VALUE=0;
double AFFINITY=0.f; double AFFINITY=0.f;
int BoundaryConditionSolid=0;
auto LabelList = electric_db->getVector<int>( "SolidLabels" ); auto LabelList = electric_db->getVector<int>( "SolidLabels" );
auto AffinityList = electric_db->getVector<double>( "SolidValues" ); auto AffinityList = electric_db->getVector<double>( "SolidValues" );
size_t NLABELS = LabelList.size(); size_t NLABELS = LabelList.size();
if (NLABELS != AffinityList.size()){ if (NLABELS != AffinityList.size() || NLABELS != BoundaryConditionSolidList.size()){
ERROR("Error: LB-Poisson Solver: SolidLabels and SolidValues must be the same length! \n"); ERROR("Error: LB-Poisson Solver: BC_SolidList, SolidLabels and SolidValues all must be of the same length! \n");
} }
std::vector<double> label_count( NLABELS, 0.0 ); std::vector<double> label_count( NLABELS, 0.0 );
@@ -268,10 +261,15 @@ void ScaLBL_Poisson::AssignSolidBoundary(double *poisson_solid)
int n = k*Nx*Ny+j*Nx+i; int n = k*Nx*Ny+j*Nx+i;
VALUE=Mask->id[n]; VALUE=Mask->id[n];
AFFINITY=0.f; AFFINITY=0.f;
BoundaryConditionSolid=0;
// Assign the affinity from the paired list // Assign the affinity from the paired list
for (unsigned int idx=0; idx < NLABELS; idx++){ for (unsigned int idx=0; idx < NLABELS; idx++){
if (VALUE == LabelList[idx]){ if (VALUE == LabelList[idx]){
AFFINITY=AffinityList[idx]; AFFINITY=AffinityList[idx];
BoundaryConditionSolid=BoundaryConditionSolidList[idx];
if (BoundaryConditionSolid!=1 && BoundaryConditionSolid!=2){
ERROR("Error: LB-Poisson Solver: Note only BC_SolidList of 1 or 2 is supported!\n");
}
//NOTE need to convert the user input phys unit to LB unit //NOTE need to convert the user input phys unit to LB unit
if (BoundaryConditionSolid==2){ if (BoundaryConditionSolid==2){
//for BCS=1, i.e. Dirichlet-type, no need for unit conversion //for BCS=1, i.e. Dirichlet-type, no need for unit conversion
@@ -283,6 +281,7 @@ void ScaLBL_Poisson::AssignSolidBoundary(double *poisson_solid)
} }
} }
poisson_solid[n] = AFFINITY; poisson_solid[n] = AFFINITY;
poisson_solid_BClabel[n] = BoundaryConditionSolid;
} }
} }
} }
@@ -295,17 +294,16 @@ void ScaLBL_Poisson::AssignSolidBoundary(double *poisson_solid)
for (unsigned int idx=0; idx<NLABELS; idx++){ for (unsigned int idx=0; idx<NLABELS; idx++){
VALUE=LabelList[idx]; VALUE=LabelList[idx];
AFFINITY=AffinityList[idx]; AFFINITY=AffinityList[idx];
BoundaryConditionSolid=BoundaryConditionSolidList[idx];
double volume_fraction = double(label_count_global[idx])/double((Nx-2)*(Ny-2)*(Nz-2)*nprocs); double volume_fraction = double(label_count_global[idx])/double((Nx-2)*(Ny-2)*(Nz-2)*nprocs);
switch (BoundaryConditionSolid){ if (BoundaryConditionSolid==1){
case 1:
printf(" label=%d, surface potential=%.3g [V], volume fraction=%.2g\n",VALUE,AFFINITY,volume_fraction); printf(" label=%d, surface potential=%.3g [V], volume fraction=%.2g\n",VALUE,AFFINITY,volume_fraction);
break; }
case 2: else if (BoundaryConditionSolid==2){
printf(" label=%d, surface charge density=%.3g [C/m^2], volume fraction=%.2g\n",VALUE,AFFINITY,volume_fraction); printf(" label=%d, surface charge density=%.3g [C/m^2], volume fraction=%.2g\n",VALUE,AFFINITY,volume_fraction);
break; }
default: else{
printf(" label=%d, surface potential=%.3g [V], volume fraction=%.2g\n",VALUE,AFFINITY,volume_fraction); ERROR("Error: LB-Poisson Solver: Note only BC_SolidList of 1 or 2 is supported!\n");
break;
} }
} }
} }
@@ -349,6 +347,7 @@ void ScaLBL_Poisson::Create(){
//ScaLBL_AllocateDeviceMemory((void **) &dvcID, sizeof(signed char)*Nx*Ny*Nz); //ScaLBL_AllocateDeviceMemory((void **) &dvcID, sizeof(signed char)*Nx*Ny*Nz);
ScaLBL_AllocateDeviceMemory((void **) &fq, 7*dist_mem_size); ScaLBL_AllocateDeviceMemory((void **) &fq, 7*dist_mem_size);
ScaLBL_AllocateDeviceMemory((void **) &Psi, sizeof(double)*Nx*Ny*Nz); ScaLBL_AllocateDeviceMemory((void **) &Psi, sizeof(double)*Nx*Ny*Nz);
ScaLBL_AllocateDeviceMemory((void **) &Psi_BCLabel, sizeof(int)*Nx*Ny*Nz);
ScaLBL_AllocateDeviceMemory((void **) &ElectricField, 3*sizeof(double)*Np); ScaLBL_AllocateDeviceMemory((void **) &ElectricField, 3*sizeof(double)*Np);
ScaLBL_AllocateDeviceMemory((void **) &ResidualError, sizeof(double)*Np); ScaLBL_AllocateDeviceMemory((void **) &ResidualError, sizeof(double)*Np);
//........................................................................... //...........................................................................
@@ -524,15 +523,19 @@ void ScaLBL_Poisson::Initialize(double time_conv_from_Study){
//1. assign solid boundary value (surface potential or surface change density) //1. assign solid boundary value (surface potential or surface change density)
//2. Initialize electric potential for pore nodes //2. Initialize electric potential for pore nodes
double *psi_host; double *psi_host;
int *psi_BCLabel_host;
psi_host = new double [Nx*Ny*Nz]; psi_host = new double [Nx*Ny*Nz];
psi_BCLabel_host = new int [Nx*Ny*Nz];
time_conv = time_conv_from_Study; time_conv = time_conv_from_Study;
AssignSolidBoundary(psi_host);//step1 AssignSolidBoundary(psi_host,psi_BCLabel_host);//step1
Potential_Init(psi_host);//step2 Potential_Init(psi_host);//step2
ScaLBL_CopyToDevice(Psi, psi_host, Nx*Ny*Nz*sizeof(double)); ScaLBL_CopyToDevice(Psi, psi_host, Nx*Ny*Nz*sizeof(double));
ScaLBL_CopyToDevice(Psi_BCLabel, psi_BCLabel_host, Nx*Ny*Nz*sizeof(int));
ScaLBL_Comm->Barrier(); ScaLBL_Comm->Barrier();
ScaLBL_D3Q7_Poisson_Init(dvcMap, fq, Psi, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np); ScaLBL_D3Q7_Poisson_Init(dvcMap, fq, Psi, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np);
ScaLBL_D3Q7_Poisson_Init(dvcMap, fq, Psi, 0, ScaLBL_Comm->LastExterior(), Np); ScaLBL_D3Q7_Poisson_Init(dvcMap, fq, Psi, 0, ScaLBL_Comm->LastExterior(), Np);
delete [] psi_host; delete [] psi_host;
delete [] psi_BCLabel_host;
//extra treatment for halo layer //extra treatment for halo layer
//if (BoundaryCondition==1){ //if (BoundaryCondition==1){
@@ -749,23 +752,25 @@ void ScaLBL_Poisson::SolveElectricPotentialAAeven(int timestep_from_Study){
void ScaLBL_Poisson::SolvePoissonAAodd(double *ChargeDensity){ void ScaLBL_Poisson::SolvePoissonAAodd(double *ChargeDensity){
ScaLBL_D3Q7_AAodd_Poisson(NeighborList, dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np); ScaLBL_D3Q7_AAodd_Poisson(NeighborList, dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np);
ScaLBL_D3Q7_AAodd_Poisson(NeighborList, dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, 0, ScaLBL_Comm->LastExterior(), Np); ScaLBL_D3Q7_AAodd_Poisson(NeighborList, dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, 0, ScaLBL_Comm->LastExterior(), Np);
if (BoundaryConditionSolid==1){ ScaLBL_Comm->SolidDirichletAndNeumannD3Q7(fq, Psi, Psi_BCLabel);
ScaLBL_Comm->SolidDirichletD3Q7(fq, Psi); //if (BoundaryConditionSolid==1){
} // ScaLBL_Comm->SolidDirichletD3Q7(fq, Psi);
else if (BoundaryConditionSolid==2){ //}
ScaLBL_Comm->SolidNeumannD3Q7(fq, Psi); //else if (BoundaryConditionSolid==2){
} // ScaLBL_Comm->SolidNeumannD3Q7(fq, Psi);
//}
} }
void ScaLBL_Poisson::SolvePoissonAAeven(double *ChargeDensity){ void ScaLBL_Poisson::SolvePoissonAAeven(double *ChargeDensity){
ScaLBL_D3Q7_AAeven_Poisson(dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np); ScaLBL_D3Q7_AAeven_Poisson(dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, ScaLBL_Comm->FirstInterior(), ScaLBL_Comm->LastInterior(), Np);
ScaLBL_D3Q7_AAeven_Poisson(dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, 0, ScaLBL_Comm->LastExterior(), Np); ScaLBL_D3Q7_AAeven_Poisson(dvcMap, fq, ChargeDensity, Psi, ElectricField, tau, epsilon_LB, 0, ScaLBL_Comm->LastExterior(), Np);
if (BoundaryConditionSolid==1){ ScaLBL_Comm->SolidDirichletAndNeumannD3Q7(fq, Psi, Psi_BCLabel);
ScaLBL_Comm->SolidDirichletD3Q7(fq, Psi); //if (BoundaryConditionSolid==1){
} // ScaLBL_Comm->SolidDirichletD3Q7(fq, Psi);
else if (BoundaryConditionSolid==2){ //}
ScaLBL_Comm->SolidNeumannD3Q7(fq, Psi); //else if (BoundaryConditionSolid==2){
} // ScaLBL_Comm->SolidNeumannD3Q7(fq, Psi);
//}
} }
void ScaLBL_Poisson::DummyChargeDensity(){ void ScaLBL_Poisson::DummyChargeDensity(){

View File

@@ -46,7 +46,7 @@ public:
int analysis_interval; int analysis_interval;
int BoundaryConditionInlet; int BoundaryConditionInlet;
int BoundaryConditionOutlet; int BoundaryConditionOutlet;
int BoundaryConditionSolid; vector<int> BoundaryConditionSolidList;
double tau; double tau;
double tolerance; double tolerance;
std::string tolerance_method; std::string tolerance_method;
@@ -86,6 +86,7 @@ public:
//signed char *dvcID; //signed char *dvcID;
double *fq; double *fq;
double *Psi; double *Psi;
int *Psi_BCLabel;
double *ElectricField; double *ElectricField;
double *ChargeDensityDummy;// for debugging double *ChargeDensityDummy;// for debugging
double *ResidualError; double *ResidualError;