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