https://mooseframework.inl.gov
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"
13 #include "MooseHashing.h"
14 #include "ConsoleStreamInterface.h"
15 #include "MooseError.h"
16 #include "MooseUtils.h"
17 
18 // libMesh includes
19 #include "libmesh/id_types.h"
20 #include "libmesh/equation_systems.h"
21 #include "libmesh/elem.h"
22 #include "libmesh/int_range.h"
23 
24 // C++ includes
25 #include <optional>
26 #include <set>
27 #include <memory>
28 #include <vector>
29 #include <unordered_map>
30 
31 // Forward declarations
32 namespace libMesh
33 {
34 class MeshBase;
35 class System;
36 }
37 class GetPot;
38 
39 // Using statements
43 using libMesh::Elem;
44 using libMesh::MeshBase;
45 using libMesh::Node;
46 using libMesh::Point;
47 using libMesh::Real;
49 
52 
58 {
59 public:
64  const static std::string system_name;
65 
71  MeshBase & mesh_in,
72  const std::pair<BoundaryID, BoundaryID> & boundary_key,
73  const std::pair<SubdomainID, SubdomainID> & subdomain_key,
74  bool on_displaced,
75  bool periodic,
76  const bool debug,
77  const bool correct_edge_dropping,
78  const Real minimum_projection_angle);
79 
86  void buildNodeToElemMaps();
87 
95  void computeNodalGeometry();
96 
110  void projectSecondaryNodes();
111 
126  void projectPrimaryNodes();
127 
144  void buildMortarSegmentMesh();
145 
158 
164  {
175  std::size_t msm_n_elems;
179  };
180 
185  std::vector<MsmSubdomainStats> computeMsmStatistics();
186 
190  void msmStatistics();
191 
195  void clear();
196 
201  void meshChanged() { _msm_node_id_start = std::nullopt; }
202 
206  bool onDisplaced() const { return _on_displaced; }
207 
211  std::vector<Point> getNodalNormals(const Elem & secondary_elem) const;
212 
217  std::array<MooseUtils::SemidynamicVector<Point, 9>, 2>
218  getNodalTangents(const Elem & secondary_elem) const;
219 
224  std::map<unsigned int, unsigned int>
225  getSecondaryIpToLowerElementMap(const Elem & lower_secondary_elem) const;
226 
233  std::map<unsigned int, unsigned int>
234  getPrimaryIpToLowerElementMap(const Elem & primary_elem,
235  const Elem & primary_elem_ip,
236  const Elem & lower_secondary_elem) const;
237 
246  std::vector<Point> getNormals(const Elem & secondary_elem,
247  const std::vector<Point> & xi1_pts) const;
248 
257  std::vector<Point> getNormals(const Elem & secondary_elem,
258  const std::vector<Real> & oned_xi1_pts) const;
259 
267  const Elem * getSecondaryLowerdElemFromSecondaryElem(dof_id_type secondary_elem_id) const;
268 
273  void computeInactiveLMNodes();
274 
280 
285  void computeInactiveLMElems();
286 
290  const std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> &
292  {
294  }
295 
299  const std::pair<BoundaryID, BoundaryID> & primarySecondaryBoundaryIDPair() const;
300 
304  const MeshBase & mortarSegmentMesh() const { return *_mortar_segment_mesh; }
305 
309  const std::unordered_map<const Elem *, MortarSegmentInfo> & mortarSegmentMeshElemToInfo() const
310  {
311  return _msm_elem_to_info;
312  }
313 
314  int dim() const { return _mesh.mesh_dimension(); }
315 
319  const std::unordered_set<const Node *> & getInactiveLMNodes() const
320  {
322  }
323 
327  const std::unordered_set<const Elem *> & getInactiveLMElems() const
328  {
330  }
331 
333 
334  using MortarFilterIter =
335  std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>>::const_iterator;
336 
343  std::vector<MortarFilterIter> secondariesToMortarSegments(const Node & node) const;
344 
349  const std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>> &
351  {
353  }
354 
358  const std::set<SubdomainID> & secondaryIPSubIDs() const { return _secondary_ip_sub_ids; }
359 
363  const std::set<SubdomainID> & primaryIPSubIDs() const { return _primary_ip_sub_ids; }
364 
368  const std::unordered_map<dof_id_type, std::vector<const Elem *>> & nodesToSecondaryElem() const
369  {
371  }
372 
376  void initOutput();
377 
378 private:
382  void outputMortarMesh();
383 
387  std::string mortarInterfaceName() const;
388 
393 
396 
399 
401  std::set<BoundaryID> _secondary_requested_boundary_ids;
402 
404  std::set<BoundaryID> _primary_requested_boundary_ids;
405 
408  std::vector<std::pair<BoundaryID, BoundaryID>> _primary_secondary_boundary_id_pairs;
409 
411  std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_secondary_elem_map;
412  std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_primary_elem_map;
413 
431  std::unordered_map<std::pair<const Node *, const Elem *>, std::pair<Real, const Elem *>>
433 
439  std::map<std::tuple<dof_id_type, const Node *, const Elem *>, std::pair<Real, const Elem *>>
441 
444  std::unique_ptr<MeshBase> _mortar_segment_mesh;
445 
449  std::unordered_map<const Elem *, MortarSegmentInfo> _msm_elem_to_info;
450 
453  std::unordered_map<const Elem *, unsigned int> _lower_elem_to_side_id;
454 
457  std::vector<std::pair<SubdomainID, SubdomainID>> _primary_secondary_subdomain_id_pairs;
458 
461  std::set<SubdomainID> _secondary_boundary_subdomain_ids;
462  std::set<SubdomainID> _primary_boundary_subdomain_ids;
463 
472  std::unordered_map<dof_id_type, std::unordered_set<dof_id_type>> _mortar_interface_coupling;
473 
475  std::unordered_map<const Node *, Point> _secondary_node_to_nodal_normal;
476 
479  std::unordered_map<const Node *, std::array<Point, 2>> _secondary_node_to_hh_nodal_tangents;
480 
482  std::unordered_map<dof_id_type, const Elem *> _secondary_element_to_secondary_lowerd_element;
483 
484  // List of inactive lagrange multiplier nodes (for nodal variables)
485  std::unordered_set<const Node *> _inactive_local_lm_nodes;
486 
488  std::unordered_set<const Elem *> _inactive_local_lm_elems;
489 
493  std::unordered_map<dof_id_type, std::set<Elem *, CompareDofObjectsByID>>
495 
497  std::set<SubdomainID> _secondary_ip_sub_ids;
498 
500  std::set<SubdomainID> _primary_ip_sub_ids;
501 
507  void projectSecondaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id,
508  SubdomainID lower_dimensional_secondary_subdomain_id);
509 
513  void projectPrimaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id,
514  SubdomainID lower_dimensional_secondary_subdomain_id);
515 
519  void
520  householderOrthogolization(const Point & normal, Point & tangent_one, Point & tangent_two) const;
521 
526  bool processAlignedNodes(const Node & secondary_node,
527  const Node & primary_node,
528  const std::vector<const Elem *> * secondary_node_neighbors,
529  const std::vector<const Elem *> * primary_node_neighbors,
530  const VectorValue<Real> & nodal_normal,
531  const Elem & candidate_element,
532  std::set<const Elem *> & rejected_element_candidates);
533 
535  const bool _debug;
536 
538  const bool _on_displaced;
539 
541  const bool _periodic;
542 
544  const bool _distributed;
545 
548 
553 
557 
563 
565  std::unique_ptr<InputParameters> _output_params;
566 
570  std::optional<dof_id_type> _msm_node_id_start;
571 
574  std::unordered_set<dof_id_type> _projected_secondary_nodes;
575 
577  std::unordered_set<dof_id_type> _failed_secondary_node_projections;
578 
581 };
582 
583 inline const std::pair<BoundaryID, BoundaryID> &
585 {
586  mooseAssert(_primary_secondary_boundary_id_pairs.size() == 1,
587  "We currently only support a single boundary pair per mortar generation object");
588 
590 }
std::set< SubdomainID > _primary_boundary_subdomain_ids
const std::pair< BoundaryID, BoundaryID > & primarySecondaryBoundaryIDPair() const
const Elem * getSecondaryLowerdElemFromSecondaryElem(dof_id_type secondary_elem_id) const
Return lower dimensional secondary element given its interior parent.
std::unordered_set< const Elem * > _inactive_local_lm_elems
List of inactive lagrange multiplier nodes (for elemental variables)
std::unordered_map< dof_id_type, std::set< Elem *, CompareDofObjectsByID > >::const_iterator MortarFilterIter
void computeInactiveLMNodes()
Get list of secondary nodes that don&#39;t contribute to interaction with any primary element...
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 clear()
Clears the mortar segment mesh and accompanying data structures.
std::set< SubdomainID > _secondary_boundary_subdomain_ids
The secondary/primary lower-dimensional boundary subdomain ids are the secondary/primary boundary ids...
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...
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 ...
const bool _periodic
Whether this object will be generating a mortar segment mesh for periodic constraints.
void outputMortarMesh()
Write the mortar segment mesh to exodus.
Real _newton_tolerance
Newton solve tolerance for node projections.
TestClass subdomain_id_type
std::unordered_map< const Elem *, MortarSegmentInfo > _msm_elem_to_info
Map between Elems in the mortar segment mesh and their info structs.
const bool _distributed
Whether the mortar segment mesh is distributed.
Base class for MOOSE-based applications.
Definition: MooseApp.h:108
void buildMortarSegmentMesh()
Builds the mortar segment mesh once the secondary and primary node projections have been completed...
const std::set< SubdomainID > & primaryIPSubIDs() const
void msmStatistics()
Prints mortar segment mesh statistics to console (calls computeMsmStatistics internally) ...
const std::unordered_set< const Elem * > & getInactiveLMElems() const
void buildCouplingInformation()
build the _mortar_interface_coupling data
std::vector< Point > getNodalNormals(const Elem &secondary_elem) const
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
static const std::string system_name
The name of the nodal normals system.
void projectSecondaryNodes()
Project secondary nodes (find xi^(2) values) to the closest points on the primary surface...
const std::unordered_map< dof_id_type, std::set< Elem *, CompareDofObjectsByID > > & secondariesToMortarSegments() const
std::unordered_set< dof_id_type > _projected_secondary_nodes
Debugging container for printing information about fraction of successful projections for secondary n...
const std::set< SubdomainID > & secondaryIPSubIDs() const
This class is a container/interface for the objects involved in automatic generation of mortar spaces...
const bool _debug
Whether to print debug output.
Statistics for one primary-secondary subdomain pair.
std::set< SubdomainID > _secondary_ip_sub_ids
All the secondary interior parent subdomain IDs associated with the mortar mesh.
std::optional< dof_id_type > _msm_node_id_start
Cached per-rank starting ID for 3D MSM nodes/elements.
void projectPrimaryNodes()
(Inverse) project primary nodes to the points on the secondary surface where they would have come fro...
int8_t boundary_id_type
AutomaticMortarGeneration(MooseApp &app, MeshBase &mesh_in, const std::pair< BoundaryID, BoundaryID > &boundary_key, const std::pair< SubdomainID, SubdomainID > &subdomain_key, bool on_displaced, bool periodic, const bool debug, const bool correct_edge_dropping, const Real minimum_projection_angle)
Must be constructed with a reference to the Mesh we are generating mortar spaces for.
void meshChanged()
Invalidates the cached MSM node/element ID starting offset so that the next call to buildMortarSegmen...
void buildNodeToElemMaps()
Once the secondary_requested_boundary_ids and primary_requested_boundary_ids containers have been fil...
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.
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)...
boundary_id_type BoundaryID
void projectPrimaryNodesSinglePair(SubdomainID lower_dimensional_primary_subdomain_id, SubdomainID lower_dimensional_secondary_subdomain_id)
Helper function used internally by AutomaticMortarGeneration::project_primary_nodes().
std::unordered_map< dof_id_type, std::vector< const Elem * > > _nodes_to_primary_elem_map
const bool _correct_edge_dropping
Flag to enable regressed treatment of edge dropping where all LM DoFs on edge dropping element are st...
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.
An inteface for the _console for outputting to the Console object.
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::unique_ptr< InputParameters > _output_params
Storage for the input parameters used by the mortar nodal geometry output.
const std::unordered_map< dof_id_type, std::unordered_set< dof_id_type > > & mortarInterfaceCoupling() const
std::set< BoundaryID > _primary_requested_boundary_ids
The boundary ids corresponding to all the primary surfaces.
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...
subdomain_id_type SubdomainID
void computeNodalGeometry()
Computes and stores the nodal normal/tangent vectors in a local data structure instead of using the E...
Real _xi_tolerance
Tolerance for checking projection xi values.
void computeIncorrectEdgeDroppingInactiveLMNodes()
Computes inactive secondary nodes when incorrect edge dropping behavior is enabled (any node touching...
std::unordered_set< dof_id_type > _failed_secondary_node_projections
Secondary nodes that failed to project.
void buildMortarSegmentMesh3d()
Builds the mortar segment mesh once the secondary and primary node projections have been completed...
const std::unordered_map< dof_id_type, std::vector< const Elem * > > & nodesToSecondaryElem() const
bool onDisplaced() const
returns whether this object is on the displaced mesh
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...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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)...
const bool _on_displaced
Whether this object is on the displaced mesh.
std::vector< MsmSubdomainStats > computeMsmStatistics()
Computes mortar segment mesh statistics and returns one entry per subdomain pair. ...
void initOutput()
initialize mortar-mesh based output
const std::unordered_map< const Elem *, MortarSegmentInfo > & mortarSegmentMeshElemToInfo() const
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...
unsigned int mesh_dimension() const
const Real _minimum_projection_angle
Parameter to control which angle (in degrees) is admissible for the creation of mortar segments...
MeshBase & _mesh
Reference to the mesh stored in equation_systems.
const MeshBase & mortarSegmentMesh() const
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...
const std::unordered_set< const Node * > & getInactiveLMNodes() const
std::set< BoundaryID > _secondary_requested_boundary_ids
The boundary ids corresponding to all the secondary surfaces.
std::unordered_map< const Node *, Point > _secondary_node_to_nodal_normal
Container for storing the nodal normal vector associated with each secondary node.
std::unordered_set< const Node * > _inactive_local_lm_nodes
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::set< SubdomainID > _primary_ip_sub_ids
All the primary interior parent subdomain IDs associated with the mortar mesh.
void householderOrthogolization(const Point &normal, Point &tangent_one, Point &tangent_two) const
Householder orthogonalization procedure to obtain proper basis for tangent and binormal vectors...
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.
MooseApp & _app
The Moose app.
std::unique_ptr< MeshBase > _mortar_segment_mesh
1D Mesh of mortar segment elements which gets built by the call to build_mortar_segment_mesh().
uint8_t dof_id_type
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::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 ...
void computeInactiveLMElems()
Get list of secondary elems without any corresponding primary elements.