#pragma once #include "memory.h" #include "sdf.h" template class CellMaterials : public SharedVector { private: const descriptor::Cuboid _cuboid; int* const _materials; public: CellMaterials(descriptor::Cuboid cuboid): SharedVector(cuboid.volume), _cuboid(cuboid), _materials(this->host()) { } template CellMaterials(descriptor::Cuboid cuboid, F f): CellMaterials(cuboid) { set(f); } descriptor::Cuboid cuboid() const { return _cuboid; }; int get(std::size_t iCell) const { return _materials[iCell]; } void set(std::size_t iCell, int material) { _materials[iCell] = material; } template void set(F f) { for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { set(iCell, f(gidInverse(_cuboid, iCell))); } } template void sdf(S distance, int material, float eps=1e-2) { for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { auto p = gidInverseSmooth(_cuboid, iCell); if (distance(p) < eps) { set(iCell, material); } } } void clean(int material) { for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { if (get(iCell) == material) { if (_cuboid.isInside(iCell)) { bool surrounded = true; for (unsigned iPop=0; iPop < DESCRIPTOR::q; ++iPop) { int m = get(descriptor::neighbor(_cuboid, iCell, iPop)); surrounded &= m == material || m == 0; } if (surrounded) { set(iCell, 0); } } } } } DeviceBuffer list_of_material(int material) { std::vector cells; for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { if (_materials[iCell] == material) { cells.emplace_back(iCell); } } return DeviceBuffer(cells); } DeviceBuffer mask_of_material(int material) { std::unique_ptr mask(new bool[_cuboid.volume]{}); for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { mask[iCell] = (_materials[iCell] == material); } return DeviceBuffer(mask.get(), _cuboid.volume); } std::size_t get_link_count(int bulk, int solid) { std::size_t count = 0; for (pop_index_t iPop=0; iPop < DESCRIPTOR::q; ++iPop) { for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { std::size_t jCell = descriptor::neighbor(_cuboid, iCell, iPop); if (get(iCell) == bulk && get(jCell) == solid) { count++; } } } return count; } template void for_links(int bulk, int solid, F f) { for (pop_index_t iPop=0; iPop < DESCRIPTOR::q; ++iPop) { for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) { std::size_t jCell = descriptor::neighbor(_cuboid, iCell, iPop); if (get(iCell) == bulk && get(jCell) == solid) { f(iCell, iPop); } } } } };