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 64599 : MortarInterfaceWarehouse::MortarInterfaceWarehouse(const libMesh::ParallelObject & other) 18 64599 : : libMesh::ParallelObject(other), _mortar_initd(false) 19 : { 20 64599 : } 21 : 22 : void 23 1448 : 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 1448 : _mortar_subdomain_coverage.insert(subdomain_key.first); 34 1448 : _mortar_subdomain_coverage.insert(subdomain_key.second); 35 : 36 1448 : _mortar_boundary_coverage.insert(boundary_key.first); 37 1448 : _mortar_boundary_coverage.insert(boundary_key.second); 38 : 39 1448 : MeshBase & mesh = subproblem.mesh().getMesh(); 40 : 41 1448 : auto & periodic_map = on_displaced ? _displaced_periodic_map : _periodic_map; 42 1448 : auto & debug_flag_map = on_displaced ? _displaced_debug_flag_map : _debug_flag_map; 43 1448 : auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces; 44 : 45 : // Periodic flag 46 1448 : auto periodic_map_iterator = periodic_map.find(boundary_key); 47 1448 : 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 1448 : periodic_map.insert(periodic_map_iterator, std::make_pair(boundary_key, periodic)); 52 : 53 : // Debug mesh flag displaced 54 1448 : auto debug_flag_map_iterator = debug_flag_map.find(boundary_key); 55 1448 : 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 1448 : debug_flag_map.insert(debug_flag_map_iterator, std::make_pair(boundary_key, debug)); 62 : 63 : // Generate lower-d mesh 64 1448 : if (mortar_interfaces.find(boundary_key) == mortar_interfaces.end()) 65 : { 66 2048 : auto [it, inserted] = mortar_interfaces.emplace( 67 : boundary_key, 68 2048 : 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 1024 : if (inserted) 78 1024 : it->second->initOutput(); 79 : } 80 : 81 : // See whether to query the mesh 82 1448 : SubdomainID key1 = subdomain_key.first; 83 1448 : 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 1448 : auto it1 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key1, std::set<SubdomainID>{})); 88 1448 : 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 1448 : std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe; 94 : 95 1448 : if (it1.second) 96 1024 : subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second)); 97 1448 : if (it2.second) 98 1024 : subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second)); 99 : 100 3496 : for (auto & pr : subdomains_to_probe) 101 : { 102 4096 : for (const Elem * lower_d_elem : as_range(mesh.active_local_subdomain_elements_begin(pr.first), 103 23573 : mesh.active_local_subdomain_elements_end(pr.first))) 104 : { 105 17429 : 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 17429 : pr.second->insert(ip->subdomain_id()); 110 2048 : } 111 : 112 : // Make sure that we get this right in parallel 113 2048 : _communicator.set_union(*pr.second); 114 : } 115 1448 : } 116 : 117 : const AutomaticMortarGeneration & 118 258234 : 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 258234 : auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces; 124 258234 : auto it = mortar_interfaces.find(boundary_key); 125 258234 : if (it == mortar_interfaces.end()) 126 0 : mooseError( 127 : "The requested mortar interface AutomaticMortarGeneration object does not yet exist!"); 128 516468 : return *it->second; 129 : } 130 : 131 : AutomaticMortarGeneration & 132 258234 : 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 258234 : const_cast<const MortarInterfaceWarehouse *>(this)->getMortarInterface( 139 258234 : boundary_key, subdomain_key, on_displaced)); 140 : } 141 : 142 : void 143 73886 : MortarInterfaceWarehouse::update() 144 : { 145 74898 : for (auto & mortar_pair : _mortar_interfaces) 146 1012 : update(*mortar_pair.second); 147 77811 : for (auto & mortar_pair : _displaced_mortar_interfaces) 148 3925 : update(*mortar_pair.second); 149 : 150 73886 : _mortar_initd = true; 151 73886 : } 152 : 153 : void 154 4937 : MortarInterfaceWarehouse::update(AutomaticMortarGeneration & amg) 155 : { 156 : // Clear exiting data 157 4937 : amg.clear(); 158 : 159 : // Construct maps from nodes -> lower dimensional elements on the primary and secondary 160 : // boundaries. 161 4937 : amg.buildNodeToElemMaps(); 162 : 163 : // Compute nodal geometry (normals and tangents). 164 4937 : amg.computeNodalGeometry(); 165 : 166 4937 : const auto dim = amg.dim(); 167 4937 : if (dim == 2) 168 : { 169 : // Project secondary nodes (find xi^(2) values). 170 4719 : amg.projectSecondaryNodes(); 171 : 172 : // Project primary nodes (find xi^(1) values). 173 4719 : amg.projectPrimaryNodes(); 174 : 175 : // Build the mortar segment mesh on the secondary boundary. 176 4719 : amg.buildMortarSegmentMesh(); 177 : } 178 218 : else if (dim == 3) 179 218 : amg.buildMortarSegmentMesh3d(); 180 : else 181 0 : mooseError("Invalid mesh dimension for mortar constraint"); 182 : 183 4937 : amg.computeInactiveLMNodes(); 184 4937 : amg.computeInactiveLMElems(); 185 4937 : } 186 : 187 : const std::set<SubdomainID> & 188 2896 : MortarInterfaceWarehouse::getHigherDimSubdomainIDs(SubdomainID lower_d_subdomain_id) const 189 : { 190 2896 : if (_lower_d_sub_to_higher_d_subs.find(lower_d_subdomain_id) == 191 5792 : _lower_d_sub_to_higher_d_subs.end()) 192 0 : mooseError("The lower dimensional ID ", 193 : lower_d_subdomain_id, 194 : " has not been added to MortarInterfaceWarehouse yet"); 195 2896 : return _lower_d_sub_to_higher_d_subs.at(lower_d_subdomain_id); 196 : } 197 : 198 : void 199 0 : MortarInterfaceWarehouse::notifyWhenMortarSetup(MortarExecutorInterface * const mei_obj) 200 : { 201 0 : _mei_objs.insert(mei_obj); 202 0 : } 203 : 204 : void 205 0 : MortarInterfaceWarehouse::dontNotifyWhenMortarSetup(MortarExecutorInterface * const mei_obj) 206 : { 207 0 : _mei_objs.erase(mei_obj); 208 0 : }