1 #ifndef OMEGA_H_SHAPE_HPP
2 #define OMEGA_H_SHAPE_HPP
4 #include <Omega_h_adj.hpp>
5 #include <Omega_h_affine.hpp>
6 #include <Omega_h_mesh.hpp>
7 #include <Omega_h_metric.hpp>
8 #include <Omega_h_qr.hpp>
9 #include <Omega_h_simplex.hpp>
10 #include "Omega_h_macros.h"
14 template <Int sdim, Int edim>
15 OMEGA_H_INLINE Matrix<sdim, edim> simplex_basis(Few<Vector<sdim>, edim + 1>
const & p) {
17 for (Int i = 0; i < edim; ++i) b[i] = p[i + 1] - p[0];
35 return (plane.
n * point) - plane.
d;
39 OMEGA_H_INLINE Plane<dim> normalize(Plane<dim> p) {
41 return {p.n / l, p.d / l};
49 for (Int i = 1; i < dim+1; ++i) {
57 template <Int sdim, Int edim>
60 const auto inverse_basis = pseudo_invert(simplex_basis<sdim,edim>(node_coordinates));
61 const auto lambda = inverse_basis*(global_coordinate-node_coordinates[0]);
66 OMEGA_H_INLINE
bool is_barycentric_inside(Vector<n> xi, Real fuzz=0) {
67 return (0.0-fuzz) <= reduce(xi, minimum<Real>()) &&
68 reduce(xi, maximum<Real>()) <= (1.0+fuzz);
72 OMEGA_H_INLINE Real edge_length_from_basis(Few<Vector<sdim>, 1> b) {
77 OMEGA_H_INLINE Real simplex_size_from_basis(Few<Vector<sdim>, 1> b) {
78 return edge_length_from_basis(b);
81 OMEGA_H_INLINE Real triangle_area_from_basis(Few<Vector<2>, 2> b) {
82 return cross(b[0], b[1]) / 2.0;
85 OMEGA_H_INLINE Real triangle_area_from_basis(Few<Vector<3>, 2> b) {
86 return norm(cross(b[0], b[1])) / 2.0;
90 OMEGA_H_INLINE Real simplex_size_from_basis(Few<Vector<sdim>, 2> b) {
91 return triangle_area_from_basis(b);
94 OMEGA_H_INLINE Real tet_volume_from_basis(Few<Vector<3>, 3> b) {
95 return (cross(b[0], b[1]) * b[2]) / 6.0;
98 OMEGA_H_INLINE Real simplex_size_from_basis(Few<Vector<3>, 3> b) {
99 return tet_volume_from_basis(b);
112 OMEGA_H_INLINE Real anisotropic_edge_length(Real l_a, Real l_b) {
113 if (std::abs(l_a - l_b) > 1e-3) {
114 return (l_a - l_b) / (std::log(l_a / l_b));
116 return (l_a + l_b) / 2.;
119 template <Int space_dim, Int metric_dim>
120 OMEGA_H_INLINE Real metric_edge_length(
121 Few<Vector<space_dim>, 2> p, Few<Matrix<metric_dim, metric_dim>, 2> ms) {
122 auto v = p[1] - p[0];
123 auto l_a = metric_length(ms[0], v);
124 auto l_b = metric_length(ms[1], v);
125 return anisotropic_edge_length(l_a, l_b);
128 template <Int space_dim, Int metric_dim>
129 OMEGA_H_DEVICE Real metric_edge_length(
130 Few<LO, 2> v, Reals coords, Reals metrics) {
131 auto p = gather_vectors<2, space_dim>(coords, v);
132 auto ms = gather_symms<2, metric_dim>(metrics, v);
133 return metric_edge_length<space_dim, metric_dim>(p, ms);
136 template <Int space_dim>
140 OMEGA_H_DEVICE Real measure(
Few<LO, 2> v)
const {
141 auto p = gather_vectors<2, space_dim>(coords, v);
142 return norm(p[1] - p[0]);
146 template <Int space_dim, Int metric_dim>
151 : coords(mesh->coords()), metrics(metrics_in) {}
154 OMEGA_H_DEVICE Real measure(
Few<LO, 2> v)
const {
155 return metric_edge_length<space_dim, metric_dim>(v, coords, metrics);
166 template <Int sdim, Int edim>
168 auto b = simplex_basis<sdim, edim>(p);
169 return simplex_size_from_basis(b);
175 template <Int sdim, Int edim>
177 auto p = gather_vectors<edim + 1, sdim>(coords, v);
178 return real_simplex_size<sdim, edim>(p);
191 OMEGA_H_INLINE Few<Vector<2>, 3> element_edge_vectors(
192 Few<Vector<2>, 3> p, Few<Vector<2>, 2> b) {
193 Few<Vector<2>, 3> ev;
200 OMEGA_H_INLINE Few<Vector<3>, 6> element_edge_vectors(
201 Few<Vector<3>, 4> p, Few<Vector<3>, 3> b) {
202 Few<Vector<3>, 6> ev;
212 template <Int space_dim, Int metric_dim>
213 OMEGA_H_INLINE Real squared_metric_length(
214 Vector<space_dim> v, Matrix<metric_dim, metric_dim> m) {
215 return metric_product(m, v);
218 template <
typename EdgeVectors,
typename Metric>
219 OMEGA_H_INLINE Real mean_squared_metric_length(
220 EdgeVectors edge_vectors, Metric metric) {
221 auto const nedges = edge_vectors.size();
223 for (Int i = 0; i < nedges; ++i) {
224 msl += squared_metric_length(edge_vectors[i], metric);
229 template <
typename EdgeVectors>
230 OMEGA_H_INLINE Real mean_squared_real_length(EdgeVectors edge_vectors) {
231 return mean_squared_metric_length(edge_vectors, matrix_1x1(1.0));
234 OMEGA_H_INLINE Matrix<1, 1> element_implied_metric(Few<Vector<1>, 2> p) {
235 auto h = p[1][0] - p[0][0];
236 auto l = metric_eigenvalue_from_length(h);
237 return matrix_1x1(l);
240 OMEGA_H_INLINE Matrix<2, 2> element_implied_metric(Few<Vector<2>, 3> p) {
241 auto b = simplex_basis<2, 2>(p);
242 auto ev = element_edge_vectors(p, b);
245 for (Int i = 0; i < 3; ++i) {
247 a[0][i] = square(ev[i][0]);
248 a[1][i] = square(ev[i][1]);
249 a[2][i] = 2 * ev[i][0] * ev[i][1];
252 auto x = invert(a) * rhs;
253 return vector2symm(x);
256 OMEGA_H_INLINE Matrix<3, 3> element_implied_metric(Few<Vector<3>, 4> p) {
257 auto b = simplex_basis<3, 3>(p);
258 auto ev = element_edge_vectors(p, b);
261 for (Int i = 0; i < 6; ++i) {
263 a[0][i] = square(ev[i][0]);
264 a[1][i] = square(ev[i][1]);
265 a[2][i] = square(ev[i][2]);
266 a[3][i] = 2 * ev[i][0] * ev[i][1];
267 a[4][i] = 2 * ev[i][1] * ev[i][2];
268 a[5][i] = 2 * ev[i][0] * ev[i][2];
271 auto x = solve_using_qr(a, rhs);
272 return vector2symm(x);
276 OMEGA_H_INLINE Vector<dim> get_triangle_normal(
277 Vector<dim> a, Vector<dim> b, Vector<dim> c) {
278 return cross(b - a, c - a);
281 OMEGA_H_INLINE Vector<1> get_side_vector(Few<Vector<1>, 2>, Int ivert) {
282 return vector_1((ivert == 1) ? 1.0 : -1.0);
285 OMEGA_H_INLINE Vector<2> get_side_vector(Few<Vector<2>, 2> p) {
286 return -perp(p[1] - p[0]);
289 OMEGA_H_INLINE Vector<2> get_side_vector(Few<Vector<2>, 3> p, Int iedge) {
290 Few<Vector<2>, 2> sp;
293 return get_side_vector(sp);
296 OMEGA_H_INLINE Vector<3> get_side_vector(Few<Vector<3>, 3> p) {
297 return get_triangle_normal<3>(p[0], p[1], p[2]);
300 OMEGA_H_INLINE Vector<3> get_side_vector(Few<Vector<3>, 4> p, Int iface) {
301 Few<Vector<3>, 3> sp;
305 return get_side_vector(sp);
309 OMEGA_H_INLINE Plane<dim> get_side_plane(
310 Few<Vector<dim>, dim + 1> p, Int iside) {
311 auto n = get_side_vector(p, iside);
317 OMEGA_H_INLINE Sphere<dim> get_inball(Few<Vector<dim>, dim + 1> p) {
318 constexpr
auto nsides = dim + 1;
319 Few<Plane<dim>, dim + 1> planes;
320 for (Int iside = 0; iside < nsides; ++iside) {
321 planes[iside] = normalize(get_side_plane(p, iside));
324 for (Int i = 0; i < dim; ++i) {
325 a[i] = planes[i + 1].n - planes[0].n;
328 for (Int i = 0; i < dim; ++i) {
329 b[i] = planes[i + 1].d - planes[0].d;
332 auto const c = invert(a) * b;
333 auto const r = -distance(planes[0], c);
338 OMEGA_H_INLINE Vector<dim> get_size_gradient(
339 Few<Vector<dim>, dim + 1> p, Int ivert) {
340 auto iside = simplex_opposite_template(dim, VERT, ivert);
341 auto n = -get_side_vector(p, iside);
342 return n / Real(factorial(dim));
346 OMEGA_H_INLINE Matrix<dim, dim + 1> get_size_gradients(
347 Few<Vector<dim>, dim + 1> p) {
348 Matrix<dim, dim + 1> sgrads;
349 for (Int i = 0; i < dim + 1; ++i) sgrads[i] = get_size_gradient(p, i);
366 OMEGA_H_INLINE Vector<3> get_circumcenter_vector(Few<Vector<3>, 2> basis) {
369 auto balength = norm_squared(ba);
370 auto calength = norm_squared(ca);
371 auto crossbc = cross(ba, ca);
372 auto factor = 0.5 / norm_squared(crossbc);
373 auto xcirca = ((balength * ca[1] - calength * ba[1]) * crossbc[2] -
374 (balength * ca[2] - calength * ba[2]) * crossbc[1]) *
376 auto ycirca = ((balength * ca[2] - calength * ba[2]) * crossbc[0] -
377 (balength * ca[0] - calength * ba[0]) * crossbc[2]) *
379 auto zcirca = ((balength * ca[0] - calength * ba[0]) * crossbc[1] -
380 (balength * ca[1] - calength * ba[1]) * crossbc[0]) *
382 return vector_3(xcirca, ycirca, zcirca);
399 template <Int space_dim, Int metric_dim>
400 OMEGA_H_INLINE Real metric_size(
401 Real real_size, Matrix<metric_dim, metric_dim> metric) {
402 return real_size * power<space_dim, 2 * metric_dim>(determinant(metric));
406 OMEGA_H_INLINE constexpr Real equilateral_simplex_size(Int dim) {
408 dim == 3 ? 0.1178511301977579 : (dim == 2 ? 0.4330127018922193 : 1.0));
412 OMEGA_H_INLINE Affine<dim> simplex_affine(Few<Vector<dim>, dim + 1> p) {
414 a.r = simplex_basis<dim, dim>(p);
420 Real max_simplex_edge_length(Few<Vector<dim>, dim + 1> p) {
421 auto b = simplex_basis<dim, dim>(p);
422 auto ev = element_edge_vectors(p, b);
423 Real mel = norm(ev[0]);
424 for (Int i = 1; i < ev.size; ++i) mel = max2(mel, norm(ev[1]));
Definition: Omega_h_few.hpp:61
Definition: Omega_h_mesh.hpp:35
Definition: amr_mpi_test.cpp:6
OMEGA_H_INLINE Vector< edim+1 > barycentric_from_global(Vector< sdim > const &global_coordinate, Few< Vector< sdim >, edim+1 > const &node_coordinates)
Compute the barycentric coordinates from a position in global coordinates and the element nodal coord...
Definition: Omega_h_shape.hpp:58
OMEGA_H_INLINE Vector< dim+1 > form_barycentric(Vector< dim > const &c)
Constructs full barycentric representation (xi_0,xi_1,...) from xi_1, xi_2, ...
Definition: Omega_h_shape.hpp:46
constexpr OMEGA_H_INLINE Int simplex_down_template(Int elem_dim, Int bdry_dim, Int which_bdry, Int which_vert)
Relates bounding simplex vertices to the parent simplex's vertices.
Definition: Omega_h_simplex.hpp:23
Definition: Omega_h_shape.hpp:147
Definition: Omega_h_shape.hpp:28
Real d
Definition: Omega_h_shape.hpp:30
Vector< dim > n
Definition: Omega_h_shape.hpp:29
Definition: Omega_h_shape.hpp:137
Definition: Omega_h_shape.hpp:172
Definition: Omega_h_shape.hpp:22