28#include <boost/container/small_vector.hpp>
51 const double theta = dir.
norm();
61 return tmp / tmp.
norm();
78 template <
int spacedim>
90 ExcMessage(
"The direction parameter must not be zero!"));
97 normal[0] = (vector[1] + vector[2]) / vector[0];
104 normal[1] = (vector[0] + vector[2]) / vector[1];
110 normal[2] = (vector[0] + vector[1]) / vector[2];
113 normal /= normal.
norm();
125template <
int dim,
int spacedim>
136template <
int dim,
int spacedim>
137std::unique_ptr<Manifold<dim, spacedim>>
140 return std::make_unique<PolarManifold<dim, spacedim>>(*this);
145template <
int dim,
int spacedim>
162template <
int dim,
int spacedim>
167 Assert(spherical_point[0] >= 0.0,
168 ExcMessage(
"Negative radius for given point."));
169 const double rho = spherical_point[0];
170 const double theta = spherical_point[1];
182 const double phi = spherical_point[2];
196template <
int dim,
int spacedim>
202 const double rho = R.
norm();
211 p[1] = std::atan2(R[1], R[0]);
219 const double z = R[2];
220 p[2] = std::atan2(R[1], R[0]);
223 p[1] = std::atan2(
std::sqrt(R[0] * R[0] + R[1] * R[1]), z);
235template <
int dim,
int spacedim>
240 Assert(spherical_point[0] >= 0.0,
241 ExcMessage(
"Negative radius for given point."));
242 const double rho = spherical_point[0];
243 const double theta = spherical_point[1];
260 const double phi = spherical_point[2];
285 template <
int dim,
int spacedim>
287 spherical_face_is_horizontal(
297 constexpr unsigned int n_vertices =
299 std::array<double, n_vertices> sqr_distances_to_center;
300 std::array<double, n_vertices - 1> sqr_distances_to_first_vertex;
301 sqr_distances_to_center[0] =
302 (face->vertex(0) - manifold_center).norm_square();
303 for (
unsigned int i = 1; i < n_vertices; ++i)
305 sqr_distances_to_center[i] =
306 (face->vertex(i) - manifold_center).norm_square();
307 sqr_distances_to_first_vertex[i - 1] =
308 (face->vertex(i) - face->vertex(0)).norm_square();
310 const auto minmax_sqr_distance =
311 std::minmax_element(sqr_distances_to_center.begin(),
312 sqr_distances_to_center.end());
313 const auto min_sqr_distance_to_first_vertex =
314 std::min_element(sqr_distances_to_first_vertex.begin(),
315 sqr_distances_to_first_vertex.end());
317 return (*minmax_sqr_distance.second - *minmax_sqr_distance.first <
318 1.e-10 * *min_sqr_distance_to_first_vertex);
324template <
int dim,
int spacedim>
334 if (spherical_face_is_horizontal<dim, spacedim>(face, p_center))
341 unnormalized_spherical_normal / unnormalized_spherical_normal.
norm();
342 return normalized_spherical_normal;
359template <
int dim,
int spacedim>
364 , polar_manifold(center)
370template <
int dim,
int spacedim>
371std::unique_ptr<Manifold<dim, spacedim>>
374 return std::make_unique<SphericalManifold<dim, spacedim>>(*this);
379template <
int dim,
int spacedim>
384 const double w)
const
386 const double tol = 1e-10;
388 if ((p1 - p2).norm_square() < tol * tol ||
std::abs(w) < tol)
400 const double r1 =
v1.norm();
401 const double r2 = v2.
norm();
403 Assert(r1 > tol && r2 > tol,
404 ExcMessage(
"p1 and p2 cannot coincide with the center."));
410 const double cosgamma = e1 * e2;
413 if (cosgamma < -1 + 8. * std::numeric_limits<double>::epsilon())
417 if (cosgamma > 1 - 8. * std::numeric_limits<double>::epsilon())
423 const double sigma = w *
std::acos(cosgamma);
428 const double n_norm = n.
norm();
431 "Probably, this means v1==v2 or v2==0."));
445template <
int dim,
int spacedim>
451 const double tol = 1e-10;
457 const double r1 =
v1.norm();
458 const double r2 = v2.
norm();
468 const double cosgamma = e1 * e2;
470 Assert(cosgamma > -1 + 8. * std::numeric_limits<double>::epsilon(),
471 ExcMessage(
"p1 and p2 cannot lie on the same diameter and be opposite "
472 "respect to the center."));
474 if (cosgamma > 1 - 8. * std::numeric_limits<double>::epsilon())
480 const double n_norm = n.
norm();
483 "Probably, this means v1==v2 or v2==0."));
489 const double gamma =
std::acos(cosgamma);
490 return (r2 - r1) * e1 + r1 * gamma * n;
495template <
int dim,
int spacedim>
505 if (spherical_face_is_horizontal<dim, spacedim>(face, p_center))
512 unnormalized_spherical_normal / unnormalized_spherical_normal.
norm();
513 return normalized_spherical_normal;
547template <
int dim,
int spacedim>
558 if (spherical_face_is_horizontal<dim, spacedim>(face, p_center))
563 for (
unsigned int vertex = 0;
564 vertex < GeometryInfo<spacedim>::vertices_per_face;
566 face_vertex_normals[vertex] = face->vertex(vertex) - p_center;
574template <
int dim,
int spacedim>
584 do_get_new_points(surrounding_points,
make_array_view(weights), new_points);
591template <
int dim,
int spacedim>
600 do_get_new_points(vertices,
615 template <
int spacedim>
637 Point<3> candidate = candidate_point;
638 const unsigned int n_merged_points = directions.size();
639 const double tolerance = 1e-10;
640 const int max_iterations = 10;
645 for (
unsigned int i = 0; i < n_merged_points; ++i)
647 const double squared_distance =
648 (candidate - directions[i]).norm_square();
649 if (squared_distance < tolerance * tolerance)
655 if (n_merged_points == 2)
657 static const ::SphericalManifold<3, 3> unit_manifold;
661 unit_manifold.get_intermediate_point(
Point<3>(directions[0]),
674 for (
unsigned int i = 0; i < max_iterations; ++i)
680 const Tensor<1, 3> Clocaly = cross_product_3d(candidate, Clocalx);
688 for (
unsigned int i = 0; i < n_merged_points; ++i)
694 const double sintheta =
std::sqrt(sinthetaSq);
695 if (sintheta < tolerance)
697 Hessian[0][0] += weights[i];
698 Hessian[1][1] += weights[i];
702 const double costheta = (directions[i]) * candidate;
703 const double theta = std::atan2(sintheta, costheta);
704 const double sincthetaInv = theta / sintheta;
706 const double cosphi = vPerp * Clocalx;
707 const double sinphi = vPerp * Clocaly;
709 gradlocal[0] = cosphi;
710 gradlocal[1] = sinphi;
711 gradient += (weights[i] * sincthetaInv) * gradlocal;
713 const double wt = weights[i] / sinthetaSq;
714 const double sinphiSq = sinphi * sinphi;
715 const double cosphiSq = cosphi * cosphi;
716 const double tt = sincthetaInv * costheta;
717 const double offdiag =
718 cosphi * sinphi * wt * (1.0 - tt);
719 Hessian[0][0] += wt * (cosphiSq + tt * sinphiSq);
720 Hessian[0][1] += offdiag;
721 Hessian[1][0] += offdiag;
722 Hessian[1][1] += wt * (sinphiSq + tt * cosphiSq);
732 xDisplocal[0] * Clocalx + xDisplocal[1] * Clocaly;
736 const Point<3> candidateOld = candidate;
741 if ((candidate - candidateOld).norm_square() <
742 tolerance * tolerance)
754template <
int dim,
int spacedim>
762 new_points.size() * surrounding_points.size());
763 const unsigned int weight_rows = new_points.size();
764 const unsigned int weight_columns = surrounding_points.size();
766 if (surrounding_points.size() == 2)
768 for (
unsigned int row = 0; row < weight_rows; ++row)
771 surrounding_points[0],
772 surrounding_points[1],
773 weights[row * weight_columns + 1]);
777 boost::container::small_vector<std::pair<double, Tensor<1, spacedim>>, 100>
778 new_candidates(new_points.size());
779 boost::container::small_vector<Tensor<1, spacedim>, 100> directions(
781 boost::container::small_vector<double, 100> distances(
782 surrounding_points.size(), 0.0);
783 double max_distance = 0.;
784 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
786 directions[i] = surrounding_points[i] - p_center;
787 distances[i] = directions[i].norm();
789 if (distances[i] != 0.)
790 directions[i] /= distances[i];
793 ExcMessage(
"One of the vertices coincides with the center. "
794 "This is not allowed!"));
798 for (
unsigned int k = 0; k < i; ++k)
800 const double squared_distance =
801 (directions[i] - directions[k]).norm_square();
802 max_distance =
std::max(max_distance, squared_distance);
808 const double tolerance = 1e-10;
809 boost::container::small_vector<bool, 100> accurate_point_was_found(
810 new_points.size(),
false);
815 for (
unsigned int row = 0; row < weight_rows; ++row)
817 new_candidates[row] =
818 guess_new_point(array_directions,
825 if (new_candidates[row].
first == 0.0)
827 new_points[row] = p_center;
828 accurate_point_was_found[row] =
true;
835 new_points[row] = polar_manifold.get_new_point(
843 if constexpr (spacedim < 3)
851 if (max_distance < 2e-2)
853 for (
unsigned int row = 0; row < weight_rows; ++row)
855 p_center + new_candidates[row].
first * new_candidates[row].
second;
865 boost::container::small_vector<double, 1000> merged_weights(
867 boost::container::small_vector<Tensor<1, spacedim>, 100>
869 boost::container::small_vector<double, 100> merged_distances(
870 surrounding_points.size(), 0.0);
872 unsigned int n_unique_directions = 0;
873 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
875 bool found_duplicate =
false;
879 for (
unsigned int j = 0; j < n_unique_directions; ++j)
881 const double squared_distance =
882 (directions[i] - directions[j]).norm_square();
883 if (!found_duplicate && squared_distance < 1e-28)
885 found_duplicate =
true;
886 for (
unsigned int row = 0; row < weight_rows; ++row)
887 merged_weights[row * weight_columns + j] +=
888 weights[row * weight_columns + i];
892 if (found_duplicate ==
false)
894 merged_directions[n_unique_directions] = directions[i];
895 merged_distances[n_unique_directions] = distances[i];
896 for (
unsigned int row = 0; row < weight_rows; ++row)
897 merged_weights[row * weight_columns + n_unique_directions] =
898 weights[row * weight_columns + i];
900 ++n_unique_directions;
906 boost::container::small_vector<unsigned int, 100> merged_weights_index(
908 for (
unsigned int row = 0; row < weight_rows; ++row)
910 for (
unsigned int existing_row = 0; existing_row < row;
913 bool identical_weights =
true;
915 for (
unsigned int weight_index = 0;
916 weight_index < n_unique_directions;
919 merged_weights[row * weight_columns + weight_index] -
920 merged_weights[existing_row * weight_columns +
921 weight_index]) > tolerance)
923 identical_weights =
false;
927 if (identical_weights)
929 merged_weights_index[row] = existing_row;
939 merged_directions.begin() + n_unique_directions);
942 merged_distances.begin() + n_unique_directions);
944 for (
unsigned int row = 0; row < weight_rows; ++row)
945 if (!accurate_point_was_found[row])
950 &merged_weights[row * weight_columns], n_unique_directions);
951 new_candidates[row].second =
952 internal::SphericalManifold::do_get_new_point(
953 array_merged_directions,
954 array_merged_distances,
955 array_merged_weights,
959 new_candidates[row].second =
960 new_candidates[merged_weights_index[row]].second;
963 p_center + new_candidates[row].first * new_candidates[row].second;
970template <
int dim,
int spacedim>
971std::pair<double, Tensor<1, spacedim>>
977 const double tolerance = 1e-10;
982 double total_weights = 0.;
983 for (
unsigned int i = 0; i < directions.size(); ++i)
986 if (
std::abs(1 - weights[i]) < tolerance)
987 return std::make_pair(distances[i], directions[i]);
989 rho += distances[i] * weights[i];
990 candidate += directions[i] * weights[i];
991 total_weights += weights[i];
995 const double norm = candidate.
norm();
999 rho /= total_weights;
1001 return std::make_pair(rho, candidate);
1009template <
int dim,
int spacedim>
1011 const double tolerance)
1019 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1024template <
int dim,
int spacedim>
1028 const double tolerance)
1031 , direction(direction / direction.norm())
1032 , point_on_axis(point_on_axis)
1033 , tolerance(tolerance)
1034 , dxn(cross_product_3d(this->direction, normal_direction))
1039 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1044template <
int dim,
int spacedim>
1045std::unique_ptr<Manifold<dim, spacedim>>
1048 return std::make_unique<CylindricalManifold<dim, spacedim>>(*this);
1053template <
int dim,
int spacedim>
1060 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1064 double average_length = 0.;
1065 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
1067 middle += surrounding_points[i] * weights[i];
1068 average_length += surrounding_points[i].square() * weights[i];
1070 middle -= point_on_axis;
1071 const double lambda = middle * direction;
1073 if ((middle - direction * lambda).square() < tolerance * average_length)
1074 return point_on_axis + direction * lambda;
1082template <
int dim,
int spacedim>
1088 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1092 const double lambda = normalized_point * direction;
1093 const Point<spacedim> projection = point_on_axis + direction * lambda;
1108template <
int dim,
int spacedim>
1114 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1117 const double sine_r =
std::sin(chart_point[1]) * chart_point[0];
1118 const double cosine_r =
std::cos(chart_point[1]) * chart_point[0];
1120 normal_direction * cosine_r + dxn * sine_r;
1123 return point_on_axis + direction * chart_point[2] + intermediate;
1128template <
int dim,
int spacedim>
1134 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1139 const double sine =
std::sin(chart_point[1]);
1140 const double cosine =
std::cos(chart_point[1]);
1142 normal_direction * cosine + dxn * sine;
1145 constexpr int s0 = 0 % spacedim;
1146 constexpr int s1 = 1 % spacedim;
1147 constexpr int s2 = 2 % spacedim;
1150 derivatives[s0][s0] = intermediate[s0];
1151 derivatives[s1][s0] = intermediate[s1];
1152 derivatives[s2][s0] = intermediate[s2];
1155 derivatives[s0][s1] = -normal_direction[s0] * sine + dxn[s0] * cosine;
1156 derivatives[s1][s1] = -normal_direction[s1] * sine + dxn[s1] * cosine;
1157 derivatives[s2][s1] = -normal_direction[s2] * sine + dxn[s2] * cosine;
1160 derivatives[s0][s2] = direction[s0];
1161 derivatives[s1][s2] = direction[s1];
1162 derivatives[s2][s2] = direction[s2];
1175 const double norm = t.
norm();
1176 Assert(norm > 0.0,
ExcMessage(
"The major axis must have a positive norm."));
1186template <
int dim,
int spacedim>
1190 const double eccentricity)
1193 , direction(check_and_normalize(major_axis_direction))
1195 , eccentricity(eccentricity)
1196 , cosh_u(1.0 / eccentricity)
1197 , sinh_u(
std::sqrt(cosh_u * cosh_u - 1.0))
1204 "Invalid eccentricity: It must satisfy 0 < eccentricity < 1."));
1209template <
int dim,
int spacedim>
1210std::unique_ptr<Manifold<dim, spacedim>>
1213 return std::make_unique<EllipticalManifold<dim, spacedim>>(*this);
1218template <
int dim,
int spacedim>
1231template <
int dim,
int spacedim>
1245 const double cs =
std::cos(chart_point[1]);
1246 const double sn =
std::sin(chart_point[1]);
1249 const double x = chart_point[0] * cosh_u * cs;
1250 const double y = chart_point[0] * sinh_u * sn;
1252 const Point<2> p(direction[0] * x - direction[1] * y,
1253 direction[1] * x + direction[0] * y);
1259template <
int dim,
int spacedim>
1274 const double x0 = space_point[0] - center[0];
1275 const double y0 = space_point[1] - center[1];
1276 const double x = direction[0] * x0 + direction[1] * y0;
1277 const double y = -direction[1] * x0 + direction[0] * y0;
1279 std::sqrt((x * x) / (cosh_u * cosh_u) + (y * y) / (sinh_u * sinh_u));
1285 double cos_eta = x / (pt0 * cosh_u);
1295 const double pt1 = (std::signbit(y) ? 2.0 *
numbers::PI - eta : eta);
1301template <
int dim,
int spacedim>
1317 const double cs =
std::cos(chart_point[1]);
1318 const double sn =
std::sin(chart_point[1]);
1320 dX[0][0] = cosh_u * cs;
1321 dX[0][1] = -chart_point[0] * cosh_u * sn;
1322 dX[1][0] = sinh_u * sn;
1323 dX[1][1] = chart_point[0] * sinh_u * cs;
1327 {{+direction[0], -direction[1]}, {direction[1], direction[0]}}};
1337template <
int dim,
int spacedim,
int chartdim>
1342 const double tolerance)
1345 , push_forward_function(&push_forward_function)
1346 , pull_back_function(&pull_back_function)
1347 , tolerance(tolerance)
1348 , owns_pointers(false)
1349 , finite_difference_step(0)
1357template <
int dim,
int spacedim,
int chartdim>
1362 const double tolerance)
1365 , push_forward_function(push_forward.
release())
1366 , pull_back_function(pull_back.
release())
1367 , tolerance(tolerance)
1368 , owns_pointers(true)
1369 , finite_difference_step(0)
1377template <
int dim,
int spacedim,
int chartdim>
1379 const std::string push_forward_expression,
1380 const std::string pull_back_expression,
1383 const std::string chart_vars,
1384 const std::string space_vars,
1385 const double tolerance,
1388 , const_map(const_map)
1389 , tolerance(tolerance)
1390 , owns_pointers(true)
1391 , push_forward_expression(push_forward_expression)
1392 , pull_back_expression(pull_back_expression)
1393 , chart_vars(chart_vars)
1394 , space_vars(space_vars)
1395 , finite_difference_step(h)
1407template <
int dim,
int spacedim,
int chartdim>
1410 if (owns_pointers ==
true)
1413 push_forward_function =
nullptr;
1417 pull_back_function =
nullptr;
1424template <
int dim,
int spacedim,
int chartdim>
1425std::unique_ptr<Manifold<dim, spacedim>>
1440 if (!(push_forward_expression.empty() && pull_back_expression.empty()))
1442 return std::make_unique<FunctionManifold<dim, spacedim, chartdim>>(
1443 push_forward_expression,
1444 pull_back_expression,
1445 this->get_periodicity(),
1450 finite_difference_step);
1454 return std::make_unique<FunctionManifold<dim, spacedim, chartdim>>(
1455 *push_forward_function,
1456 *pull_back_function,
1457 this->get_periodicity(),
1464template <
int dim,
int spacedim,
int chartdim>
1471 push_forward_function->vector_value(chart_point, pf);
1472 for (
unsigned int i = 0; i < spacedim; ++i)
1478 pull_back_function->vector_value(result, pb);
1479 for (
unsigned int i = 0; i < chartdim; ++i)
1481 (chart_point.
norm() > tolerance &&
1482 (
std::abs(pb[i] - chart_point[i]) <
1483 tolerance * chart_point.
norm())) ||
1484 (
std::abs(pb[i] - chart_point[i]) < tolerance),
1486 "The push forward is not the inverse of the pull back! Bailing out."));
1494template <
int dim,
int spacedim,
int chartdim>
1500 for (
unsigned int i = 0; i < spacedim; ++i)
1502 const auto gradient = push_forward_function->gradient(chart_point, i);
1503 for (
unsigned int j = 0; j < chartdim; ++j)
1504 DF[i][j] = gradient[j];
1511template <
int dim,
int spacedim,
int chartdim>
1518 pull_back_function->vector_value(space_point, pb);
1519 for (
unsigned int i = 0; i < chartdim; ++i)
1536 double phi = std::atan2(y, x);
1537 double theta = std::atan2(z,
std::sqrt(x * x + y * y) - centerline_radius);
1540 Utilities::fixed_power<2>(x -
std::cos(phi) * centerline_radius) +
1543 return {phi, theta, w};
1552 double phi = chart_point[0];
1553 double theta = chart_point[1];
1554 double w = chart_point[2];
1556 return {
std::cos(phi) * centerline_radius +
1558 inner_radius * w *
std::sin(theta),
1559 std::sin(phi) * centerline_radius +
1567 const double inner_radius)
1569 , centerline_radius(centerline_radius)
1570 , inner_radius(inner_radius)
1573 ExcMessage(
"The centerline radius must be greater than the "
1581std::unique_ptr<Manifold<dim, 3>>
1584 return std::make_unique<TorusManifold<dim>>(centerline_radius, inner_radius);
1595 double phi = chart_point[0];
1596 double theta = chart_point[1];
1597 double w = chart_point[2];
1599 DX[0][0] = -
std::sin(phi) * centerline_radius -
1605 DX[1][1] = inner_radius * w *
std::cos(theta);
1606 DX[1][2] = inner_radius *
std::sin(theta);
1608 DX[2][0] =
std::cos(phi) * centerline_radius +
1621template <
int dim,
int spacedim>
1624 : triangulation(nullptr)
1632template <
int dim,
int spacedim>
1634 spacedim>::~TransfiniteInterpolationManifold()
1636 if (clear_signal.connected())
1637 clear_signal.disconnect();
1642template <
int dim,
int spacedim>
1643std::unique_ptr<Manifold<dim, spacedim>>
1648 ptr->initialize(*triangulation);
1649 return std::unique_ptr<Manifold<dim, spacedim>>(ptr);
1654template <
int dim,
int spacedim>
1659 this->triangulation = &triangulation;
1661 clear_signal.disconnect();
1662 clear_signal = triangulation.
signals.
clear.connect([&]() ->
void {
1663 this->triangulation =
nullptr;
1664 this->level_coarse = -1;
1666 level_coarse = triangulation.
last()->level();
1667 coarse_cell_is_flat.resize(triangulation.
n_cells(level_coarse),
false);
1668 quadratic_approximation.clear();
1678 const std::vector<Point<dim>> unit_points =
1680 std::vector<Point<spacedim>> real_points(unit_points.size());
1684 bool cell_is_flat =
true;
1685 for (
const auto l : cell->line_indices())
1686 if (cell->line(l)->manifold_id() != cell->manifold_id() &&
1688 cell_is_flat =
false;
1689 if constexpr (dim > 2)
1690 for (
const auto q : cell->face_indices())
1691 if (cell->quad(q)->manifold_id() != cell->manifold_id() &&
1693 cell_is_flat =
false;
1695 coarse_cell_is_flat.size());
1696 coarse_cell_is_flat[cell->index()] = cell_is_flat;
1699 for (
unsigned int i = 0; i < unit_points.size(); ++i)
1700 real_points[i] = push_forward(cell, unit_points[i]);
1701 quadratic_approximation.emplace_back(real_points, unit_points);
1710 template <
typename AccessorType>
1712 compute_transfinite_interpolation(
const AccessorType &cell,
1716 return cell.vertex(0) * (1. - chart_point[0]) +
1717 cell.vertex(1) * chart_point[0];
1721 template <
typename AccessorType>
1723 compute_transfinite_interpolation(
const AccessorType &cell,
1725 const bool cell_is_flat)
1727 const unsigned int dim = AccessorType::dimension;
1728 const unsigned int spacedim = AccessorType::space_dimension;
1736 const std::array<Point<spacedim>, 4> vertices{
1737 {cell.vertex(0), cell.vertex(1), cell.vertex(2), cell.vertex(3)}};
1742 std::array<double, 4> weights_vertices{
1743 {(1. - chart_point[0]) * (1. - chart_point[1]),
1744 chart_point[0] * (1. - chart_point[1]),
1745 (1. - chart_point[0]) * chart_point[1],
1746 chart_point[0] * chart_point[1]}};
1751 new_point += weights_vertices[v] * vertices[v];
1763 std::array<double, GeometryInfo<2>::vertices_per_face> weights;
1766 const auto weights_view =
1768 const auto points_view =
make_array_view(points.begin(), points.end());
1770 for (
unsigned int line = 0; line < GeometryInfo<2>::lines_per_cell;
1773 const double my_weight =
1774 (line % 2) ? chart_point[line / 2] : 1 - chart_point[line / 2];
1775 const double line_point = chart_point[1 - line / 2];
1782 cell.line(line)->manifold_id();
1783 if (line_manifold_id == my_manifold_id ||
1788 my_weight * (1. - line_point);
1791 my_weight * line_point;
1799 weights[0] = 1. - line_point;
1800 weights[1] = line_point;
1809 new_point -= weights_vertices[v] * vertices[v];
1818 static constexpr unsigned int face_to_cell_vertices_3d[6][4] = {{0, 2, 4, 6},
1828 static constexpr unsigned int face_to_cell_lines_3d[6][4] = {{8, 10, 0, 4},
1836 template <
typename AccessorType>
1838 compute_transfinite_interpolation(
const AccessorType &cell,
1840 const bool cell_is_flat)
1842 const unsigned int dim = AccessorType::dimension;
1843 const unsigned int spacedim = AccessorType::space_dimension;
1849 const std::array<Point<spacedim>, 8> vertices{{cell.vertex(0),
1861 double linear_shapes[10];
1862 for (
unsigned int d = 0;
d < 3; ++
d)
1864 linear_shapes[2 *
d] = 1. - chart_point[
d];
1865 linear_shapes[2 *
d + 1] = chart_point[
d];
1869 for (
unsigned int d = 6;
d < 10; ++
d)
1870 linear_shapes[d] = linear_shapes[d - 6];
1872 std::array<double, 8> weights_vertices;
1873 for (
unsigned int i2 = 0, v = 0; i2 < 2; ++i2)
1874 for (
unsigned int i1 = 0; i1 < 2; ++i1)
1875 for (
unsigned int i0 = 0; i0 < 2; ++i0, ++v)
1876 weights_vertices[v] =
1877 (linear_shapes[4 + i2] * linear_shapes[2 + i1]) * linear_shapes[i0];
1881 for (
unsigned int v = 0; v < 8; ++v)
1882 new_point += weights_vertices[v] * vertices[v];
1888 std::array<double, GeometryInfo<3>::lines_per_cell> weights_lines;
1889 std::fill(weights_lines.begin(), weights_lines.end(), 0.0);
1892 std::array<double, GeometryInfo<2>::vertices_per_cell> weights;
1895 const auto weights_view =
1897 const auto points_view =
make_array_view(points.begin(), points.end());
1899 for (
const unsigned int face :
GeometryInfo<3>::face_indices())
1901 const double my_weight = linear_shapes[face];
1902 const unsigned int face_even = face - face % 2;
1910 cell.face(face)->manifold_id();
1911 if (face_manifold_id == my_manifold_id ||
1914 for (
unsigned int line = 0;
1915 line < GeometryInfo<2>::lines_per_cell;
1918 const double line_weight =
1919 linear_shapes[face_even + 2 + line];
1920 weights_lines[face_to_cell_lines_3d[face][line]] +=
1921 my_weight * line_weight;
1927 weights_vertices[face_to_cell_vertices_3d[face][0]] -=
1928 linear_shapes[face_even + 2] *
1929 (linear_shapes[face_even + 4] * my_weight);
1930 weights_vertices[face_to_cell_vertices_3d[face][1]] -=
1931 linear_shapes[face_even + 3] *
1932 (linear_shapes[face_even + 4] * my_weight);
1933 weights_vertices[face_to_cell_vertices_3d[face][2]] -=
1934 linear_shapes[face_even + 2] *
1935 (linear_shapes[face_even + 5] * my_weight);
1936 weights_vertices[face_to_cell_vertices_3d[face][3]] -=
1937 linear_shapes[face_even + 3] *
1938 (linear_shapes[face_even + 5] * my_weight);
1943 points[v] = vertices[face_to_cell_vertices_3d[face][v]];
1945 linear_shapes[face_even + 2] * linear_shapes[face_even + 4];
1947 linear_shapes[face_even + 3] * linear_shapes[face_even + 4];
1949 linear_shapes[face_even + 2] * linear_shapes[face_even + 5];
1951 linear_shapes[face_even + 3] * linear_shapes[face_even + 5];
1959 const auto weights_view_line =
1961 const auto points_view_line =
1963 for (
unsigned int line = 0; line < GeometryInfo<3>::lines_per_cell;
1966 const double line_point =
1967 (line < 8 ? chart_point[1 - (line % 4) / 2] : chart_point[2]);
1968 double my_weight = 0.;
1970 my_weight = linear_shapes[line % 4] * linear_shapes[4 + line / 4];
1973 const unsigned int subline = line - 8;
1975 linear_shapes[subline % 2] * linear_shapes[2 + subline / 2];
1977 my_weight -= weights_lines[line];
1983 cell.line(line)->manifold_id();
1984 if (line_manifold_id == my_manifold_id ||
1989 my_weight * (1. - line_point);
1992 my_weight * (line_point);
2000 weights[0] = 1. - line_point;
2001 weights[1] = line_point;
2002 new_point -= my_weight * tria.
get_manifold(line_manifold_id)
2010 new_point += weights_vertices[v] * vertices[v];
2018template <
int dim,
int spacedim>
2030 ExcMessage(
"chart_point is not in unit interval"));
2032 return compute_transfinite_interpolation(*cell,
2034 coarse_cell_is_flat[cell->index()]);
2039template <
int dim,
int spacedim>
2048 for (
unsigned int d = 0; d < dim; ++d)
2051 const double step = chart_point[d] > 0.5 ? -1e-8 : 1e-8;
2054 modified[d] += step;
2056 compute_transfinite_interpolation(*cell,
2058 coarse_cell_is_flat[cell->index()]) -
2059 pushed_forward_chart_point;
2060 for (
unsigned int e = 0; e < spacedim; ++e)
2061 grad[e][d] = difference[e] / step;
2068template <
int dim,
int spacedim>
2076 for (
unsigned int d = 0; d < dim; ++d)
2080 Point<dim> chart_point = cell->reference_cell().closest_point(initial_guess);
2089 compute_transfinite_interpolation(*cell,
2091 coarse_cell_is_flat[cell->index()]);
2092 const double tolerance = 1e-21 * Utilities::fixed_power<2>(cell->diameter());
2093 double residual_norm_square = residual.
norm_square();
2095 bool must_recompute_jacobian =
true;
2096 for (
unsigned int i = 0; i < 100; ++i)
2098 if (residual_norm_square < tolerance)
2105 for (
unsigned int d = 0; d < spacedim; ++d)
2106 for (
unsigned int e = 0; e < dim; ++e)
2107 update[e] += inv_grad[d][e] * residual[d];
2108 return chart_point + update;
2120 if (must_recompute_jacobian || i % 9 == 0)
2128 push_forward_gradient(cell,
2134 must_recompute_jacobian =
false;
2137 for (
unsigned int d = 0; d < spacedim; ++d)
2138 for (
unsigned int e = 0; e < dim; ++e)
2139 update[e] += inv_grad[d][e] * residual[d];
2153 while (alpha > 1e-4)
2155 Point<dim> guess = chart_point + alpha * update;
2157 point - compute_transfinite_interpolation(
2158 *cell, guess, coarse_cell_is_flat[cell->index()]);
2159 const double residual_norm_new = residual_guess.
norm_square();
2160 if (residual_norm_new < residual_norm_square)
2162 residual = residual_guess;
2163 residual_norm_square = residual_norm_new;
2164 chart_point += alpha * update;
2177 must_recompute_jacobian =
true;
2191 for (
unsigned int d = 0; d < spacedim; ++d)
2192 for (
unsigned int e = 0; e < dim; ++e)
2193 Jinv_deltaf[e] += inv_grad[d][e] * delta_f[d];
2200 if (
std::abs(delta_x * Jinv_deltaf) > 1e-12 && !must_recompute_jacobian)
2203 (delta_x - Jinv_deltaf) / (delta_x * Jinv_deltaf);
2205 for (
unsigned int d = 0; d < spacedim; ++d)
2206 for (
unsigned int e = 0; e < dim; ++e)
2207 jac_update[d] += delta_x[e] * inv_grad[d][e];
2208 for (
unsigned int d = 0; d < spacedim; ++d)
2209 for (
unsigned int e = 0; e < dim; ++e)
2210 inv_grad[d][e] += factor[e] * jac_update[d];
2218template <
int dim,
int spacedim>
2219std::array<unsigned int, 20>
2228 Assert(triangulation->begin_active()->level() >= level_coarse,
2229 ExcMessage(
"The manifold was initialized with level " +
2230 std::to_string(level_coarse) +
" but there are now" +
2231 "active cells on a lower level. Coarsening the mesh is " +
2232 "currently not supported"));
2237 triangulation->begin(
2242 boost::container::small_vector<std::pair<double, unsigned int>, 200>
2243 distances_and_cells;
2244 for (; cell != endc; ++cell)
2247 if (&cell->get_manifold() !=
this)
2254 vertices[vertex_n] = cell->vertex(vertex_n);
2262 center += vertices[v];
2264 double radius_square = 0.;
2267 std::max(radius_square, (center - vertices[v]).norm_square());
2268 bool inside_circle =
true;
2269 for (
unsigned int i = 0; i < points.size(); ++i)
2270 if ((center - points[i]).norm_square() > radius_square * 1.5)
2272 inside_circle =
false;
2275 if (inside_circle ==
false)
2279 double current_distance = 0;
2280 for (
unsigned int i = 0; i < points.size(); ++i)
2283 quadratic_approximation[cell->index()].compute(points[i]);
2286 distances_and_cells.push_back(
2287 std::make_pair(current_distance, cell->index()));
2292 std::sort(distances_and_cells.begin(), distances_and_cells.end());
2293 std::array<unsigned int, 20> cells;
2295 for (
unsigned int i = 0; i < distances_and_cells.size() && i < cells.size();
2297 cells[i] = distances_and_cells[i].
second;
2304template <
int dim,
int spacedim>
2310 Assert(surrounding_points.size() == chart_points.size(),
2311 ExcMessage(
"The chart points array view must be as large as the "
2312 "surrounding points array view."));
2314 std::array<unsigned int, 20> nearby_cells =
2315 get_possible_cells_around_points(surrounding_points);
2339 auto guess_chart_point_structdim_2 = [&](
const unsigned int i) ->
Point<dim> {
2340 Assert(surrounding_points.size() == 8 && 2 < i && i < 8,
2341 ExcMessage(
"This function assumes that there are eight surrounding "
2342 "points around a two-dimensional object. It also assumes "
2343 "that the first three chart points have already been "
2353 return chart_points[1] + (chart_points[2] - chart_points[0]);
2355 return 0.5 * (chart_points[0] + chart_points[2]);
2357 return 0.5 * (chart_points[1] + chart_points[3]);
2359 return 0.5 * (chart_points[0] + chart_points[1]);
2361 return 0.5 * (chart_points[2] + chart_points[3]);
2390 auto guess_chart_point_structdim_3 = [&](
const unsigned int i) ->
Point<dim> {
2391 Assert(surrounding_points.size() == 8 && 4 < i && i < 8,
2392 ExcMessage(
"This function assumes that there are eight surrounding "
2393 "points around a three-dimensional object. It also "
2394 "assumes that the first five chart points have already "
2396 return chart_points[i - 4] + (chart_points[4] - chart_points[0]);
2400 bool use_structdim_2_guesses =
false;
2401 bool use_structdim_3_guesses =
false;
2406 if (surrounding_points.size() == 8)
2409 surrounding_points[6] - surrounding_points[0];
2411 surrounding_points[7] - surrounding_points[2];
2414 const double cosine = scalar_product(v06, v27) /
2419 use_structdim_2_guesses =
true;
2420 else if (spacedim == 3)
2423 use_structdim_3_guesses =
true;
2426 Assert((!use_structdim_2_guesses && !use_structdim_3_guesses) ||
2427 (use_structdim_2_guesses ^ use_structdim_3_guesses),
2432 auto compute_chart_point =
2434 const unsigned int point_index) {
2440 bool used_quadratic_approximation =
false;
2443 if (point_index == 3 && surrounding_points.size() >= 8)
2444 guess = chart_points[1] + (chart_points[2] - chart_points[0]);
2445 else if (use_structdim_2_guesses && 3 < point_index)
2446 guess = guess_chart_point_structdim_2(point_index);
2447 else if (use_structdim_3_guesses && 4 < point_index)
2448 guess = guess_chart_point_structdim_3(point_index);
2449 else if (dim == 3 && point_index > 7 && surrounding_points.size() == 26)
2451 if (point_index < 20)
2454 point_index - 8, 0)] +
2456 point_index - 8, 1)]);
2460 point_index - 20, 0)] +
2462 point_index - 20, 1)] +
2464 point_index - 20, 2)] +
2466 point_index - 20, 3)]);
2470 guess = quadratic_approximation[cell->index()].compute(
2471 surrounding_points[point_index]);
2472 used_quadratic_approximation =
true;
2474 chart_points[point_index] =
2475 pull_back(cell, surrounding_points[point_index], guess);
2480 if (chart_points[point_index][0] ==
2482 !used_quadratic_approximation)
2484 guess = quadratic_approximation[cell->index()].compute(
2485 surrounding_points[point_index]);
2486 chart_points[point_index] =
2487 pull_back(cell, surrounding_points[point_index], guess);
2490 if (chart_points[point_index][0] ==
2493 for (
unsigned int d = 0; d < dim; ++d)
2495 chart_points[point_index] =
2496 pull_back(cell, surrounding_points[point_index], guess);
2501 for (
unsigned int c = 0; c < nearby_cells.size(); ++c)
2504 triangulation, level_coarse, nearby_cells[c]);
2505 bool inside_unit_cell =
true;
2506 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
2508 compute_chart_point(cell, i);
2515 inside_unit_cell =
false;
2519 if (inside_unit_cell ==
true)
2526 if (c == nearby_cells.size() - 1 ||
2531 std::ostringstream message;
2532 for (
unsigned int b = 0; b <= c; ++b)
2535 triangulation, level_coarse, nearby_cells[b]);
2536 message <<
"Looking at cell " << cell->id()
2537 <<
" with vertices: " << std::endl;
2539 message << cell->vertex(v) <<
" ";
2540 message << std::endl;
2541 message <<
"Transformation to chart coordinates: " << std::endl;
2542 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
2544 compute_chart_point(cell, i);
2545 message << surrounding_points[i] <<
" -> " << chart_points[i]
2565template <
int dim,
int spacedim>
2571 boost::container::small_vector<Point<dim>, 100> chart_points(
2572 surrounding_points.size());
2575 const auto cell = compute_chart_points(surrounding_points, chart_points_view);
2578 chart_manifold.get_new_point(chart_points_view, weights);
2580 return push_forward(cell, p_chart);
2585template <
int dim,
int spacedim>
2595 boost::container::small_vector<Point<dim>, 100> chart_points(
2596 surrounding_points.size());
2599 const auto cell = compute_chart_points(surrounding_points, chart_points_view);
2601 boost::container::small_vector<Point<dim>, 100> new_points_on_chart(
2603 chart_manifold.get_new_points(chart_points_view,
2606 new_points_on_chart.end()));
2608 for (
unsigned int row = 0; row < weights.size(0); ++row)
2609 new_points[row] = push_forward(cell, new_points_on_chart[row]);
2615#include "grid/manifold_lib.inst"
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim > > &surrounding_points, const ArrayView< const double > &weights) const override
virtual Point< spacedim > push_forward(const Point< 3 > &chart_point) const override
virtual DerivativeForm< 1, 3, spacedim > push_forward_gradient(const Point< 3 > &chart_point) const override
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim > > &surrounding_points, const ArrayView< const double > &weights) const override
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
CylindricalManifold(const unsigned int axis=0, const double tolerance=1e-10)
virtual Point< 3 > pull_back(const Point< spacedim > &space_point) const override
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
virtual Point< spacedim > push_forward(const Point< spacedim > &chart_point) const override
EllipticalManifold(const Point< spacedim > ¢er, const Tensor< 1, spacedim > &major_axis_direction, const double eccentricity)
virtual DerivativeForm< 1, spacedim, spacedim > push_forward_gradient(const Point< spacedim > &chart_point) const override
virtual Point< spacedim > pull_back(const Point< spacedim > &space_point) const override
static Tensor< 1, spacedim > get_periodicity()
const FunctionParser< spacedim >::ConstMap const_map
const std::string chart_vars
const std::string pull_back_expression
virtual DerivativeForm< 1, chartdim, spacedim > push_forward_gradient(const Point< chartdim > &chart_point) const override
const std::string space_vars
virtual Point< spacedim > push_forward(const Point< chartdim > &chart_point) const override
FunctionManifold(const Function< chartdim > &push_forward_function, const Function< spacedim > &pull_back_function, const Tensor< 1, chartdim > &periodicity=Tensor< 1, chartdim >(), const double tolerance=1e-10)
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
const std::string push_forward_expression
virtual Point< chartdim > pull_back(const Point< spacedim > &space_point) const override
ObserverPointer< const Function< chartdim >, FunctionManifold< dim, spacedim, chartdim > > push_forward_function
ObserverPointer< const Function< spacedim >, FunctionManifold< dim, spacedim, chartdim > > pull_back_function
virtual ~FunctionManifold() override
virtual void initialize(const std::string &vars, const std::vector< std::string > &expressions, const ConstMap &constants, const bool time_dependent=false) override
std::map< std::string, double > ConstMap
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
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim > > &surrounding_points, const ArrayView< const double > &weights) const
Abstract base class for mapping classes.
PolarManifold(const Point< spacedim > center=Point< spacedim >())
static Tensor< 1, spacedim > get_periodicity()
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
virtual DerivativeForm< 1, spacedim, spacedim > push_forward_gradient(const Point< spacedim > &chart_point) const override
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const override
virtual Point< spacedim > push_forward(const Point< spacedim > &chart_point) const override
virtual Point< spacedim > pull_back(const Point< spacedim > &space_point) const override
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim > > &vertices, const ArrayView< const double > &weights) const override
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
virtual Point< spacedim > get_intermediate_point(const Point< spacedim > &p1, const Point< spacedim > &p2, const double w) const override
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, typename Manifold< dim, spacedim >::FaceVertexNormals &face_vertex_normals) const override
std::pair< double, Tensor< 1, spacedim > > guess_new_point(const ArrayView< const Tensor< 1, spacedim > > &directions, const ArrayView< const double > &distances, const ArrayView< const double > &weights) const
virtual void get_new_points(const ArrayView< const Point< spacedim > > &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim > > new_points) const override
SphericalManifold(const Point< spacedim > center=Point< spacedim >())
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const override
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const override
void do_get_new_points(const ArrayView< const Point< spacedim > > &surrounding_points, const ArrayView< const double > &weights, ArrayView< Point< spacedim > > new_points) const
numbers::NumberTraits< Number >::real_type norm() const
constexpr numbers::NumberTraits< Number >::real_type norm_square() const
virtual Point< 3 > pull_back(const Point< 3 > &p) const override
virtual DerivativeForm< 1, 3, 3 > push_forward_gradient(const Point< 3 > &chart_point) const override
virtual Point< 3 > push_forward(const Point< 3 > &chart_point) const override
TorusManifold(const double centerline_radius, const double inner_radius)
virtual std::unique_ptr< Manifold< dim, 3 > > clone() const override
DerivativeForm< 1, dim, spacedim > push_forward_gradient(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &chart_point, const Point< spacedim > &pushed_forward_chart_point) const
void initialize(const Triangulation< dim, spacedim > &triangulation)
Triangulation< dim, spacedim >::cell_iterator compute_chart_points(const ArrayView< const Point< spacedim > > &surrounding_points, ArrayView< Point< dim > > chart_points) const
std::array< unsigned int, 20 > get_possible_cells_around_points(const ArrayView< const Point< spacedim > > &surrounding_points) const
Point< dim > pull_back(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p, const Point< dim > &initial_guess) const
virtual void get_new_points(const ArrayView< const Point< spacedim > > &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim > > new_points) const override
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim > > &surrounding_points, const ArrayView< const double > &weights) const override
Point< spacedim > push_forward(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &chart_point) const
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
cell_iterator last() const
unsigned int n_cells() const
Triangulation< dim, spacedim > & get_triangulation()
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
IteratorRange< active_cell_iterator > active_cell_iterators() const
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcEmptyObject()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
Number signed_angle(const Tensor< 1, spacedim, Number > &a, const Tensor< 1, spacedim, Number > &b, const Tensor< 1, spacedim, Number > &axis)
Tensor< 1, 3 > projected_direction(const Tensor< 1, 3 > &u, const Tensor< 1, 3 > &v)
Tensor< 1, 3 > apply_exponential_map(const Tensor< 1, 3 > &u, const Tensor< 1, 3 > &dir)
static constexpr double invalid_pull_back_coordinate
Point< spacedim > compute_normal(const Tensor< 1, spacedim > &, bool=false)
constexpr unsigned int invalid_unsigned_int
constexpr types::manifold_id flat_manifold_id
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
inline ::VectorizedArray< Number, width > acos(const ::VectorizedArray< Number, width > &x)
static double distance_to_unit_cell(const Point< dim > &p)
static unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int line_to_cell_vertices(const unsigned int line, const unsigned int vertex)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_indices()
boost::signals2::signal< void()> clear
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)