21#ifndef CDT_PLUSPLUS_FOLIATEDTRIANGULATION_HPP
22#define CDT_PLUSPLUS_FOLIATEDTRIANGULATION_HPP
27template <
int dimension>
30template <
int dimension>
33template <
int dimension>
34using Causal_vertices_t =
37template <
int dimension>
40template <
int dimension>
43template <
int dimension>
46template <
int dimension>
49template <
int dimension>
52template <
int dimension>
53using Spherical_points_generator_t =
79namespace foliated_triangulations
81 static int constexpr MAX_FIX_PASSES = 50;
88 template <
int dimension>
90 std::span<size_t const> timevalues)
91 -> Causal_vertices_t<dimension>
93 if (vertices.size() != timevalues.size())
95 throw std::length_error(
"Vertices and timevalues must be the same size.");
97 Causal_vertices_t<dimension> causal_vertices;
98 causal_vertices.reserve(vertices.size());
99 std::ranges::transform(vertices, timevalues,
100 std::back_inserter(causal_vertices),
101 [](Point_t<dimension> point,
size_t time) {
102 return std::make_pair(point, time);
104 return causal_vertices;
113 template <
int dimension>
116 assert(delaunay.is_valid());
117 std::vector<Edge_handle_t<dimension>> init_edges;
118 init_edges.reserve(delaunay.number_of_finite_edges());
119 for (
auto eit = delaunay.finite_edges_begin();
120 eit != delaunay.finite_edges_end(); ++eit)
122 Cell_handle_t<3>
const cell = eit->first;
123 Edge_handle_t<3> thisEdge{cell, cell->index(cell->vertex(eit->second)),
124 cell->index(cell->vertex(eit->third))};
126 assert(delaunay.tds().is_valid(thisEdge.first, thisEdge.second,
128 init_edges.emplace_back(thisEdge);
130 assert(init_edges.size() == delaunay.number_of_finite_edges());
141 template <
int dimension>
142 [[nodiscard]]
auto find_vertex(Delaunay_t<dimension>
const& delaunay,
143 Point_t<dimension>
const& point)
144 -> std::optional<Vertex_handle_t<dimension>>
146 if (Vertex_handle_t<dimension> vertex{
nullptr};
147 delaunay.is_vertex(point, vertex))
164 template <
int dimension>
165 [[nodiscard]]
auto find_cell(Delaunay_t<dimension>
const& delaunay,
166 Vertex_handle_t<dimension>
const& vh1,
167 Vertex_handle_t<dimension>
const& vh2,
168 Vertex_handle_t<dimension>
const& vh3,
169 Vertex_handle_t<dimension>
const& vh4)
170 -> std::optional<Cell_handle_t<dimension>>
172 if (Cell_handle_t<dimension> cell{
nullptr};
173 delaunay.is_cell(vh1, vh2, vh3, vh4, cell))
182 template <
int dimension>
184 Vertex_handle_t<dimension>
const& rhs) {
185 return lhs->info() < rhs->info();
191 template <
int dimension, ContainerType Container>
194 auto vertices = std::forward<Container>(t_vertices);
195 assert(!vertices.empty());
196 auto max_element = std::max_element(vertices.begin(), vertices.end(),
197 compare_v_info<dimension>);
198 auto result_index = std::distance(vertices.begin(), max_element);
201 assert(result_index >= 0);
202 auto const index =
static_cast<std::size_t
>(std::abs(result_index));
203 return vertices[index]->info();
209 template <
int dimension, ContainerType Container>
212 auto vertices = std::forward<Container>(t_vertices);
213 assert(!vertices.empty());
214 auto min_element = std::min_element(vertices.begin(), vertices.end(),
215 compare_v_info<dimension>);
216 auto result_index = std::distance(vertices.begin(), min_element);
217 assert(result_index >= 0);
218 auto const index =
static_cast<std::size_t
>(std::abs(result_index));
219 return vertices[index]->info();
226 template <
int dimension>
231 spdlog::debug(
"{} called.\n", __PRETTY_FUNCTION__);
233 auto const& cell = t_edge.first;
234 auto time1 = cell->vertex(t_edge.second)->info();
235 auto time2 = cell->vertex(t_edge.third)->info();
238 spdlog::trace(
"Edge: Vertex(1) timevalue: {} Vertex(2) timevalue: {}\n",
242 return time1 != time2;
249 template <
int dimension>
251 std::vector<Edge_handle_t<dimension>>
const& t_edges,
252 bool t_is_Timelike_pred) -> std::vector<Edge_handle_t<dimension>>
254 std::vector<Edge_handle_t<dimension>> filtered_edges;
256 if (t_edges.empty()) {
return filtered_edges; }
257 std::copy_if(t_edges.begin(), t_edges.end(),
258 std::back_inserter(filtered_edges), [&](
auto const& edge) {
259 return t_is_Timelike_pred == classify_edge<dimension>(edge);
261 return filtered_edges;
268 template <
int dimension>
270 std::vector<Cell_handle_t<dimension>>
const& t_cells,
271 Cell_type const& t_cell_type) -> std::vector<Cell_handle_t<dimension>>
273 std::vector<Cell_handle_t<dimension>> filtered_cells;
275 if (t_cells.empty()) {
return filtered_cells; }
276 std::copy_if(t_cells.begin(), t_cells.end(),
277 std::back_inserter(filtered_cells),
278 [&t_cell_type](
auto const& cell) {
279 return cell->info() == static_cast<int>(t_cell_type);
281 return filtered_cells;
288 template <
int dimension>
308 template <
int dimension>
310 Vertex_handle_t<dimension>
const& t_vertex,
double t_initial_radius,
313 auto const radius = std::sqrt(squared_radius<dimension>(t_vertex));
315 std::lround((radius - t_initial_radius + t_foliation_spacing) /
316 t_foliation_spacing));
325 template <
int dimension>
327 Vertex_handle_t<dimension>
const& t_vertex,
double const t_initial_radius,
328 double const t_foliation_spacing) ->
bool
330 auto const timevalue = expected_timevalue<dimension>(
331 t_vertex, t_initial_radius, t_foliation_spacing);
333 spdlog::trace(
"Vertex({}) timevalue {} has expected timevalue == {}\n",
334 utilities::point_to_str(t_vertex->point()), t_vertex->info(),
337 return timevalue == t_vertex->info();
344 template <
int dimension>
346 Delaunay_t<dimension>
const& t_triangulation)
348 std::vector<Vertex_handle_t<dimension>> vertices;
349 for (
auto vit = t_triangulation.finite_vertices_begin();
350 vit != t_triangulation.finite_vertices_end(); ++vit)
353 assert(t_triangulation.tds().is_vertex(vit));
354 vertices.emplace_back(vit);
366 template <
int dimension>
368 Delaunay_t<dimension>
const& t_triangulation,
double t_initial_radius,
369 double t_foliation_spacing)
371 auto checked_vertices = collect_vertices<dimension>(t_triangulation);
372 return std::all_of(checked_vertices.begin(), checked_vertices.end(),
373 [&](
auto const& vertex) {
374 return is_vertex_timevalue_correct<dimension>(
375 vertex, t_initial_radius, t_foliation_spacing);
383 template <
int dimension>
384 [[nodiscard]]
auto collect_cells(Delaunay_t<dimension>
const& t_triangulation)
385 -> std::vector<Cell_handle_t<dimension>>
387 std::vector<Cell_handle_t<dimension>> cells;
388 for (
auto cit = t_triangulation.finite_cells_begin();
389 cit != t_triangulation.finite_cells_end(); ++cit)
392 assert(t_triangulation.tds().is_cell(cit));
393 cells.emplace_back(cit);
401 template <
int dimension>
403 std::vector<Cell_handle_t<dimension>>
const& t_cells)
405 std::unordered_set<Vertex_handle_t<dimension>> cell_vertices;
406 auto get_vertices = [&cell_vertices](
auto const& t_cell) {
407 for (
int i = 0; i < dimension + 1; ++i)
409 cell_vertices.emplace(t_cell->vertex(i));
412 std::for_each(t_cells.begin(), t_cells.end(), get_vertices);
413 std::vector<Vertex_handle_t<dimension>> result(cell_vertices.begin(),
414 cell_vertices.end());
424 template <
int dimension>
426 std::vector<Cell_handle_t<dimension>>
const& t_cells,
427 double t_initial_radius,
double t_foliation_spacing)
429 auto checked_vertices = get_vertices_from_cells<dimension>(t_cells);
430 std::vector<Vertex_handle_t<dimension>> incorrect_vertices;
432 std::copy_if(checked_vertices.begin(), checked_vertices.end(),
433 std::back_inserter(incorrect_vertices),
434 [&](
auto const& vertex) {
435 return !is_vertex_timevalue_correct<dimension>(
436 vertex, t_initial_radius, t_foliation_spacing);
438 return incorrect_vertices;
448 template <
int dimension>
450 Delaunay_t<dimension>
const& t_triangulation,
double t_initial_radius,
451 double t_foliation_spacing)
453 auto cells_to_check = collect_cells<dimension>(t_triangulation);
454 return find_incorrect_vertices<dimension>(cells_to_check, t_initial_radius,
455 t_foliation_spacing);
466 template <
int dimension>
468 std::vector<Cell_handle_t<dimension>>
const& t_cells,
469 double t_initial_radius,
double t_foliation_spacing)
471 auto incorrect_vertices = find_incorrect_vertices<dimension>(
472 t_cells, t_initial_radius, t_foliation_spacing);
473 std::for_each(incorrect_vertices.begin(), incorrect_vertices.end(),
474 [&](
auto const& vertex) {
475 vertex->info() = expected_timevalue<dimension>(
476 vertex, t_initial_radius, t_foliation_spacing);
478 return !incorrect_vertices.empty();
489 template <
int dimension>
490 [[nodiscard]]
auto fix_vertices(Delaunay_t<dimension>
const& t_triangulation,
491 double const t_initial_radius,
492 double const t_foliation_spacing) ->
bool
494 return fix_vertices<dimension>(collect_cells<dimension>(t_triangulation),
495 t_initial_radius, t_foliation_spacing);
502 template <
int dimension>
506 spdlog::debug(
"{} called.\n", __PRETTY_FUNCTION__);
508 std::array<int, static_cast<std::size_t>(dimension) + 1>
511 for (
auto i = 0; i < dimension + 1; ++i)
514 vertex_timevalues.at(
static_cast<std::size_t
>(i)) =
515 t_cell->vertex(i)->info();
517 auto const maxtime_ref =
518 std::max_element(vertex_timevalues.begin(), vertex_timevalues.end());
519 auto const mintime_ref =
520 std::min_element(vertex_timevalues.begin(), vertex_timevalues.end());
521 auto maxtime = *maxtime_ref;
522 auto mintime = *mintime_ref;
524 if (maxtime - mintime != 1 || maxtime == mintime)
527 spdlog::trace(
"This simplex is acausal:\n");
528 spdlog::trace(
"Max timevalue is {} and min timevalue is {}.\n", maxtime,
530 spdlog::trace(
"--\n");
532 return Cell_type::ACAUSAL;
534 std::multiset<int>
const timevalues{vertex_timevalues.begin(),
535 vertex_timevalues.end()};
536 auto max_vertices = timevalues.count(maxtime);
537 auto min_vertices = timevalues.count(mintime);
540 if (max_vertices == 3 && min_vertices == 1) {
return Cell_type::ONE_THREE; }
541 if (max_vertices == 2 && min_vertices == 2) {
return Cell_type::TWO_TWO; }
542 if (max_vertices == 1 && min_vertices == 3) {
return Cell_type::THREE_ONE; }
545 if (max_vertices == 4 && min_vertices == 1) {
return Cell_type::ONE_FOUR; }
546 if (max_vertices == 3 && min_vertices == 2) {
return Cell_type::TWO_THREE; }
547 if (max_vertices == 2 && min_vertices == 3) {
return Cell_type::THREE_TWO; }
548 if (max_vertices == 1 && min_vertices == 4) {
return Cell_type::FOUR_ONE; }
552 spdlog::trace(
"This simplex has an error:\n");
553 spdlog::trace(
"Max timevalue is {} and min timevalue is {}.\n", maxtime,
556 "There are {} vertices with the max timevalue and {} vertices with "
557 "the min timevalue.\n",
558 max_vertices, min_vertices);
559 spdlog::trace(
"--\n");
561 return Cell_type::UNCLASSIFIED;
568 template <
int dimension>
570 Cell_handle_t<dimension>
const& t_cell) ->
bool
572 auto cell_type = expected_cell_type<dimension>(t_cell);
573 return cell_type != Cell_type::ACAUSAL &&
574 cell_type != Cell_type::UNCLASSIFIED &&
575 cell_type ==
static_cast<Cell_type>(t_cell->info());
583 template <
int dimension>
584 [[nodiscard]]
auto check_cells(Delaunay_t<dimension>
const& t_triangulation)
587 auto checked_cells = collect_cells<dimension>(t_triangulation);
588 return checked_cells.empty() ||
589 std::all_of(checked_cells.begin(), checked_cells.end(),
590 [&](
auto const& cell) {
591 return is_cell_type_correct<dimension>(cell);
599 template <
int dimension>
601 Delaunay_t<dimension>
const& t_triangulation)
603 auto checked_cells = collect_cells<dimension>(t_triangulation);
605 std::vector<Cell_handle_t<dimension>> incorrect_cells;
606 std::copy_if(checked_cells.begin(), checked_cells.end(),
607 std::back_inserter(incorrect_cells), [&](
auto const& cell) {
608 return !is_cell_type_correct<dimension>(cell);
610 return incorrect_cells;
617 template <
int dimension>
618 [[nodiscard]]
auto fix_cells(Delaunay_t<dimension>
const& t_triangulation)
621 auto incorrect_cells = find_incorrect_cells<dimension>(t_triangulation);
623 incorrect_cells.begin(), incorrect_cells.end(), [&](
auto const& cell) {
625 static_cast<Int_precision>(expected_cell_type<dimension>(cell));
627 return !incorrect_cells.empty();
633 template <
int dimension>
636 fmt::print(
"Cell info => {}\n", cell->info());
638 for (
int j = 0; j < dimension + 1; ++j)
640 fmt::print(
"Vertex({}) Point: ({}) Timevalue: {}\n", j,
641 utilities::point_to_str(cell->vertex(j)->point()),
642 cell->vertex(j)->info());
651 template <
int dimension,
typename Container>
654 for (
auto cells = std::forward<Container>(t_cells);
655 auto const& cell : cells)
657 print_cell<dimension>(cell);
666 template <
int dimension, ContainerType Container>
669 for (
auto cells = std::forward<Container>(t_cells);
670 auto const& cell : cells)
672 spdlog::debug(
"Cell info => {}\n", cell->info());
673 for (
int j = 0; j < dimension + 1; ++j)
675 spdlog::debug(
"Vertex({}) Point: ({}) Timevalue: {}\n", j,
676 utilities::point_to_str(cell->vertex(j)->point()),
677 cell->vertex(j)->info());
679 spdlog::debug(
"---\n");
686 template <
int dimension>
689 for (
int j = 0; j < dimension + 1; ++j)
691 fmt::print(
"Neighboring cell {}:", j);
692 print_cell<dimension>(cell->neighbor(j));
704 template <
int dimension>
708 "Edge: Vertex({}) Point({}) Timevalue: {} -> Vertex({}) Point({}) "
711 utilities::point_to_str(t_edge.first->vertex(t_edge.second)->point()),
712 t_edge.first->vertex(t_edge.second)->info(), t_edge.third,
713 utilities::point_to_str(t_edge.first->vertex(t_edge.third)->point()),
714 t_edge.first->vertex(t_edge.third)->info());
723 template <
int dimension, ContainerType Container>
725 -> std::multimap<Int_precision, Facet_t<3>>
728 spdlog::debug(
"{} called.\n", __PRETTY_FUNCTION__);
730 std::multimap<Int_precision, Facet_t<3>> space_faces;
731 for (
auto facets = std::forward<Container>(t_facets);
732 auto const& face : facets)
734 Cell_handle_t<dimension>
const cell = face.first;
735 auto index_of_facet = face.second;
737 spdlog::trace(
"Facet index is {}\n", index_of_facet);
739 std::set<Int_precision> facet_timevalues;
741 for (
int i = 0; i < dimension + 1; ++i)
743 if (i != index_of_facet)
746 spdlog::trace(
"Vertex[{}] has timevalue {}\n", i,
747 cell->vertex(i)->info());
749 facet_timevalues.insert(cell->vertex(i)->info());
754 if (facet_timevalues.size() == 1)
757 spdlog::trace(
"Facet is spacelike on timevalue {}.\n",
758 *facet_timevalues.begin());
760 space_faces.insert({*facet_timevalues.begin(), face});
765 spdlog::trace(
"Facet is timelike.\n");
786 template <
int dimension>
788 Delaunay_t<dimension>
const& t_triangulation)
789 -> std::optional<std::vector<Cell_handle_t<dimension>>>
791 auto const& cells = collect_cells<dimension>(t_triangulation);
792 std::vector<Cell_handle_t<dimension>> invalid_cells;
794 cells.begin(), cells.end(), std::back_inserter(invalid_cells),
795 [](
auto const& cell) {
796 return expected_cell_type<dimension>(cell) == Cell_type::ACAUSAL ||
797 expected_cell_type<dimension>(cell) == Cell_type::UNCLASSIFIED;
799 auto result = invalid_cells.empty() ? std::nullopt
800 : std::make_optional(invalid_cells);
808 template <
int dimension>
810 -> Vertex_handle_t<dimension>
813 spdlog::debug(
"{} called.\n", __PRETTY_FUNCTION__);
814 spdlog::debug(
"===Invalid Cell===\n");
815 std::vector<Cell_handle_t<dimension>> bad_cell{cell};
816 debug_print_cells<dimension>(std::span{bad_cell});
818 std::multimap<Int_precision, Vertex_handle_t<dimension>> vertices;
819 for (
int i = 0; i < dimension + 1; ++i)
822 std::make_pair(cell->vertex(i)->info(), cell->vertex(i)));
825 auto const minvalue = vertices.cbegin()->first;
826 auto const maxvalue = vertices.crbegin()->first;
827 auto const minvalue_count = vertices.count(minvalue);
828 auto const maxvalue_count = vertices.count(maxvalue);
833 return minvalue_count >= maxvalue_count ? vertices.rbegin()->second
834 : vertices.begin()->second;
842 template <
int dimension>
847 if (
auto invalid_cells = check_timevalues<dimension>(t_triangulation);
850 std::set<Vertex_handle_t<dimension>> vertices_to_remove;
854 invalid_cells->begin(), invalid_cells->end(),
855 std::inserter(vertices_to_remove, vertices_to_remove.begin()),
856 find_bad_vertex<dimension>);
859 spdlog::warn(
"There are {} invalid vertices.\n",
860 vertices_to_remove.size());
862 t_triangulation.remove(vertices_to_remove.begin(),
863 vertices_to_remove.end());
864 assert(t_triangulation.tds().is_valid());
865 assert(t_triangulation.is_valid());
881 template <
int dimension>
885 double const foliation_spacing = FOLIATION_SPACING)
887 Causal_vertices_t<dimension> causal_vertices;
888 causal_vertices.reserve(
static_cast<std::size_t
>(t_simplices));
889 auto const points_per_timeslice = utilities::expected_points_per_timeslice(
890 dimension, t_simplices, t_timeslices);
891 assert(points_per_timeslice >= 2);
893 for (gsl::index i = 0; i < t_timeslices; ++i)
896 initial_radius +
static_cast<double>(i) * foliation_spacing;
897 Spherical_points_generator_t<dimension> gen{radius};
899 for (gsl::index j = 0;
900 j < static_cast<Int_precision>(points_per_timeslice * radius); ++j)
902 causal_vertices.emplace_back(*gen++, i + 1);
905 return causal_vertices;
915 template <
int dimension>
919 double const foliation_spacing = FOLIATION_SPACING)
920 -> Delaunay_t<dimension>
923 spdlog::debug(
"{} called.\n", __PRETTY_FUNCTION__);
925 fmt::print(
"\nGenerating universe ...\n");
926#ifdef CGAL_LINKED_WITH_TBB
929 auto bounding_box_size =
static_cast<double>(t_timeslices + 1);
930 typename Delaunay_t<dimension>::Lock_data_structure locking_ds{
931 CGAL::Bbox_3{-bounding_box_size, -bounding_box_size, -bounding_box_size,
932 bounding_box_size, bounding_box_size, bounding_box_size},
935 Delaunay_t<dimension> triangulation =
938 Delaunay_t<dimension> triangulation = Delaunay_t<dimension>{};
942 auto causal_vertices = make_foliated_ball<dimension>(
943 t_simplices, t_timeslices, initial_radius, foliation_spacing);
944 triangulation.insert(causal_vertices.begin(), causal_vertices.end());
947 for (
auto passes = 1; passes < MAX_FIX_PASSES + 1; ++passes)
949 if (!fix_vertices<dimension>(triangulation, initial_radius,
955 spdlog::warn(
"Deleting incorrect vertices pass #{}\n", passes);
960 for (
auto passes = 1; passes < MAX_FIX_PASSES + 1; ++passes)
962 if (!fix_timevalues<dimension>(triangulation)) {
break; }
964 spdlog::warn(
"Fixing timeslices pass #{}\n", passes);
969 for (
auto i = 1; i < MAX_FIX_PASSES + 1; ++i)
971 if (!fix_cells<dimension>(triangulation)) {
break; }
973 spdlog::warn(
"Fixing incorrect cells pass #{}\n", i);
977 utilities::print_delaunay(triangulation);
978 assert(!check_timevalues<dimension>(triangulation));
979 return triangulation;
984 template <
int dimension>
997 using Delaunay = Delaunay_t<3>;
998 using Cell_handle = Cell_handle_t<3>;
999 using Cell_container = std::vector<Cell_handle>;
1000 using Face_container = std::vector<Face_handle_t<3>>;
1001 using Edge_container = std::vector<Edge_handle_t<3>>;
1002 using Vertex_handle = Vertex_handle_t<3>;
1003 using Vertex_container = std::vector<Vertex_handle>;
1004 using Volume_by_timeslice = std::multimap<Int_precision, Facet_t<3>>;
1008 Delaunay m_triangulation{Delaunay{}};
1010 double m_foliation_spacing{FOLIATION_SPACING};
1011 Vertex_container m_vertices;
1012 Cell_container m_cells;
1013 Cell_container m_three_one;
1014 Cell_container m_two_two;
1015 Cell_container m_one_three;
1016 Face_container m_faces;
1017 Volume_by_timeslice m_spacelike_facets;
1018 Edge_container m_edges;
1019 Edge_container m_timelike_edges;
1020 Edge_container m_spacelike_edges;
1034 static_cast<Delaunay const&
>(other.get_delaunay()),
1035 other.m_initial_radius, other.m_foliation_spacing)
1063 spdlog::debug(
"{} called.\n", __PRETTY_FUNCTION__);
1069 swap_into.m_triangulation.swap(swap_from.m_triangulation);
1071 swap(swap_from.m_initial_radius, swap_into.m_initial_radius);
1072 swap(swap_from.m_foliation_spacing, swap_into.m_foliation_spacing);
1073 swap(swap_from.m_vertices, swap_into.m_vertices);
1074 swap(swap_from.m_cells, swap_into.m_cells);
1075 swap(swap_from.m_three_one, swap_into.m_three_one);
1076 swap(swap_from.m_two_two, swap_into.m_two_two);
1077 swap(swap_from.m_one_three, swap_into.m_one_three);
1078 swap(swap_from.m_faces, swap_into.m_faces);
1079 swap(swap_from.m_spacelike_facets, swap_into.m_spacelike_facets);
1080 swap(swap_from.m_edges, swap_into.m_edges);
1081 swap(swap_from.m_timelike_edges, swap_into.m_timelike_edges);
1082 swap(swap_from.m_spacelike_edges, swap_into.m_spacelike_edges);
1083 swap(swap_from.m_max_timevalue, swap_into.m_max_timevalue);
1084 swap(swap_from.m_min_timevalue, swap_into.m_min_timevalue);
1095 Delaunay triangulation,
double const initial_radius =
INITIAL_RADIUS,
1096 double const foliation_spacing = FOLIATION_SPACING)
1097 : m_triangulation{std::move(triangulation)}
1098 , m_initial_radius{initial_radius}
1099 , m_foliation_spacing{foliation_spacing}
1101 , m_cells{classify_cells(
collect_cells<3>(m_triangulation))}
1105 , m_faces{collect_faces()}
1122 double const t_foliation_spacing = FOLIATION_SPACING)
1125 t_foliation_spacing),
1126 t_initial_radius, t_foliation_spacing}
1135 Causal_vertices_t<3>
const& causal_vertices,
1137 double const t_foliation_spacing = FOLIATION_SPACING)
1139 Delaunay{causal_vertices.begin(), causal_vertices.end()},
1140 t_initial_radius, t_foliation_spacing
1152 return !
static_cast<bool>(check_timevalues<3>(this->get_delaunay()));
1158 return get_delaunay().is_valid();
1164 return get_delaunay().tds().is_valid();
1170 return is_foliated() && is_tds_valid() && check_all_cells();
1177 return is_correct() && is_delaunay();
1183 auto const fixed_vertices = foliated_triangulations::fix_vertices<3>(
1184 m_triangulation, m_initial_radius, m_foliation_spacing);
1185 auto const fixed_cells =
1186 foliated_triangulations::fix_cells<3>(m_triangulation);
1187 auto const fixed_timeslices =
1188 foliated_triangulations::fix_timevalues<3>(m_triangulation);
1189 return fixed_vertices || fixed_cells || fixed_timeslices;
1193 [[nodiscard]]
auto delaunay() -> Delaunay& {
return m_triangulation; }
1198 return std::cref(m_triangulation);
1204 return m_triangulation.number_of_finite_cells();
1210 return m_triangulation.number_of_finite_facets();
1216 return m_triangulation.number_of_finite_edges();
1222 return m_triangulation.number_of_vertices();
1227 template <
typename VertexHandle>
1230 return m_triangulation.is_infinite(std::forward<VertexHandle>(t_vertex));
1241 template <
typename... Ts>
1242 [[nodiscard]]
auto flip(Ts&&... args)
1244 return m_triangulation.flip(std::forward<Ts>(args)...);
1250 return m_triangulation.infinite_vertex();
1254 [[nodiscard]]
auto dimension()
const {
return m_triangulation.dimension(); }
1260 return m_spacelike_facets;
1272 return static_cast<Int_precision>(m_spacelike_edges.size());
1277 -> Edge_container const&
1279 return m_timelike_edges;
1285 return m_spacelike_edges;
1289 [[nodiscard]]
auto get_vertices() const noexcept -> Vertex_container const&
1296 -> std::span<Vertex_handle const>
1298 return std::span{m_vertices};
1302 [[nodiscard]]
auto max_time()
const {
return m_max_timevalue; }
1305 [[nodiscard]]
auto min_time()
const {
return m_min_timevalue; }
1317 template <
typename VertexHandle>
1318 [[nodiscard]]
auto degree(VertexHandle&& t_vertex)
const
1320 return m_triangulation.degree(std::forward<VertexHandle>(t_vertex));
1331 template <
typename VertexHandle>
1335 Cell_container inc_cells;
1336 get_delaunay().tds().incident_cells(std::forward<VertexHandle>(t_vh),
1337 std::back_inserter(inc_cells));
1348 template <
typename... Ts>
1352 return get_delaunay().tds().incident_cells(std::forward<Ts>(args)...);
1360 Vertex_handle_t<3>
const t_vertex)
const ->
bool
1362 auto const actual_radius_squared = squared_radius<3>(t_vertex);
1363 auto const radius = expected_radius(t_vertex);
1364 auto const expected_radius_squared = std::pow(radius, 2);
1365 return actual_radius_squared >
1366 expected_radius_squared * (1 -
TOLERANCE) &&
1367 actual_radius_squared < expected_radius_squared * (1 +
TOLERANCE);
1382 auto const timevalue = t_vertex->info();
1383 return m_initial_radius + m_foliation_spacing * (timevalue - 1);
1390 Vertex_handle_t<3>
const& t_vertex)
const ->
int
1392 return foliated_triangulations::expected_timevalue<3>(
1393 t_vertex, m_initial_radius, m_foliation_spacing);
1399 return foliated_triangulations::check_vertices<3>(
1400 m_triangulation, m_initial_radius, m_foliation_spacing);
1406 return foliated_triangulations::find_incorrect_vertices<3>(
1407 m_triangulation, m_initial_radius, m_foliation_spacing);
1413 return foliated_triangulations::fix_vertices<3>(
1414 m_triangulation, m_initial_radius, m_foliation_spacing);
1420 for (
auto const& vertex : m_vertices)
1422 fmt::print(
"Vertex Point: ({}) Timevalue: {} Expected Timevalue: {}\n",
1423 utilities::point_to_str(vertex->point()), vertex->info(),
1432 for (
auto const& edge : m_edges)
1434 if (classify_edge<3>(edge)) { fmt::print(
"==> timelike\n"); }
1435 else { fmt::print(
"==> spacelike\n"); }
1442 for (
auto j = min_time(); j <= max_time(); ++j)
1444 fmt::print(
"Timeslice {} has {} spacelike faces.\n", j,
1445 m_spacelike_facets.count(j));
1450 [[nodiscard]]
auto get_cells() const -> Cell_container const&
1452 assert(m_cells.size() == number_of_finite_cells());
1458 -> std::span<Cell_handle const>
1460 return std::span{m_three_one};
1464 [[nodiscard]]
auto get_two_two() const noexcept -> Cell_container const&
1482 return foliated_triangulations::check_cells<3>(get_delaunay());
1488 return foliated_triangulations::fix_cells<3>(get_delaunay());
1495 foliated_triangulations::print_cells<3>(m_cells);
1502 "Triangulation has {} vertices and {} edges and {} faces and {} "
1504 this->number_of_vertices(), this->number_of_finite_edges(),
1505 this->number_of_finite_facets(), this->number_of_finite_cells());
1509 [[nodiscard]]
auto classify_vertices(Vertex_container
const& vertices)
const
1512 assert(vertices.size() == number_of_vertices());
1513 for (
auto const& vertex : vertices)
1526 assert(cells.size() == number_of_finite_cells());
1527 for (
auto const& cell : cells)
1529 cell->info() =
static_cast<int>(expected_cell_type<3>(cell));
1538 assert(is_tds_valid());
1539 Face_container init_faces;
1540 init_faces.reserve(get_delaunay().number_of_finite_facets());
1541 for (
auto fit = get_delaunay().finite_facets_begin();
1542 fit != get_delaunay().finite_facets_end(); ++fit)
1544 Cell_handle_t<3>
const cell = fit->first;
1546 assert(get_delaunay().tds().is_facet(cell, fit->second));
1547 Face_handle_t<3>
const thisFacet{std::make_pair(cell, fit->second)};
1548 init_faces.emplace_back(thisFacet);
1550 assert(init_faces.size() == get_delaunay().number_of_finite_facets());
1557 assert(is_tds_valid());
1558 Edge_container init_edges;
1559 init_edges.reserve(number_of_finite_edges());
1560 for (
auto eit = get_delaunay().finite_edges_begin();
1561 eit != get_delaunay().finite_edges_end(); ++eit)
1563 Cell_handle_t<3>
const cell = eit->first;
1564 Edge_handle_t<3>
const thisEdge{cell,
1565 cell->index(cell->vertex(eit->second)),
1566 cell->index(cell->vertex(eit->third))};
1568 assert(get_delaunay().tds().is_valid(thisEdge.first, thisEdge.second,
1570 init_edges.emplace_back(thisEdge);
1572 assert(init_edges.size() == number_of_finite_edges());
1577 using FoliatedTriangulation_3 = FoliatedTriangulation<3>;
void print_edge(Edge_handle_t< dimension > const &t_edge)
Print edge.
auto get_vertices_from_cells(std::vector< Cell_handle_t< dimension > > const &t_cells)
Extracts vertices from cells.
auto find_min_timevalue(Container &&t_vertices) -> Int_precision
auto filter_edges(std::vector< Edge_handle_t< dimension > > const &t_edges, bool t_is_Timelike_pred) -> std::vector< Edge_handle_t< dimension > >
auto squared_radius(Vertex_handle_t< dimension > const &t_vertex) -> double
Calculate the squared radius from the origin.
auto make_causal_vertices(std::span< Point_t< dimension > const > vertices, std::span< size_t const > timevalues) -> Causal_vertices_t< dimension >
Create causal vertices from vertices and timevalues.
auto fix_timevalues(Delaunay_t< dimension > &t_triangulation) -> bool
Fix the vertices of a cell to be consistent with the foliation.
void print_neighboring_cells(Cell_handle_t< dimension > cell)
Print neighboring cells.
auto check_cells(Delaunay_t< dimension > const &t_triangulation) -> bool
Check all finite cells in the Delaunay triangulation.
auto constexpr compare_v_info
auto collect_vertices(Delaunay_t< dimension > const &t_triangulation)
Obtain all finite vertices in the Delaunay triangulation.
auto check_timevalues(Delaunay_t< dimension > const &t_triangulation) -> std::optional< std::vector< Cell_handle_t< dimension > > >
Check cells for correct foliation.
auto is_cell_type_correct(Cell_handle_t< dimension > const &t_cell) -> bool
Checks if a cell is classified correctly.
void print_cell(Cell_handle_t< dimension > cell)
Print a cell in the triangulation.
auto expected_timevalue(Vertex_handle_t< dimension > const &t_vertex, double t_initial_radius, double t_foliation_spacing) -> Int_precision
Find the expected timevalue for a vertex.
auto collect_edges(Delaunay_t< dimension > const &delaunay)
Returns a container of all the finite edges in the triangulation.
auto classify_edge(Edge_handle_t< dimension > const &t_edge) -> bool
Predicate to classify edge as timelike or spacelike.
auto check_vertices(Delaunay_t< dimension > const &t_triangulation, double t_initial_radius, double t_foliation_spacing)
Check if vertices have the correct timevalues.
auto find_vertex(Delaunay_t< dimension > const &delaunay, Point_t< dimension > const &point) -> std::optional< Vertex_handle_t< dimension > >
Returns the vertex containing the given point.
Cell_type
(n,m) is number of vertices on (lower, higher) timeslice
auto find_incorrect_vertices(std::vector< Cell_handle_t< dimension > > const &t_cells, double t_initial_radius, double t_foliation_spacing)
Obtain vertices with incorrect timevalues.
auto is_vertex_timevalue_correct(Vertex_handle_t< dimension > const &t_vertex, double const t_initial_radius, double const t_foliation_spacing) -> bool
Checks if vertex timevalue is correct.
void debug_print_cells(Container &&t_cells)
Write to debug log timevalues of each vertex in the cell and the resulting cell->info.
auto collect_cells(Delaunay_t< dimension > const &t_triangulation) -> std::vector< Cell_handle_t< dimension > >
Obtain all finite cells in the Delaunay triangulation.
auto volume_per_timeslice(Container &&t_facets) -> std::multimap< Int_precision, Facet_t< 3 > >
Collect spacelike facets into a container indexed by time value.
auto fix_cells(Delaunay_t< dimension > const &t_triangulation) -> bool
Fix simplices with the wrong type.
auto filter_cells(std::vector< Cell_handle_t< dimension > > const &t_cells, Cell_type const &t_cell_type) -> std::vector< Cell_handle_t< dimension > >
auto find_max_timevalue(Container &&t_vertices) -> Int_precision
auto expected_cell_type(Cell_handle_t< dimension > const &t_cell)
Classifies cells by their timevalues.
auto find_cell(Delaunay_t< dimension > const &delaunay, Vertex_handle_t< dimension > const &vh1, Vertex_handle_t< dimension > const &vh2, Vertex_handle_t< dimension > const &vh3, Vertex_handle_t< dimension > const &vh4) -> std::optional< Cell_handle_t< dimension > >
Returns the cell containing the vertices.
void print_cells(Container &&t_cells)
Print timevalues of each vertex in the cell and the resulting cell->info()
auto find_incorrect_cells(Delaunay_t< dimension > const &t_triangulation)
Check all finite cells in the Delaunay triangulation.
auto find_bad_vertex(Cell_handle_t< dimension > const &cell) -> Vertex_handle_t< dimension >
Find the vertex that is causing a cell's foliation to be invalid.
auto fix_vertices(std::vector< Cell_handle_t< dimension > > const &t_cells, double t_initial_radius, double t_foliation_spacing)
Fix vertices with incorrect timevalues.
auto make_foliated_ball(Int_precision const t_simplices, Int_precision const t_timeslices, double const initial_radius=INITIAL_RADIUS, double const foliation_spacing=FOLIATION_SPACING)
Make foliated ball.
auto make_triangulation(Int_precision const t_simplices, Int_precision t_timeslices, double const initial_radius=INITIAL_RADIUS, double const foliation_spacing=FOLIATION_SPACING) -> Delaunay_t< dimension >
Make a Delaunay triangulation.
static double constexpr TOLERANCE
Sets epsilon values for floating point comparisons.
std::int_fast32_t Int_precision
static double constexpr INITIAL_RADIUS
Default foliated triangulation spacings.
Traits class for particular uses of CGAL.
auto incident_cells(Ts &&... args) const noexcept -> decltype(auto)
Perfect forwarding to TriangulationDataStructure_3::incident_cells.
auto find_incorrect_vertices() const
auto infinite_vertex() const
void print_vertices() const
Print values of a vertex.
FoliatedTriangulation(FoliatedTriangulation &&other) noexcept
Move ctor.
auto is_foliated() const -> bool
Verifies the triangulation is properly foliated.
FoliatedTriangulation(Int_precision const t_simplices, Int_precision const t_timeslices, double const t_initial_radius=INITIAL_RADIUS, double const t_foliation_spacing=FOLIATION_SPACING)
Constructor with parameters.
void print_edges() const
Print timevalues of each vertex in the edge and classify as timelike or spacelike.
auto get_vertices_span() const noexcept -> std::span< Vertex_handle const >
auto initial_radius() const
auto degree(VertexHandle &&t_vertex) const
Perfect forwarding to TriangulationDataStructure_3::degree.
auto N2_SL() const -> std::multimap< Int_precision, TriangulationTraits< 3 >::Facet > const &
auto is_initialized() const -> bool
auto get_spacelike_edges() const -> Edge_container const &
auto get_one_three() const noexcept -> Cell_container const &
auto number_of_finite_edges() const
auto is_correct() const -> bool
void print_volume_per_timeslice() const
Print the number of spacelike faces per timeslice.
~FoliatedTriangulation()=default
Default dtor.
FoliatedTriangulation(Delaunay triangulation, double const initial_radius=INITIAL_RADIUS, double const foliation_spacing=FOLIATION_SPACING)
Constructor using delaunay triangulation Pass-by-value-then-move. Delaunay is the ctor for the Delaun...
auto get_delaunay() const -> Delaunay const &
auto get_three_one() const noexcept -> std::span< Cell_handle const >
FoliatedTriangulation(Causal_vertices_t< 3 > const &causal_vertices, double const t_initial_radius=INITIAL_RADIUS, double const t_foliation_spacing=FOLIATION_SPACING)
Constructor from Causal_vertices.
auto delaunay() -> Delaunay &
auto does_vertex_radius_match_timevalue(Vertex_handle_t< 3 > const t_vertex) const -> bool
Check the radius of a vertex from the origin with its timevalue.
FoliatedTriangulation(FoliatedTriangulation const &other) noexcept
Copy Constructor.
auto is_infinite(VertexHandle &&t_vertex) const
auto flip(Ts &&... args)
Call one of the TSD3.flip functions.
auto get_timelike_edges() const noexcept -> Edge_container const &
auto foliation_spacing() const
auto fix_vertices() const -> bool
Fix vertices with wrong timevalues after foliation.
auto fix_cells() const -> bool
Fix all cells in the triangulation.
void print() const
Print triangulation statistics.
auto get_vertices() const noexcept -> Vertex_container const &
auto operator=(FoliatedTriangulation other) noexcept -> FoliatedTriangulation &
Copy/Move Assignment operator.
auto check_all_vertices() const -> bool
auto get_cells() const -> Cell_container const &
auto incident_cells(VertexHandle &&t_vh) const noexcept -> decltype(auto)
Perfect forwarding to TriangulationDataStructure_3::incident_cells.
auto expected_timevalue(Vertex_handle_t< 3 > const &t_vertex) const -> int
Calculate the expected timevalue for a vertex.
auto get_two_two() const noexcept -> Cell_container const &
auto expected_radius(Vertex_handle_t< 3 > const &t_vertex) const -> double
Calculates the expected radial distance of a vertex.
auto number_of_finite_cells() const
friend void swap(FoliatedTriangulation &swap_from, FoliatedTriangulation &swap_into) noexcept
Non-member swap function for Foliated Triangulations.
FoliatedTriangulation()=default
Default ctor.
auto is_tds_valid() const -> bool
auto check_all_cells() const -> bool
Check that all cells are correctly classified.
void print_cells() const
Print timevalues of each vertex in the cell and the resulting cell->info()
auto classify_cells(Cell_container const &cells) const -> Cell_container
Classify cells.
auto number_of_finite_facets() const
auto collect_edges() const -> Edge_container
auto number_of_vertices() const
auto is_delaunay() const -> bool
auto collect_faces() const -> Face_container
This is std::movable from <concepts>