https://mooseframework.inl.gov
Loading...
Searching...
No Matches
AutomaticMortarGeneration.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12#include "MortarSegmentInfo.h"
14#include "MooseHashing.h"
16#include "MooseError.h"
17#include "MooseUtils.h"
18
19// libMesh includes
20#include "libmesh/id_types.h"
21#include "libmesh/equation_systems.h"
22#include "libmesh/elem.h"
23#include "libmesh/int_range.h"
24#include "libmesh/vector_value.h"
25
26#include "metaphysicl/raw_type.h"
27
28// C++ includes
29#include <array>
30#include <cmath>
31#include <functional>
32#include <optional>
33#include <set>
34#include <memory>
35#include <vector>
36#include <unordered_map>
37
38// Forward declarations
39class GetPot;
40
41// Using statements
43
44typedef boundary_id_type BoundaryID;
45typedef subdomain_id_type SubdomainID;
46
47namespace Moose
48{
49namespace Mortar
50{
61template <typename Vector>
62std::array<Vector, 2>
63householderTangents(const Vector & normal)
64{
65 mooseAssert(MooseUtils::absoluteFuzzyEqual(MetaPhysicL::raw_value(normal.norm()), 1),
66 "The input nodal normal should have unity norm");
67
68 const Vector h_vector(normal(0) + 1.0, normal(1), normal(2));
69
70 // The h = n + e_x chart is singular at (-1, 0, 0), where the complementary h2 = n - e_x chart
71 // is regular. The h2 frame has determinant -1, so negating its second tangent gives the same
72 // positive orientation as the primary chart. At the pole, the frame is
73 // {(0, 1, 0), (0, 0, -1)} with nonzero derivatives.
74 if (std::abs(MetaPhysicL::raw_value(h_vector(0))) < TOLERANCE)
75 {
76 const Vector h2_vector(normal(0) - 1.0, normal(1), normal(2));
77 const auto h2_squared = h2_vector.norm_sq();
78 return {{Vector(-2.0 * h2_vector(0) * h2_vector(1) / h2_squared,
79 1.0 - 2.0 * h2_vector(1) * h2_vector(1) / h2_squared,
80 -2.0 * h2_vector(1) * h2_vector(2) / h2_squared),
81 Vector(2.0 * h2_vector(0) * h2_vector(2) / h2_squared,
82 2.0 * h2_vector(1) * h2_vector(2) / h2_squared,
83 2.0 * h2_vector(2) * h2_vector(2) / h2_squared - 1.0)}};
84 }
85
86 // The squared norm avoids propagating derivatives through a square root.
87 const auto h_squared = h_vector.norm_sq();
88 return {{Vector(-2.0 * h_vector(0) * h_vector(1) / h_squared,
89 1.0 - 2.0 * h_vector(1) * h_vector(1) / h_squared,
90 -2.0 * h_vector(1) * h_vector(2) / h_squared),
91 Vector(-2.0 * h_vector(0) * h_vector(2) / h_squared,
92 -2.0 * h_vector(1) * h_vector(2) / h_squared,
93 1.0 - 2.0 * h_vector(2) * h_vector(2) / h_squared)}};
94}
95
108template <typename Vector>
109std::array<Vector, 2>
110nodalTangents(const Vector & normal, const unsigned int dim)
111{
112 if (dim == 2)
113 return {{Vector(-normal(1), normal(0), 0.0), Vector(0.0, 0.0, 1.0)}};
114
115 return householderTangents(normal);
116}
117}
118}
119
124{
125 std::array<Point, 3> secondary_reference_points;
126 std::array<Point, 3> primary_reference_points;
127};
128
134{
135public:
140 const static std::string system_name;
141
147 MeshBase & mesh_in,
148 const std::pair<BoundaryID, BoundaryID> & boundary_key,
149 const std::pair<SubdomainID, SubdomainID> & subdomain_key,
150 bool on_displaced,
151 bool periodic,
152 const bool debug,
153 const bool correct_edge_dropping,
154 const Real minimum_projection_angle,
155 const Mortar3DSubpatchPlane mortar_3d_subpatch_plane,
156 const MortarSegmentTriangulationMode triangulation_mode,
157 const bool triangulate_triangles,
158 const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping =
159 Mortar3DQuadraturePointMapping::NORMAL_PROJECTION);
160
167 void buildNodeToElemMaps();
168
177
192
207 void projectPrimaryNodes();
208
226
239
261
266 std::vector<MsmSubdomainStats> computeMsmStatistics();
267
271 void msmStatistics();
272
276 void clear();
277
282 void meshChanged() { _msm_node_id_start = std::nullopt; }
283
287 bool onDisplaced() const { return _on_displaced; }
288
292 std::vector<Point> getNodalNormals(const Elem & secondary_elem) const;
293
298 std::array<MooseUtils::SemidynamicVector<Point, 9>, 2>
299 getNodalTangents(const Elem & secondary_elem) const;
300
307 void
308 computeADNodalNormals(const std::function<ADPoint(const Node &)> & coordinate,
309 std::unordered_map<const Node *, ADRealVectorValue> & nodal_normals) const;
310
315 std::map<unsigned int, unsigned int>
316 getSecondaryIpToLowerElementMap(const Elem & lower_secondary_elem) const;
317
324 std::map<unsigned int, unsigned int>
325 getPrimaryIpToLowerElementMap(const Elem & primary_elem,
326 const Elem & primary_elem_ip,
327 const Elem & lower_secondary_elem) const;
328
337 std::vector<Point> getNormals(const Elem & secondary_elem,
338 const std::vector<Point> & xi1_pts) const;
339
348 std::vector<Point> getNormals(const Elem & secondary_elem,
349 const std::vector<Real> & oned_xi1_pts) const;
350
358 const Elem * getSecondaryLowerdElemFromSecondaryElem(dof_id_type secondary_elem_id) const;
359
365
371
377
381 const std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> &
386
396
400 const std::pair<BoundaryID, BoundaryID> & primarySecondaryBoundaryIDPair() const;
401
405 const MeshBase & mortarSegmentMesh() const { return *_mortar_segment_mesh; }
406
410 const std::unordered_map<const Elem *, MortarSegmentInfo> & mortarSegmentMeshElemToInfo() const
411 {
412 return _msm_elem_to_info;
413 }
414
415 int dim() const { return _mesh.mesh_dimension(); }
416
418 Mortar3DQuadraturePointMapping mortar3DQpMapping() const { return _mortar_3d_qp_mapping; }
419
422 mortarSegmentReferencePoints(const Elem & mortar_segment_elem) const;
423
427 const std::unordered_set<const Node *> & getInactiveLMNodes() const
428 {
430 }
431
435 const std::unordered_set<const Elem *> & getInactiveLMElems() const
436 {
438 }
439
441
443 std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>>::const_iterator;
444
451 std::vector<MortarFilterIter> secondariesToMortarSegments(const Node & node) const;
452
457 const std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>> &
462
466 const std::set<SubdomainID> & secondaryIPSubIDs() const { return _secondary_ip_sub_ids; }
467
471 const std::set<SubdomainID> & primaryIPSubIDs() const { return _primary_ip_sub_ids; }
472
476 const std::unordered_map<dof_id_type, std::vector<const Elem *>> & nodesToSecondaryElem() const
477 {
479 }
480
484 void initOutput();
485
486private:
490 void outputMortarMesh();
491
495 std::string mortarInterfaceName() const;
496
501
504
506 MeshBase & _mesh;
507
510
513
516 std::vector<std::pair<BoundaryID, BoundaryID>> _primary_secondary_boundary_id_pairs;
517
519 std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_secondary_elem_map;
520 std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_primary_elem_map;
521
539 std::unordered_map<std::pair<const Node *, const Elem *>, std::pair<Real, const Elem *>>
541
547 std::map<std::tuple<dof_id_type, const Node *, const Elem *>, std::pair<Real, const Elem *>>
549
552 std::unique_ptr<MeshBase> _mortar_segment_mesh;
553
557 std::unordered_map<const Elem *, MortarSegmentInfo> _msm_elem_to_info;
558
561 std::unordered_map<const Elem *, unsigned int> _lower_elem_to_side_id;
562
565 std::vector<std::pair<SubdomainID, SubdomainID>> _primary_secondary_subdomain_id_pairs;
566
570 std::set<SubdomainID> _primary_boundary_subdomain_ids;
571
580 std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> _mortar_interface_coupling;
581
583 std::unordered_map<const Node *, Point> _secondary_node_to_nodal_normal;
584
587 std::unordered_map<const Node *, std::array<Point, 2>> _secondary_node_to_hh_nodal_tangents;
588
590 std::unordered_map<dof_id_type, const Elem *> _secondary_element_to_secondary_lowerd_element;
591
593 std::unordered_set<const Node *> _inactive_local_lm_nodes;
594
596 std::unordered_set<const Elem *> _inactive_local_lm_elems;
597
601 std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>>
603
605 std::set<SubdomainID> _secondary_ip_sub_ids;
606
608 std::set<SubdomainID> _primary_ip_sub_ids;
609
615 void projectSecondaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id,
616 SubdomainID lower_dimensional_secondary_subdomain_id);
617
621 void projectPrimaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id,
622 SubdomainID lower_dimensional_secondary_subdomain_id);
623
628 bool processAlignedNodes(const Node & secondary_node,
629 const Node & primary_node,
630 const std::vector<const Elem *> * secondary_node_neighbors,
631 const std::vector<const Elem *> * primary_node_neighbors,
632 const VectorValue<Real> & nodal_normal,
633 const Elem & candidate_element,
634 std::set<const Elem *> & rejected_element_candidates);
635
637 const bool _debug;
638
640 const bool _on_displaced;
641
643 const bool _periodic;
644
646 const bool _distributed;
647
651
653 Real _newton_tolerance = 1e-12;
654
658 Real _xi_tolerance = 1e-6;
659
663
669
671 const Mortar3DSubpatchPlane _mortar_3d_subpatch_plane;
672
675
678
680 const Mortar3DQuadraturePointMapping _mortar_3d_qp_mapping;
681
683 std::unordered_map<const Elem *, MortarSegmentReferencePoints> _msm_elem_to_reference_points;
684
686 std::unique_ptr<InputParameters> _output_params;
687
691 std::optional<dof_id_type> _msm_node_id_start;
692
695 std::unordered_set<dof_id_type> _projected_secondary_nodes;
696
698 std::unordered_set<dof_id_type> _failed_secondary_node_projections;
699
702};
703
704inline const std::pair<BoundaryID, BoundaryID> &
706{
707 mooseAssert(_primary_secondary_boundary_id_pairs.size() == 1,
708 "We currently only support a single boundary pair per mortar generation object");
709
711}
boundary_id_type BoundaryID
subdomain_id_type SubdomainID
libMesh::VectorValue< ADReal > ADPoint
Definition MooseTypes.h:413
MortarSegmentTriangulationMode
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
const Elem * getSecondaryLowerdElemFromSecondaryElem(dof_id_type secondary_elem_id) const
Return lower dimensional secondary element given its interior parent.
Real _newton_tolerance
Newton solve tolerance for node projections.
std::unordered_map< const Node *, Point > _secondary_node_to_nodal_normal
Container for storing the nodal normal vector associated with each secondary node.
const MortarSegmentReferencePoints & mortarSegmentReferencePoints(const Elem &mortar_segment_elem) const
Return the parent-face reference coordinates for a mortar segment.
std::unordered_map< const Elem *, unsigned int > _lower_elem_to_side_id
Keeps track of the mapping between lower-dimensional elements and the side_id of the interior_parent ...
bool _nonlocal_secondary_couplings
Whether buildCouplingInformation() also gathers the couplings of nonlocal secondary lower-dimensional...
Mortar3DQuadraturePointMapping mortar3DQpMapping() const
Return the 3D mortar quadrature-point mapping method.
std::unordered_map< const Elem *, MortarSegmentReferencePoints > _msm_elem_to_reference_points
Reference-coordinate data used only by the reference-interpolation mapping mode.
std::unordered_set< dof_id_type > _projected_secondary_nodes
Debugging container for printing information about fraction of successful projections for secondary n...
std::unordered_map< dof_id_type, std::vector< const Elem * > > _nodes_to_secondary_elem_map
Map from nodes to connected lower-dimensional elements on the secondary/primary subdomains.
std::set< BoundaryID > _secondary_requested_boundary_ids
The boundary ids corresponding to all the secondary surfaces.
std::unordered_map< dof_id_type, std::vector< const Elem * > > _nodes_to_primary_elem_map
std::unordered_map< dof_id_type, std::set< Elem *, CompareDofObjectsByID > >::const_iterator MortarFilterIter
Real _xi_tolerance
Tolerance for checking projection xi values.
void outputMortarMesh()
Write the mortar segment mesh to exodus.
void computeNodalGeometry()
Computes and stores the nodal normal/tangent vectors in a local data structure instead of using the E...
const Mortar3DQuadraturePointMapping _mortar_3d_qp_mapping
Method used to map 3D mortar segment quadrature points to primary and secondary faces.
void msmStatistics()
Prints mortar segment mesh statistics to console (calls computeMsmStatistics internally)
std::vector< std::pair< BoundaryID, BoundaryID > > _primary_secondary_boundary_id_pairs
A list of primary/secondary boundary id pairs corresponding to each side of the mortar interface.
void requestNonlocalSecondaryCouplings()
Request that every process receive the mortar interface couplings of the nonlocal secondary lower-dim...
std::unique_ptr< InputParameters > _output_params
Storage for the input parameters used by the mortar nodal geometry output.
void buildMortarSegmentMesh()
Builds the mortar segment mesh once the secondary and primary node projections have been completed.
std::unordered_set< const Node * > _inactive_local_lm_nodes
List of inactive lagrange multiplier nodes owned by this processor (for nodal variables)
const bool _periodic
Whether this object will be generating a mortar segment mesh for periodic constraints.
const std::pair< BoundaryID, BoundaryID > & primarySecondaryBoundaryIDPair() const
void projectSecondaryNodes()
Project secondary nodes (find xi^(2) values) to the closest points on the primary surface.
void buildMortarSegmentMesh3d()
Builds the mortar segment mesh once the secondary and primary node projections have been completed.
void computeInactiveLMElems()
Get list of secondary elems without any corresponding primary elements.
std::set< SubdomainID > _secondary_boundary_subdomain_ids
The secondary/primary lower-dimensional boundary subdomain ids are the secondary/primary boundary ids...
static const std::string system_name
The name of the nodal normals system.
const bool _correct_edge_dropping
Flag to enable regressed treatment of edge dropping where all LM DoFs on edge dropping element are st...
void buildCouplingInformation()
build the _mortar_interface_coupling data
const Mortar3DSubpatchPlane _mortar_3d_subpatch_plane
Method used to define the local projection planes for 3D secondary subpatches.
std::vector< Point > getNormals(const Elem &secondary_elem, const std::vector< Point > &xi1_pts) const
Compute the normals at given reference points on a secondary element.
std::set< SubdomainID > _secondary_ip_sub_ids
All the secondary interior parent subdomain IDs associated with the mortar mesh.
void initOutput()
initialize mortar-mesh based output
std::unordered_map< const Node *, std::array< Point, 2 > > _secondary_node_to_hh_nodal_tangents
Container for storing the nodal tangent/binormal vectors associated with each secondary node (Househo...
bool processAlignedNodes(const Node &secondary_node, const Node &primary_node, const std::vector< const Elem * > *secondary_node_neighbors, const std::vector< const Elem * > *primary_node_neighbors, const VectorValue< Real > &nodal_normal, const Elem &candidate_element, std::set< const Elem * > &rejected_element_candidates)
Process aligned nodes.
void projectSecondaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id, SubdomainID lower_dimensional_secondary_subdomain_id)
Helper function responsible for projecting secondary nodes onto primary elements for a single primary...
std::vector< MsmSubdomainStats > computeMsmStatistics()
Computes mortar segment mesh statistics and returns one entry per subdomain pair.
MeshBase & _mesh
Reference to the mesh stored in equation_systems.
const std::set< SubdomainID > & secondaryIPSubIDs() const
const bool _debug
Whether to print debug output.
std::vector< std::pair< SubdomainID, SubdomainID > > _primary_secondary_subdomain_id_pairs
A list of primary/secondary subdomain id pairs corresponding to each side of the mortar interface.
std::map< unsigned int, unsigned int > getSecondaryIpToLowerElementMap(const Elem &lower_secondary_elem) const
Compute on-the-fly mapping from secondary interior parent nodes to lower dimensional nodes.
void buildNodeToElemMaps()
Once the secondary_requested_boundary_ids and primary_requested_boundary_ids containers have been fil...
std::unique_ptr< MeshBase > _mortar_segment_mesh
1D Mesh of mortar segment elements which gets built by the call to build_mortar_segment_mesh().
void computeADNodalNormals(const std::function< ADPoint(const Node &)> &coordinate, std::unordered_map< const Node *, ADRealVectorValue > &nodal_normals) const
Build the normalized JxW-weighted secondary nodal normals from AD nodal coordinates.
const MeshBase & mortarSegmentMesh() const
std::optional< dof_id_type > _msm_node_id_start
Cached per-rank starting ID for 3D MSM nodes/elements.
void clear()
Clears the mortar segment mesh and accompanying data structures.
const std::unordered_set< const Elem * > & getInactiveLMElems() const
const std::set< SubdomainID > & primaryIPSubIDs() const
std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > _mortar_interface_coupling
Used by the AugmentSparsityOnInterface functor to determine whether a given Elem is coupled to any ot...
std::map< unsigned int, unsigned int > getPrimaryIpToLowerElementMap(const Elem &primary_elem, const Elem &primary_elem_ip, const Elem &lower_secondary_elem) const
Compute on-the-fly mapping from primary interior parent nodes to its corresponding lower dimensional ...
bool onDisplaced() const
returns whether this object is on the displaced mesh
std::unordered_map< std::pair< const Node *, const Elem * >, std::pair< Real, const Elem * > > _secondary_node_and_elem_to_xi2_primary_elem
Similar to the map above, but associates a (Secondary Node, Secondary Elem) pair to a (xi^(2),...
std::unordered_map< const Elem *, MortarSegmentInfo > _msm_elem_to_info
Map between Elems in the mortar segment mesh and their info structs.
std::map< std::tuple< dof_id_type, const Node *, const Elem * >, std::pair< Real, const Elem * > > _primary_node_and_elem_to_xi1_secondary_elem
Same type of container, but for mapping (Primary Node ID, Primary Node, Primary Elem) -> (xi^(1),...
const bool _on_displaced
Whether this object is on the displaced mesh.
std::unordered_set< const Elem * > _inactive_local_lm_elems
List of inactive lagrange multiplier nodes (for elemental variables)
void computeIncorrectEdgeDroppingInactiveLMNodes()
Computes inactive secondary nodes when incorrect edge dropping behavior is enabled (any node touching...
const bool _distributed
Whether the mortar segment mesh is distributed.
std::array< MooseUtils::SemidynamicVector< Point, 9 >, 2 > getNodalTangents(const Elem &secondary_elem) const
Compute the two nodal tangents, which are built on-the-fly.
std::set< SubdomainID > _primary_ip_sub_ids
All the primary interior parent subdomain IDs associated with the mortar mesh.
std::unordered_map< dof_id_type, const Elem * > _secondary_element_to_secondary_lowerd_element
Map from full dimensional secondary element id to lower dimensional secondary element.
const bool _triangulate_triangles
Whether already-triangular clipped polygons should still be centroid-subdivided.
std::set< SubdomainID > _primary_boundary_subdomain_ids
void projectPrimaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id, SubdomainID lower_dimensional_secondary_subdomain_id)
Helper function used internally by AutomaticMortarGeneration::project_primary_nodes().
const MortarSegmentTriangulationMode _triangulation_mode
Triangulation mode used for clipped 3D mortar polygons.
std::set< BoundaryID > _primary_requested_boundary_ids
The boundary ids corresponding to all the primary surfaces.
std::unordered_set< dof_id_type > _failed_secondary_node_projections
Secondary nodes that failed to project.
std::vector< Point > getNodalNormals(const Elem &secondary_elem) const
const std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > & mortarInterfaceCoupling() const
std::unordered_map< dof_id_type, std::set< Elem *, CompareDofObjectsByID > > _secondary_elems_to_mortar_segments
We maintain a mapping from lower-dimensional secondary elements in the original mesh to (sets of) ele...
const std::unordered_map< dof_id_type, std::set< Elem *, CompareDofObjectsByID > > & secondariesToMortarSegments() const
const std::unordered_map< const Elem *, MortarSegmentInfo > & mortarSegmentMeshElemToInfo() const
void projectPrimaryNodes()
(Inverse) project primary nodes to the points on the secondary surface where they would have come fro...
void computeInactiveLMNodes()
Get list of secondary nodes that don't contribute to interaction with any primary element.
const Real _minimum_projection_angle
Parameter to control which angle (in degrees) is admissible for the creation of mortar segments.
const std::unordered_set< const Node * > & getInactiveLMNodes() const
void meshChanged()
Invalidates the cached MSM node/element ID starting offset so that the next call to buildMortarSegmen...
const std::unordered_map< dof_id_type, std::vector< const Elem * > > & nodesToSecondaryElem() const
An inteface for the _console for outputting to the Console object.
Base class for MOOSE-based applications.
Definition MooseApp.h:110
auto raw_value(const Eigen::Map< T > &in)
std::array< Vector, 2 > nodalTangents(const Vector &normal, const unsigned int dim)
Construct the two tangent vectors used by mortar from a unit normal on a dim dimensional mesh.
std::array< Vector, 2 > householderTangents(const Vector &normal)
Construct the two tangent vectors used by mortar from a unit normal.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:175
Statistics for one primary-secondary subdomain pair.
Parent-face reference coordinates associated with the vertices of one triangular mortar segment.
std::array< Point, 3 > primary_reference_points
std::array< Point, 3 > secondary_reference_points