14#include "libmesh/cell_hex8.h"
15#include "libmesh/cell_hex.h"
16#include "libmesh/edge_edge2.h"
17#include "libmesh/enum_elem_type.h"
18#include "libmesh/enum_point_locator_type.h"
19#include "libmesh/int_range.h"
20#include "libmesh/dof_map.h"
22#include "libmesh/elem.h"
23#include "libmesh/face_quad.h"
24#include "libmesh/face_quad4.h"
25#include "libmesh/fe_compute_data.h"
26#include "libmesh/fe_interface.h"
27#include "libmesh/id_types.h"
28#include "libmesh/int_range.h"
29#include "libmesh/libmesh_common.h"
30#include "libmesh/numeric_vector.h"
31#include "libmesh/explicit_system.h"
32#include "libmesh/plane.h"
33#include "libmesh/enum_to_string.h"
35#include "libmesh/quadrature_gauss.h"
36#include "libmesh/fe_base.h"
39 const std::string & exodus_mesh,
40 const bool find_closest,
41 const unsigned int kdtree_candidates)
42 : _communicator(MPI_COMM_SELF),
44 _find_closest(find_closest),
45 _kdtree_candidates(kdtree_candidates),
56 _eq = std::make_unique<libMesh::EquationSystems>(
_mesh);
57 _sys = &
_eq->add_system<ExplicitSystem>(
"_parameter_mesh_sys");
69 std::set<dof_id_type> var_indices;
75 for (
const auto & elem :
_mesh.element_ptr_range())
76 if (elem->default_order() != FIRST)
77 mooseError(
"Closet point projection currently does not support second order elements.");
85 for (
const auto & node :
_mesh.node_ptr_range())
89 for (
const auto & elem :
_mesh.element_ptr_range())
91 for (
const auto n : make_range(elem->n_nodes()))
93 dof_id_type node_id = elem->node_id(n);
109 std::vector<dof_id_type> & dof_indices,
110 std::vector<Real> & weights)
const
114 const Elem * elem = (*_point_locator)(test_point);
116 mooseError(
"No element was found to contain point ", test_point);
124 Point coor = FEMap::inverse_map(elem->dim(), elem, test_point);
127 FEInterface::compute_data(elem->dim(),
_fe_type, elem, fe_data);
129 weights = fe_data.
shape;
131 if (dof_indices.size() != weights.size())
132 mooseError(
"Internal error: weights and DoF indices do not have the same size.");
137 std::vector<dof_id_type> & dof_indices,
138 std::vector<RealGradient> & weights)
const
141 mooseError(
"Internal error: System being read does not contain _parameter_mesh_var.");
144 const Elem * elem = (*_point_locator)(test_point);
152 Point coor = FEMap::inverse_map(elem->dim(), elem, test_point);
156 FEInterface::compute_data(elem->dim(),
_fe_type, elem, fe_data);
160 if (dof_indices.size() != weights.size())
161 mooseError(
"Internal error: weights and DoF indices do not have the same size.");
172 auto findClosestElement = [&
p,
this](
const auto & elements) -> Point
174 Real best_d2 = std::numeric_limits<Real>::max();
175 Point best_point =
p;
177 for (
const auto * elem : elements)
180 Real d2 = (trial -
p).norm_sq();
188 if (best_d2 == std::numeric_limits<Real>::max())
189 mooseError(
"project_to_mesh failed - no candidate elements.");
197 std::vector<std::size_t> nearest_node_indices;
201 std::set<const Elem *> candidate_elements;
202 for (
auto node_idx : nearest_node_indices)
208 dof_id_type node_id = node->id();
212 const auto & connected_elems = it->second;
213 candidate_elements.insert(connected_elems.begin(), connected_elems.end());
219 std::vector<const Elem *> candidate_vector(candidate_elements.begin(),
220 candidate_elements.end());
221 return findClosestElement(candidate_vector);
226 std::vector<const Elem *> all_elements;
227 for (
const auto & elem :
_mesh.element_ptr_range())
228 all_elements.push_back(elem);
230 return findClosestElement(all_elements);
237 mooseAssert(!elem.contains_point(
p),
238 "Points inside of elements shouldn't need to find closestPoint.");
241 auto findClosest = [&
p](
auto range,
auto point_func) -> Point
243 Real min_distance = std::numeric_limits<Real>::max();
246 for (
const auto & item : range)
248 Point candidate = point_func(item);
253 min_point = candidate;
263 LineSegment ls(*(elem.node_ptr(0)), *(elem.node_ptr(1)));
269 Point
a = *(elem.node_ptr(0));
270 Point
b = *(elem.node_ptr(1));
271 Point
c = *(elem.node_ptr(2));
274 if (elem.contains_point(trial))
277 return findClosest(make_range(elem.n_edges()),
278 [&](dof_id_type i) { return closestPoint(*elem.build_edge_ptr(i), p); });
282 Point
a = *(elem.node_ptr(0));
283 Point
b = *(elem.node_ptr(1));
284 Point
c = *(elem.node_ptr(2));
285 Point
d = *(elem.node_ptr(3));
290 if (!trial1.absolute_fuzzy_equals(trial2, TOLERANCE * TOLERANCE))
293 if (elem.contains_point(trial1))
296 return findClosest(make_range(elem.n_edges()),
297 [&](dof_id_type i) { return closestPoint(*elem.build_edge_ptr(i), p); });
304 return findClosest(make_range(elem.n_sides()),
305 [&](dof_id_type i) { return closestPoint(*elem.build_side_ptr(i), p); });
310 Utility::enum_to_string(elem.type()),
311 " for projection of parameter mesh.");
324 parameter_values.size(),
325 ") does not match mesh DOFs (",
330 if constexpr (std::is_same_v<T, Real>)
332 else if constexpr (std::is_same_v<T, std::vector<Real>>)
336 for (
const auto & elem :
_mesh.element_ptr_range())
339 std::vector<dof_id_type> dof_indices;
343 const unsigned int dim = elem->dim();
347 std::unique_ptr<FEBase> fe(FEBase::build(
dim,
_fe_type));
348 fe->attach_quadrature_rule(&qrule);
351 const std::vector<Real> & JxW = fe->get_JxW();
352 const std::vector<std::vector<Real>> & phi = fe->get_phi();
353 const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
358 for (
const auto qp : make_range(qrule.n_points()))
360 if constexpr (std::is_same_v<T, Real>)
363 else if constexpr (std::is_same_v<T, std::vector<Real>>)
365 parameter_values, phi, dphi, qp, dof_indices, JxW, reg_type, result);
376 return computeRegularizationLoop<Real>(parameter_values, reg_type);
383 return computeRegularizationLoop<std::vector<Real>>(parameter_values, reg_type);
388 const std::vector<std::vector<Real>> & ,
389 const std::vector<std::vector<RealGradient>> & dphi,
390 const unsigned int qp,
391 const std::vector<dof_id_type> & dof_indices,
392 const std::vector<Real> & JxW,
395 Real objective_contribution = 0.0;
403 RealGradient param_grad;
404 for (
const auto i : index_range(dof_indices))
405 param_grad += parameter_values[dof_indices[i]] * dphi[i][qp];
408 objective_contribution = param_grad.
norm_sq() * JxW[qp];
415 return objective_contribution;
420 const std::vector<std::vector<Real>> & ,
421 const std::vector<std::vector<RealGradient>> & dphi,
422 const unsigned int qp,
423 const std::vector<dof_id_type> & dof_indices,
424 const std::vector<Real> & JxW,
426 std::vector<Real> & gradient)
const
434 RealGradient param_grad;
435 for (
const auto i : index_range(dof_indices))
436 param_grad += parameter_values[dof_indices[i]] * dphi[i][qp];
439 for (
const auto j : index_range(dof_indices))
440 gradient[dof_indices[j]] += 2.0 * param_grad * dphi[j][qp] * JxW[qp];
void mooseError(Args &&... args)
Point closest_point(const Point &p) const
RegularizationType
Enumerations for regularization computations.
unsigned int _kdtree_candidates
const bool _find_closest
Find closest projection points.
void computeRegularizationGradientQp(const std::vector< Real > ¶meter_values, const std::vector< std::vector< Real > > &phi, const std::vector< std::vector< RealGradient > > &dphi, const unsigned int qp, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &JxW, RegularizationType reg_type, std::vector< Real > &gradient) const
Compute regularization gradient for a single quadrature point This is the main function users should ...
std::vector< Real > computeRegularizationGradient(const std::vector< Real > ¶meter_values, RegularizationType reg_type) const
Computes regularization gradient for a given regularization type.
std::unordered_map< dof_id_type, std::set< const libMesh::Elem * > > _node_to_elements
Real computeRegularizationQp(const std::vector< Real > ¶meter_values, const std::vector< std::vector< Real > > &phi, const std::vector< std::vector< RealGradient > > &dphi, const unsigned int qp, const std::vector< dof_id_type > &dof_indices, const std::vector< Real > &JxW, RegularizationType reg_type) const
Compute regularization objective for a single quadrature point This is the main function users should...
std::unique_ptr< libMesh::EquationSystems > _eq
std::unique_ptr< libMesh::ExodusII_IO > _exodusII_io
Point closestPoint(const Elem &elem, const Point &p) const
Find closest point on the element to the given point.
const unsigned short int _param_var_id
std::unique_ptr< libMesh::PointLocatorBase > _point_locator
T computeRegularizationLoop(const std::vector< Real > ¶meter_values, RegularizationType reg_type) const
Template method containing the element loop for regularization computations.
Point projectToMesh(const Point &p) const
Returns the point on the parameter mesh that is projected from the test point.
libMesh::ReplicatedMesh _mesh
std::unique_ptr< KDTree > _node_kdtree
ParameterMesh(const libMesh::FEType ¶m_type, const std::string &exodus_mesh, const bool find_closest=false, const unsigned int kdtree_candidates=5)
Real computeRegularizationObjective(const std::vector< Real > ¶meter_values, RegularizationType reg_type) const
Computes regularization objective value for a given regularization type.
const libMesh::DofMap * _dof_map
const libMesh::FEType _fe_type
void getIndexAndWeight(const Point &pt, std::vector< dof_id_type > &dof_indices, std::vector< Real > &weights) const
Interpolate parameters onto the computational mesh getIndexAndWeight is only used by ParameterMeshFun...
std::vector< Point > _mesh_nodes
Node-based KDTree optimization.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
const FEType & variable_type(const unsigned int i) const
std::vector< Gradient > dshape
std::vector< Number > shape
Order default_quadrature_order() const
void allow_renumbering(bool allow)
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
virtual Point closest_point(const Point &p) const override
virtual const Node * node_ptr(const dof_id_type i) const override final
virtual dof_id_type n_nodes() const override final
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
void local_dof_indices(const unsigned int var, std::set< dof_id_type > &var_indices) const
unsigned int variable_number(std::string_view var) const
bool has_variable(std::string_view var) const
const DofMap & get_dof_map() const
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false, bool skip_detect_interior_parents=false) override
Real distance(const Point &p)