LCOV - code coverage report
Current view: top level - src/constraints - EqualValueEmbeddedConstraint.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 113 143 79.0 %
Date: 2026-05-29 20:35:17 Functions: 16 18 88.9 %
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             : // MOOSE includes
      11             : #include "EigenADReal.h"
      12             : #include "EqualValueEmbeddedConstraint.h"
      13             : #include "FEProblem.h"
      14             : #include "DisplacedProblem.h"
      15             : #include "AuxiliarySystem.h"
      16             : #include "SystemBase.h"
      17             : #include "Assembly.h"
      18             : #include "MooseMesh.h"
      19             : #include "AddVariableAction.h"
      20             : 
      21             : #include "libmesh/sparse_matrix.h"
      22             : 
      23             : registerMooseObject("MooseApp", EqualValueEmbeddedConstraint);
      24             : registerMooseObject("MooseApp", ADEqualValueEmbeddedConstraint);
      25             : 
      26             : template <bool is_ad>
      27             : InputParameters
      28        9582 : EqualValueEmbeddedConstraintTempl<is_ad>::validParams()
      29             : {
      30        9582 :   MooseEnum orders(AddVariableAction::getNonlinearVariableOrders());
      31        9582 :   InputParameters params = GenericNodeElemConstraint<is_ad>::validParams();
      32       19164 :   params.addClassDescription("This is a constraint enforcing overlapping portions of two blocks to "
      33             :                              "have the same variable value");
      34       19164 :   params.set<bool>("use_displaced_mesh") = false;
      35       19164 :   MooseEnum formulation(getFormulationOptions(), "kinematic");
      36       38328 :   params.addParam<MooseEnum>(
      37             :       "formulation", formulation, "Formulation used to enforce the constraint");
      38       28746 :   params.addRequiredParam<Real>(
      39             :       "penalty",
      40             :       "Penalty parameter used in constraint enforcement for kinematic and penalty formulations.");
      41             : 
      42       19164 :   return params;
      43        9582 : }
      44             : 
      45             : template <bool is_ad>
      46         203 : EqualValueEmbeddedConstraintTempl<is_ad>::EqualValueEmbeddedConstraintTempl(
      47             :     const InputParameters & parameters)
      48             :   : GenericNodeElemConstraint<is_ad>(parameters),
      49         203 :     _displaced_problem(parameters.get<FEProblemBase *>("_fe_problem_base")->getDisplacedProblem()),
      50         203 :     _fe_problem(*parameters.get<FEProblem *>("_fe_problem")),
      51         406 :     _formulation(this->template getParam<MooseEnum>("formulation").template getEnum<Formulation>()),
      52         406 :     _penalty(this->template getParam<Real>("penalty")),
      53         406 :     _residual_copy(_sys.residualGhosted())
      54             : {
      55         203 :   _overwrite_secondary_residual = false;
      56         203 :   prepareSecondaryToPrimaryMap();
      57             :   if constexpr (is_ad)
      58             :   {
      59          83 :     if (_formulation == Formulation::KINEMATIC)
      60           6 :       this->paramError("formulation", "AD constraints cannot be used with KINEMATIC formulation.");
      61             :   }
      62         200 : }
      63             : 
      64             : template <bool is_ad>
      65             : void
      66         203 : EqualValueEmbeddedConstraintTempl<is_ad>::prepareSecondaryToPrimaryMap()
      67             : {
      68             :   // get mesh pointLocator
      69         203 :   std::unique_ptr<libMesh::PointLocatorBase> pointLocator = _mesh.getPointLocator();
      70         203 :   pointLocator->enable_out_of_mesh_mode();
      71         406 :   const std::set<subdomain_id_type> allowed_subdomains{_primary};
      72             : 
      73             :   // secondary id and primary id
      74             :   dof_id_type sid, mid;
      75             : 
      76             :   // prepare _secondary_to_primary_map
      77         203 :   std::set<dof_id_type> unique_secondary_node_ids;
      78         203 :   const MeshBase & meshhelper = _mesh.getMesh();
      79       10129 :   for (const auto & elem : as_range(meshhelper.active_subdomain_elements_begin(_secondary),
      80         203 :                                     meshhelper.active_subdomain_elements_end(_secondary)))
      81             :   {
      82       55629 :     for (auto & sn : elem->node_ref_range())
      83             :     {
      84       45906 :       sid = sn.id();
      85       45906 :       if (_secondary_to_primary_map.find(sid) == _secondary_to_primary_map.end())
      86             :       {
      87             :         // primary element
      88       31176 :         const Elem * me = pointLocator->operator()(sn, &allowed_subdomains);
      89       31176 :         if (me != NULL)
      90             :         {
      91        7130 :           mid = me->id();
      92        7130 :           _secondary_to_primary_map.insert(std::pair<dof_id_type, dof_id_type>(sid, mid));
      93        7130 :           _subproblem.addGhostedElem(mid);
      94             :         }
      95             :       }
      96             :     }
      97             :   }
      98         203 : }
      99             : 
     100             : template <bool is_ad>
     101             : bool
     102       43736 : EqualValueEmbeddedConstraintTempl<is_ad>::shouldApply()
     103             : {
     104             :   // primary element
     105       43736 :   auto it = _secondary_to_primary_map.find(_current_node->id());
     106             : 
     107       43736 :   if (it != _secondary_to_primary_map.end())
     108             :   {
     109       19880 :     const Elem * primary_elem = _mesh.elemPtr(it->second);
     110       39760 :     std::vector<Point> points = {*_current_node};
     111             : 
     112             :     // reinit variables on the primary element at the secondary point
     113       19880 :     _fe_problem.setNeighborSubdomainID(primary_elem, 0);
     114       19880 :     _fe_problem.reinitNeighborPhys(primary_elem, points, 0);
     115             : 
     116       19880 :     reinitConstraint();
     117             : 
     118       19880 :     return true;
     119       19880 :   }
     120       23856 :   return false;
     121             : }
     122             : 
     123             : template <bool is_ad>
     124             : void
     125       19880 : EqualValueEmbeddedConstraintTempl<is_ad>::reinitConstraint()
     126             : {
     127       19880 :   const Node * node = _current_node;
     128       19880 :   unsigned int sys_num = _sys.number();
     129       19880 :   dof_id_type dof_number = node->dof_number(sys_num, _var.number(), 0);
     130             : 
     131       19880 :   switch (_formulation)
     132             :   {
     133        5320 :     case Formulation::KINEMATIC:
     134        5320 :       _constraint_residual = -_residual_copy(dof_number);
     135        5320 :       break;
     136             : 
     137       14560 :     case Formulation::PENALTY:
     138       14560 :       _constraint_residual = _penalty * (_u_secondary[0] - _u_primary[0]);
     139       14560 :       break;
     140             : 
     141           0 :     default:
     142           0 :       mooseError("Invalid formulation");
     143             :       break;
     144             :   }
     145       19880 : }
     146             : 
     147             : template <bool is_ad>
     148             : Real
     149        4970 : EqualValueEmbeddedConstraintTempl<is_ad>::computeQpSecondaryValue()
     150             : {
     151        4970 :   return MetaPhysicL::raw_value(_u_secondary[_qp]);
     152             : }
     153             : 
     154             : template <bool is_ad>
     155             : GenericReal<is_ad>
     156       85680 : EqualValueEmbeddedConstraintTempl<is_ad>::computeQpResidual(Moose::ConstraintType type)
     157             : {
     158       85680 :   GenericReal<is_ad> resid = _constraint_residual;
     159             : 
     160       85680 :   switch (type)
     161             :   {
     162       12040 :     case Moose::Secondary:
     163             :     {
     164       12040 :       if (_formulation == Formulation::KINEMATIC)
     165             :       {
     166        2660 :         GenericReal<is_ad> pen_force = _penalty * (_u_secondary[_qp] - _u_primary[_qp]);
     167        2660 :         resid += pen_force;
     168           0 :       }
     169       12040 :       return _test_secondary[_i][_qp] * resid;
     170             :     }
     171             : 
     172       73640 :     case Moose::Primary:
     173       73640 :       return _test_primary[_i][_qp] * -resid;
     174             :   }
     175             : 
     176           0 :   return 0.0;
     177       42420 : }
     178             : 
     179             : template <bool is_ad>
     180             : Real
     181      402150 : EqualValueEmbeddedConstraintTempl<is_ad>::computeQpJacobian(Moose::ConstraintJacobianType type)
     182             : {
     183             :   mooseAssert(!is_ad,
     184             :               "In ADEqualValueEmbeddedConstraint, computeQpJacobian should not be called. "
     185             :               "Check computeJacobian implementation.");
     186             : 
     187      402150 :   unsigned int sys_num = _sys.number();
     188      402150 :   const Real penalty = MetaPhysicL::raw_value(_penalty);
     189             :   Real curr_jac, secondary_jac;
     190             : 
     191      402150 :   switch (type)
     192             :   {
     193       30870 :     case Moose::SecondarySecondary:
     194       30870 :       switch (_formulation)
     195             :       {
     196       14490 :         case Formulation::KINEMATIC:
     197       14490 :           curr_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
     198       14490 :                                   _connected_dof_indices[_j]);
     199       14490 :           return -curr_jac + _phi_secondary[_j][_qp] * penalty * _test_secondary[_i][_qp];
     200       16380 :         case Formulation::PENALTY:
     201       16380 :           return _phi_secondary[_j][_qp] * penalty * _test_secondary[_i][_qp];
     202           0 :         default:
     203           0 :           mooseError("Invalid formulation");
     204             :       }
     205             : 
     206       18760 :     case Moose::SecondaryPrimary:
     207       18760 :       switch (_formulation)
     208             :       {
     209        8960 :         case Formulation::KINEMATIC:
     210        8960 :           return -_phi_primary[_j][_qp] * penalty * _test_secondary[_i][_qp];
     211        9800 :         case Formulation::PENALTY:
     212        9800 :           return -_phi_primary[_j][_qp] * penalty * _test_secondary[_i][_qp];
     213           0 :         default:
     214           0 :           mooseError("Invalid formulation");
     215             :       }
     216             : 
     217      219240 :     case Moose::PrimarySecondary:
     218      219240 :       switch (_formulation)
     219             :       {
     220      105840 :         case Formulation::KINEMATIC:
     221      105840 :           secondary_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
     222      105840 :                                        _connected_dof_indices[_j]);
     223      105840 :           return secondary_jac * _test_primary[_i][_qp];
     224      113400 :         case Formulation::PENALTY:
     225      113400 :           return -_phi_secondary[_j][_qp] * penalty * _test_primary[_i][_qp];
     226           0 :         default:
     227           0 :           mooseError("Invalid formulation");
     228             :       }
     229             : 
     230      133280 :     case Moose::PrimaryPrimary:
     231      133280 :       switch (_formulation)
     232             :       {
     233       64960 :         case Formulation::KINEMATIC:
     234       64960 :           return 0.0;
     235       68320 :         case Formulation::PENALTY:
     236       68320 :           return _test_primary[_i][_qp] * penalty * _phi_primary[_j][_qp];
     237           0 :         default:
     238           0 :           mooseError("Invalid formulation");
     239             :       }
     240             : 
     241           0 :     default:
     242           0 :       mooseError("Unsupported type");
     243             :       break;
     244             :   }
     245             :   return 0.0;
     246             : }
     247             : 
     248             : template <bool is_ad>
     249             : Real
     250        5600 : EqualValueEmbeddedConstraintTempl<is_ad>::computeQpOffDiagJacobian(
     251             :     Moose::ConstraintJacobianType type, unsigned int /*jvar*/)
     252             : {
     253             :   mooseAssert(!is_ad,
     254             :               "In ADEqualValueEmbeddedConstraint, computeQpOffDiagJacobian should not be called. "
     255             :               "Check computeJacobian implementation.");
     256             : 
     257             :   Real curr_jac, secondary_jac;
     258        5600 :   unsigned int sys_num = _sys.number();
     259             : 
     260        5600 :   switch (type)
     261             :   {
     262           0 :     case Moose::SecondarySecondary:
     263           0 :       curr_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
     264           0 :                               _connected_dof_indices[_j]);
     265           0 :       return -curr_jac;
     266             : 
     267        1120 :     case Moose::SecondaryPrimary:
     268        1120 :       return 0.0;
     269             : 
     270           0 :     case Moose::PrimarySecondary:
     271           0 :       switch (_formulation)
     272             :       {
     273           0 :         case Formulation::KINEMATIC:
     274           0 :           secondary_jac = (*_jacobian)(_current_node->dof_number(sys_num, _var.number(), 0),
     275           0 :                                        _connected_dof_indices[_j]);
     276           0 :           return secondary_jac * _test_primary[_i][_qp];
     277           0 :         case Formulation::PENALTY:
     278           0 :           return 0.0;
     279           0 :         default:
     280           0 :           mooseError("Invalid formulation");
     281             :       }
     282             : 
     283        4480 :     case Moose::PrimaryPrimary:
     284        4480 :       return 0.0;
     285             : 
     286           0 :     default:
     287           0 :       mooseError("Unsupported type");
     288             :       break;
     289             :   }
     290             : 
     291             :   return 0.0;
     292             : }
     293             : 
     294             : template class EqualValueEmbeddedConstraintTempl<false>;
     295             : template class EqualValueEmbeddedConstraintTempl<true>;

Generated by: LCOV version 1.14