LCOV - code coverage report
Current view: top level - src/constraints - MortarInterfaceWarehouse.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 80 91 87.9 %
Date: 2026-05-29 20:35:17 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14