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
mapping_c1.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) 2001 - 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
13
15
19
20#include <cmath>
21#include <memory>
22
24
25
26
27template <int dim, int spacedim>
29 : MappingQ<dim, spacedim>(3)
30{
31 Assert(dim > 1, ExcImpossibleInDim(dim));
32 Assert(dim == spacedim, ExcNotImplemented());
33}
34
35
36
37template <>
38void
41 boost::container::small_vector<Point<1>, 200> &) const
42{
43 const unsigned int dim = 1;
44 (void)dim;
45 Assert(dim > 1, ExcImpossibleInDim(dim));
46}
47
48
49
50template <>
51void
54 boost::container::small_vector<Point<2>, 200> &a) const
55{
56 const unsigned int dim = 2;
57 const std::array<double, 2> interior_gl_points{
58 {0.5 - 0.5 * std::sqrt(1.0 / 5.0), 0.5 + 0.5 * std::sqrt(1.0 / 5.0)}};
59
60 // loop over each of the lines, and if it is at the boundary, then first get
61 // the boundary description and second compute the points on it. if not at
62 // the boundary, get the respective points from another function
63 for (unsigned int line_no = 0; line_no < GeometryInfo<dim>::lines_per_cell;
64 ++line_no)
65 {
66 const Triangulation<dim>::line_iterator line = cell->line(line_no);
67
68 if (line->at_boundary())
69 {
70 // first get the normal vectors at the two vertices of this line
71 // from the boundary description
72 const Manifold<dim> &manifold = line->get_manifold();
73
74 Manifold<dim>::FaceVertexNormals face_vertex_normals;
75 manifold.get_normals_at_vertices(line, face_vertex_normals);
76
77 // then transform them into interpolation points for a cubic
78 // polynomial
79 //
80 // for this, note that if we describe the boundary curve as a
81 // polynomial in tangential coordinate @p{t=0..1} (along the line)
82 // and @p{s} in normal direction, then the cubic mapping is such
83 // that @p{s = a*t**3 + b*t**2 + c*t + d}, and we want to determine
84 // the interpolation points at @p{t=0.276} and @p{t=0.724}
85 // (Gauss-Lobatto points). Since at @p{t=0,1} we want a vertex which
86 // is actually at the boundary, we know that @p{d=0} and @p{a=-b-c},
87 // which gives @p{s(0.276)} and @p{s(0.726)} in terms of @p{b,c}. As
88 // side-conditions, we want that the derivatives at @p{t=0} and
89 // @p{t=1}, i.e. at the vertices match those returned by the
90 // boundary.
91 //
92 // The task is then first to determine the coefficients from the
93 // tangentials. for that, first rotate the tangents of @p{s(t)} into
94 // the global coordinate system. they are @p{A (1,c)} and @p{A
95 // (1,-b-2c)} with @p{A} the rotation matrix, since the tangentials
96 // in the coordinate system relative to the line are @p{(1,c)} and
97 // @p{(1,-b-2c)} at the two vertices, respectively. We then have to
98 // make sure by matching @p{b,c} that these tangentials are
99 // orthogonal to the normals returned by the boundary object
100 const Tensor<1, 2> coordinate_vector =
101 line->vertex(1) - line->vertex(0);
102 const double h = std::sqrt(coordinate_vector * coordinate_vector);
103 Tensor<1, 2> coordinate_axis = coordinate_vector;
104 coordinate_axis /= h;
105
106 const double alpha =
107 std::atan2(coordinate_axis[1], coordinate_axis[0]);
108 const double c = -((face_vertex_normals[0][1] * std::sin(alpha) +
109 face_vertex_normals[0][0] * std::cos(alpha)) /
110 (face_vertex_normals[0][1] * std::cos(alpha) -
111 face_vertex_normals[0][0] * std::sin(alpha)));
112 const double b = ((face_vertex_normals[1][1] * std::sin(alpha) +
113 face_vertex_normals[1][0] * std::cos(alpha)) /
114 (face_vertex_normals[1][1] * std::cos(alpha) -
115 face_vertex_normals[1][0] * std::sin(alpha))) -
116 2 * c;
117
118 const double t1 = interior_gl_points[0];
119 const double t2 = interior_gl_points[1];
120 const double s_t1 = (((-b - c) * t1 + b) * t1 + c) * t1;
121 const double s_t2 = (((-b - c) * t2 + b) * t2 + c) * t2;
122
123 // next evaluate the so determined cubic polynomial at the points
124 // 1/3 and 2/3, first in unit coordinates
125 const Point<2> new_unit_points[2] = {Point<2>(t1, s_t1),
126 Point<2>(t2, s_t2)};
127 // then transform these points to real coordinates by rotating,
128 // scaling and shifting
129 for (const auto &new_unit_point : new_unit_points)
130 {
131 Point<2> real_point(std::cos(alpha) * new_unit_point[0] -
132 std::sin(alpha) * new_unit_point[1],
133 std::sin(alpha) * new_unit_point[0] +
134 std::cos(alpha) * new_unit_point[1]);
135 real_point *= h;
136 real_point += line->vertex(0);
137 a.push_back(real_point);
138 }
139 }
140 else
141 // not at boundary, so just use scaled Gauss-Lobatto points (i.e., use
142 // plain straight lines).
143 {
144 // Note that the zeroth Gauss-Lobatto point is a boundary point, so
145 // we push back mapped versions of the first and second.
146 a.push_back((1.0 - interior_gl_points[0]) * line->vertex(0) +
147 (interior_gl_points[0] * line->vertex(1)));
148 a.push_back((1.0 - interior_gl_points[1]) * line->vertex(0) +
149 (interior_gl_points[1] * line->vertex(1)));
150 }
151 }
152}
153
154
155
156template <int dim, int spacedim>
157void
160 boost::container::small_vector<Point<spacedim>, 200> &) const
161{
163}
164
165
166
167template <>
168void
171 boost::container::small_vector<Point<1>, 200> &) const
172{
173 const unsigned int dim = 1;
174 (void)dim;
175 Assert(dim > 2, ExcImpossibleInDim(dim));
176}
177
178
179
180template <>
181void
184 boost::container::small_vector<Point<2>, 200> &) const
185{
186 const unsigned int dim = 2;
187 (void)dim;
188 Assert(dim > 2, ExcImpossibleInDim(dim));
189}
190
191
192
193template <int dim, int spacedim>
194void
197 boost::container::small_vector<Point<spacedim>, 200> &) const
198{
200}
201
202
203
204template <int dim, int spacedim>
205std::unique_ptr<Mapping<dim, spacedim>>
207{
208 return std::make_unique<MappingC1<dim, spacedim>>();
209}
210
211
212
213// explicit instantiations
214#include "fe/mapping_c1.inst"
215
216
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, FaceVertexNormals &face_vertex_normals) const
std::array< Tensor< 1, spacedim >, GeometryInfo< dim >::vertices_per_face > FaceVertexNormals
Definition manifold.h:304
virtual void add_line_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, boost::container::small_vector< Point< spacedim >, 200 > &points) const override
virtual std::unique_ptr< Mapping< dim, spacedim > > clone() const override
virtual void add_quad_support_points(const typename Triangulation< dim, spacedim >::cell_iterator &cell, boost::container::small_vector< Point< spacedim >, 200 > &points) const override
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1708
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)