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 : #include "MortarInterfaceWarehouse.h" 11 : #include "SubProblem.h" 12 : #include "MooseMesh.h" 13 : #include "MooseError.h" 14 : #include "MortarExecutorInterface.h" 15 : #include "AutomaticMortarGeneration.h" 16 : 17 61643 : MortarInterfaceWarehouse::MortarInterfaceWarehouse(const libMesh::ParallelObject & other) 18 61643 : : libMesh::ParallelObject(other), _mortar_initd(false) 19 : { 20 61643 : } 21 : 22 : void 23 1326 : MortarInterfaceWarehouse::createMortarInterface( 24 : const std::pair<BoundaryID, BoundaryID> & boundary_key, 25 : const std::pair<SubdomainID, SubdomainID> & subdomain_key, 26 : SubProblem & subproblem, 27 : bool on_displaced, 28 : bool periodic, 29 : const bool debug, 30 : const bool correct_edge_dropping, 31 : const Real minimum_projection_angle) 32 : { 33 1326 : _mortar_subdomain_coverage.insert(subdomain_key.first); 34 1326 : _mortar_subdomain_coverage.insert(subdomain_key.second); 35 : 36 1326 : _mortar_boundary_coverage.insert(boundary_key.first); 37 1326 : _mortar_boundary_coverage.insert(boundary_key.second); 38 : 39 1326 : MeshBase & mesh = subproblem.mesh().getMesh(); 40 : 41 1326 : auto & periodic_map = on_displaced ? _displaced_periodic_map : _periodic_map; 42 1326 : auto & debug_flag_map = on_displaced ? _displaced_debug_flag_map : _debug_flag_map; 43 1326 : auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces; 44 : 45 : // Periodic flag 46 1326 : auto periodic_map_iterator = periodic_map.find(boundary_key); 47 1326 : if (periodic_map_iterator != periodic_map.end() && periodic_map_iterator->second != periodic) 48 0 : mooseError("We do not currently support enforcing both periodic and non-periodic constraints " 49 : "on the same boundary primary-secondary pair"); 50 : else 51 1326 : periodic_map.insert(periodic_map_iterator, std::make_pair(boundary_key, periodic)); 52 : 53 : // Debug mesh flag displaced 54 1326 : auto debug_flag_map_iterator = debug_flag_map.find(boundary_key); 55 1326 : if (debug_flag_map_iterator != debug_flag_map.end() && debug_flag_map_iterator->second != debug) 56 0 : mooseError( 57 : "We do not currently support generating and not generating debug output " 58 : "on the same boundary primary-secondary surface pair. Please set debug_mesh = true for " 59 : "all constraints sharing the same primary-secondary surface pairs"); 60 : else 61 1326 : debug_flag_map.insert(debug_flag_map_iterator, std::make_pair(boundary_key, debug)); 62 : 63 : // Generate lower-d mesh 64 1326 : if (mortar_interfaces.find(boundary_key) == mortar_interfaces.end()) 65 : { 66 1860 : auto [it, inserted] = mortar_interfaces.emplace( 67 : boundary_key, 68 1860 : std::make_unique<AutomaticMortarGeneration>(subproblem.getMooseApp(), 69 : mesh, 70 : boundary_key, 71 : subdomain_key, 72 : on_displaced, 73 : periodic, 74 : debug, 75 : correct_edge_dropping, 76 : minimum_projection_angle)); 77 930 : if (inserted) 78 930 : it->second->initOutput(); 79 : } 80 : 81 : // See whether to query the mesh 82 1326 : SubdomainID key1 = subdomain_key.first; 83 1326 : SubdomainID key2 = subdomain_key.second; 84 : 85 : // it(1,2) is a a pair consisting of an iterator to the inserted element (or to the element that 86 : // prevented the insertion) and a bool denoting whether the insertion took place. 87 1326 : auto it1 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key1, std::set<SubdomainID>{})); 88 1326 : auto it2 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key2, std::set<SubdomainID>{})); 89 : 90 : // Each entry in this vector will be a pair. The first member of the pair corresponds to 91 : // the lower dimensional subomain ID. The second member of the pair corresponds to the higher 92 : // dimensional subdomain ids of the lower dimeionsal interior parents 93 1326 : std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe; 94 : 95 1326 : if (it1.second) 96 930 : subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second)); 97 1326 : if (it2.second) 98 930 : subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second)); 99 : 100 3186 : for (auto & pr : subdomains_to_probe) 101 : { 102 3720 : for (const Elem * lower_d_elem : as_range(mesh.active_local_subdomain_elements_begin(pr.first), 103 20213 : mesh.active_local_subdomain_elements_end(pr.first))) 104 : { 105 14633 : const Elem * ip = lower_d_elem->interior_parent(); 106 : mooseAssert( 107 : ip, 108 : "Lower dimensional elements should always have an interior parent set when using mortar"); 109 14633 : pr.second->insert(ip->subdomain_id()); 110 1860 : } 111 : 112 : // Make sure that we get this right in parallel 113 1860 : _communicator.set_union(*pr.second); 114 : } 115 1326 : } 116 : 117 : const AutomaticMortarGeneration & 118 165399 : MortarInterfaceWarehouse::getMortarInterface( 119 : const std::pair<BoundaryID, BoundaryID> & boundary_key, 120 : const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/, 121 : bool on_displaced) const 122 : { 123 165399 : auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces; 124 165399 : auto it = mortar_interfaces.find(boundary_key); 125 165399 : if (it == mortar_interfaces.end()) 126 0 : mooseError( 127 : "The requested mortar interface AutomaticMortarGeneration object does not yet exist!"); 128 330798 : return *it->second; 129 : } 130 : 131 : AutomaticMortarGeneration & 132 165399 : MortarInterfaceWarehouse::getMortarInterface( 133 : const std::pair<BoundaryID, BoundaryID> & boundary_key, 134 : const std::pair<SubdomainID, SubdomainID> & subdomain_key, 135 : bool on_displaced) 136 : { 137 : return const_cast<AutomaticMortarGeneration &>( 138 165399 : const_cast<const MortarInterfaceWarehouse *>(this)->getMortarInterface( 139 165399 : boundary_key, subdomain_key, on_displaced)); 140 : } 141 : 142 : void 143 70261 : MortarInterfaceWarehouse::update() 144 : { 145 71176 : for (auto & mortar_pair : _mortar_interfaces) 146 915 : update(*mortar_pair.second); 147 73827 : for (auto & mortar_pair : _displaced_mortar_interfaces) 148 3566 : update(*mortar_pair.second); 149 : 150 70261 : _mortar_initd = true; 151 70261 : } 152 : 153 : void 154 6998 : MortarInterfaceWarehouse::meshChanged() 155 : { 156 7100 : for (auto & mortar_pair : _mortar_interfaces) 157 102 : mortar_pair.second->meshChanged(); 158 7068 : for (auto & mortar_pair : _displaced_mortar_interfaces) 159 70 : mortar_pair.second->meshChanged(); 160 6998 : update(); 161 6998 : } 162 : 163 : void 164 4481 : MortarInterfaceWarehouse::update(AutomaticMortarGeneration & amg) 165 : { 166 : // Clear exiting data 167 4481 : amg.clear(); 168 : 169 : // Construct maps from nodes -> lower dimensional elements on the primary and secondary 170 : // boundaries. 171 4481 : amg.buildNodeToElemMaps(); 172 : 173 : // Compute nodal geometry (normals and tangents). 174 4481 : amg.computeNodalGeometry(); 175 : 176 4481 : const auto dim = amg.dim(); 177 4481 : if (dim == 2) 178 : { 179 : // Project secondary nodes (find xi^(2) values). 180 4263 : amg.projectSecondaryNodes(); 181 : 182 : // Project primary nodes (find xi^(1) values). 183 4263 : amg.projectPrimaryNodes(); 184 : 185 : // Build the mortar segment mesh on the secondary boundary. 186 4263 : amg.buildMortarSegmentMesh(); 187 : } 188 218 : else if (dim == 3) 189 218 : amg.buildMortarSegmentMesh3d(); 190 : else 191 0 : mooseError("Invalid mesh dimension for mortar constraint"); 192 : 193 4481 : amg.computeInactiveLMNodes(); 194 4481 : amg.computeInactiveLMElems(); 195 4481 : } 196 : 197 : const std::set<SubdomainID> & 198 2652 : MortarInterfaceWarehouse::getHigherDimSubdomainIDs(SubdomainID lower_d_subdomain_id) const 199 : { 200 2652 : if (_lower_d_sub_to_higher_d_subs.find(lower_d_subdomain_id) == 201 5304 : _lower_d_sub_to_higher_d_subs.end()) 202 0 : mooseError("The lower dimensional ID ", 203 : lower_d_subdomain_id, 204 : " has not been added to MortarInterfaceWarehouse yet"); 205 2652 : return _lower_d_sub_to_higher_d_subs.at(lower_d_subdomain_id); 206 : } 207 : 208 : void 209 0 : MortarInterfaceWarehouse::notifyWhenMortarSetup(MortarExecutorInterface * const mei_obj) 210 : { 211 0 : _mei_objs.insert(mei_obj); 212 0 : } 213 : 214 : void 215 0 : MortarInterfaceWarehouse::dontNotifyWhenMortarSetup(MortarExecutorInterface * const mei_obj) 216 : { 217 0 : _mei_objs.erase(mei_obj); 218 0 : }