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