feat(geometry/deformation/backend/mfem/detail): added radial loactor to help identify points on a surface

This commit is contained in:
2026-10-12 14:10:10 -04:00
parent c440134059
commit eb9da56438

View File

@@ -0,0 +1,79 @@
#pragma once
/**
* @file radial_locator.hpp
* @author Emily M. Boudreaux
*
* @brief File containing some utility functions for locating points on a radial shell.
*/
#include "mfem/fem/intrules.hpp"
#include "mfem/linalg/vector.hpp"
#include "serif/geometry/deformation/failure.hpp"
namespace mfem {
/**
* @brief Forward definition of the mfem::Mesh class to avoid having to parse the entire mfem mesh header file.
*/
class Mesh;
}
namespace serif::geometry::deformation::backend::mfem::detail {
/** @struct LocatedBoundaryPoint
*
* @brief A structure representing a located boundary point, including the boundary element index and the integration point on that element.
*/
struct LocatedBoundaryPoint {
int boundary_element; ///< The index of the boundary element where the point is located.
::mfem::IntegrationPoint point; ///< The integration point on the boundary element where the point is located.
};
/**
* @brief compute the cubical local radius of a given position vector. Alternative put:
* compute the \f$L\infty\f$ norm of the position vector (i.e. the maximum absolute value of its components)
*
* @param position The position vector for which to compute the logical radius.
* @returns The logical radius of the position vector, defined as the maximum absolute value of its components (i.e., the L\f$\infty\f$ norm).
*/
[[nodiscard]] double logical_radius(const ::mfem::Vector& position);
/**
* @brief Compute the logical radius of a boundary shell in a mesh, given the mesh and the boundary attribute.
*
* @param mesh The mesh containing the boundary shell.
* @param attribute The boundary attribute identifying the shell to compute the logical radius for.
*
* @returns The logical radius of the boundary shell if successful, or a DeformationFailure object if an error occurs (e.g., incompatible discretization, non-finite vertex, or invalid geometry).
*
* @par Explanation
* The algorithm here is as follows
* 1. Loop over all boundary elements. validate they they have the correct attribute id (if not skip them)
* 2. Get the geometry type of the element and validate that it has a valid transformation and is a square (which for mfem really means a quadrilateral). If not return an error
* 3. Get the vertices of the element and loop over them. For each vertex
* a. Transform the vertex into a position vector
* b. validate that each component of the position vector is finite. If not return an error
* c. Compute the logical radius of the position vector (L\f$\infty\f$ norm) and update the minimum and maximum logical radius values seen so far
* d. Increment the number of samples seen so far
* 4. validate that at least one sample was seen, that the minimum values is positive, and that are at least separated by 1e-12 * max(1, maximum). If not return an error
* 5. Return the average of the minimum and maximum logical radius values seen.
*
* Effectively then what this does is find an estimate for the radius of some enclosing surface over the boundary elements.
*/
[[nodiscard]] std::expected<double, DeformationFailure> boundary_logical_radius(::mfem::Mesh& mesh, int attribute);
/**
* @brief Locate a projected logical ray on a quadrilateral shell.
*
* @param mesh The mesh containing the boundary shell.
* @param attribute The boundary attribute identifying the shell to locate the point on.
* @param target The target position vector to locate on the boundary shell.
*
* @returns A LocatedBoundaryPoint object representing the located boundary point if successful, or a DeformationFailure object if an error occurs
*/
[[nodiscard]] std::expected<LocatedBoundaryPoint, DeformationFailure> locate_boundary_point(
::mfem::Mesh& mesh,
int attribute,
const ::mfem::Vector& target
);
}