summaryrefslogtreecommitdiff
path: root/tangle/LLBM/materials.h
blob: 57346888928557a133f5b6e30106e495a47ee07a (plain)
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);
        }
      }
    }
  }
};