29#ifndef BLOCK_GEOMETRY_HH
30#define BLOCK_GEOMETRY_HH
43template<
typename T,
unsigned D>
46 _data(this->getNcells()),
47 _communicatable(_data),
51 clout(std::cout, (
"BlockGeometry" + std::to_string(D) +
"D"))
53 _statistics.update(
false);
56template<
typename T,
unsigned D>
62template<
typename T,
unsigned D>
68template<
typename T,
unsigned D>
71 return _cuboid.getOrigin();
74template<
typename T,
unsigned D>
77 return _cuboid.getDeltaR();
80template<
typename T,
unsigned D>
83 return _data[0][this->getCellId(latticeR)];
86template<
typename T,
unsigned D>
89 return _data[0][this->getCellId(latticeR)];
92template<
typename T,
unsigned D>
95 return _data[0][iCell];
98template<
typename T,
unsigned D>
101 if (this->isInside(latticeR)) {
102 return _data[0][this->getCellId(latticeR)];
109template<
typename T,
unsigned D>
113 if (this->isInside(loc)) {
114 return _data[0][this->getCellId(loc)];
121template<
typename T,
unsigned D>
124 set(this->getCellId(latticeR), material);
127template<
typename T,
unsigned D>
130 set(this->getCellId(latticeR), material);
133template<
typename T,
unsigned D>
137 _data[0][iCell] = material;
140template<
typename T,
unsigned D>
143 physR = _cuboid.getPhysR(latticeR);
147template<
typename T,
unsigned D>
153template<
typename T,
unsigned D>
156 if constexpr (D == 3) {
157 return Vector<int,3>(this->getNx(), this->getNy(), this->getNz());
161 __builtin_unreachable();
164template<
typename T,
unsigned D>
165template<
typename DESCRIPTOR>
171 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
173 if (get(latticeR) != 0 && (!
util::isContained(bulkMaterials, get(latticeR))) ) {
175 for (
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
187 clout <<
"cleaned "<< counter <<
" outer boundary voxel(s)" << std::endl;
192template<
typename T,
unsigned D>
197 bool toClean =
false;
201 for(
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
213 clout <<
"cleaned "<< counter <<
" outer fluid voxel(s)" << std::endl;
218template<
typename T,
unsigned D>
224 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
225 if (get(latticeR) != 1 && get(latticeR) != 0) {
227 bool var[7] = {
false};
228 for(
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
233 int comb[12][3]={{1,4,2},{1,4,3},{1,4,5},{1,4,6},{2,5,1},{2,5,3},{2,5,4},{2,5,6},{3,6,1},{3,6,2},{3,6,4},{3,6,5}};
234 for(
int i = 0; i < 12; i++){
235 if (var[(comb[i][0])] ==
true
236 && var[(comb[i][1])] ==
true
237 && var[(comb[i][2])] ==
true){
244 for(
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
258 clout <<
"cleaned "<< count2 <<
" inner boundary voxel(s)" << std::endl;
263template<
typename T,
unsigned D>
269 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
270 if (get(latticeR) != 1 && get(latticeR) != 0 && get(latticeR) == fromM) {
272 bool var[7] = {
false};
273 for(
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
278 int comb[12][3]={{1,4,2},{1,4,3},{1,4,5},{1,4,6},{2,5,1},{2,5,3},{2,5,4},{2,5,6},{3,6,1},{3,6,2},{3,6,4},{3,6,5}};
279 for(
int i = 0; i < 12; i++){
280 if (var[(comb[i][0])] ==
true
281 && var[(comb[i][1])] ==
true
282 && var[(comb[i][2])] ==
true){
289 for(
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
303 clout <<
"cleaned "<< count2
304 <<
" inner boundary voxel(s) of Type " << fromM << std::endl;
309template<
typename T,
unsigned D>
312 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
315 getPhysR(physR, latticeR);
316 domain(&output, physR);
323template<
typename T,
unsigned D>
325 std::vector<int> var)
328 for (var[0] = 0; var[0] < this->getNx(); var[0]++) {
329 for (var[1] = 0; var[1] < this->getNy(); var[1]++) {
331 for (var[2] = 0; var[2] < this->getNz(); var[2]++) {
332 found = check(material, var, offset);
335 found = check(material, var, offset);
345template<
typename T,
unsigned D>
347 std::vector<unsigned> offset)
350 for (
int iOffsetX = -offset[0]; iOffsetX <= (int) offset[0]; ++iOffsetX) {
351 for (
int iOffsetY = -offset[1]; iOffsetY <= (int) offset[1]; ++iOffsetY) {
353 for (
int iOffsetZ = -offset[2]; iOffsetZ <= (int) offset[2]; ++iOffsetZ) {
354 if (getMaterial({var[0] + iOffsetX, var[1] + iOffsetY, var[2] + iOffsetZ}) != material) {
359 if (getMaterial({var[0] + iOffsetX, var[1] + iOffsetY}) != material) {
368template<
typename T,
unsigned D>
373 bool errorFound =
false;
374 this->forSpatialLocations([&](
LatticeR<D> latticeR)
376 if (get(latticeR) == 0) {
378 for(
int iPop = 1; iPop < DESCRIPTOR::q; iPop++){
391 clout <<
"error!" << std::endl;
394 clout <<
"the model is correct!" << std::endl;
400template<
typename T,
unsigned D>
403 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
404 if (get(latticeR) == fromM) {
410template<
typename T,
unsigned D>
422 this->forSpatialLocations(latticeRmin, latticeRmax, [&](
LatticeR<D> latticeR) {
423 if (get(latticeR) == fromM) {
424 getPhysR(physR, latticeR);
427 condition(inside, physR.
data());
435template<
typename T,
unsigned D>
438 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
439 if (get(latticeR) == fromM) {
441 for (
int iOffsetX = -offset[0]; iOffsetX <= (int) offset[0]; ++iOffsetX) {
442 for (
int iOffsetY = -offset[1]; iOffsetY <= (int) offset[1]; ++iOffsetY) {
443 if constexpr (D == 3) {
444 for (
int iOffsetZ = -offset[2]; iOffsetZ <= (int) offset[2]; ++iOffsetZ) {
445 if (getMaterial({latticeR[0] + iOffsetX, latticeR[1] + iOffsetY, latticeR[2] + iOffsetZ}) != fromM) {
446 if (getMaterial({latticeR[0] + iOffsetX, latticeR[1] + iOffsetY, latticeR[2] + iOffsetZ}) != 1245) {
452 if (getMaterial({latticeR[0] + iOffsetX, latticeR[1] + iOffsetY}) != fromM) {
453 if (getMaterial({latticeR[0] + iOffsetX, latticeR[1] + iOffsetY}) != 1245) {
468template<
typename T,
unsigned D>
470 std::vector<int> testDirection)
472 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
473 if (get(latticeR) == fromM) {
476 for (
int iOffsetX =
util::min(testDirection[0],0); iOffsetX <=
util::max(testDirection[0],0); ++iOffsetX) {
477 for (
int iOffsetY =
util::min(testDirection[1],0); iOffsetY <=
util::max(testDirection[1],0); ++iOffsetY) {
478 if constexpr (D == 3){
479 for (
int iOffsetZ =
util::min(testDirection[2],0); iOffsetZ <=
util::max(testDirection[2],0); ++iOffsetZ) {
480 if (iOffsetX!=0 || iOffsetY!=0 || iOffsetZ!=0) {
481 if (getMaterial({latticeR[0] + iOffsetX, latticeR[1] + iOffsetY, latticeR[2] + iOffsetZ}) != testM) {
487 if (iOffsetX!=0 || iOffsetY!=0) {
488 if (getMaterial({latticeR[0] + iOffsetX, latticeR[1] + iOffsetY}) != testM) {
503template<
typename T,
unsigned D>
507 rename(fromM, toM, condition);
511 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
512 if (get(latticeR) == toM) {
513 getPhysR(physR, latticeR);
516 condition(inside, physR.
data());
519 if (getMaterial({latticeR[0]+testDirection[0],latticeR[1]+testDirection[1],latticeR[2]+testDirection[2]})!=fluidM ||
520 getMaterial({latticeR[0]+2*testDirection[0],latticeR[1]+2*testDirection[1],latticeR[2]+2*testDirection[2]})!=fluidM ||
521 getMaterial({latticeR[0]-testDirection[0],latticeR[1]-testDirection[1],latticeR[2]-testDirection[2]})!=0 ) {
522 set(latticeR, fromM);
525 if (getMaterial({latticeR[0]+testDirection[0],latticeR[1]+testDirection[1]}) != fluidM ||
526 getMaterial({latticeR[0]+2*testDirection[0],latticeR[1]+2*testDirection[1]}) != fluidM ||
527 getMaterial({latticeR[0]-testDirection[0],latticeR[1]-testDirection[1]}) != 0) {
528 set(latticeR, fromM);
536template<
typename T,
unsigned D>
540 rename(fromM, toM, condition);
541 std::vector<int> testDirection = getStatistics().computeDiscreteNormal(toM);
544 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
545 if (get(latticeR) == toM) {
546 getPhysR(physR, latticeR);
548 condition(inside, physR);
551 if (getMaterial({latticeR[0]+testDirection[0],latticeR[1]+testDirection[1],latticeR[2]+testDirection[2]})!=fluidM ||
552 getMaterial({latticeR[0]+2*testDirection[0],latticeR[1]+2*testDirection[1],latticeR[2]+2*testDirection[2]})!=fluidM ||
553 getMaterial({latticeR[0]-testDirection[0],latticeR[1]-testDirection[1],latticeR[2]-testDirection[2]})!=0 ) {
554 set(latticeR, fromM);
557 if (getMaterial({latticeR[0]+testDirection[0],latticeR[1]+testDirection[1]})!=fluidM ||
558 getMaterial({latticeR[0]+2*testDirection[0],latticeR[1]+2*testDirection[1]})!=fluidM ||
559 getMaterial({latticeR[0]-testDirection[0],latticeR[1]-testDirection[1]})!=0 ) {
560 set(latticeR, fromM);
568template<
typename T,
unsigned D>
572 this->forCoreSpatialLocations([&](
LatticeR<D> latticeR) {
573 getPhysR(physR, latticeR);
575 condition(inside, physR);
577 for (
int i = 0; i < numberOfLayers; i++) {
578 if (0 <= latticeR[0] + i * discreteNormal[0] && latticeR[0] + i * discreteNormal[0] < this->getNx() &&
579 0 <= latticeR[1] + i * discreteNormal[1] && latticeR[1] + i * discreteNormal[1] < this->getNy()){
581 if(0 <= latticeR[2] + i * discreteNormal[2] && latticeR[2] + i * discreteNormal[2] < this->getNz()){
582 set({latticeR[0] + i * discreteNormal[0], latticeR[1] + i * discreteNormal[1], latticeR[2] + i * discreteNormal[2]}, get(latticeR));
585 set({latticeR[0] + i * discreteNormal[0], latticeR[1] + i * discreteNormal[1]}, get(latticeR));
593template<
typename T,
unsigned D>
595 std::vector<int> offset, std::map<std::vector<int>,
int>* tmp)
597 std::map<std::vector<int>,
int> tmp2;
598 bool firstCall =
false;
599 if (tmp ==
nullptr) {
604 if (getMaterial(seed) == fromM) {
605 std::vector<int> found;
606 found.push_back(seed[0]);
607 found.push_back(seed[1]);
609 found.push_back(seed[2]);
610 if (tmp->count(found) == 0) {
612 if (offset[0] != 0) {
613 regionGrowing(fromM, toM, {seed[0] + 1, seed[1], seed[2]}, offset, tmp);
614 regionGrowing(fromM, toM, {seed[0] - 1, seed[1], seed[2]}, offset, tmp);
616 if (offset[1] != 0) {
617 regionGrowing(fromM, toM, {seed[0], seed[1] + 1, seed[2]}, offset, tmp);
618 regionGrowing(fromM, toM, {seed[0], seed[1] - 1, seed[2]}, offset, tmp);
620 if (offset[2] != 0) {
621 regionGrowing(fromM, toM, {seed[0], seed[1], seed[2] + 1}, offset, tmp);
622 regionGrowing(fromM, toM, {seed[0], seed[1], seed[2] - 1}, offset, tmp);
626 if (tmp->count(found) == 0) {
628 if (offset[0] != 0) {
629 regionGrowing(fromM, toM, {seed[0] + 1, seed[1]}, offset, tmp);
630 regionGrowing(fromM, toM, {seed[0] - 1, seed[1]}, offset, tmp);
632 if (offset[1] != 0) {
633 regionGrowing(fromM, toM, {seed[0], seed[1] + 1}, offset, tmp);
634 regionGrowing(fromM, toM, {seed[0], seed[1] - 1}, offset, tmp);
640 std::map<std::vector<int>,
int>::iterator iter;
641 for (iter = tmp->begin(); iter != tmp->end(); iter++) {
643 set((iter->first)[0],(iter->first)[1],(iter->first)[2], toM);
645 set((iter->first)[0],(iter->first)[1], toM);
652template<
typename T,
unsigned D>
655 for (
int x = min[0]; x <= max[0]; x++) {
659 for (
int y = min[1]; y <= max[1]; y++) {
661 for (
int z = min[2]; z <= max[2]; z++) {
662 clout << getMaterial({x, y, z}) <<
" ";
664 if (max[1] - min[1] != 0 && max[2] - min[2] != 0) {
668 clout << getMaterial({x, y}) <<
" ";
671 if (max[0] - min[0] != 0) {
678template<
typename T,
unsigned D>
681 assert(direction >= 0 && direction <= 2);
685 printLayer({layer, 0, 0},{layer, this->getNy() - 1, this->getNz() - 1}, linenumber);
688 printLayer({0, layer, 0}, {this->getNx() - 1, layer, this->getNz() - 1}, linenumber);
691 printLayer({0, 0, layer}, {this->getNx() - 1, this->getNy() - 1, layer}, linenumber);
697 printLayer({layer, 0}, {layer, this->getNy() - 1}, linenumber);
700 printLayer({0, layer}, {this->getNx() - 1, layer}, linenumber);
706template<
typename T,
unsigned D>
709 for (
int x = loc[0] - offset; x <= loc[0] + offset; x++) {
710 if constexpr (D==3) {
711 clout <<
"yz-plane_x=" << x - loc[0] << std::endl;
713 for (
int y = loc[1] - offset; y <= loc[1] + offset; y++) {
715 for (
int z = loc[2] - offset; z <= loc[2] + offset; z++) {
716 clout << getMaterial({x, y, z}) <<
" ";
720 clout << getMaterial({x, y}) <<
" ";
729template<
typename T,
unsigned D>
732 _statistics.getStatisticsStatus() =
true;
735template<
typename T,
unsigned D>
741template<
typename T,
unsigned D>
744 return _data.getSerializableSize();
747template<
typename T,
unsigned D>
750 std::size_t currentBlock = 0;
751 bool* dataPtr =
nullptr;
753 this->registerSerializableOfConstSize(iBlock, sizeBlock, currentBlock, dataPtr, _data, loadingMode);
Representation of the 2D block geometry view – header file.
Representation of a block geometry.
int innerClean(bool verbose=true)
Changes all cell materials which are not 0 or 1 to 1 if there is a non robust constiallation.
void rename(int fromM, int toM)
Replaces all material numbers (fromM) to another (toM)
Vector< T, D > getPhysR(LatticeR< D > latticeR) const
void reset(IndicatorF< T, D > &domain)
Resets all cell materials inside of a domain to 0.
const BlockGeometryStatistics< T, D > & getStatistics() const
Read only access to the associated block statistic.
int getMaterial(LatticeR< D > latticeR) const
returns the (iX,iY) entry in the 2D scalar field
int clean(bool verbose=true, std::vector< int > bulkMaterials={1})
Changes all cell materials which are not in bulkMaterials to 0 if there is no neighbour from bulkMate...
BlockGeometry(Cuboid< T, D > &cuboid, int padding, int iCglob=-1)
bool find(int material, std::vector< unsigned > offset, std::vector< int > var)
Returns the coordinates (iX,iY) of a voxel with a given material number (material) if there exists an...
int outerClean(bool verbose=true, std::vector< int > bulkMaterials={1})
Changes all cell materials from bulkMaterials to 0 if there is a neighbour with material 0.
bool check(int material, std::vector< int > var, std::vector< unsigned > offset)
Returns true if at position (iX,iY) and in a neighbourhood of size (offsetX,offsetY) only voxels with...
int getIcGlob() const
Read only access to the global iC number which is given !=-1 if the block geometries are part of a su...
void regionGrowing(int fromM, int toM, LatticeR< D > seed, std::vector< int > offset, std::map< std::vector< int >, int > *tmp=nullptr)
Replaces all material numbers (fromM) to another (toM) using a seed point and max....
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
T getDeltaR() const
Read only access to the voxel size given in SI units (meter)
void printNode(std::vector< int > loc, int offset=1)
Prints a chosen node and its neighbourhood.
bool checkForErrors(bool verbose=true) const
Checks for errors (searches for all outer voxels (=0) with an inner voxel (=1) as a direct neighbour)
void copyMaterialLayer(IndicatorF3D< T > &condition, int discreteNormal[D], int numberOfLayers)
Copy a layer of material numbers inside an indicator in a discrete normal direction.
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
Vector< T, D > getOrigin() const
Read only access to the origin position given in SI units (meter)
Vector< int, D > getExtent() const
Returns the extend of the block in lattice units.
void printLayer(std::vector< int > min, std::vector< int > max, bool linenumber=false)
Prints a chosen part of the block geometry.
void set(LatticeR< D > latticeR, int material)
Write access to a material number.
std::size_t getSerializableSize() const override
Binary size for the serializer.
std::enable_if_t< sizeof...(L)==D, int > get(L... latticeR) const
Read-only access to a material number.
IndicatorF3D is an application from .
class for marking output with some text
constexpr const T * data() const any_platform
constexpr int c(unsigned iPop, unsigned iDim) any_platform
bool isContained(const C &c, U object)
Check, if object is contained in iteratable container c.
Top level namespace for all of OpenLB.
Vector(T &&t, Ts &&... ts) -> Vector< std::remove_cvref_t< T >, 1+sizeof...(Ts)>
std::conditional_t< D==2, BlockGeometryStatistics2D< T >, BlockGeometryStatistics3D< T > > BlockGeometryStatistics
std::conditional_t< D==2, IndicatorF2D< T >, IndicatorF3D< T > > IndicatorF