preCICE v3.1.2
Loading...
Searching...
No Matches
BarycenterTest.cpp
Go to the documentation of this file.
1#include <Eigen/Core>
2#include <boost/mpl/vector.hpp>
3#include <ostream>
4#include "math/barycenter.hpp"
5#include "math/constants.hpp"
8#include "testing/Testing.hpp"
9
10using namespace precice;
11using namespace precice::math::barycenter;
12
13BOOST_AUTO_TEST_SUITE(MathTests)
14BOOST_AUTO_TEST_SUITE(BarycenterEdge)
15
16BOOST_AUTO_TEST_CASE(BarycenterEdge2D)
17{
18 PRECICE_TEST(1_rank);
19 using Eigen::Vector2d;
20 using Eigen::Vector3d;
22 Vector2d a(0.0, 0.0);
23 Vector2d b(1.0, 0.0);
24 Vector2d n(0.0, 1.0);
25 {
26 Vector2d l(0.5, 0.0);
27 Vector2d coords(0.5, 0.5);
29 a, b, l);
30 BOOST_TEST(ret.sum() == 1.0);
31 BOOST_TEST(equals(ret, coords));
32 }
33 {
34 Vector2d l(0.0, 0.0);
35 Vector2d coords(1.0, 0.0);
37 a, b, l);
38 BOOST_TEST(ret.sum() == 1.0);
39 BOOST_TEST(equals(ret, coords));
40 }
41 {
42 Vector2d l(1.0, 0.0);
43 Vector2d coords(0, 1.0);
45 a, b, l);
46 BOOST_TEST(ret.sum() == 1.0);
47 BOOST_TEST(equals(ret, coords));
48 }
49 {
50 Vector2d l(0.75, 1.0);
51 Vector2d coords(0.25, 0.75);
52 auto ret = calcBarycentricCoordsForEdge(a, b, l);
53 BOOST_TEST(ret.sum() == 1.0);
54 BOOST_TEST(equals(ret, coords), "Coords are " << ret << " but should be " << coords);
55 }
56}
57
58BOOST_AUTO_TEST_CASE(BarycenterEdge3D)
59{
60 PRECICE_TEST(1_rank);
61 using Eigen::Vector2d;
62 using Eigen::Vector3d;
64 Vector3d a(0.0, 0.0, 0.0);
65 Vector3d b(1.0, 0.0, 0.0);
66 Vector3d n(0.0, 0.0, 1.0);
67 {
68 Vector3d l(0.5, 0.0, 0.0);
69 Vector2d coords(0.5, 0.5);
71 a, b, l);
72 BOOST_TEST(ret.sum() == 1.0);
73 BOOST_TEST(equals(ret, coords));
74 }
75 {
76 Vector3d l(0.0, 0.0, 0.0);
77 Vector2d coords(1.0, 0.0);
79 a, b, l);
80 BOOST_TEST(ret.sum() == 1.0);
81 BOOST_TEST(equals(ret, coords));
82 }
83 {
84 Vector3d l(1.0, 0.0, 0.0);
85 Vector2d coords(0, 1.0);
87 a, b, l);
88 BOOST_TEST(ret.sum() == 1.0);
89 BOOST_TEST(equals(ret, coords));
90 }
91 {
92 Vector3d l(0.75, 1.0, 0.0);
93 Vector2d coords(0.25, 0.75);
94 auto ret = calcBarycentricCoordsForEdge(a, b, l);
95 BOOST_TEST(ret.sum() == 1.0);
96 BOOST_TEST(equals(ret, coords), fmt::format("Coords are {} but should be {}", ret, coords));
97 }
98}
99
100BOOST_AUTO_TEST_SUITE_END() // BarycenterEdges
101
102BOOST_AUTO_TEST_SUITE(BarycenterTriangle)
103
104BOOST_AUTO_TEST_CASE(BarycenterTriangle3D)
105{
106 PRECICE_TEST(1_rank);
107 using Eigen::Vector3d;
109 Vector3d a(0.0, 0.0, 0.0);
110 Vector3d b(0.0, 1.0, 0.0);
111 Vector3d c(1.0, 0.0, 0.0);
112 Vector3d n(0.0, 0.0, 1.0);
113 // is a?
114 {
115 Vector3d coords(1.0, 0.0, 0.0);
116 auto ret = calcBarycentricCoordsForTriangle(a, b, c, a);
117 BOOST_TEST(ret.sum() == 1.0);
118 BOOST_TEST(equals(ret, coords));
119 }
120 // is b?
121 {
122 Vector3d coords(0.0, 1.0, 0.0);
123 auto ret = calcBarycentricCoordsForTriangle(a, b, c, b);
124 BOOST_TEST(ret.sum() == 1.0);
125 BOOST_TEST(equals(ret, coords));
126 }
127 // is c?
128 {
129 Vector3d coords(0.0, 0.0, 1.0);
130 auto ret = calcBarycentricCoordsForTriangle(a, b, c, c);
131 BOOST_TEST(ret.sum() == 1.0);
132 BOOST_TEST(equals(ret, coords));
133 }
134 // is in the middle
135 {
136 Vector3d l = (a + b + c) / 3;
137 Vector3d coords(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0);
138 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
139 BOOST_TEST(ret.sum() == 1.0);
140 BOOST_TEST(equals(ret, coords));
141 }
142 // is in the middle of ab
143 {
144 Vector3d l = (a + b) / 2;
145 Vector3d coords(0.5, 0.5, 0.0);
146 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
147 BOOST_TEST(ret.sum() == 1.0);
148 BOOST_TEST(equals(ret, coords));
149 }
150 // is in the middle of bc
151 {
152 Vector3d l = (b + c) / 2;
153 Vector3d coords(0.0, 0.5, 0.5);
154 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
155 BOOST_TEST(ret.sum() == 1.0);
156 BOOST_TEST(equals(ret, coords));
157 }
158 // is in the middle of ca
159 {
160 Vector3d l = (a + c) / 2;
161 Vector3d coords(0.5, 0.0, 0.5);
162 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
163 BOOST_TEST(ret.sum() == 1.0);
164 BOOST_TEST(equals(ret, coords));
165 }
166 // is outside
167 {
168 Vector3d l(2.0, 0.0, 0.0);
169 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
170 BOOST_TEST((ret.array() < -precice::math::NUMERICAL_ZERO_DIFFERENCE).any(), fmt::format("Min 1 coord should be negative {}", ret));
171 }
172}
173
174BOOST_AUTO_TEST_CASE(BarycenterTriangle2D)
175{
176 PRECICE_TEST(1_rank);
177 using Eigen::Vector2d;
178 using Eigen::Vector3d;
180 Vector2d a(0.0, 0.0);
181 Vector2d b(0.0, 1.0);
182 Vector2d c(1.0, 0.0);
183 Vector2d n(0.0, 0.0);
184 // is a?
185 {
186 Vector3d coords(1.0, 0.0, 0.0);
187 auto ret = calcBarycentricCoordsForTriangle(a, b, c, a);
188 BOOST_TEST(ret.sum() == 1.0);
189 BOOST_TEST(equals(ret, coords));
190 }
191 // is b?
192 {
193 Vector3d coords(0.0, 1.0, 0.0);
194 auto ret = calcBarycentricCoordsForTriangle(a, b, c, b);
195 BOOST_TEST(ret.sum() == 1.0);
196 BOOST_TEST(equals(ret, coords));
197 }
198 // is c?
199 {
200 Vector3d coords(0.0, 0.0, 1.0);
201 auto ret = calcBarycentricCoordsForTriangle(a, b, c, c);
202 BOOST_TEST(ret.sum() == 1.0);
203 BOOST_TEST(equals(ret, coords));
204 }
205 // is in the middle
206 {
207 Vector2d l = (a + b + c) / 3;
208 Vector3d coords(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0);
209 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
210 BOOST_TEST(ret.sum() == 1.0);
211 BOOST_TEST(equals(ret, coords));
212 }
213 // is in the middle of ab
214 {
215 Vector2d l = (a + b) / 2;
216 Vector3d coords(0.5, 0.5, 0.0);
217 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
218 BOOST_TEST(ret.sum() == 1.0);
219 BOOST_TEST(equals(ret, coords));
220 }
221 // is in the middle of bc
222 {
223 Vector2d l = (b + c) / 2;
224 Vector3d coords(0.0, 0.5, 0.5);
225 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
226 BOOST_TEST(ret.sum() == 1.0);
227 BOOST_TEST(equals(ret, coords));
228 }
229 // is in the middle of ca
230 {
231 Vector2d l = (a + c) / 2;
232 Vector3d coords(0.5, 0.0, 0.5);
233 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
234 BOOST_TEST(ret.sum() == 1.0);
235 BOOST_TEST(equals(ret, coords));
236 }
237 // is outside
238 {
239 Vector2d l(2.0, 0.0);
240 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
241 BOOST_TEST((ret.array() < -precice::math::NUMERICAL_ZERO_DIFFERENCE).any(), fmt::format("Min 1 coord should be negative {}", ret));
242 }
243}
244
245BOOST_AUTO_TEST_SUITE_END() // BarycenterTriangles
246
247BOOST_AUTO_TEST_SUITE(BarycenterTetrahedra)
248
250 Eigen::Vector3d a{0.0, 0.0, 0.0};
251 Eigen::Vector3d b{0.0, 1.0, 0.0};
252 Eigen::Vector3d c{1.0, 0.0, 0.0};
253 Eigen::Vector3d d{0.0, 0.0, 1.0};
254
255 Eigen::Vector3d center{0.25, 0.25, 0.25};
256};
257
259 Eigen::Vector3d a{0.0, 0.0, 0.0};
260 Eigen::Vector3d b{0.0, 1.0, 0.0};
261 Eigen::Vector3d c{1.0, 0.0, 0.0};
262 Eigen::Vector3d d{0.0, 0.0, -1.0};
263
264 Eigen::Vector3d center{0.25, 0.25, -0.25};
265};
266
268 Eigen::Vector3d a{0.0, 0.0, 0.0};
269 Eigen::Vector3d b{0.0, 1.0, 0.0};
270 Eigen::Vector3d c{1.0, 0.0, 0.0};
271 Eigen::Vector3d d{0.0, 0.0, 0.001};
272
273 Eigen::Vector3d center{0.25, 0.25, 0.00025};
274};
275
277 Eigen::Vector3d a{0.0, 0.0, 0.0};
278 Eigen::Vector3d b{0.0, 1.0, 0.0};
279 Eigen::Vector3d c{1.0, 0.0, 0.0};
280 Eigen::Vector3d d{11.0, 11.0, 1.0};
281
282 Eigen::Vector3d center{3.0, 3.0, 0.25};
283};
284
285typedef boost::mpl::vector<TetrahedronFixture, FlippedTetrahedronFixture, AlmostDegenerateTetrahedronFixture, FunnyTetrahedronFixture> TetrahedraFixtures;
286
287BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnA, T, TetrahedraFixtures, T)
288{
289 PRECICE_TEST(1_rank);
290
291 Eigen::Vector4d coords(1.0, 0.0, 0.0, 0.0);
292 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::a);
293 BOOST_TEST(precice::testing::equals(ret, coords));
294}
295
296BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnB, T, TetrahedraFixtures, T)
297{
298 PRECICE_TEST(1_rank);
299
300 Eigen::Vector4d coords(0.0, 1.0, 0.0, 0.0);
301 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::b);
302 BOOST_TEST(precice::testing::equals(ret, coords));
303}
304
305BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnC, T, TetrahedraFixtures, T)
306{
307 PRECICE_TEST(1_rank);
308
309 Eigen::Vector4d coords(0.0, 0.0, 1.0, 0.0);
310 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::c);
311 BOOST_TEST(precice::testing::equals(ret, coords));
312}
313
314BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnD, T, TetrahedraFixtures, T)
315{
316 PRECICE_TEST(1_rank);
317
318 Eigen::Vector4d coords(0.0, 0.0, 0.0, 1.0);
319 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::d);
320 BOOST_TEST(precice::testing::equals(ret, coords));
321}
322
323BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnCenter, T, TetrahedraFixtures, T)
324{
325 PRECICE_TEST(1_rank);
326
327 Eigen::Vector4d center_coords{0.25, 0.25, 0.25, 0.25};
328 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::center);
329 BOOST_TEST(precice::testing::equals(ret, center_coords));
330}
331
332BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronInsidePoint, T, TetrahedraFixtures, T)
333{
334 PRECICE_TEST(1_rank);
335
336 Eigen::Vector4d coords(0.2, 0.3, 0.4, 0.1);
337 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, 0.2 * T::a + 0.3 * T::b + 0.4 * T::c + 0.1 * T::d);
338 BOOST_TEST(ret.sum() == 1.0);
339 BOOST_TEST(precice::testing::equals(ret, coords));
340}
341
342BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronEdgeCenter, T, TetrahedraFixtures, T)
343{
344 PRECICE_TEST(1_rank);
345 using Eigen::Vector4d;
346
347 Eigen::Vector4d coords(0.5, 0.5, 0.0, 0.0);
348 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, 0.5 * T::a + 0.5 * T::b);
349 BOOST_TEST(ret.sum() == 1.0);
350 BOOST_TEST(precice::testing::equals(ret, coords));
351}
352
353BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronTriangleCenter, T, TetrahedraFixtures, T)
354{
355 PRECICE_TEST(1_rank);
356 using Eigen::Vector4d;
357
358 Eigen::Vector4d coords(1. / 3, 1. / 3, 0.0, 1. / 3);
359 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, (T::a + T::b + T::d) / 3);
360 BOOST_TEST(ret.sum() == 1.0);
361 BOOST_TEST(precice::testing::equals(ret, coords));
362}
363
364BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExtrapolationOnEdge, T, TetrahedraFixtures, T)
365{
366 PRECICE_TEST(1_rank);
367
368 Eigen::Vector4d coords(-2.0, 3.0, 0, 0);
369 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::a + 3 * (T::b - T::a));
370 BOOST_TEST(ret.sum() == 1.0);
371 BOOST_TEST(precice::testing::equals(ret, coords));
372}
373
374BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExtrapolationOnMirrored, T, TetrahedraFixtures, T)
375{
376 PRECICE_TEST(1_rank);
377
378 Eigen::Vector4d coords(2.0, 0.0, 0.0, -1.0);
379 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, 2 * T::a - T::d);
380 BOOST_TEST(ret.sum() == 1.0);
381 BOOST_TEST(precice::testing::equals(ret, coords));
382}
383
384BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExtrapolationOnMirroredFromTriangle, T, TetrahedraFixtures, T)
385{
386 PRECICE_TEST(1_rank);
387
388 Eigen::Vector4d coords(1.0, 1.0, 1.0, -2.0);
389 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, (T::a + T::b + T::c) - 2 * T::d);
390 BOOST_TEST(ret.sum() == 1.0);
391 BOOST_TEST(precice::testing::equals(ret, coords));
392}
393
394BOOST_AUTO_TEST_SUITE_END() // BarycenterTetrahedra
395
boost::mpl::vector< TetrahedronFixture, FlippedTetrahedronFixture, AlmostDegenerateTetrahedronFixture, FunnyTetrahedronFixture > TetrahedraFixtures
BOOST_AUTO_TEST_CASE(BarycenterEdge2D)
BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnA, T, TetrahedraFixtures, T)
BOOST_AUTO_TEST_SUITE(PreProcess)
BOOST_AUTO_TEST_SUITE_END()
#define PRECICE_TEST(...)
Definition Testing.hpp:27
Provides operations to calculate barycentric coordinates for a point's projection onto a primitive.
Definition barycenter.cpp:9
Eigen::Vector3d calcBarycentricCoordsForTriangle(const Eigen::VectorXd &a, const Eigen::VectorXd &b, const Eigen::VectorXd &c, const Eigen::VectorXd &u)
Eigen::Vector4d calcBarycentricCoordsForTetrahedron(const Eigen::VectorXd &a, const Eigen::VectorXd &b, const Eigen::VectorXd &c, const Eigen::VectorXd &d, const Eigen::VectorXd &u)
Eigen::Vector2d calcBarycentricCoordsForEdge(const Eigen::VectorXd &a, const Eigen::VectorXd &b, const Eigen::VectorXd &u)
constexpr double NUMERICAL_ZERO_DIFFERENCE
boost::test_tools::predicate_result equals(const std::vector< float > &VectorA, const std::vector< float > &VectorB, float tolerance)
equals to be used in tests. Compares two std::vectors using a given tolerance. Prints both operands o...
Definition Testing.cpp:65
Main namespace of the precice library.