LCOV - code coverage report
Current view: top level - src/constraints - MortarData.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 75 87 86.2 %
Date: 2025-07-17 01:28:37 Functions: 7 9 77.8 %
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 "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 : }

Generated by: LCOV version 1.14