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}
96}
97
102{
103 std::array<Point, 3> secondary_reference_points;
104 std::array<Point, 3> primary_reference_points;
105};
106
112{
113public:
118 const static std::string system_name;
119
125 MeshBase & mesh_in,
126 const std::pair<BoundaryID, BoundaryID> & boundary_key,
127 const std::pair<SubdomainID, SubdomainID> & subdomain_key,
128 bool on_displaced,
129 bool periodic,
130 const bool debug,
131 const bool correct_edge_dropping,
132 const Real minimum_projection_angle,
133 const Mortar3DSubpatchPlane mortar_3d_subpatch_plane,
134 const MortarSegmentTriangulationMode triangulation_mode,
135 const bool triangulate_triangles,
136 const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping =
137 Mortar3DQuadraturePointMapping::NORMAL_PROJECTION);
138
145 void buildNodeToElemMaps();
146
155
170
185 void projectPrimaryNodes();
186
204
217
239
244 std::vector<MsmSubdomainStats> computeMsmStatistics();
245
249 void msmStatistics();
250
254 void clear();
255
260 void meshChanged() { _msm_node_id_start = std::nullopt; }
261
265 bool onDisplaced() const { return _on_displaced; }
266
270 std::vector<Point> getNodalNormals(const Elem & secondary_elem) const;
271
276 std::array<MooseUtils::SemidynamicVector<Point, 9>, 2>
277 getNodalTangents(const Elem & secondary_elem) const;
278
285 void
286 computeADNodalNormals(const std::function<ADPoint(const Node &)> & coordinate,
287 std::unordered_map<const Node *, ADRealVectorValue> & nodal_normals) const;
288
293 std::map<unsigned int, unsigned int>
294 getSecondaryIpToLowerElementMap(const Elem & lower_secondary_elem) const;
295
302 std::map<unsigned int, unsigned int>
303 getPrimaryIpToLowerElementMap(const Elem & primary_elem,
304 const Elem & primary_elem_ip,
305 const Elem & lower_secondary_elem) const;
306
315 std::vector<Point> getNormals(const Elem & secondary_elem,
316 const std::vector<Point> & xi1_pts) const;
317
326 std::vector<Point> getNormals(const Elem & secondary_elem,
327 const std::vector<Real> & oned_xi1_pts) const;
328
336 const Elem * getSecondaryLowerdElemFromSecondaryElem(dof_id_type secondary_elem_id) const;
337
343
349
355
359 const std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> &
364
368 const std::pair<BoundaryID, BoundaryID> & primarySecondaryBoundaryIDPair() const;
369
373 const MeshBase & mortarSegmentMesh() const { return *_mortar_segment_mesh; }
374
378 const std::unordered_map<const Elem *, MortarSegmentInfo> & mortarSegmentMeshElemToInfo() const
379 {
380 return _msm_elem_to_info;
381 }
382
383 int dim() const { return _mesh.mesh_dimension(); }
384
386 Mortar3DQuadraturePointMapping mortar3DQpMapping() const { return _mortar_3d_qp_mapping; }
387
390 mortarSegmentReferencePoints(const Elem & mortar_segment_elem) const;
391
395 const std::unordered_set<const Node *> & getInactiveLMNodes() const
396 {
398 }
399
403 const std::unordered_set<const Elem *> & getInactiveLMElems() const
404 {
406 }
407
409
411 std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>>::const_iterator;
412
419 std::vector<MortarFilterIter> secondariesToMortarSegments(const Node & node) const;
420
425 const std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>> &
430
434 const std::set<SubdomainID> & secondaryIPSubIDs() const { return _secondary_ip_sub_ids; }
435
439 const std::set<SubdomainID> & primaryIPSubIDs() const { return _primary_ip_sub_ids; }
440
444 const std::unordered_map<dof_id_type, std::vector<const Elem *>> & nodesToSecondaryElem() const
445 {
447 }
448
452 void initOutput();
453
454private:
458 void outputMortarMesh();
459
463 std::string mortarInterfaceName() const;
464
469
472
474 MeshBase & _mesh;
475
478
481
484 std::vector<std::pair<BoundaryID, BoundaryID>> _primary_secondary_boundary_id_pairs;
485
487 std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_secondary_elem_map;
488 std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_primary_elem_map;
489
507 std::unordered_map<std::pair<const Node *, const Elem *>, std::pair<Real, const Elem *>>
509
515 std::map<std::tuple<dof_id_type, const Node *, const Elem *>, std::pair<Real, const Elem *>>
517
520 std::unique_ptr<MeshBase> _mortar_segment_mesh;
521
525 std::unordered_map<const Elem *, MortarSegmentInfo> _msm_elem_to_info;
526
529 std::unordered_map<const Elem *, unsigned int> _lower_elem_to_side_id;
530
533 std::vector<std::pair<SubdomainID, SubdomainID>> _primary_secondary_subdomain_id_pairs;
534
538 std::set<SubdomainID> _primary_boundary_subdomain_ids;
539
548 std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> _mortar_interface_coupling;
549
551 std::unordered_map<const Node *, Point> _secondary_node_to_nodal_normal;
552
555 std::unordered_map<const Node *, std::array<Point, 2>> _secondary_node_to_hh_nodal_tangents;
556
558 std::unordered_map<dof_id_type, const Elem *> _secondary_element_to_secondary_lowerd_element;
559
561 std::unordered_set<const Node *> _inactive_local_lm_nodes;
562
564 std::unordered_set<const Elem *> _inactive_local_lm_elems;
565
569 std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>>
571
573 std::set<SubdomainID> _secondary_ip_sub_ids;
574
576 std::set<SubdomainID> _primary_ip_sub_ids;
577
583 void projectSecondaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id,
584 SubdomainID lower_dimensional_secondary_subdomain_id);
585
589 void projectPrimaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id,
590 SubdomainID lower_dimensional_secondary_subdomain_id);
591
596 bool processAlignedNodes(const Node & secondary_node,
597 const Node & primary_node,
598 const std::vector<const Elem *> * secondary_node_neighbors,
599 const std::vector<const Elem *> * primary_node_neighbors,
600 const VectorValue<Real> & nodal_normal,
601 const Elem & candidate_element,
602 std::set<const Elem *> & rejected_element_candidates);
603
605 const bool _debug;
606
608 const bool _on_displaced;
609
611 const bool _periodic;
612
614 const bool _distributed;
615
617 Real _newton_tolerance = 1e-12;
618
622 Real _xi_tolerance = 1e-6;
623
627
633
635 const Mortar3DSubpatchPlane _mortar_3d_subpatch_plane;
636
639
642
644 const Mortar3DQuadraturePointMapping _mortar_3d_qp_mapping;
645
647 std::unordered_map<const Elem *, MortarSegmentReferencePoints> _msm_elem_to_reference_points;
648
650 std::unique_ptr<InputParameters> _output_params;
651
655 std::optional<dof_id_type> _msm_node_id_start;
656
659 std::unordered_set<dof_id_type> _projected_secondary_nodes;
660
662 std::unordered_set<dof_id_type> _failed_secondary_node_projections;
663
666};
667
668inline const std::pair<BoundaryID, BoundaryID> &
670{
671 mooseAssert(_primary_secondary_boundary_id_pairs.size() == 1,
672 "We currently only support a single boundary pair per mortar generation object");
673
675}
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 ...
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.
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 > 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...
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