Virtual Testbed
Ship dynamics simulator for extreme conditions
flooding_solver.cc
1 #include <bitset>
2 
3 #include <vtestbed/config/real_type.hh>
4 #include <vtestbed/core/bisection.hh>
5 #include <vtestbed/core/flooding_solver.hh>
6 #include <vtestbed/geometry/line_segment.hh>
7 #include <vtestbed/geometry/polyhedron.hh>
8 #include <vtestbed/geometry/tetrahedron.hh>
9 
10 template <class T>
12 _polyhedron(polyhedron) {
13  this->_z_bounds = this->_polyhedron.bounds(2);
14 }
15 
16 template <class T>
17 void
19  this->_volume = rhs;
20  this->_level = calc_level();
21  const auto& result = calc_volume(level());
22  this->_volume = result.volume();
23  this->_centre = result.point();
24 }
25 
26 template <class T>
27 void
29  this->_level = rhs;
30  const auto& result = calc_volume(level());
31  this->_volume = result.volume();
32  this->_centre = result.point();
33 }
34 
35 template <class T>
36 auto
38  Bisection<T,1> bisection;
39  // fluid level precision (1 cm)
40  bisection.argument_precision(T{1e-2});
41  // fluid volume precision (1 cm^3)
42  bisection.function_precision(T{1e-6});
43  bisection.max_iterations(20);
44  return bisection(
45  z_bounds().min(), z_bounds().max(),
46  [this] (T level) { return calc_volume(level).volume() - this->_volume; }
47  );
48 }
49 
50 template <class T>
51 auto
52 vtb::core::Flooding_solver<T>::calc_volume(T level) -> Volume<T> {
53  Volume<T> volume;
54  if (level <= z_bounds().min()) { return volume; }
55  if (level > z_bounds().max()) { level = z_bounds().max(); }
59  using vec3 = Vector<T,3>;
60  using line_segment = vtb::geometry::Line_segment<T,3>;
61  using vtb::geometry::intersection_point;
62  const auto& vertices = polyhedron().vertices();
63  const auto& faces = polyhedron().faces();
64  vec3 origin(0,0,level);
65  #if defined(DEBUG_VOLUME)
66  std::ofstream("origin.tmp") << origin;
67  std::ofstream intersectionPoints("intersection.tmp");
68  std::ofstream belowPoints("below.tmp");
69  std::ofstream borderPoints("border.tmp");
70  #endif
71  for (const auto& p : faces) {
74  vec3 v[3] = {vertices[p[0]], vertices[p[1]], vertices[p[2]]};
75  std::bitset<3> above;
76  above[0] = v[0](2) > level;
77  above[1] = v[1](2) > level;
78  above[2] = v[2](2) > level;
79  if (above.none()) {
80  // All three vertices are under water.
81  Tetrahedron<T,3> t(origin, v[0], v[1], v[2]);
82  volume.accumulate(signed_volume(t), centroid(t));
83  #if defined(DEBUG_VOLUME)
84  belowPoints << t;
85  #endif
86  } else if (above.count() < 3) {
87  // One or two vertices are under water.
88  int outstanding = 0;
89  int i1 = 0;
90  int i2 = 0;
91  const bool x01 = above[0] ^ above[1];
92  const bool x02 = above[0] ^ above[2];
93  const bool x12 = above[1] ^ above[2];
94  if (x01 && x02) { outstanding = 0, i1 = 1, i2 = 2; }
95  else if (x01 && x12) { outstanding = 1, i1 = 2, i2 = 0; }
96  else { outstanding = 2, i1 = 0, i2 = 1; }
97  const vec3 outstandingVertex = v[outstanding];
98  vec3 v_new[3];
99  v_new[outstanding] = outstandingVertex;
100  v_new[i1] = intersection_point<2>(line_segment{outstandingVertex, v[i1]}, level);
101  v_new[i2] = intersection_point<2>(line_segment{outstandingVertex, v[i2]}, level);
102  #if defined(DEBUG_VOLUME)
103  intersectionPoints << v_new[i1] << '\n';
104  intersectionPoints << v_new[i2] << '\n';
105  #endif
106  // Correct vertices order in tetrahedron constructor is needed
107  // for correct volume sign.
108  if (outstandingVertex(2) > level) {
109  Tetrahedron<T,3> t1(origin, v_new[i1], v[i1], v[i2]);
110  volume.accumulate(signed_volume(t1), centroid(t1));
111  #if defined(DEBUG_VOLUME)
112  borderPoints << t1;
113  #endif
114  Tetrahedron<T,3> t2(origin, v_new[i1], v[i2], v_new[i2]);
115  volume.accumulate(signed_volume(t2), centroid(t2));
116  #if defined(DEBUG_VOLUME)
117  borderPoints << t2;
118  #endif
119  } else {
120  Tetrahedron<T,3> t(origin, outstandingVertex, v_new[i1], v_new[i2]);
121  volume.accumulate(signed_volume(t), centroid(t));
122  #if defined(DEBUG_VOLUME)
123  borderPoints << t;
124  #endif
125  }
126  }
127  }
128  volume.normalise();
129  return volume;
130 }
131 
T min(T... args)
T max(T... args)