LCOV - code coverage report
Current view: top level - src/constraints - NodalConstraint.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 72 94 76.6 %
Date: 2025-07-17 01:28:37 Functions: 4 5 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 "NodalConstraint.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "Assembly.h"
      14             : #include "MooseVariableFE.h"
      15             : #include "SystemBase.h"
      16             : 
      17             : #include "libmesh/sparse_matrix.h"
      18             : 
      19             : InputParameters
      20       42909 : NodalConstraint::validParams()
      21             : {
      22       42909 :   InputParameters params = Constraint::validParams();
      23       42909 :   MooseEnum formulationtype("penalty kinematic", "penalty");
      24       42909 :   params.addParam<MooseEnum>("formulation",
      25             :                              formulationtype,
      26             :                              "Formulation used to calculate constraint - penalty or kinematic.");
      27       42909 :   params.addParam<NonlinearVariableName>("variable_secondary",
      28             :                                          "The name of the variable for the secondary nodes, if it "
      29             :                                          "is different from the primary nodes' variable");
      30       85818 :   return params;
      31       42909 : }
      32             : 
      33          58 : NodalConstraint::NodalConstraint(const InputParameters & parameters)
      34             :   : Constraint(parameters),
      35             :     NeighborCoupleableMooseVariableDependencyIntermediateInterface(this, true, true),
      36             :     NeighborMooseVariableInterface<Real>(
      37             :         this, true, Moose::VarKindType::VAR_SOLVER, Moose::VarFieldType::VAR_FIELD_STANDARD),
      38          58 :     _var(_sys.getFieldVariable<Real>(_tid, parameters.get<NonlinearVariableName>("variable"))),
      39          58 :     _var_secondary(_sys.getFieldVariable<Real>(
      40             :         _tid,
      41         116 :         isParamValid("variable_secondary")
      42          58 :             ? parameters.get<NonlinearVariableName>("variable_secondary")
      43         107 :             : parameters.get<NonlinearVariableName>("variable"))),
      44          58 :     _u_secondary(_var_secondary.dofValuesNeighbor()),
      45         116 :     _u_primary(_var.dofValues())
      46             : {
      47          58 :   addMooseVariableDependency(&_var);
      48          58 :   addMooseVariableDependency(&_var_secondary);
      49             : 
      50          58 :   MooseEnum temp_formulation = getParam<MooseEnum>("formulation");
      51          58 :   if (temp_formulation == "penalty")
      52          58 :     _formulation = Moose::Penalty;
      53           0 :   else if (temp_formulation == "kinematic")
      54           0 :     _formulation = Moose::Kinematic;
      55             :   else
      56           0 :     mooseError("Formulation must be either Penalty or Kinematic");
      57          58 : }
      58             : 
      59             : void
      60         547 : NodalConstraint::computeResidual(NumericVector<Number> & residual)
      61             : {
      62         547 :   if ((_weights.size() == 0) && (_primary_node_vector.size() == 1))
      63          37 :     _weights.push_back(1.0);
      64             : 
      65         547 :   std::vector<dof_id_type> primarydof = _var.dofIndices();
      66         547 :   std::vector<dof_id_type> secondarydof = _var_secondary.dofIndicesNeighbor();
      67             : 
      68         547 :   DenseVector<Number> re(primarydof.size());
      69         547 :   DenseVector<Number> neighbor_re(secondarydof.size());
      70             : 
      71         547 :   re.zero();
      72         547 :   neighbor_re.zero();
      73             : 
      74        2357 :   for (_i = 0; _i < secondarydof.size(); ++_i)
      75             :   {
      76        3620 :     for (_j = 0; _j < primarydof.size(); ++_j)
      77             :     {
      78        1810 :       switch (_formulation)
      79             :       {
      80        1810 :         case Moose::Penalty:
      81        1810 :           re(_j) += computeQpResidual(Moose::Primary) * _var.scalingFactor();
      82        1810 :           neighbor_re(_i) += computeQpResidual(Moose::Secondary) * _var_secondary.scalingFactor();
      83        1810 :           break;
      84           0 :         case Moose::Kinematic:
      85             :           // Transfer the current residual of the secondary node to the primary nodes
      86           0 :           Real res = residual(secondarydof[_i]);
      87           0 :           re(_j) += res * _weights[_j];
      88           0 :           neighbor_re(_i) +=
      89           0 :               -res / _primary_node_vector.size() + computeQpResidual(Moose::Secondary);
      90           0 :           break;
      91             :       }
      92             :     }
      93             :   }
      94             :   // We've already applied scaling
      95         547 :   if (!primarydof.empty())
      96         515 :     addResiduals(_assembly, re, primarydof, /*scaling_factor=*/1);
      97         547 :   if (!secondarydof.empty())
      98         515 :     addResiduals(_assembly, neighbor_re, secondarydof, /*scaling_factor=*/1);
      99         547 : }
     100             : 
     101             : void
     102         108 : NodalConstraint::computeJacobian(SparseMatrix<Number> & jacobian)
     103             : {
     104         108 :   if ((_weights.size() == 0) && (_primary_node_vector.size() == 1))
     105           0 :     _weights.push_back(1.0);
     106             : 
     107             :   // Calculate the dense-block Jacobian entries
     108         108 :   std::vector<dof_id_type> secondarydof = _var_secondary.dofIndicesNeighbor();
     109         108 :   std::vector<dof_id_type> primarydof = _var.dofIndices();
     110             : 
     111         108 :   DenseMatrix<Number> Kee(primarydof.size(), primarydof.size());
     112         108 :   DenseMatrix<Number> Ken(primarydof.size(), secondarydof.size());
     113         108 :   DenseMatrix<Number> Kne(secondarydof.size(), primarydof.size());
     114             : 
     115         108 :   Kee.zero();
     116         108 :   Ken.zero();
     117         108 :   Kne.zero();
     118             : 
     119         586 :   for (_i = 0; _i < secondarydof.size(); ++_i)
     120             :   {
     121         956 :     for (_j = 0; _j < primarydof.size(); ++_j)
     122             :     {
     123         478 :       switch (_formulation)
     124             :       {
     125         478 :         case Moose::Penalty:
     126         478 :           Kee(_j, _j) += computeQpJacobian(Moose::PrimaryPrimary);
     127         478 :           Ken(_j, _i) += computeQpJacobian(Moose::PrimarySecondary);
     128         478 :           Kne(_i, _j) += computeQpJacobian(Moose::SecondaryPrimary);
     129         478 :           break;
     130           0 :         case Moose::Kinematic:
     131           0 :           Kee(_j, _j) = 0.;
     132           0 :           Ken(_j, _i) += jacobian(secondarydof[_i], primarydof[_j]) * _weights[_j];
     133           0 :           Kne(_i, _j) += -jacobian(secondarydof[_i], primarydof[_j]) / primarydof.size() +
     134           0 :                          computeQpJacobian(Moose::SecondaryPrimary);
     135           0 :           break;
     136             :       }
     137             :     }
     138             :   }
     139         108 :   addJacobian(_assembly, Kee, primarydof, primarydof, _var.scalingFactor());
     140         108 :   addJacobian(_assembly, Ken, primarydof, secondarydof, _var.scalingFactor());
     141         108 :   addJacobian(_assembly, Kne, secondarydof, primarydof, _var_secondary.scalingFactor());
     142             : 
     143             :   // Calculate and cache the diagonal secondary-secondary entries
     144         586 :   for (_i = 0; _i < secondarydof.size(); ++_i)
     145             :   {
     146         478 :     Number value = 0.0;
     147         478 :     switch (_formulation)
     148             :     {
     149         478 :       case Moose::Penalty:
     150         478 :         value = computeQpJacobian(Moose::SecondarySecondary);
     151         478 :         break;
     152           0 :       case Moose::Kinematic:
     153           0 :         value = -jacobian(secondarydof[_i], secondarydof[_i]) / primarydof.size() +
     154           0 :                 computeQpJacobian(Moose::SecondarySecondary);
     155           0 :         break;
     156             :     }
     157         478 :     addJacobianElement(
     158         478 :         _assembly, value, secondarydof[_i], secondarydof[_i], _var_secondary.scalingFactor());
     159             :   }
     160         108 : }
     161             : 
     162             : void
     163           0 : NodalConstraint::updateConnectivity()
     164             : {
     165           0 : }

Generated by: LCOV version 1.14