1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#pragma once
#include "memory.h"
#include "sdf.h"
template <typename DESCRIPTOR>
class CellMaterials : public SharedVector<int> {
private:
const descriptor::Cuboid<DESCRIPTOR> _cuboid;
int* const _materials;
public:
CellMaterials(descriptor::Cuboid<DESCRIPTOR> cuboid):
SharedVector<int>(cuboid.volume),
_cuboid(cuboid),
_materials(this->host()) { }
template <typename F>
CellMaterials(descriptor::Cuboid<DESCRIPTOR> cuboid, F f):
CellMaterials(cuboid) {
set(f);
}
descriptor::Cuboid<DESCRIPTOR> 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 <typename F>
void set(F f) {
for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) {
set(iCell, f(gidInverse(_cuboid, iCell)));
}
}
template <typename S>
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<DESCRIPTOR>(_cuboid, iCell, iPop));
surrounded &= m == material || m == 0;
}
if (surrounded) {
set(iCell, 0);
}
}
}
}
}
DeviceBuffer<std::size_t> list_of_material(int material) {
std::vector<std::size_t> cells;
for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) {
if (_materials[iCell] == material) {
cells.emplace_back(iCell);
}
}
return DeviceBuffer<std::size_t>(cells);
}
DeviceBuffer<bool> mask_of_material(int material) {
std::unique_ptr<bool[]> mask(new bool[_cuboid.volume]{});
for (std::size_t iCell=0; iCell < _cuboid.volume; ++iCell) {
mask[iCell] = (_materials[iCell] == material);
}
return DeviceBuffer<bool>(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<DESCRIPTOR>(_cuboid, iCell, iPop);
if (get(iCell) == bulk && get(jCell) == solid) {
count++;
}
}
}
return count;
}
template <typename F>
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<DESCRIPTOR>(_cuboid, iCell, iPop);
if (get(iCell) == bulk && get(jCell) == solid) {
f(iCell, iPop);
}
}
}
}
};
|