3#include <deal.II/base/exceptions.h>
4#include <deal.II/base/function.h>
5#include <deal.II/base/point.h>
6#include <deal.II/base/symmetric_tensor.h>
7#include <deal.II/base/tensor.h>
28 template <
int dim,
typename number>
29 class Plane :
public dealii::Function<dim, number>
42 const dealii::Tensor<1, dim, number> &
normal,
44 const dealii::Tensor<1, dim, number> &first_tangent_direction =
45 dealii::Tensor<1, dim, number>())
51 dealii::ExcMessage(
"The normal of the wall plane must be a unit vector."));
54 if constexpr (dim == 2)
59 else if constexpr (dim == 3)
61 const number first_tangent_norm = first_tangent_direction.norm();
62 AssertThrow(first_tangent_norm >
tolerance,
63 dealii::ExcMessage(
"The first tangent direction must be nonzero in 3D."));
65 tangents[0] = first_tangent_direction / first_tangent_norm;
69 "The first tangent direction must be perpendicular to the normal."));
77 dealii::Tensor<1, dim, number>
78 gradient(
const dealii::Point<dim, number> &x,
const unsigned int component = 0)
const override
80 Assert(component == 0,
81 dealii::ExcMessage(
"The distance function is scalar; component must be 0."));
84 const number r_norm = r.norm();
102 value(
const dealii::Point<dim, number> &x,
const unsigned int component = 0)
const override
104 Assert(component == 0,
105 dealii::ExcMessage(
"The distance function is scalar; component must be 0."));
114 dealii::Tensor<1, dim, number>
117 const dealii::Tensor<1, dim, number> position_relative_to_center = x -
center_of_wall;
118 const number normal_coord = position_relative_to_center *
normal;
120 dealii::Tensor<1, dim, number> offset = normal_coord *
normal;
121 for (
unsigned int i = 0; i < dim - 1; ++i)
123 const number tangential_coord = position_relative_to_center *
tangents[i];
124 const number clamped_tangential_coord =
126 offset += (tangential_coord - clamped_tangential_coord) *
tangents[i];
139 std::array<dealii::Tensor<1, dim, number>, dim - 1>
tangents;
156 template <
int dim,
typename number>
170 const dealii::Tensor<1, dim, number> &axis_direction,
179 AssertThrow(axis_direction.norm() >
tolerance,
180 dealii::ExcMessage(
"The axis direction of the truncated cone must not be zero."));
182 dealii::ExcMessage(
"The half length of the truncated cone must be positive."));
184 dealii::ExcMessage(
"The radii of the truncated cone must not be negative."));
187 "At least one radius of the truncated cone must be greater than zero."));
189 axis = axis_direction / axis_direction.norm();
199 dealii::Tensor<1, dim, number>
200 gradient(
const dealii::Point<dim, number> &x,
const unsigned int component = 0)
const override
202 Assert(component == 0,
203 dealii::ExcMessage(
"The distance function is scalar; component must be 0."));
205 const dealii::Tensor<1, dim, number> d =
207 const dealii::Tensor<1, dim, number> d_radial =
209 const number radial_coord = d_radial.norm();
211 dealii::Tensor<1, dim, number> radial_direction;
213 radial_direction = d_radial / radial_coord;
218 unsigned int least_aligned = 0;
219 for (
unsigned int i = 1; i < dim; ++i)
220 if (std::abs(
axis[i]) < std::abs(
axis[least_aligned]))
223 dealii::Tensor<1, dim, number> unit_vector;
224 unit_vector[least_aligned] = 1.;
225 radial_direction = unit_vector - (unit_vector *
axis) *
axis;
226 radial_direction /= radial_direction.norm();
230 const number distance = std::hypot(axial_offset, radial_offset);
237 const number slant_length = std::hypot(axial_span, radial_span);
239 return (radial_span *
axis - axial_span * radial_direction) / slant_length;
242 return (radial_offset * radial_direction + axial_offset *
axis) / distance;
251 value(
const dealii::Point<dim, number> &x,
const unsigned int component = 0)
const override
253 Assert(component == 0,
254 dealii::ExcMessage(
"The distance function is scalar; component must be 0."));
257 return std::hypot(axial_offset, radial_offset);
272 std::array<number, 2>
275 const dealii::Tensor<1, dim, number> d =
277 const number axial_coord = d *
axis;
278 const number radial_coord =
279 (d - axial_coord *
axis).norm();
285 const number segment_fraction =
286 std::clamp(((axial_coord +
half_length) * axial_span +
288 (axial_span * axial_span + radial_span * radial_span),
292 const number axial_coord_closest = -
half_length + segment_fraction * axial_span;
293 const number radial_coord_closest =
radius_bottom + segment_fraction * radial_span;
295 return {{axial_coord - axial_coord_closest, radial_coord - radial_coord_closest}};
302 dealii::Tensor<1, dim, number>
axis;
Definition distance_functions.hpp:30
number value(const dealii::Point< dim, number > &x, const unsigned int component=0) const override
Definition distance_functions.hpp:102
Plane(const dealii::Point< dim, number > ¢er_of_wall, const dealii::Tensor< 1, dim, number > &normal, const std::array< number, dim - 1 > &half_extents, const dealii::Tensor< 1, dim, number > &first_tangent_direction=dealii::Tensor< 1, dim, number >())
Definition distance_functions.hpp:41
std::array< dealii::Tensor< 1, dim, number >, dim - 1 > tangents
The unit tangent directions spanning the wall plane (one in 2D, two in 3D).
Definition distance_functions.hpp:139
dealii::Tensor< 1, dim, number > normal
The normal of the wall plane.
Definition distance_functions.hpp:136
dealii::Point< dim, number > center_of_wall
The center of the rectangular wall plane.
Definition distance_functions.hpp:133
const number tolerance
Tolerance for the geometric consistency checks and for detecting points on the wall.
Definition distance_functions.hpp:145
dealii::Tensor< 1, dim, number > gradient(const dealii::Point< dim, number > &x, const unsigned int component=0) const override
Definition distance_functions.hpp:78
std::array< number, dim - 1 > half_extents
The half-widths of the wall along each tangent direction.
Definition distance_functions.hpp:142
dealii::Tensor< 1, dim, number > offset_from_wall(const dealii::Point< dim, number > &x) const
Definition distance_functions.hpp:115
Definition distance_functions.hpp:158
const number tolerance
Definition distance_functions.hpp:315
const number half_length
Half of the truncated cone height, measured from the axis center along the axis.
Definition distance_functions.hpp:311
TruncatedCone(const dealii::Point< dim, number > &axis_center, const dealii::Tensor< 1, dim, number > &axis_direction, const number radius_bottom, const number radius_top, const number half_length)
Definition distance_functions.hpp:169
std::array< number, 2 > meridian_offset_from_wall(const dealii::Point< dim, number > &x) const
Definition distance_functions.hpp:273
dealii::Tensor< 1, dim, number > axis
The unit vector along the axis, pointing from the bottom to the top end.
Definition distance_functions.hpp:302
const number radius_top
The radius at the top end, i.e. at +half_length along the axis.
Definition distance_functions.hpp:308
const number radius_bottom
The radius at the bottom end, i.e. at -half_length along the axis.
Definition distance_functions.hpp:305
number value(const dealii::Point< dim, number > &x, const unsigned int component=0) const override
Definition distance_functions.hpp:251
dealii::Tensor< 1, dim, number > gradient(const dealii::Point< dim, number > &x, const unsigned int component=0) const override
Definition distance_functions.hpp:200
const dealii::Point< dim, number > axis_center
The midpoint on its axis of the truncated cone.
Definition distance_functions.hpp:299
Definition distance_functions.hpp:19