8#ifndef PECLET_FLOW_FLOW_IBM_BC_HPP
9#define PECLET_FLOW_FLOW_IBM_BC_HPP
16 throw std::invalid_argument(
"set_domain_bc: face must be 0..5 (-x,+x,-y,+y,-z,+z)");
18 throw std::invalid_argument(
19 "set_domain_bc: type must be 0 periodic / 1 wall / 2 inflow / 3 outflow / 4 free-slip");
22 throw std::runtime_error(
23 "set_domain_bc: call BEFORE the geometry (set_solid / set_pressure_geometry / "
24 "set_solid_from_scene) to CHANGE a face's TYPE -- the type is folded into the "
25 "operators when the geometry is built. A VALUE update (vx, vy, vz) on a face whose "
26 "type is unchanged is allowed after the geometry.");
31 bcVelPhys_[face][0] =
vx;
32 bcVelPhys_[face][1] =
vy;
33 bcVelPhys_[face][2] =
vz;
34 for (
int a = 0; a < 3; ++a)
35 bcVel_[face][a] = bcVelPhys_[face][a] * u_.
velToInt(a);
38 for (
int i = 0; i < 6; ++i) {
61 if (geometryBuilt_ && bc_[face] != 2)
62 throw std::runtime_error(
63 "set_domain_bc_profile: call BEFORE the geometry (set_solid / set_pressure_geometry / "
64 "set_solid_from_scene) to make a face inflow -- the type is folded into the operators "
65 "when the geometry is built. Updating the profile on a face that is ALREADY inflow is "
66 "allowed after the geometry.");
70 bcProfRaw_[face] =
prof;
72 bcProfRawNc_[face] = nc;
80 if (bcProfRaw_[face].empty())
82 const std::vector<double>&
prof = bcProfRaw_[face];
83 const int nb = bcProfNb_[face], nc = bcProfRawNc_[face];
84 const int a = face / 2;
85 const int dims[3] = {e_.
x, e_.
y, e_.
z};
86 const int bax = (a + 1) % 3,
cax = (a + 2) % 3;
89 auto h = Kokkos::create_mirror_view(pf);
90 auto cl = [](
int v,
int n) {
return v < 0 ? 0 : (v >= n ? n - 1 : v); };
91 for (
int p0 = 0; p0 <
Lb; ++p0)
96 for (
int k = 0; k < 3; ++k)
97 h(((
long)p0 *
Lc +
p1) * 3 + k) =
100 Kokkos::deep_copy(pf, h);
102 bcProfNc_[face] =
Lc;
107 if (backflowBeta_ <= 0.0 || !hasOutflow_)
110 const double beta = backflowBeta_, rho = rho_;
112 int dims[3] = {e.x, e.y, e.z};
113 long st[3] = {1, e.x, (
long)e.x * e.y};
117 for (
int s = 0; s < 2; ++s) {
118 if (bc_[2 * a + s] != 3 || !touchesGlobalFace(2 * a + s))
120 const long sa = st[a];
121 const int na =
dims[a];
122 const int bic = (s == 0) ?
G : (na -
G - 1);
123 const double sgn = (s == 0) ? 1.0 : -1.0;
124 const int b = (a + 1) % 3, cc = (a + 2) % 3;
125 const long sb = st[b], sc = st[cc];
127 Kokkos::parallel_for(
131 const double back = sgn * u(i);
143 int dims[3] = {e.x, e.y, e.z};
144 long st[3] = {1, e.x, (
long)e.x * e.y};
145 for (
int a = 0; a < 3; ++a)
146 for (
int s = 0; s < 2; ++s) {
147 if (bc_[2 * a + s] == 0 || !touchesGlobalFace(2 * a + s))
149 const int b = (a + 1) % 3, c = (a + 2) % 3;
150 const long sa = st[a],
sb = st[b], sc = st[c];
151 const int na =
dims[a];
152 const int bic = (s == 0) ?
G : (na -
G - 1);
153 const int lo = (s == 0) ? 0 : (na -
G), hi = (s == 0) ? (
G - 1) : (na - 1);
154 Kokkos::parallel_for(
157 const long base = (
long)p0 *
sb + (
long)
p1 * sc;
158 const double pin = P(base + (
long)
bic *
sa);
159 for (
int ia = lo;
ia <= hi; ++
ia)
160 P(base + (
long)
ia *
sa) = pin;
170 outflowCorrValid_ =
false;
181#ifdef PECLET_FLOW_MPI
204 const bool keep = !Grid::collocated && !
doOutflow && hasOutflow_ && a >= 0 && a < 3 &&
205 bc_[2 * a + 1] == 3 && touchesGlobalFace(2 * a + 1);
208 const int b = (a + 1) % 3, c = (a + 2) % 3;
209 const int d[3] = {e_.
x, e_.
y, e_.
z};
210 const std::size_t
np = (std::size_t)(d[b] - 2 *
G) * (d[c] - 2 *
G);
211 if (outflowPlane_[a].extent(0) !=
np)
213 Kokkos::view_alloc(
"peclet::flow::outflow_face_plane", Kokkos::WithoutInitializing),
232 B3 e{e_.
x, e_.
y, e_.
z};
233 if constexpr (Grid::collocated) {
238 for (
int a = 0; a < 3; ++a)
239 for (
int s = 0; s < 2; ++s) {
240 const int ff = 2 * a + s;
241 const int t = bc_[
ff];
242 if (t == 0 || !touchesGlobalFace(
ff))
258 if (bcProf_[
ff].extent(0) >
267 for (
int a = 0; a < 3; ++a) {
270 for (
int s = 0; s < 2; ++s) {
271 const int ff = 2 * a + s;
272 J.j[
J.n++] =
BcVelFace{f, bcProf_[
ff], bcVel_[
ff][comp], comp, s, bcProfNc_[
ff]};
277 for (
int s = 0; s < 2; ++s)
284 const int e[3] = {e_.
x, e_.
y, e_.
z};
285 for (
int s = 0; s < 2; ++s) {
286 const int t = bc_[2 * a + s];
287 if (t == 0 || t == 3 || t == 4 || !touchesGlobalFace(2 * a + s))
296 B3 e{e_.
x, e_.
y, e_.
z};
297 const int ff = 2 * a + s;
298 const int t = bc_[
ff];
299 if (t == 0 || !touchesGlobalFace(
ff))
310 if (bcProf_[
ff].extent(0) > 0)
318 if (Grid::collocated || !hasBc_) {
319 for (
int c = 0; c < 3; ++c)
325 B3 e{e_.
x, e_.
y, e_.
z};
326 for (
int a = 0; a < 3; ++a) {
329 for (
int c = 0; c < 3; ++c)
330 for (
int s = 0; s < 2; ++s) {
331 const int ff = 2 * a + s;
337 for (
int c = 0; c < 3; ++c)
338 for (
int s = 0; s < 2; ++s)
345 B3 e{e_.
x, e_.
y, e_.
z};
346 for (
int c = 0; c < 3; ++c) {
347 Kokkos::deep_copy(bcDcorr_[c], 0.0);
348 Kokkos::deep_copy(bcBrhs_[c], 0.0);
349 for (
int a = 0; a < 3; ++a) {
352 const double beta = mu_ * u_.
w[a];
353 for (
int s = 0; s < 2; ++s) {
354 const int t = bc_[2 * a + s];
355 if (!touchesGlobalFace(2 * a + s))
361 }
else if (t == 4 && c != a) {
364 }
else if (t != 0 && c != a) {
366 bval = 2.0 * beta * bcVel_[2 * a + s][c];
void applyVelocityBcAll(int fold, bool doOutflow)
void fillVelGhosts(int comp, int fold)
void fillDomainPeriodic(CCField f)
void setDomainBc(int face, int type, double vx, double vy, double vz)
void applyBackflowStab(int c)
void applyVelocityBcComp(int comp, int fold, bool doOutflow)
void applyVelocityBcFace(CCField f, int comp, int a, int s, int fold, bool doOutflow)
void applyVelocityBcCompTo(CCField f, int comp, int fold, bool doOutflow)
bool bcVelFacePair(int a) const
void resampleBcProfile(int face)
void fillVelGhostsTo(CCField f, int comp, int fold, bool doOutflow=true)
void setDomainBcProfile(int face, const std::vector< double > &prof, int nb, int nc)
Kokkos::View< MReal *, CCMem > FV
void bcRestoreHighFacePlaneInner(BField dst, BField src, B3 ext, int g, int a)
void bcDiffusionFold(BField dcorr, BField brhs, B3 ext, int g, int a, int s, double dval, double bval)
void bcVelocityColocated(BField f, B3 ext, int g, int a, int s, double wall, int comp=0, BField prof=BField(), int prof_nc=0)
void bcSaveHighFacePlaneInner(BField dst, BField src, B3 ext, int g, int a)
void bcVelocityComp(BField f, B3 ext, int g, int a, int s, int comp, double wall, int fold, BField prof=BField(), int prof_nc=0)
void bcMirrorGhost(BField f, B3 ext, int g, int a, int s)
Kokkos::View< double *, CCMem > CCField
void bcVelocityFaces(const BcVelFaces &J, B3 ext, int g, int a, int fold)
Kokkos::DefaultExecutionSpace CCExec
void bcOutflowComp(BField f, B3 ext, int g, int a, int s, int comp, int fold)
void bcNeumannGhost(BField f, B3 ext, int g, int a, int s)
Kokkos::View< const double *, CCMem > CCConst
void bcSlipComp(BField f, B3 ext, int g, int a, int s, int comp, int fold)
double w[3]
w_a = 1 / h_a'^2 (<= 1)
double velToInt(int a) const
static constexpr double AC