deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20: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
closest_surface_point.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) 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
16
18namespace NonMatching
19{
20 template <int dim, class Number>
22 const ReadVector<Number> &level_set,
23 const DoFHandler<dim> &dof_handler,
24 Mapping<dim> &mapping,
25 const AdditionalData &data)
26 : data(data)
27 , dof_handler(&dof_handler)
28 , level_set(&level_set)
29 , mapping(&mapping)
30 {
32 {
34 dof_handler.get_triangulation().n_global_levels(),
35 ExcMessage("Level is larger than number of levels in the "
36 "Triangulation"));
37 }
38 // The only search algorithm that is implemented is for
39 // MappingCartesian, so we assert that the mapping is of this type.
41 dynamic_cast<const MappingCartesian<dim> *>(&mapping) != nullptr,
42 ExcMessage("This class is only implemented with MappingCartesian."));
43 }
44
45
46
47 template <int dim, class Number>
48 std::pair<std::vector<Point<dim>>, std::vector<Point<dim>>>
50 const typename Triangulation<dim>::cell_iterator &search_cell,
51 const typename Triangulation<dim>::cell_iterator &reference_cell,
52 const std::vector<Point<dim>> &quadrature_points) const
53 {
54 std::vector<Point<dim>> closest_unit_search_points(quadrature_points);
55 for (unsigned int q = 0; q < quadrature_points.size(); ++q)
56 closest_unit_search_points[q] =
57 mapping->transform_real_to_unit_cell(search_cell, quadrature_points[q]);
58
59 std::vector<Number> dof_values_level_set(
60 dof_handler->get_fe().dofs_per_cell);
61 std::vector<types::global_dof_index> level_set_dof_indices(
62 dof_handler->get_fe().dofs_per_cell);
63
64 typename DoFHandler<dim>::cell_iterator dof_cell(
65 &search_cell->get_triangulation(),
66 search_cell->level(),
67 search_cell->index(),
68 dof_handler.get());
69
71 dof_cell->get_mg_dof_indices(level_set_dof_indices);
72 else
73 dof_cell->get_dof_indices(level_set_dof_indices);
74
75 level_set->extract_subvector_to(level_set_dof_indices,
76 dof_values_level_set);
77
78 for (size_t i = 0; i < closest_unit_search_points.size(); ++i)
79 {
80 newton_monolithic(closest_unit_search_points[i],
81 dof_handler->get_fe(),
82 dof_values_level_set,
83 closest_unit_search_points[i]);
84 }
85 std::vector<Point<dim>> closest_real_points(quadrature_points.size());
86 std::vector<Point<dim>> closest_unit_reference_points(
87 quadrature_points.size());
88 // back to absolute coordinates
89 for (unsigned int q = 0; q < quadrature_points.size(); ++q)
90 closest_real_points[q] =
91 mapping->transform_unit_to_real_cell(search_cell,
92 closest_unit_search_points[q]);
93
94 for (unsigned int q = 0; q < quadrature_points.size(); ++q)
95 closest_unit_reference_points[q] =
96 mapping->transform_real_to_unit_cell(reference_cell,
97 closest_real_points[q]);
98
99 return {closest_real_points, closest_unit_reference_points};
100 }
101
102
103
104 template <int dim, class Number>
105 void
107 const Point<dim> &point,
108 const FiniteElement<dim> &fe,
109 const std::vector<Number> &dof_values,
110 Point<dim> &closest_point) const
111 {
112 AssertDimension(dof_values.size(), fe.dofs_per_cell);
113
114 Assert(
115 fe.degree > 1,
117 "The Newton iteration to find closest surface points requires hessians "
118 "that are not available when the finite element degree is 1."));
119
120 // X, Y, Z, lambda
121 Vector<double> current_solution(dim + 1);
122 Vector<double> solution_update(dim + 1);
123
124 Vector<double> residual(dim + 1);
125 FullMatrix<double> hessian(dim + 1, dim + 1);
126
127 for (unsigned int i = 0; i < dim; ++i)
128 current_solution[i] = closest_point[i];
129
130
131 for (unsigned int newton_iter = 0; newton_iter < data.n_iterations;
132 ++newton_iter)
133 {
134 hessian = 0.0;
135 residual = 0.0;
136 const double lambda = current_solution[dim];
137 for (unsigned int k = 0; k < dof_values.size(); ++k)
138 {
139 const auto value_k = fe.shape_value(k, closest_point);
140 const auto grad_k = fe.shape_grad(k, closest_point);
141 const auto hess_k = fe.shape_grad_grad(k, closest_point);
142 for (unsigned int i = 0; i < dim; ++i)
143 {
144 for (unsigned int j = 0; j < dim; ++j)
145 hessian(i, j) += lambda * dof_values[k] * hess_k[i][j];
146
147 hessian(i, dim) += dof_values[k] * grad_k[i];
148 hessian(dim, i) += dof_values[k] * grad_k[i];
149 }
150
151 for (unsigned int i = 0; i < dim; ++i)
152 residual[i] -= lambda * dof_values[k] * grad_k[i];
153
154 residual[dim] -= dof_values[k] * value_k;
155 }
156
157
158 for (unsigned int i = 0; i < dim; ++i)
159 {
160 residual[i] -= current_solution[i] - point[i];
161 hessian[i][i] += 1.0;
162 }
163
164 if (residual.l2_norm() < data.tolerance)
165 break;
166
167
168 hessian.gauss_jordan();
169 hessian.vmult(solution_update, residual);
170 current_solution += solution_update;
171
172 for (unsigned int i = 0; i < dim; ++i)
173 closest_point[i] = current_solution[i];
174 }
175
176 // Check if the Newton iteration converged
177 Assert(residual.l2_norm() < data.tolerance,
178 ExcMessage("Newton iteration did not converge"));
179 }
180
181#ifndef DOXYGEN
182# include "non_matching/closest_surface_point.inst"
183#endif
184} // namespace NonMatching
const unsigned int degree
Definition fe_data.h:450
const unsigned int dofs_per_cell
Definition fe_data.h:434
virtual Tensor< 1, dim > shape_grad(const unsigned int i, const Point< dim > &p) const
virtual Tensor< 2, dim > shape_grad_grad(const unsigned int i, const Point< dim > &p) const
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
Abstract base class for mapping classes.
Definition mapping.h:318
ClosestSurfacePoint(const ReadVector< Number > &level_set, const DoFHandler< dim > &dof_handler, Mapping< dim > &mapping, const AdditionalData &data=AdditionalData())
ObserverPointer< const DoFHandler< dim > > dof_handler
ObserverPointer< Mapping< dim > > mapping
void newton_monolithic(const Point< dim > &point, const FiniteElement< dim > &fe, const std::vector< Number > &dof_values, Point< dim > &closest_point) const
std::pair< std::vector< Point< dim > >, std::vector< Point< dim > > > compute_closest_surface_points(const typename Triangulation< dim >::cell_iterator &search_cell, const typename Triangulation< dim >::cell_iterator &reference_cell, const std::vector< Point< dim > > &quadrature_points) const
Definition point.h:111
real_type l2_norm() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
typename ActiveSelector::cell_iterator cell_iterator
std::vector< index_type > data
Definition mpi.cc:734
constexpr unsigned int invalid_unsigned_int
Definition types.h:228