summaryrefslogtreecommitdiff
path: root/tangle/LLBM/sdf_boundary.h
blob: f91480ef106e2f41c2360dd4dfdebcffc5dc9fea (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
109
110
111
112
113
114
#pragma once
#include <LLBM/memory.h>
#include <LLBM/materials.h>
#include <LLBM/kernel/bouzidi.h>
#include <iostream>

template <typename DESCRIPTOR, typename T, typename S, typename SDF>
class SignedDistanceBoundary {
private:
const descriptor::Cuboid<DESCRIPTOR> _cuboid;
const std::size_t _count;

SharedVector<std::size_t> _boundary;
SharedVector<std::size_t> _fluid;
SharedVector<std::size_t> _solid;
SharedVector<S> _distance;
SharedVector<S> _correction;
SharedVector<S> _factor;
SharedVector<pop_index_t> _missing;

void set(std::size_t index, std::size_t iCell, pop_index_t iPop, S dist) {
  pop_index_t jPop = descriptor::opposite<DESCRIPTOR>(iPop);
  const std::size_t jPopCell = descriptor::neighbor<DESCRIPTOR>(_cuboid, iCell, jPop);
  const std::size_t iPopCell = descriptor::neighbor<DESCRIPTOR>(_cuboid, iCell, iPop);

  _boundary[index] = iCell;
  _solid[index] = jPopCell;
  _distance[index] = dist;
  _correction[index] = 0;
  _missing[index] = iPop;

  T q = dist / descriptor::velocity_length<DESCRIPTOR>(iPop);
  if (q > 0.5) {
    _fluid[index] = iCell;
    _factor[index] = 1 / (2*q);
  } else {
    _fluid[index] = iPopCell;
    _factor[index] = 2*q;
  }
}

void syncDeviceFromHost() {
  _boundary.syncDeviceFromHost();
  _fluid.syncDeviceFromHost();
  _solid.syncDeviceFromHost();
  _distance.syncDeviceFromHost();
  _correction.syncDeviceFromHost();
  _factor.syncDeviceFromHost();
  _missing.syncDeviceFromHost();
}

public:
SignedDistanceBoundary(Lattice<DESCRIPTOR,T,S>&, CellMaterials<DESCRIPTOR>& materials, SDF geometry, int bulk, int solid):
  _cuboid(materials.cuboid()),
  _count(materials.get_link_count(bulk, solid)),
  _boundary(_count),
  _fluid(_count),
  _solid(_count),
  _distance(_count),
  _correction(_count),
  _factor(_count),
  _missing(_count)
{
  std::size_t index = 0;
  materials.for_links(bulk, solid, [&](std::size_t iCell, pop_index_t iPop) {
    auto p         = gidInverseSmooth(_cuboid, iCell);
    auto direction = normalize(descriptor::velocity<DESCRIPTOR>(iPop));
    float length   = descriptor::velocity_length<DESCRIPTOR>(iPop);
    float distance = approximateDistance(geometry, p, direction, 0, length);
    if (distance == 0.f || distance > length) {
      std::cout << "Bogus distance d=" << distance << " at cell " << iCell
                << " in direction " << std::to_string(iPop) << std::endl;
    }
    set(index++, iCell, descriptor::opposite<DESCRIPTOR>(iPop), distance);
  });
  syncDeviceFromHost();
}

template <typename VELOCITY>
void setVelocity(VELOCITY field) {
  for (std::size_t index=0; index < _count; ++index) {
    pop_index_t jPop = descriptor::opposite<DESCRIPTOR>(_missing[index]);
    auto direction = normalize(descriptor::velocity<DESCRIPTOR>(jPop));
    float length = descriptor::velocity_length<DESCRIPTOR>(jPop);
    auto p = descriptor::gidInverseSmooth(_cuboid, _boundary[index]);
    auto u_w = field(p + _distance[index] * direction);
    _correction[index] = 2*3*descriptor::weight<DESCRIPTOR>(jPop)
                       * dot(u_w, descriptor::velocity<DESCRIPTOR>(jPop));
    if (_distance[index] / length > 0.5) {
      _correction[index] *= _factor[index];
    }
  }
  _correction.syncDeviceFromHost();
}

std::size_t getCount() const {
  return _count;
}

BouzidiConfig<S> getConfig() {
  return BouzidiConfig<S>{
    _boundary.device(),
    _solid.device(),
    _fluid.device(),
    _factor.device(),
    _correction.device(),
    _missing.device()
  };
}

};

template <typename DESCRIPTOR, typename T, typename S, typename SDF>
SignedDistanceBoundary(Lattice<DESCRIPTOR,T,S>&, CellMaterials<DESCRIPTOR>&, SDF, int, int) -> SignedDistanceBoundary<DESCRIPTOR,T,S,SDF>;