LCOV - code coverage report
Current view: top level - src/constraints - MortarData.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 75 87 86.2 %
Date: 2025-09-03 20:01:23 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       63223 : MortarData::MortarData(const libMesh::ParallelObject & other)
      17       63223 :   : libMesh::ParallelObject(other), _mortar_initd(false)
      18             : {
      19       63223 : }
      20             : 
      21             : void
      22        1448 : 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        1448 :   _mortar_subdomain_coverage.insert(subdomain_key.first);
      32        1448 :   _mortar_subdomain_coverage.insert(subdomain_key.second);
      33             : 
      34        1448 :   _mortar_boundary_coverage.insert(boundary_key.first);
      35        1448 :   _mortar_boundary_coverage.insert(boundary_key.second);
      36             : 
      37        1448 :   MeshBase & mesh = subproblem.mesh().getMesh();
      38             : 
      39        1448 :   auto & periodic_map = on_displaced ? _displaced_periodic_map : _periodic_map;
      40        1448 :   auto & debug_flag_map = on_displaced ? _displaced_debug_flag_map : _debug_flag_map;
      41        1448 :   auto & mortar_interfaces = on_displaced ? _displaced_mortar_interfaces : _mortar_interfaces;
      42             : 
      43             :   // Periodic flag
      44        1448 :   auto periodic_map_iterator = periodic_map.find(boundary_key);
      45        1448 :   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        1448 :     periodic_map.insert(periodic_map_iterator, std::make_pair(boundary_key, periodic));
      50             : 
      51             :   // Debug mesh flag displaced
      52        1448 :   auto debug_flag_map_iterator = debug_flag_map.find(boundary_key);
      53        1448 :   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        1448 :     debug_flag_map.insert(debug_flag_map_iterator, std::make_pair(boundary_key, debug));
      60             : 
      61             :   // Generate lower-d mesh
      62        1448 :   if (mortar_interfaces.find(boundary_key) == mortar_interfaces.end())
      63             :   {
      64        1024 :     auto [it, inserted] =
      65        1024 :         mortar_interfaces.emplace(boundary_key,
      66        2048 :                                   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        1024 :     if (inserted)
      76        1024 :       it->second.initOutput();
      77             :   }
      78             : 
      79             :   // See whether to query the mesh
      80        1448 :   SubdomainID key1 = subdomain_key.first;
      81        1448 :   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        1448 :   auto it1 = _lower_d_sub_to_higher_d_subs.insert(std::make_pair(key1, std::set<SubdomainID>{}));
      86        1448 :   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        1448 :   std::vector<std::pair<SubdomainID, std::set<SubdomainID> *>> subdomains_to_probe;
      92             : 
      93        1448 :   if (it1.second)
      94        1024 :     subdomains_to_probe.push_back(std::make_pair(key1, &it1.first->second));
      95        1448 :   if (it2.second)
      96        1024 :     subdomains_to_probe.push_back(std::make_pair(key2, &it2.first->second));
      97             : 
      98        3496 :   for (auto & pr : subdomains_to_probe)
      99             :   {
     100        4096 :     for (const Elem * lower_d_elem : as_range(mesh.active_local_subdomain_elements_begin(pr.first),
     101       23573 :                                               mesh.active_local_subdomain_elements_end(pr.first)))
     102             :     {
     103       17429 :       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       17429 :       pr.second->insert(ip->subdomain_id());
     108        2048 :     }
     109             : 
     110             :     // Make sure that we get this right in parallel
     111        2048 :     _communicator.set_union(*pr.second);
     112             :   }
     113        1448 : }
     114             : 
     115             : const AutomaticMortarGeneration &
     116      258234 : MortarData::getMortarInterface(const std::pair<BoundaryID, BoundaryID> & boundary_key,
     117             :                                const std::pair<SubdomainID, SubdomainID> & /*subdomain_key*/,
     118             :                                bool on_displaced) const
     119             : {
     120      258234 :   if (on_displaced)
     121             :   {
     122        4160 :     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        4160 :     return _displaced_mortar_interfaces.at(boundary_key);
     127             :   }
     128             :   else
     129             :   {
     130      254074 :     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      254074 :     return _mortar_interfaces.at(boundary_key);
     135             :   }
     136             : }
     137             : 
     138             : AutomaticMortarGeneration &
     139      258234 : 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      258234 :       const_cast<const MortarData *>(this)->getMortarInterface(
     145      258234 :           boundary_key, subdomain_key, on_displaced));
     146             : }
     147             : 
     148             : void
     149       72659 : MortarData::update()
     150             : {
     151       73671 :   for (auto & mortar_pair : _mortar_interfaces)
     152        1012 :     update(mortar_pair.second);
     153       76584 :   for (auto & mortar_pair : _displaced_mortar_interfaces)
     154        3925 :     update(mortar_pair.second);
     155             : 
     156       72659 :   _mortar_initd = true;
     157       72659 : }
     158             : 
     159             : void
     160        4937 : MortarData::update(AutomaticMortarGeneration & amg)
     161             : {
     162             :   // Clear exiting data
     163        4937 :   amg.clear();
     164             : 
     165             :   // Construct maps from nodes -> lower dimensional elements on the primary and secondary
     166             :   // boundaries.
     167        4937 :   amg.buildNodeToElemMaps();
     168             : 
     169             :   // Compute nodal geometry (normals and tangents).
     170        4937 :   amg.computeNodalGeometry();
     171             : 
     172        4937 :   const auto dim = amg.dim();
     173        4937 :   if (dim == 2)
     174             :   {
     175             :     // Project secondary nodes (find xi^(2) values).
     176        4719 :     amg.projectSecondaryNodes();
     177             : 
     178             :     // Project primary nodes (find xi^(1) values).
     179        4719 :     amg.projectPrimaryNodes();
     180             : 
     181             :     // Build the mortar segment mesh on the secondary boundary.
     182        4719 :     amg.buildMortarSegmentMesh();
     183             :   }
     184         218 :   else if (dim == 3)
     185         218 :     amg.buildMortarSegmentMesh3d();
     186             :   else
     187           0 :     mooseError("Invalid mesh dimension for mortar constraint");
     188             : 
     189        4937 :   amg.computeInactiveLMNodes();
     190        4937 :   amg.computeInactiveLMElems();
     191        4937 : }
     192             : 
     193             : const std::set<SubdomainID> &
     194        2896 : MortarData::getHigherDimSubdomainIDs(SubdomainID lower_d_subdomain_id) const
     195             : {
     196        2896 :   if (_lower_d_sub_to_higher_d_subs.find(lower_d_subdomain_id) ==
     197        5792 :       _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        2896 :   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