16 #include <deal.II/base/std_cxx14/memory.h> 17 #include <deal.II/base/table.h> 18 #include <deal.II/base/tensor.h> 20 #include <deal.II/fe/mapping.h> 22 #include <deal.II/grid/manifold_lib.h> 23 #include <deal.II/grid/tria.h> 24 #include <deal.II/grid/tria_accessor.h> 25 #include <deal.II/grid/tria_iterator.h> 27 #include <deal.II/lac/vector.h> 31 DEAL_II_NAMESPACE_OPEN
40 static constexpr
double invalid_pull_back_coordinate = 20.0;
48 const double theta = dir.
norm();
57 std::cos(theta) * u + std::sin(theta) * dirUnit;
58 return tmp / tmp.
norm();
75 template <
int spacedim>
84 compute_normal(
const Tensor<1, 3> &vector,
bool normalize =
false)
87 ExcMessage(
"The direction parameter must not be zero!"));
89 if (std::abs(vector[0]) >= std::abs(vector[1]) &&
90 std::abs(vector[0]) >= std::abs(vector[2]))
94 normal[0] = (vector[1] + vector[2]) / vector[0];
96 else if (std::abs(vector[1]) >= std::abs(vector[0]) &&
97 std::abs(vector[1]) >= std::abs(vector[2]))
101 normal[1] = (vector[0] + vector[2]) / vector[1];
107 normal[2] = (vector[0] + vector[1]) / vector[2];
110 normal /= normal.
norm();
121 template <
int dim,
int spacedim>
130 template <
int dim,
int spacedim>
131 std::unique_ptr<Manifold<dim, spacedim>>
134 return std_cxx14::make_unique<PolarManifold<dim, spacedim>>(center);
139 template <
int dim,
int spacedim>
156 template <
int dim,
int spacedim>
161 Assert(spherical_point[0] >= 0.0,
162 ExcMessage(
"Negative radius for given point."));
163 const double rho = spherical_point[0];
164 const double theta = spherical_point[1];
171 p[0] = rho * std::cos(theta);
172 p[1] = rho * std::sin(theta);
176 const double phi = spherical_point[2];
177 p[0] = rho * std::sin(theta) * std::cos(phi);
178 p[1] = rho * std::sin(theta) * std::sin(phi);
179 p[2] = rho * std::cos(theta);
190 template <
int dim,
int spacedim>
196 const double rho = R.
norm();
205 p[1] = std::atan2(R[1], R[0]);
213 const double z = R[2];
214 p[2] = std::atan2(R[1], R[0]);
217 p[1] = std::atan2(std::sqrt(R[0] * R[0] + R[1] * R[1]), z);
229 template <
int dim,
int spacedim>
234 Assert(spherical_point[0] >= 0.0,
235 ExcMessage(
"Negative radius for given point."));
236 const double rho = spherical_point[0];
237 const double theta = spherical_point[1];
245 DX[0][0] = std::cos(theta);
246 DX[0][1] = -rho * std::sin(theta);
247 DX[1][0] = std::sin(theta);
248 DX[1][1] = rho * std::cos(theta);
254 const double phi = spherical_point[2];
255 DX[0][0] = std::sin(theta) * std::cos(phi);
256 DX[0][1] = rho * std::cos(theta) * std::cos(phi);
257 DX[0][2] = -rho * std::sin(theta) * std::sin(phi);
259 DX[1][0] = std::sin(theta) * std::sin(phi);
260 DX[1][1] = rho * std::cos(theta) * std::sin(phi);
261 DX[1][2] = rho * std::sin(theta) * std::cos(phi);
263 DX[2][0] = std::cos(theta);
264 DX[2][1] = -rho * std::sin(theta);
281 template <
int dim,
int spacedim>
285 , polar_manifold(center)
290 template <
int dim,
int spacedim>
291 std::unique_ptr<Manifold<dim, spacedim>>
294 return std_cxx14::make_unique<SphericalManifold<dim, spacedim>>(center);
299 template <
int dim,
int spacedim>
304 const double w)
const 306 const double tol = 1e-10;
308 if ((p1 - p2).norm_square() < tol * tol || std::abs(w) < tol)
310 else if (std::abs(w - 1.0) < tol)
320 const double r1 = v1.
norm();
321 const double r2 = v2.
norm();
323 Assert(r1 > tol && r2 > tol,
324 ExcMessage(
"p1 and p2 cannot coincide with the center."));
330 const double cosgamma = e1 * e2;
333 if (cosgamma < -1 + 8. * std::numeric_limits<double>::epsilon())
337 if (cosgamma > 1 - 8. * std::numeric_limits<double>::epsilon())
343 const double sigma = w * std::acos(cosgamma);
348 const double n_norm = n.
norm();
351 "Probably, this means v1==v2 or v2==0."));
365 template <
int dim,
int spacedim>
371 const double tol = 1e-10;
378 const double r1 = v1.
norm();
379 const double r2 = v2.
norm();
389 const double cosgamma = e1 * e2;
391 Assert(cosgamma > -1 + 8. * std::numeric_limits<double>::epsilon(),
392 ExcMessage(
"p1 and p2 cannot lie on the same diameter and be opposite " 393 "respect to the center."));
395 if (cosgamma > 1 - 8. * std::numeric_limits<double>::epsilon())
401 const double n_norm = n.
norm();
404 "Probably, this means v1==v2 or v2==0."));
410 const double gamma = std::acos(cosgamma);
411 return (r2 - r1) * e1 + r1 * gamma * n;
416 template <
int dim,
int spacedim>
427 std::array<double, n_vertices> distances_to_center;
428 std::array<double, n_vertices - 1> distances_to_first_vertex;
429 distances_to_center[0] = (face->vertex(0) - center).norm_square();
430 for (
unsigned int i = 1; i < n_vertices; ++i)
432 distances_to_center[i] = (face->vertex(i) - center).norm_square();
433 distances_to_first_vertex[i - 1] =
434 (face->vertex(i) - face->vertex(0)).norm_square();
436 const auto minmax_distance =
437 std::minmax_element(distances_to_center.begin(), distances_to_center.end());
438 const auto min_distance_to_first_vertex =
439 std::min_element(distances_to_first_vertex.begin(),
440 distances_to_first_vertex.end());
442 if (*minmax_distance.second - *minmax_distance.first <
443 1.e-10 * *min_distance_to_first_vertex)
447 unnormalized_spherical_normal / unnormalized_spherical_normal.
norm();
448 return normalized_spherical_normal;
477 template <
int dim,
int spacedim>
489 std::array<double, n_vertices> distances_to_center;
490 std::array<double, n_vertices - 1> distances_to_first_vertex;
491 distances_to_center[0] = (face->vertex(0) - center).norm_square();
492 for (
unsigned int i = 1; i < n_vertices; ++i)
494 distances_to_center[i] = (face->vertex(i) - center).norm_square();
495 distances_to_first_vertex[i - 1] =
496 (face->vertex(i) - face->vertex(0)).norm_square();
498 const auto minmax_distance =
499 std::minmax_element(distances_to_center.begin(), distances_to_center.end());
500 const auto min_distance_to_first_vertex =
501 std::min_element(distances_to_first_vertex.begin(),
502 distances_to_first_vertex.end());
504 if (*minmax_distance.second - *minmax_distance.first <
505 1.e-10 * *min_distance_to_first_vertex)
507 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
508 face_vertex_normals[vertex] = face->vertex(vertex) - center;
516 template <
int dim,
int spacedim>
526 get_new_points(surrounding_points,
make_array_view(weights), new_points);
533 template <
int dim,
int spacedim>
542 get_new_points(vertices,
551 template <
int dim,
int spacedim>
559 new_points.size() * surrounding_points.size());
560 const unsigned int weight_rows = new_points.size();
561 const unsigned int weight_columns = surrounding_points.size();
563 if (surrounding_points.size() == 2)
565 for (
unsigned int row = 0; row < weight_rows; ++row)
567 get_intermediate_point(surrounding_points[0],
568 surrounding_points[1],
569 weights[row * weight_columns + 1]);
573 boost::container::small_vector<std::pair<double, Tensor<1, spacedim>>, 100>
574 new_candidates(new_points.size());
575 boost::container::small_vector<Tensor<1, spacedim>, 100> directions(
577 boost::container::small_vector<double, 100> distances(
578 surrounding_points.size(), 0.0);
579 double max_distance = 0.;
580 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
582 directions[i] = surrounding_points[i] - center;
583 distances[i] = directions[i].
norm();
585 if (distances[i] != 0.)
586 directions[i] /= distances[i];
589 ExcMessage(
"One of the vertices coincides with the center. " 590 "This is not allowed!"));
594 for (
unsigned int k = 0; k < i; ++k)
596 const double squared_distance =
597 (directions[i] - directions[k]).norm_square();
598 max_distance = std::max(max_distance, squared_distance);
604 const double tolerance = 1e-10;
605 boost::container::small_vector<bool, 100> accurate_point_was_found(
606 new_points.size(),
false);
611 for (
unsigned int row = 0; row < weight_rows; ++row)
613 new_candidates[row] =
614 guess_new_point(array_directions,
621 if (new_candidates[row].first == 0.0)
623 new_points[row] = center;
624 accurate_point_was_found[row] =
true;
631 new_points[row] = polar_manifold.get_new_point(
646 if (max_distance < 2e-2)
648 for (
unsigned int row = 0; row < weight_rows; ++row)
650 center + new_candidates[row].first * new_candidates[row].second;
660 boost::container::small_vector<double, 1000> merged_weights(weights.
size());
661 boost::container::small_vector<Tensor<1, spacedim>, 100> merged_directions(
663 boost::container::small_vector<double, 100> merged_distances(
664 surrounding_points.size(), 0.0);
666 unsigned int n_unique_directions = 0;
667 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
669 bool found_duplicate =
false;
673 for (
unsigned int j = 0; j < n_unique_directions; ++j)
675 const double squared_distance =
676 (directions[i] - directions[j]).norm_square();
677 if (!found_duplicate && squared_distance < 1e-28)
679 found_duplicate =
true;
680 for (
unsigned int row = 0; row < weight_rows; ++row)
681 merged_weights[row * weight_columns + j] +=
682 weights[row * weight_columns + i];
686 if (found_duplicate ==
false)
688 merged_directions[n_unique_directions] = directions[i];
689 merged_distances[n_unique_directions] = distances[i];
690 for (
unsigned int row = 0; row < weight_rows; ++row)
691 merged_weights[row * weight_columns + n_unique_directions] =
692 weights[row * weight_columns + i];
694 ++n_unique_directions;
700 boost::container::small_vector<unsigned int, 100> merged_weights_index(
702 for (
unsigned int row = 0; row < weight_rows; ++row)
704 for (
unsigned int existing_row = 0; existing_row < row; ++existing_row)
706 bool identical_weights =
true;
708 for (
unsigned int weight_index = 0;
709 weight_index < n_unique_directions;
711 if (std::abs(merged_weights[row * weight_columns + weight_index] -
712 merged_weights[existing_row * weight_columns +
713 weight_index]) > tolerance)
715 identical_weights =
false;
719 if (identical_weights)
721 merged_weights_index[row] = existing_row;
731 merged_directions.begin() + n_unique_directions);
734 merged_distances.begin() + n_unique_directions);
736 for (
unsigned int row = 0; row < weight_rows; ++row)
737 if (!accurate_point_was_found[row])
742 &merged_weights[row * weight_columns], n_unique_directions);
743 new_candidates[row].second =
744 get_new_point(array_merged_directions,
745 array_merged_distances,
746 array_merged_weights,
750 new_candidates[row].second =
751 new_candidates[merged_weights_index[row]].second;
754 center + new_candidates[row].first * new_candidates[row].second;
760 template <
int dim,
int spacedim>
761 std::pair<double, Tensor<1, spacedim>>
767 const double tolerance = 1e-10;
772 double total_weights = 0.;
773 for (
unsigned int i = 0; i < directions.size(); i++)
776 if (std::abs(1 - weights[i]) < tolerance)
777 return std::make_pair(distances[i], directions[i]);
779 rho += distances[i] * weights[i];
780 candidate += directions[i] * weights[i];
781 total_weights += weights[i];
785 const double norm = candidate.
norm();
789 rho /= total_weights;
791 return std::make_pair(rho, candidate);
797 template <
int spacedim>
820 Point<3> candidate = candidate_point;
821 const unsigned int n_merged_points = directions.size();
822 const double tolerance = 1
e-10;
823 const int max_iterations = 10;
828 for (
unsigned int i = 0; i < n_merged_points; ++i)
830 const double squared_distance =
831 (candidate - directions[i]).norm_square();
832 if (squared_distance < tolerance * tolerance)
838 if (n_merged_points == 2)
841 Assert(std::abs(weights[0] + weights[1] - 1.0) < 1e-13,
857 for (
unsigned int i = 0; i < max_iterations; ++i)
862 const Tensor<1, 3> Clocalx = internal::compute_normal(candidate);
871 for (
unsigned int i = 0; i < n_merged_points; ++i)
872 if (std::abs(weights[i]) > 1.e-15)
874 vPerp = internal::projected_direction(directions[i], candidate);
876 const double sintheta = std::sqrt(sinthetaSq);
877 if (sintheta < tolerance)
879 Hessian[0][0] += weights[i];
880 Hessian[1][1] += weights[i];
884 const double costheta = (directions[i]) * candidate;
885 const double theta = std::atan2(sintheta, costheta);
886 const double sincthetaInv = theta / sintheta;
888 const double cosphi = vPerp * Clocalx;
889 const double sinphi = vPerp * Clocaly;
891 gradlocal[0] = cosphi;
892 gradlocal[1] = sinphi;
893 gradient += (weights[i] * sincthetaInv) * gradlocal;
895 const double wt = weights[i] / sinthetaSq;
896 const double sinphiSq = sinphi * sinphi;
897 const double cosphiSq = cosphi * cosphi;
898 const double tt = sincthetaInv * costheta;
899 const double offdiag = cosphi * sinphi * wt * (1.0 - tt);
900 Hessian[0][0] += wt * (cosphiSq + tt * sinphiSq);
901 Hessian[0][1] += offdiag;
902 Hessian[1][0] += offdiag;
903 Hessian[1][1] += wt * (sinphiSq + tt * cosphiSq);
911 const Tensor<1, 2> xDisplocal = inverse_Hessian * gradient;
913 xDisplocal[0] * Clocalx + xDisplocal[1] * Clocaly;
916 const Point<3> candidateOld = candidate;
918 Point<3>(internal::apply_exponential_map(candidate, xDisp));
921 if ((candidate - candidateOld).norm_square() < tolerance * tolerance)
931 template <
int dim,
int spacedim>
951 const Point<3> & candidate_point)
const 953 return do_get_new_point(directions, distances, weights, candidate_point);
964 const Point<3> & candidate_point)
const 966 return do_get_new_point(directions, distances, weights, candidate_point);
977 const Point<3> & candidate_point)
const 979 return do_get_new_point(directions, distances, weights, candidate_point);
987 template <
int dim,
int spacedim>
989 const double tolerance)
997 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1002 template <
int dim,
int spacedim>
1006 const double tolerance)
1008 , normal_direction(internal::compute_normal(direction,
true))
1009 , direction(direction / direction.norm())
1010 , point_on_axis(point_on_axis)
1011 , tolerance(tolerance)
1016 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1021 template <
int dim,
int spacedim>
1022 std::unique_ptr<Manifold<dim, spacedim>>
1025 return std_cxx14::make_unique<CylindricalManifold<dim, spacedim>>(
1026 direction, point_on_axis, tolerance);
1031 template <
int dim,
int spacedim>
1038 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1042 double average_length = 0.;
1043 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
1045 middle += surrounding_points[i] * weights[i];
1046 average_length += surrounding_points[i].square() * weights[i];
1048 middle -= point_on_axis;
1049 const double lambda = middle * direction;
1051 if ((middle - direction * lambda).square() < tolerance * average_length)
1052 return point_on_axis + direction * lambda;
1060 template <
int dim,
int spacedim>
1066 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1070 const double lambda = normalized_point * direction;
1071 const Point<spacedim> projection = point_on_axis + direction * lambda;
1076 const double dot = normal_direction * p_diff;
1078 const double phi = std::atan2(det, dot);
1081 return Point<3>(p_diff.norm(), phi, lambda);
1086 template <
int dim,
int spacedim>
1092 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1095 const double sine_r = std::sin(chart_point(1)) * chart_point(0);
1096 const double cosine_r = std::cos(chart_point(1)) * chart_point(0);
1099 normal_direction * cosine_r + dxn * sine_r;
1102 return point_on_axis + direction * chart_point(2) + intermediate;
1107 template <
int dim,
int spacedim>
1113 ExcMessage(
"CylindricalManifold can only be used for spacedim==3!"));
1118 const double sine = std::sin(chart_point(1));
1119 const double cosine = std::cos(chart_point(1));
1122 normal_direction * cosine + dxn * sine;
1125 derivatives[0][0] = intermediate[0];
1126 derivatives[1][0] = intermediate[1];
1127 derivatives[2][0] = intermediate[2];
1130 derivatives[0][1] = -normal_direction[0] * sine + dxn[0] * cosine;
1131 derivatives[1][1] = -normal_direction[1] * sine + dxn[1] * cosine;
1132 derivatives[2][1] = -normal_direction[2] * sine + dxn[2] * cosine;
1135 derivatives[0][2] = direction[0];
1136 derivatives[1][2] = direction[1];
1137 derivatives[2][2] = direction[2];
1147 template <
int dim,
int spacedim>
1151 const double eccentricity)
1154 , direction(major_axis_direction)
1156 , cosh_u(1.0 / eccentricity)
1157 , sinh_u(
std::
sqrt(cosh_u * cosh_u - 1.0))
1164 "Invalid eccentricity: It must satisfy 0 < eccentricity < 1."));
1166 Assert(direction_norm != 0.0,
1168 "Invalid major axis direction vector: Null vector not allowed."));
1174 template <
int dim,
int spacedim>
1175 std::unique_ptr<Manifold<dim, spacedim>>
1178 const double eccentricity = 1.0 / cosh_u;
1179 return std_cxx14::make_unique<EllipticalManifold<dim, spacedim>>(
1180 center, direction, eccentricity);
1185 template <
int dim,
int spacedim>
1198 template <
int dim,
int spacedim>
1212 const double cs = std::cos(chart_point[1]);
1213 const double sn = std::sin(chart_point[1]);
1216 const double x = chart_point[0] * cosh_u * cs;
1217 const double y = chart_point[0] * sinh_u * sn;
1219 const Point<2> p(direction[0] * x - direction[1] * y,
1220 direction[1] * x + direction[0] * y);
1226 template <
int dim,
int spacedim>
1241 const double x0 = space_point[0] - center[0];
1242 const double y0 = space_point[1] - center[1];
1243 const double x = direction[0] * x0 + direction[1] * y0;
1244 const double y = -direction[1] * x0 + direction[0] * y0;
1246 std::sqrt((x * x) / (cosh_u * cosh_u) + (y * y) / (sinh_u * sinh_u));
1252 double cos_eta = x / (pt0 * cosh_u);
1261 const double eta = std::acos(cos_eta);
1262 const double pt1 = (std::signbit(y) ? 2.0 *
numbers::PI - eta : eta);
1268 template <
int dim,
int spacedim>
1284 const double cs = std::cos(chart_point[1]);
1285 const double sn = std::sin(chart_point[1]);
1287 dX[0][0] = cosh_u * cs;
1288 dX[0][1] = -chart_point[0] * cosh_u * sn;
1289 dX[1][0] = sinh_u * sn;
1290 dX[1][1] = chart_point[0] * sinh_u * cs;
1294 {{+direction[0], -direction[1]}, {direction[1], direction[0]}}};
1304 template <
int dim,
int spacedim,
int chartdim>
1309 const double tolerance)
1311 , push_forward_function(&push_forward_function)
1312 , pull_back_function(&pull_back_function)
1313 , tolerance(tolerance)
1314 , owns_pointers(false)
1315 , finite_difference_step(0)
1323 template <
int dim,
int spacedim,
int chartdim>
1325 const std::string push_forward_expression,
1326 const std::string pull_back_expression,
1329 const std::string chart_vars,
1330 const std::string space_vars,
1331 const double tolerance,
1334 , const_map(const_map)
1335 , tolerance(tolerance)
1336 , owns_pointers(true)
1337 , push_forward_expression(push_forward_expression)
1338 , pull_back_expression(pull_back_expression)
1339 , chart_vars(chart_vars)
1340 , space_vars(space_vars)
1341 , finite_difference_step(h)
1353 template <
int dim,
int spacedim,
int chartdim>
1356 if (owns_pointers ==
true)
1359 push_forward_function =
nullptr;
1363 pull_back_function =
nullptr;
1370 template <
int dim,
int spacedim,
int chartdim>
1371 std::unique_ptr<Manifold<dim, spacedim>>
1384 if (owns_pointers ==
true)
1386 return std_cxx14::make_unique<FunctionManifold<dim, spacedim, chartdim>>(
1387 push_forward_expression,
1388 pull_back_expression,
1389 this->get_periodicity(),
1394 finite_difference_step);
1397 return std_cxx14::make_unique<FunctionManifold<dim, spacedim, chartdim>>(
1398 *push_forward_function,
1399 *pull_back_function,
1400 this->get_periodicity(),
1406 template <
int dim,
int spacedim,
int chartdim>
1413 push_forward_function->vector_value(chart_point, pf);
1414 for (
unsigned int i = 0; i < spacedim; ++i)
1419 pull_back_function->vector_value(result, pb);
1420 for (
unsigned int i = 0; i < chartdim; ++i)
1422 (chart_point.
norm() > tolerance &&
1423 (std::abs(pb[i] - chart_point[i]) < tolerance * chart_point.
norm())) ||
1424 (std::abs(pb[i] - chart_point[i]) < tolerance),
1426 "The push forward is not the inverse of the pull back! Bailing out."));
1434 template <
int dim,
int spacedim,
int chartdim>
1440 for (
unsigned int i = 0; i < spacedim; ++i)
1442 const auto gradient = push_forward_function->gradient(chart_point, i);
1443 for (
unsigned int j = 0; j < chartdim; ++j)
1444 DF[i][j] = gradient[j];
1451 template <
int dim,
int spacedim,
int chartdim>
1458 pull_back_function->vector_value(space_point, pb);
1459 for (
unsigned int i = 0; i < chartdim; ++i)
1476 double phi = std::atan2(y, x);
1477 double theta = std::atan2(z, std::sqrt(x * x + y * y) - R);
1478 double w = std::sqrt(std::pow(y - std::sin(phi) * R, 2.0) +
1479 std::pow(x - std::cos(phi) * R, 2.0) + z * z) /
1481 return {phi, theta, w};
1490 double phi = chart_point(0);
1491 double theta = chart_point(1);
1492 double w = chart_point(2);
1494 return {std::cos(phi) * R + r * w * std::cos(theta) * std::cos(phi),
1495 r * w * std::sin(theta),
1496 std::sin(phi) * R + r * w * std::cos(theta) * std::sin(phi)};
1508 ExcMessage(
"Outer radius R must be greater than the inner " 1516 std::unique_ptr<Manifold<dim, 3>>
1519 return std_cxx14::make_unique<TorusManifold<dim>>(R, r);
1530 double phi = chart_point(0);
1531 double theta = chart_point(1);
1532 double w = chart_point(2);
1534 DX[0][0] = -std::sin(phi) * R - r * w * std::cos(theta) * std::sin(phi);
1535 DX[0][1] = -r * w * std::sin(theta) * std::cos(phi);
1536 DX[0][2] = r * std::cos(theta) * std::cos(phi);
1539 DX[1][1] = r * w * std::cos(theta);
1540 DX[1][2] = r * std::sin(theta);
1542 DX[2][0] = std::cos(phi) * R + r * w * std::cos(theta) * std::cos(phi);
1543 DX[2][1] = -r * w * std::sin(theta) * std::sin(phi);
1544 DX[2][2] = r * std::cos(theta) * std::sin(phi);
1554 template <
int dim,
int spacedim>
1557 : triangulation(nullptr)
1565 template <
int dim,
int spacedim>
1567 spacedim>::~TransfiniteInterpolationManifold()
1569 if (clear_signal.connected())
1570 clear_signal.disconnect();
1575 template <
int dim,
int spacedim>
1576 std::unique_ptr<Manifold<dim, spacedim>>
1582 return std::unique_ptr<Manifold<dim, spacedim>>(ptr);
1587 template <
int dim,
int spacedim>
1592 this->triangulation = &triangulation;
1594 clear_signal = triangulation.signals.clear.connect([&]() ->
void {
1595 this->triangulation =
nullptr;
1596 this->level_coarse = -1;
1598 level_coarse = triangulation.last()->level();
1599 coarse_cell_is_flat.resize(triangulation.n_cells(level_coarse),
false);
1601 cell = triangulation.begin(level_coarse),
1602 endc = triangulation.end(level_coarse);
1603 for (; cell != endc; ++cell)
1605 bool cell_is_flat =
true;
1606 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
1607 if (cell->line(l)->manifold_id() != cell->manifold_id() &&
1609 cell_is_flat =
false;
1611 for (
unsigned int q = 0; q < GeometryInfo<dim>::quads_per_cell; ++q)
1612 if (cell->quad(q)->manifold_id() != cell->manifold_id() &&
1614 cell_is_flat =
false;
1616 coarse_cell_is_flat.size());
1617 coarse_cell_is_flat[cell->index()] = cell_is_flat;
1626 template <
typename AccessorType>
1628 compute_transfinite_interpolation(
const AccessorType &cell,
1632 return cell.vertex(0) * (1. - chart_point[0]) +
1633 cell.vertex(1) * chart_point[0];
1637 template <
typename AccessorType>
1639 compute_transfinite_interpolation(
const AccessorType &cell,
1641 const bool cell_is_flat)
1643 const unsigned int dim = AccessorType::dimension;
1644 const unsigned int spacedim = AccessorType::space_dimension;
1652 const std::array<Point<spacedim>, 4> vertices{
1653 {cell.vertex(0), cell.vertex(1), cell.vertex(2), cell.vertex(3)}};
1658 std::array<double, 4> weights_vertices{
1659 {(1. - chart_point[0]) * (1. - chart_point[1]),
1660 chart_point[0] * (1. - chart_point[1]),
1661 (1. - chart_point[0]) * chart_point[1],
1662 chart_point[0] * chart_point[1]}};
1666 for (
unsigned int v = 0; v < GeometryInfo<2>::vertices_per_cell; ++v)
1667 new_point += weights_vertices[v] * vertices[v];
1679 std::array<double, GeometryInfo<2>::vertices_per_face> weights;
1682 const auto weights_view =
1684 const auto points_view =
make_array_view(points.begin(), points.end());
1686 for (
unsigned int line = 0; line < GeometryInfo<2>::lines_per_cell;
1689 const double my_weight =
1690 (line % 2) ? chart_point[line / 2] : 1 - chart_point[line / 2];
1691 const double line_point = chart_point[1 - line / 2];
1698 cell.line(line)->manifold_id();
1699 if (line_manifold_id == my_manifold_id ||
1704 my_weight * (1. - line_point);
1707 my_weight * line_point;
1715 weights[0] = 1. - line_point;
1716 weights[1] = line_point;
1719 .get_new_point(points_view, weights_view);
1724 for (
unsigned int v = 0; v < GeometryInfo<2>::vertices_per_cell; ++v)
1725 new_point -= weights_vertices[v] * vertices[v];
1734 static constexpr
unsigned int face_to_cell_vertices_3d[6][4] = {{0, 2, 4, 6},
1744 static constexpr
unsigned int face_to_cell_lines_3d[6][4] = {{8, 10, 0, 4},
1752 template <
typename AccessorType>
1754 compute_transfinite_interpolation(
const AccessorType &cell,
1756 const bool cell_is_flat)
1758 const unsigned int dim = AccessorType::dimension;
1759 const unsigned int spacedim = AccessorType::space_dimension;
1765 const std::array<Point<spacedim>, 8> vertices{{cell.vertex(0),
1777 double linear_shapes[10];
1778 for (
unsigned int d = 0;
d < 3; ++
d)
1780 linear_shapes[2 *
d] = 1. - chart_point[
d];
1781 linear_shapes[2 *
d + 1] = chart_point[
d];
1785 for (
unsigned int d = 6;
d < 10; ++
d)
1786 linear_shapes[d] = linear_shapes[d - 6];
1788 std::array<double, 8> weights_vertices;
1789 for (
unsigned int i2 = 0, v = 0; i2 < 2; ++i2)
1790 for (
unsigned int i1 = 0; i1 < 2; ++i1)
1791 for (
unsigned int i0 = 0; i0 < 2; ++i0, ++v)
1792 weights_vertices[v] =
1793 (linear_shapes[4 + i2] * linear_shapes[2 + i1]) * linear_shapes[i0];
1797 for (
unsigned int v = 0; v < 8; ++v)
1798 new_point += weights_vertices[v] * vertices[v];
1804 std::array<double, GeometryInfo<3>::lines_per_cell> weights_lines;
1805 std::fill(weights_lines.begin(), weights_lines.end(), 0.0);
1808 std::array<double, GeometryInfo<2>::vertices_per_cell> weights;
1811 const auto weights_view =
1813 const auto points_view =
make_array_view(points.begin(), points.end());
1815 for (
unsigned int face = 0; face < GeometryInfo<3>::faces_per_cell;
1818 const double my_weight = linear_shapes[face];
1819 const unsigned int face_even = face - face % 2;
1821 if (std::abs(my_weight) < 1
e-13)
1827 cell.face(face)->manifold_id();
1828 if (face_manifold_id == my_manifold_id ||
1831 for (
unsigned int line = 0;
1832 line < GeometryInfo<2>::lines_per_cell;
1835 const double line_weight =
1836 linear_shapes[face_even + 2 + line];
1837 weights_lines[face_to_cell_lines_3d[face][line]] +=
1838 my_weight * line_weight;
1844 weights_vertices[face_to_cell_vertices_3d[face][0]] -=
1845 linear_shapes[face_even + 2] *
1846 (linear_shapes[face_even + 4] * my_weight);
1847 weights_vertices[face_to_cell_vertices_3d[face][1]] -=
1848 linear_shapes[face_even + 3] *
1849 (linear_shapes[face_even + 4] * my_weight);
1850 weights_vertices[face_to_cell_vertices_3d[face][2]] -=
1851 linear_shapes[face_even + 2] *
1852 (linear_shapes[face_even + 5] * my_weight);
1853 weights_vertices[face_to_cell_vertices_3d[face][3]] -=
1854 linear_shapes[face_even + 3] *
1855 (linear_shapes[face_even + 5] * my_weight);
1859 for (
unsigned int v = 0; v < GeometryInfo<2>::vertices_per_cell;
1861 points[v] = vertices[face_to_cell_vertices_3d[face][v]];
1863 linear_shapes[face_even + 2] * linear_shapes[face_even + 4];
1865 linear_shapes[face_even + 3] * linear_shapes[face_even + 4];
1867 linear_shapes[face_even + 2] * linear_shapes[face_even + 5];
1869 linear_shapes[face_even + 3] * linear_shapes[face_even + 5];
1872 .get_new_point(points_view, weights_view);
1877 const auto weights_view_line =
1879 const auto points_view_line =
1881 for (
unsigned int line = 0; line < GeometryInfo<3>::lines_per_cell;
1884 const double line_point =
1885 (line < 8 ? chart_point[1 - (line % 4) / 2] : chart_point[2]);
1886 double my_weight = 0.;
1888 my_weight = linear_shapes[line % 4] * linear_shapes[4 + line / 4];
1891 const unsigned int subline = line - 8;
1893 linear_shapes[subline % 2] * linear_shapes[2 + subline / 2];
1895 my_weight -= weights_lines[line];
1897 if (std::abs(my_weight) < 1
e-13)
1901 cell.line(line)->manifold_id();
1902 if (line_manifold_id == my_manifold_id ||
1907 my_weight * (1. - line_point);
1910 my_weight * (line_point);
1918 weights[0] = 1. - line_point;
1919 weights[1] = line_point;
1920 new_point -= my_weight * tria.
get_manifold(line_manifold_id)
1921 .get_new_point(points_view_line,
1927 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
1928 new_point += weights_vertices[v] * vertices[v];
1936 template <
int dim,
int spacedim>
1948 ExcMessage(
"chart_point is not in unit interval"));
1950 return compute_transfinite_interpolation(*cell,
1952 coarse_cell_is_flat[cell->index()]);
1957 template <
int dim,
int spacedim>
1966 for (
unsigned int d = 0; d < dim; ++d)
1969 const double step = chart_point[d] > 0.5 ? -1e-8 : 1e-8;
1972 modified[d] += step;
1974 compute_transfinite_interpolation(*cell,
1976 coarse_cell_is_flat[cell->index()]) -
1977 pushed_forward_chart_point;
1978 for (
unsigned int e = 0; e < spacedim; ++e)
1979 grad[e][d] = difference[e] / step;
1986 template <
int dim,
int spacedim>
1994 for (
unsigned int d = 0; d < dim; ++d)
1995 outside[d] = internal::invalid_pull_back_coordinate;
2008 compute_transfinite_interpolation(*cell,
2010 coarse_cell_is_flat[cell->index()]);
2011 const double tolerance = 1e-21 * Utilities::fixed_power<2>(cell->diameter());
2012 double residual_norm_square = residual.
norm_square();
2014 bool must_recompute_jacobian =
true;
2015 for (
unsigned int i = 0; i < 100; ++i)
2017 if (residual_norm_square < tolerance)
2024 for (
unsigned int d = 0; d < spacedim; ++d)
2025 for (
unsigned int e = 0; e < dim; ++e)
2026 update[e] += inv_grad[d][e] * residual[d];
2027 return chart_point + update;
2039 if (must_recompute_jacobian || i % 9 == 0)
2047 push_forward_gradient(cell,
2053 must_recompute_jacobian =
false;
2056 for (
unsigned int d = 0; d < spacedim; ++d)
2057 for (
unsigned int e = 0; e < dim; ++e)
2058 update[e] += inv_grad[d][e] * residual[d];
2072 while (alpha > 1e-4)
2074 Point<dim> guess = chart_point + alpha * update;
2076 point - compute_transfinite_interpolation(
2077 *cell, guess, coarse_cell_is_flat[cell->index()]);
2078 const double residual_norm_new = residual.
norm_square();
2079 if (residual_norm_new < residual_norm_square)
2081 residual_norm_square = residual_norm_new;
2082 chart_point += alpha * update;
2095 must_recompute_jacobian =
true;
2109 for (
unsigned int d = 0; d < spacedim; ++d)
2110 for (
unsigned int e = 0; e < dim; ++e)
2111 Jinv_deltaf[e] += inv_grad[d][e] * delta_f[d];
2118 if (std::abs(delta_x * Jinv_deltaf) > 1e-12)
2121 (delta_x - Jinv_deltaf) / (delta_x * Jinv_deltaf);
2123 for (
unsigned int d = 0; d < spacedim; ++d)
2124 for (
unsigned int e = 0; e < dim; ++e)
2125 jac_update[d] += delta_x[e] * inv_grad[d][e];
2126 for (
unsigned int d = 0; d < spacedim; ++d)
2127 for (
unsigned int e = 0; e < dim; ++e)
2128 inv_grad[d][e] += factor[e] * jac_update[d];
2136 template <
int dim,
int spacedim>
2137 std::array<unsigned int, 20>
2146 Assert(triangulation->begin_active()->level() >= level_coarse,
2147 ExcMessage(
"The manifold was initialized with level " +
2149 "active cells on a lower level. Coarsening the mesh is " +
2150 "currently not supported"));
2155 triangulation->begin(
2160 boost::container::small_vector<std::pair<double, unsigned int>, 200>
2161 distances_and_cells;
2162 for (; cell != endc; ++cell)
2165 if (&cell->get_manifold() !=
this)
2170 for (
unsigned int vertex_n = 0;
2171 vertex_n < GeometryInfo<dim>::vertices_per_cell;
2174 vertices[vertex_n] = cell->vertex(vertex_n);
2181 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
2182 center += vertices[v];
2184 double radius_square = 0.;
2185 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
2187 std::max(radius_square, (center - vertices[v]).norm_square());
2188 bool inside_circle =
true;
2189 for (
unsigned int i = 0; i < points.size(); ++i)
2190 if ((center - points[i]).norm_square() > radius_square * 1.5)
2192 inside_circle =
false;
2195 if (inside_circle ==
false)
2199 double current_distance = 0;
2200 for (
unsigned int i = 0; i < points.size(); ++i)
2203 cell->real_to_unit_cell_affine_approximation(points[i]);
2206 distances_and_cells.push_back(
2207 std::make_pair(current_distance, cell->index()));
2212 std::sort(distances_and_cells.begin(), distances_and_cells.end());
2213 std::array<unsigned int, 20> cells;
2215 for (
unsigned int i = 0; i < distances_and_cells.size() && i < cells.size();
2217 cells[i] = distances_and_cells[i].second;
2224 template <
int dim,
int spacedim>
2230 Assert(surrounding_points.size() == chart_points.size(),
2231 ExcMessage(
"The chart points array view must be as large as the " 2232 "surrounding points array view."));
2234 std::array<unsigned int, 20> nearby_cells =
2235 get_possible_cells_around_points(surrounding_points);
2259 auto guess_chart_point_structdim_2 = [&](
const unsigned int i) ->
Point<dim> {
2260 Assert(surrounding_points.size() == 8 && 2 < i && i < 8,
2261 ExcMessage(
"This function assumes that there are eight surrounding " 2262 "points around a two-dimensional object. It also assumes " 2263 "that the first three chart points have already been " 2273 return chart_points[1] + (chart_points[2] - chart_points[0]);
2275 return 0.5 * (chart_points[0] + chart_points[2]);
2277 return 0.5 * (chart_points[1] + chart_points[3]);
2279 return 0.5 * (chart_points[0] + chart_points[1]);
2281 return 0.5 * (chart_points[2] + chart_points[3]);
2310 auto guess_chart_point_structdim_3 = [&](
const unsigned int i) ->
Point<dim> {
2311 Assert(surrounding_points.size() == 8 && 4 < i && i < 8,
2312 ExcMessage(
"This function assumes that there are eight surrounding " 2313 "points around a three-dimensional object. It also " 2314 "assumes that the first five chart points have already " 2316 return chart_points[i - 4] + (chart_points[4] - chart_points[0]);
2320 bool use_structdim_2_guesses =
false;
2321 bool use_structdim_3_guesses =
false;
2326 if (surrounding_points.size() == 8)
2329 surrounding_points[6] - surrounding_points[0];
2331 surrounding_points[7] - surrounding_points[2];
2339 use_structdim_2_guesses =
true;
2340 else if (spacedim == 3)
2343 use_structdim_3_guesses =
true;
2346 Assert((!use_structdim_2_guesses && !use_structdim_3_guesses) ||
2347 (use_structdim_2_guesses ^ use_structdim_3_guesses),
2352 auto compute_chart_point =
2354 const unsigned int point_index) {
2360 bool used_affine_approximation =
false;
2363 if (point_index == 3 && surrounding_points.size() >= 8)
2364 guess = chart_points[1] + (chart_points[2] - chart_points[0]);
2365 else if (use_structdim_2_guesses && 3 < point_index)
2366 guess = guess_chart_point_structdim_2(point_index);
2367 else if (use_structdim_3_guesses && 4 < point_index)
2368 guess = guess_chart_point_structdim_3(point_index);
2369 else if (dim == 3 && point_index > 7 && surrounding_points.size() == 26)
2371 if (point_index < 20)
2374 point_index - 8, 0)] +
2376 point_index - 8, 1)]);
2380 point_index - 20, 0)] +
2382 point_index - 20, 1)] +
2384 point_index - 20, 2)] +
2386 point_index - 20, 3)]);
2390 guess = cell->real_to_unit_cell_affine_approximation(
2391 surrounding_points[point_index]);
2392 used_affine_approximation =
true;
2394 chart_points[point_index] =
2395 pull_back(cell, surrounding_points[point_index], guess);
2400 if (chart_points[point_index][0] ==
2401 internal::invalid_pull_back_coordinate &&
2402 !used_affine_approximation)
2404 guess = cell->real_to_unit_cell_affine_approximation(
2405 surrounding_points[point_index]);
2406 chart_points[point_index] =
2407 pull_back(cell, surrounding_points[point_index], guess);
2410 if (chart_points[point_index][0] ==
2411 internal::invalid_pull_back_coordinate)
2413 for (
unsigned int d = 0; d < dim; ++d)
2415 chart_points[point_index] =
2416 pull_back(cell, surrounding_points[point_index], guess);
2421 for (
unsigned int c = 0; c < nearby_cells.size(); ++c)
2424 triangulation, level_coarse, nearby_cells[c]);
2425 bool inside_unit_cell =
true;
2426 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
2428 compute_chart_point(cell, i);
2435 inside_unit_cell =
false;
2439 if (inside_unit_cell ==
true)
2446 if (c == nearby_cells.size() - 1 ||
2451 std::ostringstream message;
2452 for (
unsigned int b = 0; b <= c; ++b)
2455 triangulation, level_coarse, nearby_cells[b]);
2456 message <<
"Looking at cell " << cell->id()
2457 <<
" with vertices: " << std::endl;
2458 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
2460 message << cell->vertex(v) <<
" ";
2461 message << std::endl;
2462 message <<
"Transformation to chart coordinates: " << std::endl;
2463 for (
unsigned int i = 0; i < surrounding_points.size(); ++i)
2465 compute_chart_point(cell, i);
2466 message << surrounding_points[i] <<
" -> " << chart_points[i]
2486 template <
int dim,
int spacedim>
2492 boost::container::small_vector<Point<dim>, 100> chart_points(
2493 surrounding_points.size());
2496 const auto cell = compute_chart_points(surrounding_points, chart_points_view);
2499 chart_manifold.get_new_point(chart_points_view, weights);
2501 return push_forward(cell, p_chart);
2506 template <
int dim,
int spacedim>
2516 boost::container::small_vector<Point<dim>, 100> chart_points(
2517 surrounding_points.size());
2520 const auto cell = compute_chart_points(surrounding_points, chart_points_view);
2522 boost::container::small_vector<Point<dim>, 100> new_points_on_chart(
2524 chart_manifold.get_new_points(chart_points_view,
2527 new_points_on_chart.end()));
2529 for (
unsigned int row = 0; row < weights.
size(0); ++row)
2530 new_points[row] = push_forward(cell, new_points_on_chart[row]);
2536 #include "manifold_lib.inst" 2538 DEAL_II_NAMESPACE_CLOSE
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
static ::ExceptionBase & ExcTransformationFailed()
const types::manifold_id flat_manifold_id
static const unsigned int invalid_unsigned_int
Triangulation< dim, spacedim >::cell_iterator compute_chart_points(const ArrayView< const Point< spacedim >> &surrounding_points, ArrayView< Point< dim >> chart_points) const
virtual Point< spacedim > push_forward(const Point< 3 > &chart_point) const override
#define AssertDimension(dim1, dim2)
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)
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)
EllipticalManifold(const Point< spacedim > ¢er, const Tensor< 1, spacedim > &major_axis_direction, const double eccentricity)
static Tensor< 1, spacedim > get_periodicity()
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
std::array< unsigned int, 20 > get_possible_cells_around_points(const ArrayView< const Point< spacedim >> &surrounding_points) const
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
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, 3 > > clone() const override
static unsigned int line_to_cell_vertices(const unsigned int line, const unsigned int vertex)
virtual void get_new_points(const ArrayView< const Point< spacedim >> &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim >> new_points) const override
#define AssertIndexRange(index, range)
static Tensor< 1, spacedim > get_periodicity()
const std::string pull_back_expression
virtual DerivativeForm< 1, 3, 3 > push_forward_gradient(const Point< 3 > &chart_point) const override
static ::ExceptionBase & ExcNotInitialized()
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim >> &vertices, const ArrayView< const double > &weights) const override
virtual Point< 3 > pull_back(const Point< 3 > &p) const override
#define AssertThrow(cond, exc)
numbers::NumberTraits< Number >::real_type norm() const
TorusManifold(const double R, const double r)
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
void initialize(const Triangulation< dim, spacedim > &triangulation)
virtual Point< spacedim > push_forward(const Point< spacedim > &chart_point) const override
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
static double distance_to_unit_cell(const Point< dim > &p)
virtual Point< 3 > push_forward(const Point< 3 > &chart_point) const override
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
virtual DerivativeForm< 1, 3, spacedim > push_forward_gradient(const Point< 3 > &chart_point) const override
CylindricalManifold(const unsigned int axis=0, const double tolerance=1e-10)
virtual Point< spacedim > pull_back(const Point< spacedim > &space_point) const override
SmartPointer< const Function< spacedim >, FunctionManifold< dim, spacedim, chartdim > > pull_back_function
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
Tensor< 1, spacedim > direction
PolarManifold(const Point< spacedim > center=Point< spacedim >())
#define Assert(cond, exc)
virtual ~FunctionManifold() override
const std::string chart_vars
virtual Point< chartdim > pull_back(const Point< spacedim > &space_point) const override
Abstract base class for mapping classes.
virtual Point< 3 > pull_back(const Point< spacedim > &space_point) const override
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const override
Point< spacedim > push_forward(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &chart_point) const
virtual Point< spacedim > push_forward(const Point< spacedim > &chart_point) const override
SmartPointer< const Function< chartdim >, FunctionManifold< dim, spacedim, chartdim > > push_forward_function
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim >> &surrounding_points, const ArrayView< const double > &weights) const override
numbers::NumberTraits< Number >::real_type norm_square() const
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() 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
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
Tensor< 1, dim, Number > cross_product_3d(const Tensor< 1, dim, Number > &src1, const Tensor< 1, dim, Number > &src2)
ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
virtual void get_new_points(const ArrayView< const Point< spacedim >> &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim >> new_points) const override
static Point< dim > project_to_unit_cell(const Point< dim > &p)
Number determinant(const SymmetricTensor< 2, dim, Number > &t)
VectorizedArray< Number > sqrt(const ::VectorizedArray< Number > &x)
virtual Point< spacedim > push_forward(const Point< chartdim > &chart_point) const override
virtual Point< spacedim > pull_back(const Point< spacedim > &space_point) const override
size_type size(const unsigned int i) const
void initialize(const std::string &vars, const std::vector< std::string > &expressions, const ConstMap &constants, const bool time_dependent=false)
virtual DerivativeForm< 1, chartdim, spacedim > push_forward_gradient(const Point< chartdim > &chart_point) const override
const std::string space_vars
Point< dim > pull_back(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p, const Point< dim > &initial_guess) const
static constexpr double PI
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim >> &surrounding_points, const ArrayView< const double > &weights) const override
virtual DerivativeForm< 1, spacedim, spacedim > push_forward_gradient(const Point< spacedim > &chart_point) const override
static ::ExceptionBase & ExcEmptyObject()
const std::string push_forward_expression
std::array< Tensor< 1, spacedim >, GeometryInfo< dim >::vertices_per_face > FaceVertexNormals
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
static ::ExceptionBase & ExcNotImplemented()
const FunctionParser< spacedim >::ConstMap const_map
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
SphericalManifold(const Point< spacedim > center=Point< spacedim >())
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, FaceVertexNormals &face_vertex_normals) const
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
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
static ::ExceptionBase & ExcInternalError()
Triangulation< dim, spacedim > & get_triangulation()