24#ifndef SET_BOUZIDI_BOUNDARY_H
25#define SET_BOUZIDI_BOUNDARY_H
39namespace descriptors {
43 template <
typename T,
typename DESCRIPTOR>
51 template <
typename T,
typename DESCRIPTOR>
59 template <
typename T,
typename DESCRIPTOR>
75 template <
typename CELL,
typename V =
typename CELL::value_t>
77 using DESCRIPTOR =
typename CELL::descriptor_t;
78 const auto q = x_b.template getFieldPointer<descriptors::BOUZIDI_DISTANCE>();
79 for (
int iPop = 1; iPop < descriptors::q<DESCRIPTOR>(); ++iPop) {
82 const auto c = descriptors::c<DESCRIPTOR>(iPop);
83 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
84 auto x_s = x_b.neighbor(c);
85 auto x_f = x_b.neighbor(descriptors::c<DESCRIPTOR>(iPop_opposite));
87 x_b[iPop_opposite] = (q[iPop] <= V{0.5})
88 * (V{2} * q[iPop] * x_s[iPop] + (V{1} - V{2} * q[iPop]) * x_b[iPop])
90 * (V{0.5} / q[iPop] * x_s[iPop] + V{0.5} * (V{2} * q[iPop] - V{1}) / q[iPop] * x_f[iPop_opposite]);
93 else if (q[iPop] == V{0}) {
94 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
95 x_b[iPop_opposite] = x_b[iPop];
109 template <
typename CELL,
typename V =
typename CELL::value_t>
111 using DESCRIPTOR =
typename CELL::descriptor_t;
112 const auto q = x_b.template getFieldPointer<descriptors::BOUZIDI_DISTANCE>();
113 const auto phi_d = x_b.template getFieldPointer<descriptors::BOUZIDI_ADE_DIRICHLET>();
115 if (descriptors::q<DESCRIPTOR>() == 7) {
118 for (
int iPop = 1; iPop < descriptors::q<DESCRIPTOR>(); ++iPop) {
120 if (q[iPop] > V{0}) {
121 const auto c = descriptors::c<DESCRIPTOR>(iPop);
122 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
123 auto x_s = x_b.neighbor(c);
124 auto x_f = x_b.neighbor(descriptors::c<DESCRIPTOR>(iPop_opposite));
125 auto source_d = phi_d[iPop] * f;
126 auto t_i = descriptors::t<V,DESCRIPTOR>(iPop);
127 auto t_iopp = descriptors::t<V,DESCRIPTOR>(iPop_opposite);
129 x_b[iPop_opposite] = (q[iPop] <= V{0.5})
130 * (V{-2} * q[iPop] * (x_s[iPop] + t_i) + (V{2} * q[iPop] - V{1}) * (x_b[iPop] + t_i) + source_d)
132 * (V{-1} / (V{2} * q[iPop]) * (x_s[iPop] + t_i) + (V{1} - V{1} / (V{2} * q[iPop])) * (x_f[iPop_opposite] + t_iopp) + (V{1} / (V{2} * q[iPop])) * source_d)
136 else if (q[iPop] == V{0}) {
137 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
138 auto source_d = phi_d[iPop] * f;
139 auto t_i = descriptors::t<V,DESCRIPTOR>(iPop);
140 auto t_iopp = descriptors::t<V,DESCRIPTOR>(iPop_opposite);
141 x_b[iPop_opposite] = -(x_b[iPop] + t_i) + source_d - t_iopp;
156 template <
typename CELL,
typename V =
typename CELL::value_t>
158 using DESCRIPTOR =
typename CELL::descriptor_t;
159 const auto q = x_b.template getFieldPointer<descriptors::BOUZIDI_DISTANCE>();
160 const auto veloCoeff = x_b.template getFieldPointer<descriptors::BOUZIDI_VELOCITY>();
161 for (
int iPop=1; iPop < descriptors::q<DESCRIPTOR>(); ++iPop) {
164 const auto c = descriptors::c<DESCRIPTOR>(iPop);
165 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
166 auto x_s = x_b.neighbor(c);
167 auto x_f = x_b.neighbor(descriptors::c<DESCRIPTOR>(iPop_opposite));
168 auto veloTerm = veloCoeff[iPop] * (descriptors::t<V,DESCRIPTOR>(iPop)) * (descriptors::invCs2<V,DESCRIPTOR>());
170 x_b[iPop_opposite] = (q[iPop] <= V{0.5})
171 * (V{2} * q[iPop] * x_s[iPop] + (V{1} - V{2} * q[iPop]) * x_b[iPop] - V{2} * veloTerm)
173 * (V{0.5} / q[iPop] * x_s[iPop] + V{0.5} * (V{2} * q[iPop] - V{1}) / q[iPop] * x_f[iPop_opposite] - V{1}/q[iPop] * veloTerm);
176 else if (q[iPop] == V{0}) {
177 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
178 auto veloTerm = veloCoeff[iPop] * (descriptors::t<V,DESCRIPTOR>(iPop)) * (descriptors::invCs2<V,DESCRIPTOR>());
179 x_b[iPop_opposite] = x_b[iPop] - V{2} * veloTerm;
194 template <
typename CELL,
typename V =
typename CELL::value_t>
196 using DESCRIPTOR =
typename CELL::descriptor_t;
197 const auto q = x_b.template getFieldPointer<descriptors::BOUZIDI_DISTANCE>();
198 for (
int iPop=1; iPop < descriptors::q<DESCRIPTOR>(); ++iPop) {
200 const auto c = descriptors::c<DESCRIPTOR>(iPop);
201 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
202 auto x_s = x_b.neighbor(c);
203 auto x_f = x_b.neighbor(descriptors::c<DESCRIPTOR>(iPop_opposite));
204 auto f_tmp = x_b[iPop] + q[iPop]*(x_s[iPop] - x_b[iPop]);
205 x_b[iPop_opposite] = f_tmp + q[iPop]/(V{1}+q[iPop]) * (x_f[iPop_opposite] - f_tmp);
212template<
typename T,
typename DESCRIPTOR,
typename OPERATOR = Bouz
idiPostProcessor>
221 for (
int iC=0; iC < load.size(); ++iC) {
222 setBouzidiBoundary<T,DESCRIPTOR,OPERATOR>(sLattice.
getBlock(iC),
223 (bulkIndicator->getBlockIndicatorF(iC)).getBlockGeometry(),
224 boundaryIndicator->getBlockIndicatorF(iC),
225 bulkIndicator->getBlockIndicatorF(iC),
226 indicatorAnalyticalBoundary);
228 addPoints2CommBC<T,DESCRIPTOR>(sLattice, std::forward<
decltype(boundaryIndicator)>(boundaryIndicator), _overlap);
233template<
typename T,
typename DESCRIPTOR,
typename OPERATOR = Bouz
idiPostProcessor>
236 int materialOfSolidObstacle,
238 std::vector<int> bulkMaterials = std::vector<int>(1,1))
241 setBouzidiBoundary<T,DESCRIPTOR,OPERATOR>(sLattice,
244 indicatorAnalyticalBoundary);
249template<
typename T,
typename DESCRIPTOR,
typename OPERATOR = Bouz
idiPostProcessor>
255 bool verbose =
false)
260 const T deltaR = blockGeometry.
getDeltaR();
264 if (boundaryIndicator(solidLatticeR)) {
265 for (
int iPop=1; iPop < DESCRIPTOR::q; ++iPop) {
267 const auto c = descriptors::c<DESCRIPTOR>(iPop);
268 const auto iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
270 if (blockGeometry.
isInside(boundaryLatticeR)) {
271 T boundaryPhysR[DESCRIPTOR::d] { };
272 blockGeometry.
getPhysR(boundaryPhysR,boundaryLatticeR);
274 if (bulkIndicator(boundaryLatticeR)) {
277 const T
norm = deltaR * util::norm<DESCRIPTOR::d>(descriptors::c<DESCRIPTOR>(iPop));
278 auto direction = -deltaR * c;
281 if (indicatorAnalyticalBoundary.distance(dist, boundaryPhysR, direction, blockGeometry.
getIcGlob())) {
285 if ((qIpop < 0) || (qIpop > 1)) {
287 clout <<
"Error, non suitable dist. at lattice: (" << boundaryLatticeR <<
"), physical: (" << blockGeometry.
getPhysR(boundaryLatticeR) <<
"), direction " << iPop <<
". Fall-back to bounce-back." << std::endl;
297 clout <<
"Error, no boundary found at lattice:(" << boundaryLatticeR <<
"), physical: (" << blockGeometry.
getPhysR(boundaryLatticeR) <<
"), direction: " << iPop <<
".Fall-back to bounce-back." << std::endl;
307 if (bulkIndicator(boundaryLatticeR + descriptors::c<DESCRIPTOR>(iPop))) {
309 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_DISTANCE>(iPop_opposite, qIpop);
313 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_DISTANCE>(iPop_opposite, T{0.5});
316 if constexpr (std::is_same_v<OPERATOR, BouzidiVelocityPostProcessor>) {
317 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_VELOCITY>(iPop_opposite, 0);
320 if constexpr (std::is_same_v<OPERATOR, BouzidiAdeDirichletPostProcessor>) {
321 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_ADE_DIRICHLET>(iPop_opposite, 0);
324 if (!block.
isPadding(boundaryLatticeR)) {
334 if (blockGeometry.
getMaterial(boundaryLatticeR) != 0) {
336 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_DISTANCE>(iPop_opposite, T{0.5});
338 if constexpr (std::is_same_v<OPERATOR, BouzidiVelocityPostProcessor>) {
339 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_VELOCITY>(iPop_opposite, 0);
342 if constexpr (std::is_same_v<OPERATOR, BouzidiAdeDirichletPostProcessor>) {
343 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_ADE_DIRICHLET>(iPop_opposite, 0);
345 if (!block.
isPadding(boundaryLatticeR)) {
359template<
typename T,
typename DESCRIPTOR>
363 std::vector<int> bulkMaterials = std::vector<int>(1,1))
365 setBouzidiVelocity<T,DESCRIPTOR>(sLattice, superGeometry.
getMaterialIndicator(material), u, bulkMaterials);
369template<
typename T,
typename DESCRIPTOR>
373 std::vector<int> bulkMaterials = std::vector<int>(1,1))
375 setBouzidiVelocity<T,DESCRIPTOR>(sLattice, std::forward<
decltype(boundaryIndicator)>(boundaryIndicator),
376 boundaryIndicator->getSuperGeometry().getMaterialIndicator(std::move(bulkMaterials)),
381template<
typename T,
typename DESCRIPTOR>
388 auto& cuboidGeometry = boundaryIndicator->getSuperGeometry().getCuboidGeometry();
389 for (
int iCloc = 0; iCloc < load.size(); ++iCloc) {
390 auto& cuboid = cuboidGeometry.get(load.glob(iCloc));
391 setBouzidiVelocity<T,DESCRIPTOR>(sLattice.
getBlock(iCloc),
392 boundaryIndicator->getBlockIndicatorF(iCloc),
393 bulkIndicator->getBlockIndicatorF(iCloc),
400template<
typename T,
typename DESCRIPTOR>
407 const T deltaR = cuboid.getDeltaR();
409 if (boundaryIndicator(solidLatticeR)) {
410 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
412 if (block.
isInside(boundaryLatticeR)) {
413 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
414 auto x_b = block.
get(boundaryLatticeR);
415 const auto opp_bouzidi_dist = x_b.template getFieldComponent<descriptors::BOUZIDI_DISTANCE>(iPop_opposite);
418 if (opp_bouzidi_dist >= 0) {
419 T wallVelocity[DESCRIPTOR::d] = { };
420 T physicalIntersection[DESCRIPTOR::d] = { };
421 T boundaryPhysR[DESCRIPTOR::d] { };
422 cuboid.getPhysR(boundaryPhysR, boundaryLatticeR);
425 for (
int i = 0; i< DESCRIPTOR::d; ++i) {
426 physicalIntersection[i] = boundaryPhysR[i] + opp_bouzidi_dist * deltaR * descriptors::c<DESCRIPTOR>(iPop_opposite,i);
430 u(wallVelocity, physicalIntersection);
431 const auto c = descriptors::c<DESCRIPTOR>(iPop_opposite);
435 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_VELOCITY>(iPop_opposite, vel_coeff);
443template<
typename T,
typename DESCRIPTOR>
447 std::vector<int> bulkMaterials = std::vector<int>(1,1))
449 setBouzidiAdeDirichlet<T,DESCRIPTOR>(sLattice, superGeometry.
getMaterialIndicator(material), phi_d, bulkMaterials);
452template<
typename T,
typename DESCRIPTOR>
456 std::vector<int> bulkMaterials = std::vector<int>(1,1))
458 setBouzidiAdeDirichlet<T,DESCRIPTOR>(sLattice, superGeometry.
getMaterialIndicator(material), phi_d, bulkMaterials);
461template<
typename T,
typename DESCRIPTOR>
468 auto& cuboidGeometry = boundaryIndicator->getSuperGeometry().getCuboidGeometry();
469 for (
int iCloc = 0; iCloc < load.size(); ++iCloc) {
470 auto& cuboid = cuboidGeometry.get(load.glob(iCloc));
471 setBouzidiAdeDirichlet<T,DESCRIPTOR>(sLattice.
getBlock(iCloc),
472 boundaryIndicator->getBlockIndicatorF(iCloc),
473 bulkIndicator->getBlockIndicatorF(iCloc),
479template<
typename T,
typename DESCRIPTOR>
486 auto& cuboidGeometry = boundaryIndicator->getSuperGeometry().getCuboidGeometry();
487 for (
int iCloc = 0; iCloc < load.size(); ++iCloc) {
488 auto& cuboid = cuboidGeometry.get(load.glob(iCloc));
489 setBouzidiAdeDirichlet<T,DESCRIPTOR>(sLattice.
getBlock(iCloc),
490 boundaryIndicator->getBlockIndicatorF(iCloc),
491 bulkIndicator->getBlockIndicatorF(iCloc),
497template<
typename T,
typename DESCRIPTOR>
501 std::vector<int> bulkMaterials = std::vector<int>(1,1))
503 setBouzidiAdeDirichlet<T,DESCRIPTOR>(sLattice, std::forward<
decltype(boundaryIndicator)>(boundaryIndicator),
504 boundaryIndicator->getSuperGeometry().getMaterialIndicator(std::move(bulkMaterials)),
508template<
typename T,
typename DESCRIPTOR>
512 std::vector<int> bulkMaterials = std::vector<int>(1,1))
514 setBouzidiAdeDirichlet<T,DESCRIPTOR>(sLattice, std::forward<
decltype(boundaryIndicator)>(boundaryIndicator),
515 boundaryIndicator->getSuperGeometry().getMaterialIndicator(std::move(bulkMaterials)),
519template<
typename T,
typename DESCRIPTOR>
527 if (boundaryIndicator(solidLatticeR)) {
528 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
530 if (block.
isInside(boundaryLatticeR)) {
531 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
532 auto x_b = block.
get(boundaryLatticeR);
533 const auto opp_bouzidi_dist = x_b.template getFieldComponent<descriptors::BOUZIDI_DISTANCE>(iPop_opposite);
536 if (opp_bouzidi_dist >= 0) {
538 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_ADE_DIRICHLET>(iPop_opposite, phi_d);
546template<
typename T,
typename DESCRIPTOR>
554 if (boundaryIndicator(solidLatticeR)) {
555 for (
int iPop = 1; iPop < DESCRIPTOR::q; ++iPop) {
557 if (block.
isInside(boundaryLatticeR)) {
558 const int iPop_opposite = descriptors::opposite<DESCRIPTOR>(iPop);
559 auto x_b = block.
get(boundaryLatticeR);
560 const auto opp_bouzidi_dist = x_b.template getFieldComponent<descriptors::BOUZIDI_DISTANCE>(iPop_opposite);
563 if (opp_bouzidi_dist >= 0) {
564 T boundaryPhysR[DESCRIPTOR::d] { };
565 T phi_at_cell[1] { };
566 cuboid.getPhysR(boundaryPhysR, boundaryLatticeR);
568 phi_d(phi_at_cell, boundaryPhysR);
571 block.
get(boundaryLatticeR).template setFieldComponent<descriptors::BOUZIDI_ADE_DIRICHLET>(iPop_opposite, phi_at_cell[0]);
AnalyticalF are applications from DD to XD, where X is set by the constructor.
Representation of a block geometry.
Vector< T, D > getPhysR(LatticeR< D > latticeR)
int getMaterial(LatticeR< D > latticeR) const
returns the (iX,iY) entry in the 2D scalar field
int getIcGlob() const
Read only access to the global iC number which is given !=-1 if the block geometries are part of a su...
T getDeltaR() const
Read only access to the voxel size given in SI units (meter)
Platform-abstracted block lattice for external access and inter-block interaction.
virtual void addPostProcessor(std::type_index stage, LatticeR< DESCRIPTOR::d > latticeR, PostProcessorPromise< T, DESCRIPTOR > &&promise)=0
Schedule post processor for application to latticeR in stage.
Cell< T, DESCRIPTOR > get(CellID iCell)
Get Cell interface for index iCell.
void forSpatialLocations(F f) const
bool isPadding(LatticeR< D > latticeR) const
Return whether location is valid.
bool isInside(LatticeR< D > latticeR) const
Return whether location is valid.
static constexpr OperatorScope scope
void apply(CELL &x_b) any_platform
Post processor for the zero-velocity Bouzidi boundary.
static constexpr OperatorScope scope
void apply(CELL &x_b) any_platform
Post processor for the velocity Bouzidi boundary.
static constexpr OperatorScope scope
void apply(CELL &x_b) any_platform
Smart pointer for managing the various ways of passing functors around.
class for marking output with some text
void setMultiOutput(bool b)
enable message output for all MPI processes, disabled by default
Representation of a statistic for a parallel 2D geometry.
std::unique_ptr< SuperIndicatorF< T, D > > getMaterialIndicator(std::vector< int > &&materials)
Returns a material indicator using the given vector of materials.
Super class maintaining block lattices for a cuboid decomposition.
BlockLattice< T, DESCRIPTOR > & getBlock(int locC)
Return BlockLattice with local index locC.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
void apply(CELL &x_b) any_platform
static constexpr OperatorScope scope
Top level namespace for all of OpenLB.
void setBouzidiVelocity(SuperLattice< T, DESCRIPTOR > &sLattice, SuperGeometry< T, DESCRIPTOR::d > &superGeometry, int material, AnalyticalF< DESCRIPTOR::d, T, T > &u, std::vector< int > bulkMaterials=std::vector< int >(1, 1))
Set Bouzidi velocity boundary on material cells of sLattice.
void setBouzidiBoundary(SuperLattice< T, DESCRIPTOR > &sLattice, FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&boundaryIndicator, FunctorPtr< SuperIndicatorF< T, DESCRIPTOR::d > > &&bulkIndicator, IndicatorF< T, DESCRIPTOR::d > &indicatorAnalyticalBoundary)
Set Bouzidi boundary on indicated cells of sLattice.
std::conditional_t< D==2, BlockIndicatorF2D< T >, BlockIndicatorF3D< T > > BlockIndicatorF
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
std::conditional_t< D==2, IndicatorF2D< T >, IndicatorF3D< T > > IndicatorF
OperatorScope
Block-wide operator application scopes.
@ PerCell
Per-cell application, i.e. OPERATOR::apply is passed a CELL concept implementation.
std::conditional_t< D==2, SuperIndicatorF2D< T >, SuperIndicatorF3D< T > > SuperIndicatorF
std::conditional_t< D==2, Cuboid2D< T >, Cuboid3D< T > > Cuboid
void setBouzidiAdeDirichlet(SuperLattice< T, DESCRIPTOR > &sLattice, SuperGeometry< T, DESCRIPTOR::d > &superGeometry, int material, T phi_d, std::vector< int > bulkMaterials=std::vector< int >(1, 1))
Interpolated Bounce Back (Bouzidi) for ADE Dirichlet field.
static constexpr auto getInitialValue()
Interpolated Bounce Back (Bouzidi) distance field.
static constexpr auto getInitialValue()
Interpolated Bounce Back (Bouzidi) velocity coefficient field.
static constexpr auto getInitialValue()
Base of a field whose size is defined by [C,U_1,...,U_N]^T * [1,V_1,...V_N].
Communication after propagation.