Line data Source code
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 "Mortar3DSubpatchPlane.h" 13 : #include "MooseTypes.h" 14 : #include "MooseHashing.h" 15 : #include "MortarSegmentInfo.h" 16 : 17 : #include "libmesh/parallel_object.h" 18 : 19 : #include <memory> 20 : #include <unordered_map> 21 : #include <set> 22 : #include <string> 23 : 24 : class SubProblem; 25 : class MortarExecutorInterface; 26 : class AutomaticMortarGeneration; 27 : class MooseEnum; 28 : 29 : /** 30 : * Per-mortar-interface configuration. Owns the AutomaticMortarGeneration object together with 31 : * the user-supplied flags that must remain consistent across all constraints sharing a primary- 32 : * secondary surface pair (periodic, debug, minimum projection angle, 3D subpatch plane mode, 33 : * triangulation mode, triangulate-triangles, and 3D quadrature point mapping). 34 : */ 35 : struct MortarInterfaceConfig 36 : { 37 : std::unique_ptr<AutomaticMortarGeneration> amg; 38 : bool periodic; 39 : bool debug; 40 : Real minimum_projection_angle; 41 : Mortar3DSubpatchPlane mortar_3d_subpatch_plane; 42 : MortarSegmentTriangulationMode triangulation; 43 : bool triangulate_triangles; 44 : Mortar3DQuadraturePointMapping mortar_3d_qp_mapping; 45 : }; 46 : 47 : class MortarInterfaceWarehouse : public libMesh::ParallelObject 48 : { 49 : public: 50 : MortarInterfaceWarehouse(const libMesh::ParallelObject & other); 51 : 52 : /** 53 : * Create mortar generation object 54 : * @param boundary_key The primary-secondary boundary pair on which the AMG objects lives 55 : * @param subdomain_key The primary-secondary subdomain pair on which the AMG objects lives 56 : * @param subproblem A reference to the subproblem 57 : * @param on_displaced Whether the AMG object lives on the displaced mesh 58 : * @param periodic Whether the AMG object will be used for enforcing periodic constraints. Note 59 : * that this changes the direction of the projection normals so one AMG object cannot be used to 60 : * enforce both periodic and non-periodic constraints 61 : * @param debug whether to output mortar segment mesh exodus file for debugging purposes 62 : * @param correct_edge_dropping edge dropping treatment selection 63 : * @param minimum_projection_angle minimum projection angle allowed for building mortar segment 64 : * mesh 65 : * @param mortar_3d_subpatch_plane method for constructing 3D mortar subpatch planes 66 : * @param triangulation triangulation strategy used for clipped 3D mortar polygons 67 : * @param triangulate_triangles whether a clipped polygon that is already a triangle should still 68 : * be subdivided 69 : * @param mortar_3d_qp_mapping method for mapping 3D mortar quadrature points to faces 70 : */ 71 : void createMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key, 72 : const std::pair<SubdomainID, SubdomainID> & subdomain_key, 73 : SubProblem & subproblem, 74 : bool on_displaced, 75 : bool periodic, 76 : const bool debug, 77 : const bool correct_edge_dropping, 78 : const Real minimum_projection_angle, 79 : const Mortar3DSubpatchPlane mortar_3d_subpatch_plane, 80 : const MooseEnum & triangulation, 81 : const bool triangulate_triangles, 82 : const Mortar3DQuadraturePointMapping mortar_3d_qp_mapping = 83 : Mortar3DQuadraturePointMapping::NORMAL_PROJECTION); 84 : 85 : /** 86 : * Getter to retrieve the AutomaticMortarGeneration object corresponding to the boundary and 87 : * subdomain keys. If the AutomaticMortarGeneration object does not yet exist, then we error 88 : */ 89 : const AutomaticMortarGeneration & 90 : getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key, 91 : const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/, 92 : bool on_displaced) const; 93 : 94 : /** 95 : * Non-const getter to retrieve the AutomaticMortarGeneration object corresponding to the boundary 96 : * and subdomain keys. If the AutomaticMortarGeneration object does not yet exist, then we error 97 : */ 98 : AutomaticMortarGeneration & 99 : getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key, 100 : const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/, 101 : bool on_displaced); 102 : 103 : /** 104 : * Return the per-interface configuration map (AutomaticMortarGeneration object plus the 105 : * associated user flags) for either the displaced or undisplaced mesh. Iterating callers 106 : * should reach the AMG via the value's \p amg member. 107 : */ 108 : const std::unordered_map<std::pair<BoundaryID, BoundaryID>, MortarInterfaceConfig> & 109 119113 : getMortarInterfaces(bool on_displaced) const 110 : { 111 119113 : if (on_displaced) 112 59530 : return _displaced_mortar_interfaces; 113 : else 114 59583 : return _mortar_interfaces; 115 : } 116 : 117 : /** 118 : * Returns the mortar covered subdomains 119 : */ 120 61011 : const std::set<SubdomainID> & getMortarSubdomainIDs() const { return _mortar_subdomain_coverage; } 121 : 122 : /** 123 : * Returns the mortar covered boundaries 124 : */ 125 : const std::set<BoundaryID> & getMortarBoundaryIDs() const { return _mortar_boundary_coverage; } 126 : 127 : /** 128 : * Builds mortar segment meshes for each mortar interface 129 : */ 130 : void update(); 131 : 132 : /** 133 : * Invalidates cached MSM node/element ID offsets on all mortar interfaces so they are 134 : * recomputed on the next update(). Call when mesh topology changes. 135 : */ 136 : void meshChanged(); 137 : 138 : /** 139 : * Returns whether any of the AutomaticMortarGeneration objects are running on a displaced mesh 140 : */ 141 128004 : bool hasDisplacedObjects() const { return _displaced_mortar_interfaces.size(); } 142 : 143 : /** 144 : * Returns whether we have **any** active AutomaticMortarGeneration objects 145 : */ 146 66972 : bool hasObjects() const { return _mortar_interfaces.size(); } 147 : 148 : /** 149 : * Returns the higher dimensional subdomain ids of the interior parents of the given lower-d 150 : * subdomain id 151 : */ 152 : const std::set<SubdomainID> & getHigherDimSubdomainIDs(SubdomainID lower_d_subdomain_id) const; 153 : 154 : /** 155 : * \em Adds \p mei to the container of objects that will have their \p mortarSetup method called 156 : * as soon as the mortar mesh has been generated for the first time 157 : */ 158 : void notifyWhenMortarSetup(MortarExecutorInterface * mei); 159 : 160 : /** 161 : * \em Removes \p mei from the container of objects that will have their \p mortarSetup method 162 : * called as soon as the mortar mesh has been generated for the first time 163 : */ 164 : void dontNotifyWhenMortarSetup(MortarExecutorInterface * mei); 165 : 166 : /** 167 : * @return whether we have performed an initial mortar mesh construction 168 : */ 169 61159 : bool initialized() const { return _mortar_initd; } 170 : 171 : private: 172 : /** 173 : * Builds mortar segment mesh from specific AutomaticMortarGeneration object 174 : */ 175 : void update(AutomaticMortarGeneration & amg); 176 : 177 : typedef std::pair<BoundaryID, BoundaryID> MortarKey; 178 : 179 : /// Map from primary-secondary (in that order) boundary ID pair to the configuration of the 180 : /// undisplaced mortar interface (AMG object + per-interface flags). 181 : std::unordered_map<MortarKey, MortarInterfaceConfig> _mortar_interfaces; 182 : 183 : /// Map from primary-secondary (in that order) boundary ID pair to the configuration of the 184 : /// displaced mortar interface (AMG object + per-interface flags). 185 : std::unordered_map<MortarKey, MortarInterfaceConfig> _displaced_mortar_interfaces; 186 : 187 : /// A set containing the subdomain ids covered by all the mortar interfaces in this MortarInterfaceWarehouse 188 : /// object 189 : std::set<SubdomainID> _mortar_subdomain_coverage; 190 : 191 : /// A set containing the boundary ids covered by all the mortar interfaces in this MortarInterfaceWarehouse 192 : /// object 193 : std::set<BoundaryID> _mortar_boundary_coverage; 194 : 195 : /// Map from lower dimensional subdomain ids to corresponding higher simensional subdomain ids 196 : /// (e.g. the ids of the interior parents) 197 : std::unordered_map<SubdomainID, std::set<SubdomainID>> _lower_d_sub_to_higher_d_subs; 198 : 199 : /// A container of objects for whom the \p mortarSetup method will be called after the mortar mesh 200 : /// has been setup for the first time 201 : std::set<MortarExecutorInterface *> _mei_objs; 202 : 203 : /// Whether we have performed any mortar mesh construction 204 : bool _mortar_initd; 205 : };