15#include <doctest/doctest.h>
20using namespace foliated_triangulations;
22static inline auto constexpr RADIUS_2 = 2.0 * std::numbers::inv_sqrt3_v<double>;
23static inline std::floating_point
auto constexpr SQRT_2 =
24 std::numbers::sqrt2_v<double>;
25static inline auto constexpr INV_SQRT_2 = 1.0 / SQRT_2;
27SCENARIO(
"FoliatedTriangulation special member and swap properties" *
28 doctest::test_suite(
"foliated_triangulation"))
30 spdlog::debug(
"FoliatedTriangulation special member and swap properties.\n");
31 GIVEN(
"A FoliatedTriangulation_3 class.")
33 WHEN(
"It's properties are examined.")
35 THEN(
"It is no-throw destructible.")
37 REQUIRE(is_nothrow_destructible_v<FoliatedTriangulation_3>);
38 spdlog::debug(
"It is no-throw destructible.\n");
40 THEN(
"It is default constructible.")
42 REQUIRE(is_default_constructible_v<FoliatedTriangulation_3>);
43 spdlog::debug(
"It is default destructible.\n");
45 THEN(
"It is NOT trivially default constructible.")
48 is_trivially_default_constructible_v<FoliatedTriangulation_3>);
50 THEN(
"Delaunay_triangulation_3 is NOT no-throw default constructible.")
52 CHECK_FALSE(is_nothrow_default_constructible_v<Delaunay_t<3>>);
55 "Therefore FoliatedTriangulation is NOT no-throw default "
59 is_nothrow_default_constructible_v<FoliatedTriangulation_3>);
61 THEN(
"It is no-throw copy constructible.")
63 REQUIRE(is_nothrow_copy_constructible_v<FoliatedTriangulation_3>);
64 spdlog::debug(
"It is no-throw copy constructible.\n");
66 THEN(
"It is no-throw copy assignable.")
68 REQUIRE(is_nothrow_copy_assignable_v<FoliatedTriangulation_3>);
69 spdlog::debug(
"It is no-throw copy assignable.\n");
71 THEN(
"It is no-throw move constructible.")
73 REQUIRE(is_nothrow_move_constructible_v<FoliatedTriangulation_3>);
74 spdlog::debug(
"It is no-throw move constructible.\n");
76 THEN(
"It is no-throw move assignable.")
78 REQUIRE(is_nothrow_move_assignable_v<FoliatedTriangulation_3>);
79 spdlog::debug(
"It is no-throw move assignable.\n");
81 THEN(
"It is no-throw swappable.")
83 REQUIRE(is_nothrow_swappable_v<FoliatedTriangulation_3>);
84 spdlog::debug(
"It is no-throw swappable.\n");
86 THEN(
"It is constructible from a Delaunay triangulation.")
89 spdlog::debug(
"It is constructible from a Delaunay triangulation.\n");
91 THEN(
"It is constructible from parameters.")
95 spdlog::debug(
"It is constructible from parameters.\n");
97 THEN(
"It is constructible from Causal_vertices.")
101 spdlog::debug(
"It is constructible from Causal_vertices.\n");
103 THEN(
"It is constructible from Causal_vertices and INITIAL_RADIUS.")
106 Causal_vertices_t<3>,
double>);
108 "It is constructible from Causal_vertices and INITIAL_RADIUS.\n");
111 "It is constructible from Causal_vertices, INITIAL_RADIUS, and "
112 "RADIAL_SEPARATION.")
115 Causal_vertices_t<3>,
double,
double>);
117 "It is constructible from Causal_vertices, INITIAL_RADIUS, and "
118 "RADIAL_SEPARATION.\n");
124SCENARIO(
"FoliatedTriangulation free functions" *
125 doctest::test_suite(
"foliated_triangulation"))
127 spdlog::debug(
"foliated_triangulations:: free functions.\n");
129 GIVEN(
"A vector of points and timevalues.")
131 vector
const Vertices{Point_t<3>(1, 0, 0), Point_t<3>(0, 1, 0),
133 Point_t<3>(RADIUS_2, RADIUS_2, RADIUS_2)};
134 vector<size_t>
const Timevalues{1, 1, 1, 2};
135 WHEN(
"Causal vertices are created.")
137 auto causal_vertices = make_causal_vertices<3>(Vertices, Timevalues);
138 THEN(
"They are correct.")
140 REQUIRE_EQ(causal_vertices.size(), 4);
141 REQUIRE_EQ(causal_vertices[0].first, Point_t<3>(1, 0, 0));
142 REQUIRE_EQ(causal_vertices[0].second, 1);
143 REQUIRE_EQ(causal_vertices[1].first, Point_t<3>(0, 1, 0));
144 REQUIRE_EQ(causal_vertices[1].second, 1);
145 REQUIRE_EQ(causal_vertices[2].first, Point_t<3>(0, 0, 1));
146 REQUIRE_EQ(causal_vertices[2].second, 1);
147 REQUIRE_EQ(causal_vertices[3].first,
148 Point_t<3>(RADIUS_2, RADIUS_2, RADIUS_2));
149 REQUIRE_EQ(causal_vertices[3].second, 2);
153 GIVEN(
"A mismatched set of points and timevalues.")
155 vector
const Vertices{Point_t<3>(1, 0, 0), Point_t<3>(0, 1, 0),
157 Point_t<3>(RADIUS_2, RADIUS_2, RADIUS_2)};
158 vector<size_t>
const Timevalues{1, 1, 1};
159 WHEN(
"Causal vertices are created.")
161 THEN(
"An exception is thrown.")
163 REQUIRE_THROWS(make_causal_vertices<3>(Vertices, Timevalues));
168 GIVEN(
"A small foliated 3D triangulation.")
171 Point_t<3>{ 1, 0, 0},
172 Point_t<3>{ 0, 1, 0},
173 Point_t<3>{ 0, 0, 1},
174 Point_t<3>{RADIUS_2, RADIUS_2, RADIUS_2}
176 vector<std::size_t> timevalues{1, 1, 1, 2};
177 auto vertices = make_causal_vertices<3>(Vertices, timevalues);
179 auto print = [&triangulation](
auto& vertex) {
181 "Vertex: ({}) Timevalue: {} is a vertex: {} and is "
183 utilities::point_to_str(vertex->point()), vertex->info(),
184 triangulation.get_delaunay().tds().is_vertex(vertex),
185 triangulation.is_infinite(vertex));
188 REQUIRE(triangulation.is_initialized());
189 WHEN(
"check_vertices() is called.")
191 THEN(
"The vertices are correct.")
193 CHECK(foliated_triangulations::check_vertices<3>(
194 triangulation.get_delaunay(), 1.0, 1.0));
197 WHEN(
"check_cells() is called.")
199 THEN(
"Cells are correctly classified.")
201 CHECK(foliated_triangulations::check_cells<3>(
202 triangulation.get_delaunay()));
204 triangulation.print_cells();
208 WHEN(
"We print a cell in the triangulation.")
210 THEN(
"A cell is printed correctly.")
212 foliated_triangulations::print_cell<3>(triangulation.get_cells().at(0));
216 WHEN(
"We ask for a container of vertices given a container of cells.")
218 auto&& all_vertices =
219 get_vertices_from_cells<3>(triangulation.get_cells());
220 THEN(
"We get back the correct number of vertices.")
222 REQUIRE_EQ(all_vertices.size(), 4);
224 ranges::for_each(all_vertices, print);
229 "A minimal triangulation with non-default initial radius and radial "
232 auto constexpr desired_simplices = 2;
233 auto constexpr desired_timeslices = 2;
234 auto constexpr initial_radius = 3.0;
235 auto constexpr foliation_spacing = 2.0;
237 desired_simplices, desired_timeslices, initial_radius,
239 THEN(
"The triangulation is initialized correctly.")
241 REQUIRE(triangulation.is_initialized());
243 THEN(
"The initial radius and radial separation are correct.")
245 REQUIRE_EQ(triangulation.initial_radius(), initial_radius);
246 REQUIRE_EQ(triangulation.foliation_spacing(), foliation_spacing);
249 "The triangulation has an initial radius of {} and a radial "
250 "separation of {}\n",
251 initial_radius, foliation_spacing);
253 THEN(
"Each vertex has a valid timevalue.")
255 for (std::span
const checked_vertices(triangulation.get_vertices());
256 auto const& vertex : checked_vertices)
258 CHECK(triangulation.does_vertex_radius_match_timevalue(vertex));
260 "Vertex ({}) with timevalue of {} has a squared radius of {} and a "
261 "squared expected radius of {} with an expected timevalue of {}.\n",
262 utilities::point_to_str(vertex->point()), vertex->info(),
263 squared_radius<3>(vertex),
264 std::pow(triangulation.expected_radius(vertex), 2),
265 triangulation.expected_timevalue(vertex));
269 GIVEN(
"A triangulation setup for a (4,4) move")
272 Point_t<3>{ 0, 0, 0},
273 Point_t<3>{ INV_SQRT_2, 0, INV_SQRT_2},
274 Point_t<3>{ 0, INV_SQRT_2, INV_SQRT_2},
275 Point_t<3>{-INV_SQRT_2, 0, INV_SQRT_2},
276 Point_t<3>{ 0, -INV_SQRT_2, INV_SQRT_2},
279 vector<size_t> timevalue{1, 2, 2, 2, 2, 3};
280 auto causal_vertices = make_causal_vertices<3>(vertices, timevalue);
283 REQUIRE_EQ(triangulation.number_of_vertices(), 6);
284 REQUIRE_EQ(triangulation.number_of_finite_edges(), 13);
285 REQUIRE_EQ(triangulation.number_of_finite_facets(), 12);
286 REQUIRE(triangulation.number_of_finite_cells() == 4);
287 CHECK_EQ(triangulation.initial_radius(), 0);
288 CHECK_EQ(triangulation.foliation_spacing(), 1);
289 REQUIRE(triangulation.is_delaunay());
290 REQUIRE(triangulation.is_correct());
291 WHEN(
"We collect edges.")
293 auto edges = foliated_triangulations::collect_edges<3>(
294 triangulation.get_delaunay());
295 THEN(
"We have 13 edges.") { REQUIRE_EQ(edges.size(), 13); }
297 WHEN(
"We have a point in the triangulation.")
299 THEN(
"We can obtain the vertex")
301 auto vertex = foliated_triangulations::find_vertex<3>(
302 triangulation.get_delaunay(), Point_t<3>{0, 0, 0});
303 REQUIRE_MESSAGE(vertex,
"Vertex not found.");
306 CHECK_EQ(vertex.value()->point(), Point_t<3>{0, 0, 0});
307 CHECK_EQ(vertex.value()->info(), 1);
310 "Point(0,0,0) was found as vertex ({}) with a timevalue of {}.\n",
311 utilities::point_to_str(vertex.value()->point()),
312 vertex.value()->info());
315 WHEN(
"We choose a point not in the triangulation.")
317 THEN(
"No vertex is found.")
319 auto vertex = foliated_triangulations::find_vertex<3>(
320 triangulation.get_delaunay(), Point_t<3>{3, 3, 3});
321 REQUIRE_FALSE(vertex);
323 fmt::print(
"Point(3,3,3) was not found.\n");
326 WHEN(
"We check vertices in a cell.")
328 THEN(
"The correct vertices yields the correct cell.")
330 auto v_1 = foliated_triangulations::find_vertex<3>(
331 triangulation.get_delaunay(), Point_t<3>{0, 0, 0});
332 auto v_2 = foliated_triangulations::find_vertex<3>(
333 triangulation.get_delaunay(),
334 Point_t<3>{0, INV_SQRT_2, INV_SQRT_2});
335 auto v_3 = foliated_triangulations::find_vertex<3>(
336 triangulation.get_delaunay(),
337 Point_t<3>{0, -INV_SQRT_2, INV_SQRT_2});
338 auto v_4 = foliated_triangulations::find_vertex<3>(
339 triangulation.get_delaunay(),
340 Point_t<3>{-INV_SQRT_2, 0, INV_SQRT_2});
341 REQUIRE_MESSAGE(v_1,
"Vertex v_1 not found.");
342 REQUIRE_MESSAGE(v_2,
"Vertex v_2 not found.");
343 REQUIRE_MESSAGE(v_3,
"Vertex v_3 not found.");
344 REQUIRE_MESSAGE(v_4,
"Vertex v_4 not found.");
345 if (v_1 && v_2 && v_3 && v_4)
347 auto cell = foliated_triangulations::find_cell<3>(
348 triangulation.get_delaunay(), v_1.value(), v_2.value(),
349 v_3.value(), v_4.value());
352 triangulation.print_cells();
355 THEN(
"The incorrect vertices do not return a cell.")
357 auto v_1 = foliated_triangulations::find_vertex<3>(
358 triangulation.get_delaunay(), Point_t<3>{0, 0, 0});
359 auto v_2 = foliated_triangulations::find_vertex<3>(
360 triangulation.get_delaunay(),
361 Point_t<3>{INV_SQRT_2, 0, INV_SQRT_2});
362 auto v_3 = foliated_triangulations::find_vertex<3>(
363 triangulation.get_delaunay(),
364 Point_t<3>{0, INV_SQRT_2, INV_SQRT_2});
365 auto v_4 = foliated_triangulations::find_vertex<3>(
366 triangulation.get_delaunay(), Point_t<3>{0, 0, 2});
367 REQUIRE_MESSAGE(v_1,
"Vertex v_1 not found.");
368 REQUIRE_MESSAGE(v_2,
"Vertex v_2 not found.");
369 REQUIRE_MESSAGE(v_3,
"Vertex v_3 not found.");
370 REQUIRE_MESSAGE(v_4,
"Vertex v_4 not found.");
371 if (v_1 && v_2 && v_3 && v_4)
373 auto cell = foliated_triangulations::find_cell<3>(
374 triangulation.get_delaunay(), v_1.value(), v_2.value(),
375 v_3.value(), v_4.value());
381 WHEN(
"A container of cells is printed.")
383 THEN(
"The container is printed correctly.")
385 foliated_triangulations::print_cells<3>(triangulation.get_cells());
388 WHEN(
"We choose a cell in the triangulation.")
390 auto cell = triangulation.get_cells().at(0);
391 THEN(
"We can print it's neighbors.")
393 foliated_triangulations::print_cell<3>(cell);
394 foliated_triangulations::print_neighboring_cells<3>(cell);
400SCENARIO(
"FoliatedTriangulation_3 initialization" *
401 doctest::test_suite(
"foliated_triangulation"))
403 spdlog::debug(
"FoliatedTriangulation initialization.\n");
404 GIVEN(
"A 3D foliated triangulation.")
406 WHEN(
"It is default constructed.")
408 THEN(
"The default Delaunay triangulation is valid.")
412 REQUIRE_EQ(triangulation.
max_time(), 0);
413 REQUIRE_EQ(triangulation.
min_time(), 0);
419 "It is constructed from a Delaunay triangulation with 4 causal "
423 Point_t<3>{ 1, 0, 0},
424 Point_t<3>{ 0, 1, 0},
425 Point_t<3>{ 0, 0, 1},
426 Point_t<3>{RADIUS_2, RADIUS_2, RADIUS_2}
428 vector<std::size_t> timevalues{1, 1, 1, 2};
429 auto vertices = make_causal_vertices<3>(Vertices, timevalues);
431 THEN(
"Triangulation is valid and foliated.")
433 REQUIRE(triangulation.is_initialized());
434 REQUIRE_EQ(triangulation.dimension(), 3);
435 REQUIRE_EQ(triangulation.number_of_vertices(), 4);
436 REQUIRE_EQ(triangulation.number_of_finite_edges(), 6);
437 REQUIRE_EQ(triangulation.number_of_finite_facets(), 4);
438 REQUIRE_EQ(triangulation.number_of_finite_cells(), 1);
439 REQUIRE_EQ(triangulation.max_time(), 2);
440 REQUIRE_EQ(triangulation.min_time(), 1);
442 REQUIRE_EQ(triangulation.foliation_spacing(), FOLIATION_SPACING);
443 REQUIRE(triangulation.is_foliated());
445 triangulation.print_cells();
448 WHEN(
"Constructing the minimum triangulation.")
450 auto constexpr desired_simplices = 2;
451 auto constexpr desired_timeslices = 2;
454 THEN(
"Triangulation is valid and foliated.")
456 REQUIRE(triangulation.is_initialized());
458 THEN(
"The triangulation has sensible values.")
461 auto vertex_count{triangulation.number_of_vertices()};
462 CHECK_GE(vertex_count, 1);
463 CHECK_LE(vertex_count, 8);
465 auto simplex_count{triangulation.number_of_finite_cells()};
466 CHECK_GE(simplex_count, 1);
467 CHECK_LE(simplex_count, 12);
470 triangulation.print();
472 THEN(
"The vertices have correct timevalues.")
474 auto check = [&triangulation](Vertex_handle_t<3>
const& vertex) {
475 CHECK(triangulation.does_vertex_radius_match_timevalue(vertex));
477 ranges::for_each(triangulation.get_vertices(), check);
479 auto print = [&triangulation](Vertex_handle_t<3>
const& vertex) {
481 "Vertex: ({}) Timevalue: {} has a squared radius of {} and "
482 "a squared expected radius of {} with an expected timevalue of "
484 utilities::point_to_str(vertex->point()), vertex->info(),
485 squared_radius<3>(vertex),
486 std::pow(triangulation.expected_radius(vertex), 2),
487 triangulation.expected_timevalue(vertex));
489 ranges::for_each(triangulation.get_vertices(), print);
493 "Constructing the minimal triangulation with non-default initial "
494 "radius and separation.")
496 auto constexpr desired_simplices = 2;
497 auto constexpr desired_timeslices = 2;
498 auto constexpr initial_radius = 3.0;
499 auto constexpr radial_factor = 2.0;
501 desired_simplices, desired_timeslices, initial_radius, radial_factor);
502 THEN(
"The triangulation is initialized correctly.")
504 REQUIRE(triangulation.is_initialized());
506 THEN(
"The initial radius and radial separation are correct.")
508 REQUIRE_EQ(triangulation.initial_radius(), initial_radius);
509 REQUIRE_EQ(triangulation.foliation_spacing(), radial_factor);
513 "Constructing a small triangulation with fractional initial radius and "
516 auto constexpr desired_simplices = 24;
517 auto constexpr desired_timeslices = 3;
518 auto constexpr initial_radius = 1.5;
519 auto constexpr radial_factor = 1.1;
521 desired_simplices, desired_timeslices, initial_radius, radial_factor);
522 THEN(
"The triangulation is initialized correctly.")
524 REQUIRE(triangulation.is_initialized());
526 THEN(
"The initial radius and radial separation are correct.")
528 REQUIRE_EQ(triangulation.initial_radius(), initial_radius);
529 REQUIRE_EQ(triangulation.foliation_spacing(), radial_factor);
532 WHEN(
"Constructing a medium triangulation.")
534 auto constexpr desired_simplices = 6400;
535 auto constexpr desired_timeslices = 7;
538 THEN(
"Triangulation is valid and foliated.")
540 REQUIRE(triangulation.is_initialized());
542 THEN(
"The triangulation has sensible values.")
544 REQUIRE_EQ(triangulation.min_time(), 1);
546 triangulation.print();
548 THEN(
"Data members are correctly populated.")
550 triangulation.print();
552 CHECK_EQ(triangulation.get_cells().size(),
553 triangulation.get_three_one().size() +
554 triangulation.get_two_two().size() +
555 triangulation.get_one_three().size());
557 CHECK(triangulation.check_all_cells());
559 CHECK_FALSE(triangulation.N2_SL().empty());
561 CHECK_GT(triangulation.max_time(), 0);
562 CHECK_GT(triangulation.min_time(), 0);
563 CHECK_GT(triangulation.max_time(), triangulation.min_time());
564 auto check_timelike = [](Edge_handle_t<3>
const& edge) {
565 CHECK(classify_edge<3>(edge));
567 ranges::for_each(triangulation.get_timelike_edges(), check_timelike);
569 auto check_spacelike = [](Edge_handle_t<3>
const& edge) {
570 CHECK(!classify_edge<3>(edge));
572 ranges::for_each(triangulation.get_spacelike_edges(), check_spacelike);
574 fmt::print(
"There are {} edges.\n",
575 triangulation.number_of_finite_edges());
576 fmt::print(
"There are {} timelike edges and {} spacelike edges.\n",
577 triangulation.N1_TL(), triangulation.N1_SL());
579 "There are {} vertices with a max timevalue of {} and a min "
580 "timevalue of {}.\n",
581 triangulation.number_of_vertices(), triangulation.max_time(),
582 triangulation.min_time());
583 triangulation.print_volume_per_timeslice();
589SCENARIO(
"FoliatedTriangulation_3 copying" *
590 doctest::test_suite(
"foliated_triangulation"))
592 spdlog::debug(
"FoliatedTriangulation_3 copying.\n");
593 GIVEN(
"A FoliatedTriangulation_3")
595 auto constexpr desired_simplices = 6400;
596 auto constexpr desired_timeslices = 7;
601 auto ft2 = triangulation;
602 THEN(
"The two objects are distinct.")
604 auto* ft_ptr = &triangulation;
605 auto* ft2_ptr = &ft2;
606 CHECK_NE(ft_ptr, ft2_ptr);
608 THEN(
"The foliated triangulations have identical properties.")
610 CHECK_EQ(triangulation.is_initialized(), ft2.is_initialized());
611 CHECK_EQ(triangulation.number_of_finite_cells(),
612 ft2.number_of_finite_cells());
613 CHECK_EQ(triangulation.min_time(), ft2.min_time());
614 CHECK_EQ(triangulation.get_cells().size(), ft2.get_cells().size());
615 CHECK_EQ(triangulation.get_three_one().size(),
616 ft2.get_three_one().size());
617 CHECK_EQ(triangulation.get_two_two().size(), ft2.get_two_two().size());
618 CHECK_EQ(triangulation.get_one_three().size(),
619 ft2.get_one_three().size());
620 CHECK_EQ(triangulation.N2_SL().size(), ft2.N2_SL().size());
626SCENARIO(
"Detecting and fixing problems with vertices and cells" *
627 doctest::test_suite(
"foliated_triangulation"))
629 spdlog::debug(
"Detecting and fixing problems with vertices and cells.\n");
630 GIVEN(
"A FoliatedTriangulation_3.")
632 WHEN(
"Constructing a triangulation with 4 correct vertices.")
635 Point_t<3>{ 1, 0, 0},
636 Point_t<3>{ 0, 1, 0},
637 Point_t<3>{ 0, 0, 1},
638 Point_t<3>{RADIUS_2, RADIUS_2, RADIUS_2}
640 vector<std::size_t> timevalues{1, 1, 1, 2};
641 auto vertices = make_causal_vertices<3>(Vertices, timevalues);
643 THEN(
"No errors in the vertices are detected.")
645 CHECK(triangulation.check_all_vertices());
647 triangulation.print_vertices();
649 THEN(
"No errors in the simplex are detected.")
651 CHECK(triangulation.is_correct());
652 CHECK_FALSE(check_timevalues<3>(triangulation.get_delaunay()));
654 triangulation.print_cells();
656 THEN(
"No errors in the triangulation foliation are detected")
658 CHECK_FALSE(foliated_triangulations::fix_timevalues<3>(
659 triangulation.delaunay()));
663 AND_WHEN(
"The vertices are mis-labelled.")
665 auto break_vertices = [](Vertex_handle_t<3>
const& vertex) {
668 ranges::for_each(triangulation.get_vertices(), break_vertices);
670 THEN(
"The incorrect vertex labelling is identified.")
672 CHECK_FALSE(triangulation.check_all_vertices());
673 auto bad_vertices = triangulation.find_incorrect_vertices();
674 CHECK_FALSE(bad_vertices.empty());
676 fmt::print(
"=== Wrong vertex info! ===\n");
677 triangulation.print_vertices();
679 AND_THEN(
"The incorrect vertex labelling is fixed.")
681 CHECK_FALSE(triangulation.check_all_vertices());
682 auto bad_vertices = triangulation.find_incorrect_vertices();
683 CHECK_FALSE(bad_vertices.empty());
685 CHECK(triangulation.fix_vertices());
686 CHECK(triangulation.check_all_vertices());
687 fmt::print(
"=== Corrected vertex info ===\n");
688 triangulation.print_vertices();
691 AND_WHEN(
"The cells are mis-labelled.")
693 auto break_cells = [](Cell_handle_t<3>
const& cell) {
696 ranges::for_each(triangulation.get_cells(), break_cells);
697 THEN(
"The incorrect cell labelling is identified.")
699 CHECK_FALSE(triangulation.check_all_cells());
701 fmt::print(
"=== Wrong cell info! ===\n");
702 triangulation.print_cells();
704 THEN(
"The incorrect cell labelling is fixed.")
706 CHECK_FALSE(triangulation.check_all_cells());
707 CHECK(triangulation.fix_cells());
709 fmt::print(
"=== Corrected cell info ===\n");
710 triangulation.print_cells();
711 CHECK(triangulation.check_all_cells());
716 "Constructing a triangulation with an incorrect high timevalue "
720 Point_t<3>{ 1, 0, 0},
721 Point_t<3>{ 0, 1, 0},
722 Point_t<3>{ 0, 0, 1},
723 Point_t<3>{RADIUS_2, RADIUS_2, RADIUS_2}
725 vector<std::size_t> timevalues{1, 1, 1, std::numeric_limits<int>::max()};
726 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
728 THEN(
"The vertex is fixed on construction.")
730 CHECK_FALSE(triangulation.fix_vertices());
731 CHECK(triangulation.is_initialized());
732 triangulation.print_cells();
735 WHEN(
"Constructing a triangulation with an incorrect low value vertex.")
743 vector<std::size_t> timevalues{0, 2, 2, 2};
744 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
746 THEN(
"The vertex is fixed on construction.")
748 CHECK_FALSE(triangulation.fix_vertices());
749 CHECK(triangulation.is_initialized());
750 triangulation.print_cells();
754 "Constructing a triangulation with two incorrect low values and two "
755 "incorrect high values.")
763 vector<std::size_t> timevalues{0, 0, 2, 2};
764 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
766 THEN(
"The vertices are fixed on construction.")
768 CHECK_FALSE(triangulation.fix_vertices());
769 CHECK(triangulation.is_initialized());
770 triangulation.print_cells();
772 AND_THEN(
"The cell type is correct.")
774 CHECK_FALSE(triangulation.fix_vertices());
775 CHECK_FALSE(triangulation.fix_cells());
776 CHECK(triangulation.is_initialized());
777 triangulation.print_cells();
781 "Constructing a triangulation with all vertices on the same timeslice.")
789 vector<std::size_t> timevalues{1, 1, 1, 1};
790 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
792 THEN(
"The vertex error is detected.")
794 CHECK_FALSE(triangulation.is_initialized());
795 auto cell = triangulation.get_delaunay().finite_cells_begin();
796 CHECK_EQ(expected_cell_type<3>(cell), Cell_type::ACAUSAL);
798 triangulation.print_cells();
801 WHEN(
"Constructing a triangulation with an unfixable vertex.")
811 vector<std::size_t> timevalues{1, 1, 1, 2, 2, 3};
812 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
813 Delaunay_t<3>
const delaunay_triangulation{causal_vertices.begin(),
814 causal_vertices.end()};
819 THEN(
"The incorrect cell can be identified.")
821 auto bad_cells = check_timevalues<3>(delaunay_triangulation);
822 CHECK_MESSAGE(bad_cells.has_value(),
"No bad cells found.");
825 fmt::print(
"Bad cells:\n");
826 print_cells<3>(bad_cells.value());
829 AND_THEN(
"The incorrect vertex can be identified.")
831 auto bad_cells = check_timevalues<3>(delaunay_triangulation);
832 CHECK_MESSAGE(bad_cells.has_value(),
"No bad cells found.");
835 auto bad_vertex = find_bad_vertex<3>(bad_cells->front());
836 fmt::print(
"Bad vertex ({}) has timevalues {}.\n",
837 utilities::point_to_str(bad_vertex->point()),
839 CHECK_EQ(bad_vertex->info(), 3);
842 AND_THEN(
"The triangulation is fixed.")
844 fmt::print(
"Unfixed triangulation:\n");
845 triangulation.print_cells();
846 CHECK(foliated_triangulations::fix_timevalues<3>(
847 triangulation.delaunay()));
848 CHECK(triangulation.is_initialized());
849 fmt::print(
"Fixed triangulation:\n");
850 print_cells<3>(collect_cells<3>(triangulation.delaunay()));
856SCENARIO(
"FoliatedTriangulation_3 functions from Delaunay3" *
857 doctest::test_suite(
"foliated_triangulation"))
859 spdlog::debug(
"FoliatedTriangulation_3 functions from Delaunay3.\n");
860 GIVEN(
"A FoliatedTriangulation_3.")
862 WHEN(
"Constructing a small triangulation.")
872 vector<std::size_t> timevalues{1, 1, 1, 2, 2, 3};
873 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
875 THEN(
"The Foliated triangulation is initially wrong.")
877 CHECK_FALSE(triangulation.is_initialized());
880 fmt::print(
"Unfixed triangulation:\n");
881 triangulation.print_cells();
884 THEN(
"After being fixed, Delaunay3 functions work as expected.")
887 CHECK(triangulation.is_fixed());
888 CHECK_EQ(triangulation.number_of_finite_cells(), 2);
889 fmt::print(
"Base Delaunay number of cells: {}\n",
890 triangulation.number_of_finite_cells());
891 CHECK_EQ(triangulation.number_of_finite_facets(), 7);
892 fmt::print(
"Base Delaunay number of faces: {}\n",
893 triangulation.number_of_finite_facets());
894 triangulation.print_volume_per_timeslice();
895 CHECK_EQ(triangulation.number_of_finite_edges(), 9);
896 fmt::print(
"Base Delaunay number of edges: {}\n",
897 triangulation.number_of_finite_edges());
898 triangulation.print_edges();
899 CHECK_EQ(triangulation.number_of_vertices(), 5);
900 fmt::print(
"Base Delaunay number of vertices: {}\n",
901 triangulation.number_of_vertices());
902 CHECK_EQ(triangulation.dimension(), 3);
903 fmt::print(
"Base Delaunay dimension is: {}\n",
904 triangulation.dimension());
911 WHEN(
"Constructing the default triangulation.")
915 THEN(
"is_infinite() identifies a single infinite vertex.")
917 auto&& vertices = triangulation.
get_delaunay().tds().vertices();
918 auto&& vertex = vertices.begin();
919 CHECK_EQ(vertices.size(), 1);
920 CHECK(triangulation.
get_delaunay().tds().is_vertex(vertex));
924 WHEN(
"Constructing a triangulation with 4 causal vertices.")
927 Point_t<3>{ 1, 0, 0},
928 Point_t<3>{ 0, 1, 0},
929 Point_t<3>{ 0, 0, 1},
930 Point_t<3>{RADIUS_2, RADIUS_2, RADIUS_2}
932 vector<std::size_t> timevalues{1, 1, 1, 2};
933 auto causal_vertices = make_causal_vertices<3>(vertices, timevalues);
936 THEN(
"The degree of each vertex is 4 (including infinite vertex).")
938 auto check = [&triangulation](Vertex_handle_t<3>
const& vertex) {
939 CHECK_EQ(triangulation.
degree(vertex), 4);
Create foliated spherical triangulations.
std::int_fast32_t Int_precision
static double constexpr INITIAL_RADIUS
Default foliated triangulation spacings.
void print_delaunay(TriangulationType const &t_triangulation)
Print triangulation statistics.
SCENARIO("Perform bistellar flip on Delaunay triangulation" *doctest::test_suite("bistellar"))
3D Foliated triangulation
auto initial_radius() const
auto degree(VertexHandle &&t_vertex) const
Perfect forwarding to TriangulationDataStructure_3::degree.
auto is_initialized() const -> bool
auto get_delaunay() const -> Delaunay const &
auto is_infinite(VertexHandle &&t_vertex) const
auto foliation_spacing() const
auto get_vertices() const noexcept -> Vertex_container const &