deal.II version GIT relicensing-6917-gb466a1809f 2026-10-16 06:30:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
grid_generator_cgal.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2022 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
14
17
18#ifdef DEAL_II_WITH_CGAL
19// Functions needed by the CGAL mesh generation utilities are inside
21
22# include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
23# include <CGAL/Labeled_mesh_domain_3.h>
24# include <CGAL/Mesh_triangulation_3.h>
25#endif
26
27
29
30// work around the problem that doxygen for some reason lists all template
31// specializations in this file
32#ifndef DOXYGEN
33
34namespace GridGenerator
35{
36 template <int dim>
37 void
39 const Function<3> &dealii_implicit_function,
41 const Point<3> &interior_point,
42 const double &outer_ball_radius)
43 {
44# ifdef DEAL_II_WITH_CGAL
45 Assert(dealii_implicit_function.n_components == 1,
47 "The implicit function must have exactly one component."));
48 Assert(dealii_implicit_function.value(interior_point) < 0,
50 "The implicit function must be negative at the interior point."));
51 Assert(outer_ball_radius > 0,
52 ExcMessage("The outer ball radius must be positive."));
53 Assert(tria.n_active_cells() == 0,
54 ExcMessage("The triangulation must be empty."));
55
56 if constexpr (dim == 3)
57 {
58 using K = CGAL::Exact_predicates_inexact_constructions_kernel;
59 using NumberType = K::FT;
60 using Point_3 = K::Point_3;
61 using Sphere_3 = K::Sphere_3;
62
63 using Mesh_domain = CGAL::Labeled_mesh_domain_3<K>;
64 using Tr =
65 CGAL::Mesh_triangulation_3<Mesh_domain,
66 CGAL::Default,
68 using C3t3 = CGAL::Mesh_complex_3_in_triangulation_3<Tr, int, int>;
69 using Mesh_criteria = CGAL::Mesh_criteria_3<Tr>;
70
71
72 auto cgal_implicit_function = [&](const Point_3 &p) {
73 return NumberType(
74 dealii_implicit_function.value(Point<3>(p.x(), p.y(), p.z())));
75 };
76
77 Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(
78 cgal_implicit_function,
79 K::Sphere_3(
80 Point_3(interior_point[0], interior_point[1], interior_point[2]),
81 outer_ball_radius * outer_ball_radius));
82
83 Mesh_criteria criteria(CGAL::parameters::facet_size = data.facet_size,
84 CGAL::parameters::facet_angle = data.facet_angle,
85 CGAL::parameters::facet_distance =
86 data.facet_distance,
87 CGAL::parameters::cell_radius_edge_ratio =
88 data.cell_radius_edge_ratio,
89 CGAL::parameters::cell_size = data.cell_size);
90
91 auto cgal_triangulation = CGAL::make_mesh_3<C3t3>(domain, criteria);
92 CGALWrappers::cgal_triangulation_to_dealii_triangulation(
93 cgal_triangulation, tria);
94 }
95 else if constexpr (dim == 2)
96 {
97 // default triangulation for Surface_mesher
98 using Tr = CGAL::Surface_mesh_default_triangulation_3;
99 using C2t3 = CGAL::Complex_2_in_triangulation_3<Tr>;
100 using GT = Tr::Geom_traits;
101 using Sphere_3 = GT::Sphere_3;
102 using Point_3 = GT::Point_3;
103 using FT = GT::FT;
104 using Function = FT (*)(Point_3);
105 using Surface_3 = CGAL::Implicit_surface_3<GT, Function>;
106 using Surface_mesh = CGAL::Surface_mesh<Point_3>;
107
108
109 auto cgal_implicit_function = [&](const Point_3 &p) {
110 return FT(
111 dealii_implicit_function.value(Point<3>(p.x(), p.y(), p.z())));
112 };
113
114 Surface_3 surface(cgal_implicit_function,
115 Sphere_3(Point_3(interior_point[0],
116 interior_point[1],
117 interior_point[2]),
118 outer_ball_radius * outer_ball_radius));
119
120 Tr tr;
121 C2t3 c2t3(tr);
122 Surface_mesh mesh;
123
124 CGAL::Surface_mesh_default_criteria_3<Tr> criteria(data.angular_bound,
125 data.radius_bound,
126 data.distance_bound);
127 CGAL::make_surface_mesh(c2t3,
128 surface,
129 criteria,
130 CGAL::Non_manifold_tag());
131 CGAL::facets_in_complex_2_to_triangle_mesh(c2t3, mesh);
132 CGALWrappers::cgal_surface_mesh_to_dealii_triangulation(mesh, tria);
133 }
134 else
135 {
136 Assert(false, ExcImpossibleInDim(dim));
137 }
138
139# else
140
141 (void)tria;
142 (void)dealii_implicit_function;
143 (void)data;
144 (void)interior_point;
145 (void)outer_ball_radius;
146 AssertThrow(false, ExcMessage("This function needs CGAL to be installed."));
147
148# endif
149 }
150
151
152
153 void
155 Triangulation<3> &vol_tria,
157 {
158# ifdef DEAL_II_WITH_CGAL
159 Assert(
160 surface_tria.n_cells() > 0,
162 "The input triangulation cannot be empty when calling this function."));
163 Assert(
164 vol_tria.n_cells() == 0,
166 "The output triangulation must be empty when calling this function."));
167 using K = CGAL::Exact_predicates_inexact_constructions_kernel;
168 using Point_3 = K::Point_3;
169
170 using Mesh_domain =
171 CGAL::Polyhedral_mesh_domain_with_features_3<K,
172 CGAL::Surface_mesh<Point_3>>;
173 using Tr = CGAL::Mesh_triangulation_3<Mesh_domain,
174 CGAL::Default,
176 using Mesh_criteria = CGAL::Mesh_criteria_3<Tr>;
177 using C3t3 =
178 CGAL::Mesh_complex_3_in_triangulation_3<Tr,
179 Mesh_domain::Corner_index,
180 Mesh_domain::Curve_index>;
181
182 CGAL::Surface_mesh<Point_3> mesh;
183 // This function "fills" the missing arrow of the following diagram.
184 // Tria<2,3> Tria<3>
185 // | ^
186 // | |
187 // | |
188 // | |
189 // V |
190 // CGAL::Surface_mesh -----------> CGAL::C3t3
192 CGAL::Polygon_mesh_processing::triangulate_faces(mesh);
193 CGAL::Polygon_mesh_processing::stitch_borders(mesh);
194 Mesh_domain domain(mesh);
195 domain.detect_features();
196 Mesh_criteria criteria(CGAL::parameters::facet_size = data.facet_size,
197 CGAL::parameters::facet_angle = data.facet_angle,
198 CGAL::parameters::facet_distance =
199 data.facet_distance,
200 CGAL::parameters::cell_radius_edge_ratio =
201 data.cell_radius_edge_ratio,
202 CGAL::parameters::cell_size = data.cell_size);
203 const auto cgal_triangulation = CGAL::make_mesh_3<C3t3>(domain, criteria);
204 CGALWrappers::cgal_triangulation_to_dealii_triangulation(cgal_triangulation,
205 vol_tria);
206
207# else
208
209 (void)surface_tria;
210 (void)vol_tria;
211 (void)data;
212 AssertThrow(false, ExcMessage("This function needs CGAL to be installed."));
213
214# endif
215 }
216} // namespace GridGenerator
217
218// explicit instantiations
219# include "grid/grid_generator_cgal.inst"
220
221#endif // DOXYGEN
222
const unsigned int n_components
Definition function.h:162
virtual RangeNumberType value(const Point< dim > &p, const unsigned int component=0) const
Definition point.h:111
unsigned int n_active_cells() const
unsigned int n_cells() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
void dealii_tria_to_cgal_surface_mesh(const ::Triangulation< dim, spacedim > &triangulation, CGAL::Surface_mesh< CGALPointType > &mesh)
CGAL::Surface_mesh< K_exact::Point_3 > Surface_mesh
CGAL::Sequential_tag ConcurrencyTag
Definition utilities.h:87
CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt K
void surface_mesh_to_volumetric_mesh(const Triangulation< 2, 3 > &surface_tria, Triangulation< 3 > &vol_tria, const CGALWrappers::AdditionalData< 3 > &data=CGALWrappers::AdditionalData< 3 >{})
void implicit_function(Triangulation< dim, 3 > &tria, const Function< 3 > &implicit_function, const CGALWrappers::AdditionalData< dim > &data=CGALWrappers::AdditionalData< dim >{}, const Point< 3 > &interior_point=Point< 3 >(), const double &outer_ball_radius=1.0)