218:
public SubGridManagerBase<Dune::YaspGrid<dim, Coordinates>, GridManager<Dune::YaspGrid<dim, Coordinates>>>
231 void init(
const std::string& paramGroup =
"")
244 DUNE_THROW(Dune::GridError,
"Portable Bitmap Format only supports dim == 2");
248 createGridFromImage_(img, paramGroup, overlap, periodic);
251 DUNE_THROW(Dune::IOError,
"The SubGridManager doesn't support image files with extension: *." << ext);
257 std::ifstream mask(maskFileName, std::ios_base::binary);
258 std::vector<char> buffer(std::istreambuf_iterator<char>(mask), std::istreambuf_iterator<char>{});
260 if (
const auto c = std::accumulate(cells.begin(), cells.end(), 1, std::multiplies<int>{}); c != buffer.size())
261 DUNE_THROW(Dune::IOError,
"Grid dimensions doesn't match number of cells specified " << c <<
":" << buffer.size());
263 maybePostProcessBinaryMask_(buffer, cells, paramGroup);
265 using GlobalPosition =
typename ParentType::Grid::template Codim<0>::Geometry::GlobalCoordinate;
266 const auto lowerLeft = GlobalPosition(0.0);
267 const auto upperRight = [&]{
271 for (
int i = 0; i < upperRight.size(); ++i)
272 upperRight[i] *= cells[i];
273 upperRight += lowerLeft;
281 this->
initHostGrid_(lowerLeft, upperRight, cells, paramGroup, overlap, periodic);
286 const auto elementSelector = [&](
const auto& element)
288 auto level0 = element;
289 while(level0.hasFather())
290 level0 = level0.father();
291 const auto eIdx = this->
hostGrid_().levelGridView(0).indexSet().index(level0);
292 return buffer[eIdx] != marker;
302 std::cerr <<
"No element selector provided and Grid.Image or Grid.BinaryMask not found" << std::endl;
303 std::cerr <<
"Constructing sub-grid with all elements of the host grid" << std::endl;
306 using GlobalPosition =
typename ParentType::Grid::template Codim<0>::Geometry::GlobalCoordinate;
310 this->
initHostGrid_(lowerLeft, upperRight, cells, paramGroup, overlap, periodic);
311 const auto elementSelector = [](
const auto& element){
return true; };
321 void createGridFromImage_(
const Img& img,
const std::string& paramGroup,
const int overlap,
const std::bitset<dim> periodic)
323 using GlobalPosition =
typename ParentType::Grid::template Codim<0>::Geometry::GlobalCoordinate;
327 const std::array<int, dim> imageDimensions{
static_cast<int>(img.header().nCols),
static_cast<int>(img.header().nRows)};
328 std::array<int, dim> cells{imageDimensions[0], imageDimensions[1]};
330 std::array<int, dim> repeatsDefault; repeatsDefault.fill(1);
332 for (
int i = 0; i < dim; i++)
333 cells[i] = cells[i] * numRepeats[i];
336 const auto [lowerLeft, upperRight] = [&]()
342 for (
int i = 0; i < upperRight.size(); ++i)
343 upperRight[i] *= cells[i];
344 upperRight += lowerLeft;
345 return std::make_pair(lowerLeft, upperRight);
352 this->initHostGrid_(lowerLeft, upperRight, cells, paramGroup, overlap, periodic);
359 const auto elementSelector = [&](
const auto&
element)
361 auto eIdx = this->hostGrid_().leafGridView().indexSet().index(element);
367 auto level0Element =
element.father();
368 while (level0Element.hasFather())
369 level0Element = level0Element.father();
371 assert(level0Element.level() == 0);
372 eIdx = this->hostGrid_().levelGridView(0).indexSet().index(level0Element);
374 return img[eIdx] == marked;
378 const auto repeatedElementSelector = [&](
const auto&
element)
380 auto eIdx = this->hostGrid_().leafGridView().indexSet().index(element);
386 auto level0Element =
element.father();
387 while (level0Element.hasFather())
388 level0Element = level0Element.father();
390 assert(level0Element.level() == 0);
391 eIdx = this->hostGrid_().levelGridView(0).indexSet().index(level0Element);
395 const int numCols = imageDimensions[0];
396 const int numRows = imageDimensions[1];
399 const int repeatUnitIndex = eIdx % (numCols * numRepeats[0] * numRows);
400 const int imgI = repeatUnitIndex % numCols;
401 const int imgJ = repeatUnitIndex / (numCols * numRepeats[0]);
402 return img[ (imgJ * numCols + imgI) ] == marked;
408 this->
gridPtr() = std::make_unique<Grid>(this->hostGrid_());
409 this->updateSubGrid_(repeatedElementSelector);
413 this->
gridPtr() = std::make_unique<Grid>(this->hostGrid_());
414 this->updateSubGrid_(elementSelector);
421 void maybePostProcessBinaryMask_(std::vector<char>& mask,
const std::array<int, dim>& cells,
const std::string& paramGroup)
const
427 std::vector<int> marker(mask.size(), 0);
429 if constexpr (dim == 3)
431 if (direction ==
"Y")
433 std::cout <<
"Keeping only cells connected to both boundaries in y-direction" << std::endl;
434 flood_(mask, marker, cells, 0, 0, 0, cells[0], 1, cells[2], 1);
435 flood_(mask, marker, cells, 0, cells[1]-1, 0, cells[0], cells[1], cells[2], 2);
437 else if (direction ==
"Z")
439 std::cout <<
"Keeping only cells connected to both boundaries in z-direction" << std::endl;
440 flood_(mask, marker, cells, 0, 0, 0, cells[0], cells[1], 1, 1);
441 flood_(mask, marker, cells, 0, 0, cells[2]-1, cells[0], cells[1], cells[2], 2);
445 std::cout <<
"Keeping only cells connected to both boundaries in x-direction" << std::endl;
446 flood_(mask, marker, cells, 0, 0, 0, 1, cells[1], cells[2], 1);
447 flood_(mask, marker, cells, cells[0]-1, 0, 0, cells[0], cells[1], cells[2], 2);
450 for (
unsigned int i = 0; i < cells[0]; ++i)
451 for (
unsigned int j = 0; j < cells[1]; ++j)
452 for (
unsigned int k = 0; k < cells[2]; ++k)
453 if (
const auto ijk = getIJK_(i, j, k, cells); marker[ijk] < 2)
457 else if constexpr (dim == 2)
459 if (direction ==
"Y")
461 std::cout <<
"Keeping only cells connected to both boundaries in y-direction" << std::endl;
462 flood_(mask, marker, cells, 0, 0, cells[0], 1, 1);
463 flood_(mask, marker, cells, 0, cells[1]-1, cells[0], cells[1], 2);
467 std::cout <<
"Keeping only cells connected to both boundaries in x-direction" << std::endl;
468 flood_(mask, marker, cells, 0, 0, 1, cells[1], 1);
469 flood_(mask, marker, cells, cells[0]-1, 0, cells[0], cells[1], 2);
472 for (
unsigned int i = 0; i < cells[0]; ++i)
473 for (
unsigned int j = 0; j < cells[1]; ++j)
474 if (
const auto ij = getIJ_(i, j, cells); marker[ij] < 2)
478 DUNE_THROW(Dune::NotImplemented,
"KeepOnlyConnected only implemented for 2D and 3D");
482 void flood_(std::vector<char>& mask, std::vector<int>& markers,
const std::array<int, 3>& cells,
483 unsigned int iMin,
unsigned int jMin,
unsigned int kMin,
484 unsigned int iMax,
unsigned int jMax,
unsigned int kMax,
488 for (
unsigned int i = iMin; i < iMax; ++i)
489 for (
unsigned int j = jMin; j < jMax; ++j)
490 for (
unsigned int k = kMin; k < kMax; ++k)
491 fill_(mask, markers, cells, i, j, k, marker);
494 void flood_(std::vector<char>& mask, std::vector<int>& markers,
const std::array<int, 2>& cells,
495 unsigned int iMin,
unsigned int jMin,
496 unsigned int iMax,
unsigned int jMax,
500 for (
unsigned int i = iMin; i < iMax; ++i)
501 for (
unsigned int j = jMin; j < jMax; ++j)
502 fill_(mask, markers, cells, i, j, marker);
505 void fill_(std::vector<char>& mask, std::vector<int>& markers,
const std::array<int, 3>& cells,
506 unsigned int i,
unsigned int j,
unsigned int k,
int marker)
const
508 std::stack<std::tuple<unsigned int, unsigned int, unsigned int>> st;
509 st.push(std::make_tuple(i, j, k));
512 std::tie(i, j, k) = st.top();
515 if (i >= cells[0] || j >= cells[1] || k >= cells[2])
518 const auto ijk = getIJK_(i, j, k, cells);
519 if (!mask[ijk] || markers[ijk] >= marker)
525 st.push(std::make_tuple(i+1, j, k));
526 st.push(std::make_tuple(i-1, j, k));
527 st.push(std::make_tuple(i, j+1, k));
528 st.push(std::make_tuple(i, j-1, k));
529 st.push(std::make_tuple(i, j, k+1));
530 st.push(std::make_tuple(i, j, k-1));
534 void fill_(std::vector<char>& mask, std::vector<int>& markers,
const std::array<int, 2>& cells,
535 unsigned int i,
unsigned int j,
int marker)
const
537 std::stack<std::tuple<unsigned int, unsigned int>> st;
538 st.push(std::make_tuple(i, j));
541 std::tie(i, j) = st.top();
544 if (i >= cells[0] || j >= cells[1])
547 const auto ij = getIJ_(i, j, cells);
548 if (!mask[ij] || markers[ij] >= marker)
554 st.push(std::make_tuple(i+1, j));
555 st.push(std::make_tuple(i-1, j));
556 st.push(std::make_tuple(i, j+1));
557 st.push(std::make_tuple(i, j-1));
561 int getIJK_(
int i,
int j,
int k,
const std::array<int, 3>& cells)
const
562 {
return i + j*cells[0] + k*cells[0]*cells[1]; }
564 int getIJ_(
int i,
int j,
const std::array<int, 2>& cells)
const
565 {
return i + j*cells[0]; }