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 42921 : NodalConstraint::validParams()
21 : {
22 42921 : InputParameters params = Constraint::validParams();
23 42921 : MooseEnum formulationtype("penalty kinematic", "penalty");
24 42921 : params.addParam<MooseEnum>("formulation",
25 : formulationtype,
26 : "Formulation used to calculate constraint - penalty or kinematic.");
27 42921 : 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 85842 : return params;
31 42921 : }
32 :
33 64 : 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 64 : _var(_sys.getFieldVariable<Real>(_tid, parameters.get<NonlinearVariableName>("variable"))),
39 64 : _var_secondary(_sys.getFieldVariable<Real>(
40 : _tid,
41 128 : isParamValid("variable_secondary")
42 64 : ? parameters.get<NonlinearVariableName>("variable_secondary")
43 118 : : parameters.get<NonlinearVariableName>("variable"))),
44 64 : _u_secondary(_var_secondary.dofValuesNeighbor()),
45 128 : _u_primary(_var.dofValues())
46 : {
47 64 : addMooseVariableDependency(&_var);
48 64 : addMooseVariableDependency(&_var_secondary);
49 :
50 64 : MooseEnum temp_formulation = getParam<MooseEnum>("formulation");
51 64 : if (temp_formulation == "penalty")
52 64 : _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 64 : }
58 :
59 : void
60 602 : NodalConstraint::computeResidual(NumericVector<Number> & residual)
61 : {
62 602 : if ((_weights.size() == 0) && (_primary_node_vector.size() == 1))
63 41 : _weights.push_back(1.0);
64 :
65 602 : std::vector<dof_id_type> primarydof = _var.dofIndices();
66 602 : std::vector<dof_id_type> secondarydof = _var_secondary.dofIndicesNeighbor();
67 :
68 602 : DenseVector<Number> re(primarydof.size());
69 602 : DenseVector<Number> neighbor_re(secondarydof.size());
70 :
71 602 : re.zero();
72 602 : neighbor_re.zero();
73 :
74 2648 : for (_i = 0; _i < secondarydof.size(); ++_i)
75 : {
76 4092 : for (_j = 0; _j < primarydof.size(); ++_j)
77 : {
78 2046 : switch (_formulation)
79 : {
80 2046 : case Moose::Penalty:
81 2046 : re(_j) += computeQpResidual(Moose::Primary) * _var.scalingFactor();
82 2046 : neighbor_re(_i) += computeQpResidual(Moose::Secondary) * _var_secondary.scalingFactor();
83 2046 : 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 602 : if (!primarydof.empty())
96 566 : addResiduals(_assembly, re, primarydof, /*scaling_factor=*/1);
97 602 : if (!secondarydof.empty())
98 566 : addResiduals(_assembly, neighbor_re, secondarydof, /*scaling_factor=*/1);
99 602 : }
100 :
101 : void
102 121 : NodalConstraint::computeJacobian(SparseMatrix<Number> & jacobian)
103 : {
104 121 : 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 121 : std::vector<dof_id_type> secondarydof = _var_secondary.dofIndicesNeighbor();
109 121 : std::vector<dof_id_type> primarydof = _var.dofIndices();
110 :
111 121 : DenseMatrix<Number> Kee(primarydof.size(), primarydof.size());
112 121 : DenseMatrix<Number> Ken(primarydof.size(), secondarydof.size());
113 121 : DenseMatrix<Number> Kne(secondarydof.size(), primarydof.size());
114 :
115 121 : Kee.zero();
116 121 : Ken.zero();
117 121 : Kne.zero();
118 :
119 676 : for (_i = 0; _i < secondarydof.size(); ++_i)
120 : {
121 1110 : for (_j = 0; _j < primarydof.size(); ++_j)
122 : {
123 555 : switch (_formulation)
124 : {
125 555 : case Moose::Penalty:
126 555 : Kee(_j, _j) += computeQpJacobian(Moose::PrimaryPrimary);
127 555 : Ken(_j, _i) += computeQpJacobian(Moose::PrimarySecondary);
128 555 : Kne(_i, _j) += computeQpJacobian(Moose::SecondaryPrimary);
129 555 : 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 121 : addJacobian(_assembly, Kee, primarydof, primarydof, _var.scalingFactor());
140 121 : addJacobian(_assembly, Ken, primarydof, secondarydof, _var.scalingFactor());
141 121 : addJacobian(_assembly, Kne, secondarydof, primarydof, _var_secondary.scalingFactor());
142 :
143 : // Calculate and cache the diagonal secondary-secondary entries
144 676 : for (_i = 0; _i < secondarydof.size(); ++_i)
145 : {
146 555 : Number value = 0.0;
147 555 : switch (_formulation)
148 : {
149 555 : case Moose::Penalty:
150 555 : value = computeQpJacobian(Moose::SecondarySecondary);
151 555 : 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 555 : addJacobianElement(
158 555 : _assembly, value, secondarydof[_i], secondarydof[_i], _var_secondary.scalingFactor());
159 : }
160 121 : }
161 :
162 : void
163 0 : NodalConstraint::updateConnectivity()
164 : {
165 0 : }
|