preCICE v3.2.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
17BOOST_AUTO_TEST_CASE(BarycenterEdge2D)
18{
20 using Eigen::Vector2d;
21 using Eigen::Vector3d;
23 Vector2d a(0.0, 0.0);
24 Vector2d b(1.0, 0.0);
25 Vector2d n(0.0, 1.0);
26 {
27 Vector2d l(0.5, 0.0);
28 Vector2d coords(0.5, 0.5);
30 a, b, l);
31 BOOST_TEST(ret.sum() == 1.0);
32 BOOST_TEST(equals(ret, coords));
33 }
34 {
35 Vector2d l(0.0, 0.0);
36 Vector2d coords(1.0, 0.0);
38 a, b, l);
39 BOOST_TEST(ret.sum() == 1.0);
40 BOOST_TEST(equals(ret, coords));
41 }
42 {
43 Vector2d l(1.0, 0.0);
44 Vector2d coords(0, 1.0);
46 a, b, l);
47 BOOST_TEST(ret.sum() == 1.0);
48 BOOST_TEST(equals(ret, coords));
49 }
50 {
51 Vector2d l(0.75, 1.0);
52 Vector2d coords(0.25, 0.75);
53 auto ret = calcBarycentricCoordsForEdge(a, b, l);
54 BOOST_TEST(ret.sum() == 1.0);
55 BOOST_TEST(equals(ret, coords), "Coords are " << ret << " but should be " << coords);
56 }
57}
58
60BOOST_AUTO_TEST_CASE(BarycenterEdge3D)
61{
63 using Eigen::Vector2d;
64 using Eigen::Vector3d;
66 Vector3d a(0.0, 0.0, 0.0);
67 Vector3d b(1.0, 0.0, 0.0);
68 Vector3d n(0.0, 0.0, 1.0);
69 {
70 Vector3d l(0.5, 0.0, 0.0);
71 Vector2d coords(0.5, 0.5);
73 a, b, l);
74 BOOST_TEST(ret.sum() == 1.0);
75 BOOST_TEST(equals(ret, coords));
76 }
77 {
78 Vector3d l(0.0, 0.0, 0.0);
79 Vector2d coords(1.0, 0.0);
81 a, b, l);
82 BOOST_TEST(ret.sum() == 1.0);
83 BOOST_TEST(equals(ret, coords));
84 }
85 {
86 Vector3d l(1.0, 0.0, 0.0);
87 Vector2d coords(0, 1.0);
89 a, b, l);
90 BOOST_TEST(ret.sum() == 1.0);
91 BOOST_TEST(equals(ret, coords));
92 }
93 {
94 Vector3d l(0.75, 1.0, 0.0);
95 Vector2d coords(0.25, 0.75);
96 auto ret = calcBarycentricCoordsForEdge(a, b, l);
97 BOOST_TEST(ret.sum() == 1.0);
98 BOOST_TEST(equals(ret, coords), fmt::format("Coords are {} but should be {}", ret, coords));
99 }
100}
101
102BOOST_AUTO_TEST_SUITE_END() // BarycenterEdges
103
104BOOST_AUTO_TEST_SUITE(BarycenterTriangle)
105
106PRECICE_TEST_SETUP(1_rank)
107BOOST_AUTO_TEST_CASE(BarycenterTriangle3D)
108{
109 PRECICE_TEST();
110 using Eigen::Vector3d;
112 Vector3d a(0.0, 0.0, 0.0);
113 Vector3d b(0.0, 1.0, 0.0);
114 Vector3d c(1.0, 0.0, 0.0);
115 Vector3d n(0.0, 0.0, 1.0);
116 // is a?
117 {
118 Vector3d coords(1.0, 0.0, 0.0);
119 auto ret = calcBarycentricCoordsForTriangle(a, b, c, a);
120 BOOST_TEST(ret.sum() == 1.0);
121 BOOST_TEST(equals(ret, coords));
122 }
123 // is b?
124 {
125 Vector3d coords(0.0, 1.0, 0.0);
126 auto ret = calcBarycentricCoordsForTriangle(a, b, c, b);
127 BOOST_TEST(ret.sum() == 1.0);
128 BOOST_TEST(equals(ret, coords));
129 }
130 // is c?
131 {
132 Vector3d coords(0.0, 0.0, 1.0);
133 auto ret = calcBarycentricCoordsForTriangle(a, b, c, c);
134 BOOST_TEST(ret.sum() == 1.0);
135 BOOST_TEST(equals(ret, coords));
136 }
137 // is in the middle
138 {
139 Vector3d l = (a + b + c) / 3;
140 Vector3d coords(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0);
141 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
142 BOOST_TEST(ret.sum() == 1.0);
143 BOOST_TEST(equals(ret, coords));
144 }
145 // is in the middle of ab
146 {
147 Vector3d l = (a + b) / 2;
148 Vector3d coords(0.5, 0.5, 0.0);
149 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
150 BOOST_TEST(ret.sum() == 1.0);
151 BOOST_TEST(equals(ret, coords));
152 }
153 // is in the middle of bc
154 {
155 Vector3d l = (b + c) / 2;
156 Vector3d coords(0.0, 0.5, 0.5);
157 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
158 BOOST_TEST(ret.sum() == 1.0);
159 BOOST_TEST(equals(ret, coords));
160 }
161 // is in the middle of ca
162 {
163 Vector3d l = (a + c) / 2;
164 Vector3d coords(0.5, 0.0, 0.5);
165 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
166 BOOST_TEST(ret.sum() == 1.0);
167 BOOST_TEST(equals(ret, coords));
168 }
169 // is outside
170 {
171 Vector3d l(2.0, 0.0, 0.0);
172 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
173 BOOST_TEST((ret.array() < -precice::math::NUMERICAL_ZERO_DIFFERENCE).any(), fmt::format("Min 1 coord should be negative {}", ret));
174 }
175}
176
177PRECICE_TEST_SETUP(1_rank)
178BOOST_AUTO_TEST_CASE(BarycenterTriangle2D)
179{
180 PRECICE_TEST();
181 using Eigen::Vector2d;
182 using Eigen::Vector3d;
184 Vector2d a(0.0, 0.0);
185 Vector2d b(0.0, 1.0);
186 Vector2d c(1.0, 0.0);
187 Vector2d n(0.0, 0.0);
188 // is a?
189 {
190 Vector3d coords(1.0, 0.0, 0.0);
191 auto ret = calcBarycentricCoordsForTriangle(a, b, c, a);
192 BOOST_TEST(ret.sum() == 1.0);
193 BOOST_TEST(equals(ret, coords));
194 }
195 // is b?
196 {
197 Vector3d coords(0.0, 1.0, 0.0);
198 auto ret = calcBarycentricCoordsForTriangle(a, b, c, b);
199 BOOST_TEST(ret.sum() == 1.0);
200 BOOST_TEST(equals(ret, coords));
201 }
202 // is c?
203 {
204 Vector3d coords(0.0, 0.0, 1.0);
205 auto ret = calcBarycentricCoordsForTriangle(a, b, c, c);
206 BOOST_TEST(ret.sum() == 1.0);
207 BOOST_TEST(equals(ret, coords));
208 }
209 // is in the middle
210 {
211 Vector2d l = (a + b + c) / 3;
212 Vector3d coords(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0);
213 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
214 BOOST_TEST(ret.sum() == 1.0);
215 BOOST_TEST(equals(ret, coords));
216 }
217 // is in the middle of ab
218 {
219 Vector2d l = (a + b) / 2;
220 Vector3d coords(0.5, 0.5, 0.0);
221 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
222 BOOST_TEST(ret.sum() == 1.0);
223 BOOST_TEST(equals(ret, coords));
224 }
225 // is in the middle of bc
226 {
227 Vector2d l = (b + c) / 2;
228 Vector3d coords(0.0, 0.5, 0.5);
229 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
230 BOOST_TEST(ret.sum() == 1.0);
231 BOOST_TEST(equals(ret, coords));
232 }
233 // is in the middle of ca
234 {
235 Vector2d l = (a + c) / 2;
236 Vector3d coords(0.5, 0.0, 0.5);
237 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
238 BOOST_TEST(ret.sum() == 1.0);
239 BOOST_TEST(equals(ret, coords));
240 }
241 // is outside
242 {
243 Vector2d l(2.0, 0.0);
244 auto ret = calcBarycentricCoordsForTriangle(a, b, c, l);
245 BOOST_TEST((ret.array() < -precice::math::NUMERICAL_ZERO_DIFFERENCE).any(), fmt::format("Min 1 coord should be negative {}", ret));
246 }
247}
248
249BOOST_AUTO_TEST_SUITE_END() // BarycenterTriangles
250
251BOOST_AUTO_TEST_SUITE(BarycenterTetrahedra)
252
254 Eigen::Vector3d a{0.0, 0.0, 0.0};
255 Eigen::Vector3d b{0.0, 1.0, 0.0};
256 Eigen::Vector3d c{1.0, 0.0, 0.0};
257 Eigen::Vector3d d{0.0, 0.0, 1.0};
258
259 Eigen::Vector3d center{0.25, 0.25, 0.25};
260};
261
263 Eigen::Vector3d a{0.0, 0.0, 0.0};
264 Eigen::Vector3d b{0.0, 1.0, 0.0};
265 Eigen::Vector3d c{1.0, 0.0, 0.0};
266 Eigen::Vector3d d{0.0, 0.0, -1.0};
267
268 Eigen::Vector3d center{0.25, 0.25, -0.25};
269};
270
272 Eigen::Vector3d a{0.0, 0.0, 0.0};
273 Eigen::Vector3d b{0.0, 1.0, 0.0};
274 Eigen::Vector3d c{1.0, 0.0, 0.0};
275 Eigen::Vector3d d{0.0, 0.0, 0.001};
276
277 Eigen::Vector3d center{0.25, 0.25, 0.00025};
278};
279
281 Eigen::Vector3d a{0.0, 0.0, 0.0};
282 Eigen::Vector3d b{0.0, 1.0, 0.0};
283 Eigen::Vector3d c{1.0, 0.0, 0.0};
284 Eigen::Vector3d d{11.0, 11.0, 1.0};
285
286 Eigen::Vector3d center{3.0, 3.0, 0.25};
287};
288
289typedef boost::mpl::vector<TetrahedronFixture, FlippedTetrahedronFixture, AlmostDegenerateTetrahedronFixture, FunnyTetrahedronFixture> TetrahedraFixtures;
290
291PRECICE_TEST_SETUP(1_rank)
292BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnA, T, TetrahedraFixtures, T)
293{
294 PRECICE_TEST();
295
296 Eigen::Vector4d coords(1.0, 0.0, 0.0, 0.0);
297 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::a);
298 BOOST_TEST(precice::testing::equals(ret, coords));
299}
300
301PRECICE_TEST_SETUP(1_rank)
302BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnB, T, TetrahedraFixtures, T)
303{
304 PRECICE_TEST();
305
306 Eigen::Vector4d coords(0.0, 1.0, 0.0, 0.0);
307 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::b);
308 BOOST_TEST(precice::testing::equals(ret, coords));
309}
310
311PRECICE_TEST_SETUP(1_rank)
312BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnC, T, TetrahedraFixtures, T)
313{
314 PRECICE_TEST();
315
316 Eigen::Vector4d coords(0.0, 0.0, 1.0, 0.0);
317 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::c);
318 BOOST_TEST(precice::testing::equals(ret, coords));
319}
320
321PRECICE_TEST_SETUP(1_rank)
322BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnD, T, TetrahedraFixtures, T)
323{
324 PRECICE_TEST();
325
326 Eigen::Vector4d coords(0.0, 0.0, 0.0, 1.0);
327 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::d);
328 BOOST_TEST(precice::testing::equals(ret, coords));
329}
330
331PRECICE_TEST_SETUP(1_rank)
332BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExactOnCenter, T, TetrahedraFixtures, T)
333{
334 PRECICE_TEST();
335
336 Eigen::Vector4d center_coords{0.25, 0.25, 0.25, 0.25};
337 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::center);
338 BOOST_TEST(precice::testing::equals(ret, center_coords));
339}
340
341PRECICE_TEST_SETUP(1_rank)
342BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronInsidePoint, T, TetrahedraFixtures, T)
343{
344 PRECICE_TEST();
345
346 Eigen::Vector4d coords(0.2, 0.3, 0.4, 0.1);
347 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);
348 BOOST_TEST(ret.sum() == 1.0);
349 BOOST_TEST(precice::testing::equals(ret, coords));
350}
351
352PRECICE_TEST_SETUP(1_rank)
353BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronEdgeCenter, T, TetrahedraFixtures, T)
354{
355 PRECICE_TEST();
356 using Eigen::Vector4d;
357
358 Eigen::Vector4d coords(0.5, 0.5, 0.0, 0.0);
359 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, 0.5 * T::a + 0.5 * T::b);
360 BOOST_TEST(ret.sum() == 1.0);
361 BOOST_TEST(precice::testing::equals(ret, coords));
362}
363
364PRECICE_TEST_SETUP(1_rank)
365BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronTriangleCenter, T, TetrahedraFixtures, T)
366{
367 PRECICE_TEST();
368 using Eigen::Vector4d;
369
370 Eigen::Vector4d coords(1. / 3, 1. / 3, 0.0, 1. / 3);
371 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, (T::a + T::b + T::d) / 3);
372 BOOST_TEST(ret.sum() == 1.0);
373 BOOST_TEST(precice::testing::equals(ret, coords));
374}
375
376PRECICE_TEST_SETUP(1_rank)
377BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExtrapolationOnEdge, T, TetrahedraFixtures, T)
378{
379 PRECICE_TEST();
380
381 Eigen::Vector4d coords(-2.0, 3.0, 0, 0);
382 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, T::a + 3 * (T::b - T::a));
383 BOOST_TEST(ret.sum() == 1.0);
384 BOOST_TEST(precice::testing::equals(ret, coords));
385}
386
387PRECICE_TEST_SETUP(1_rank)
388BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExtrapolationOnMirrored, T, TetrahedraFixtures, T)
389{
390 PRECICE_TEST();
391
392 Eigen::Vector4d coords(2.0, 0.0, 0.0, -1.0);
393 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, 2 * T::a - T::d);
394 BOOST_TEST(ret.sum() == 1.0);
395 BOOST_TEST(precice::testing::equals(ret, coords));
396}
397
398PRECICE_TEST_SETUP(1_rank)
399BOOST_FIXTURE_TEST_CASE_TEMPLATE(BarycenterTetrahedronExtrapolationOnMirroredFromTriangle, T, TetrahedraFixtures, T)
400{
401 PRECICE_TEST();
402
403 Eigen::Vector4d coords(1.0, 1.0, 1.0, -2.0);
404 auto ret = calcBarycentricCoordsForTetrahedron(T::a, T::b, T::c, T::d, (T::a + T::b + T::c) - 2 * T::d);
405 BOOST_TEST(ret.sum() == 1.0);
406 BOOST_TEST(precice::testing::equals(ret, coords));
407}
408
409BOOST_AUTO_TEST_SUITE_END() // BarycenterTetrahedra
410
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:39
#define PRECICE_TEST_SETUP(...)
Creates and attaches a TestSetup to a Boost test case.
Definition Testing.hpp:29
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:93
Main namespace of the precice library.