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 "ArrayIntegratedBC.h"
11 :
12 : #include "Assembly.h"
13 : #include "SubProblem.h"
14 : #include "SystemBase.h"
15 : #include "MooseVariableFE.h"
16 : #include "MooseVariableScalar.h"
17 :
18 : #include "libmesh/quadrature.h"
19 :
20 : InputParameters
21 15832 : ArrayIntegratedBC::validParams()
22 : {
23 15832 : InputParameters params = IntegratedBCBase::validParams();
24 15832 : return params;
25 : }
26 :
27 274 : ArrayIntegratedBC::ArrayIntegratedBC(const InputParameters & parameters)
28 : : IntegratedBCBase(parameters),
29 : MooseVariableInterface<RealEigenVector>(this,
30 : false,
31 : "variable",
32 : Moose::VarKindType::VAR_SOLVER,
33 : Moose::VarFieldType::VAR_FIELD_ARRAY),
34 548 : _var(*mooseVariable()),
35 274 : _normals(_assembly.normals()),
36 274 : _phi(_assembly.phiFace(_var)),
37 274 : _test(_var.phiFace()),
38 274 : _u(_is_implicit ? _var.sln() : _var.slnOld()),
39 274 : _count(_var.count()),
40 1096 : _work_vector(_count)
41 : {
42 274 : addMooseVariableDependency(mooseVariable());
43 :
44 274 : _save_in.resize(_save_in_strings.size());
45 274 : _diag_save_in.resize(_diag_save_in_strings.size());
46 :
47 287 : for (unsigned int i = 0; i < _save_in_strings.size(); i++)
48 : {
49 13 : ArrayMooseVariable * var = &_subproblem.getArrayVariable(_tid, _save_in_strings[i]);
50 :
51 13 : if (var->feType() != _var.feType())
52 0 : paramError(
53 : "save_in",
54 : "saved-in auxiliary variable is incompatible with the object's nonlinear variable: ",
55 0 : moose::internal::incompatVarMsg(*var, _var));
56 13 : _save_in[i] = var;
57 13 : var->sys().addVariableToZeroOnResidual(_save_in_strings[i]);
58 13 : addMooseVariableDependency(var);
59 : }
60 :
61 274 : _has_save_in = _save_in.size() > 0;
62 :
63 287 : for (unsigned int i = 0; i < _diag_save_in_strings.size(); i++)
64 : {
65 13 : ArrayMooseVariable * var = &_subproblem.getArrayVariable(_tid, _diag_save_in_strings[i]);
66 :
67 13 : if (var->feType() != _var.feType())
68 0 : paramError(
69 : "diag_save_in",
70 : "saved-in auxiliary variable is incompatible with the object's nonlinear variable: ",
71 0 : moose::internal::incompatVarMsg(*var, _var));
72 :
73 13 : _diag_save_in[i] = var;
74 13 : var->sys().addVariableToZeroOnJacobian(_diag_save_in_strings[i]);
75 13 : addMooseVariableDependency(var);
76 : }
77 :
78 274 : _has_diag_save_in = _diag_save_in.size() > 0;
79 274 : }
80 :
81 : void
82 49508 : ArrayIntegratedBC::computeResidual()
83 : {
84 49508 : prepareVectorTag(_assembly, _var.number());
85 :
86 159444 : for (_qp = 0; _qp < _qrule->n_points(); _qp++)
87 : {
88 109936 : initQpResidual();
89 683984 : for (_i = 0; _i < _test.size(); _i++)
90 : {
91 574048 : _work_vector.setZero();
92 574048 : computeQpResidual(_work_vector);
93 : mooseAssert(_work_vector.size() == _count,
94 : "Size of local residual is not equal to the number of array variable compoments");
95 574048 : _work_vector *= _JxW[_qp] * _coord[_qp];
96 574048 : _assembly.saveLocalArrayResidual(_local_re, _i, _test.size(), _work_vector);
97 : }
98 : }
99 :
100 49508 : accumulateTaggedLocalResidual();
101 :
102 49508 : if (_has_save_in)
103 192 : for (const auto & var : _save_in)
104 : {
105 96 : auto * avar = dynamic_cast<ArrayMooseVariable *>(var);
106 96 : if (avar)
107 96 : avar->addSolution(_local_re);
108 : else
109 0 : mooseError("Save-in variable for an array kernel must be an array variable");
110 : }
111 49508 : }
112 :
113 : void
114 7210 : ArrayIntegratedBC::computeJacobian()
115 : {
116 7210 : prepareMatrixTag(_assembly, _var.number(), _var.number());
117 :
118 22014 : for (_qp = 0; _qp < _qrule->n_points(); _qp++)
119 : {
120 14804 : initQpJacobian();
121 78628 : for (_i = 0; _i < _test.size(); _i++)
122 365200 : for (_j = 0; _j < _phi.size(); _j++)
123 : {
124 301376 : RealEigenVector v = _JxW[_qp] * _coord[_qp] * computeQpJacobian();
125 1205504 : _assembly.saveDiagLocalArrayJacobian(
126 301376 : _local_ke, _i, _test.size(), _j, _phi.size(), _var.number(), v);
127 301376 : }
128 : }
129 :
130 7210 : accumulateTaggedLocalMatrix();
131 :
132 7210 : if (_has_diag_save_in)
133 : {
134 0 : DenseVector<Number> diag = _assembly.getJacobianDiagonal(_local_ke);
135 0 : for (const auto & var : _diag_save_in)
136 : {
137 0 : auto * avar = dynamic_cast<ArrayMooseVariable *>(var);
138 0 : if (avar)
139 0 : avar->addSolution(diag);
140 : else
141 0 : mooseError("Save-in variable for an array kernel must be an array variable");
142 : }
143 0 : }
144 7210 : }
145 :
146 : RealEigenVector
147 527680 : ArrayIntegratedBC::computeQpJacobian()
148 : {
149 527680 : return RealEigenVector::Zero(_var.count());
150 : }
151 :
152 : void
153 2144 : ArrayIntegratedBC::computeOffDiagJacobian(const unsigned int jvar_num)
154 : {
155 2144 : const auto & jvar = getVariable(jvar_num);
156 2144 : if (!jvar.dofIndices().size())
157 : // If we have no dof indices then data like phiSize() can't be trusted. For instance a variable
158 : // of constant monomial finite element type that lives only on lower-dimensional subdomains will
159 : // have zero dof indices here (assuming this BC is being applied on a higher-D face) but will
160 : // have a phiSize() of 1 corresponding to the number of shapes for that finite element type
161 : // on the higher-dimensional element.
162 576 : return;
163 :
164 1568 : const auto phi_size = jvar.phiSize();
165 :
166 1568 : bool same_var = jvar_num == _var.number();
167 :
168 1568 : prepareMatrixTag(_assembly, _var.number(), jvar_num);
169 :
170 6720 : for (_qp = 0; _qp < _qrule->n_points(); _qp++)
171 : {
172 5152 : initQpOffDiagJacobian(jvar);
173 51584 : for (_i = 0; _i < _test.size(); _i++)
174 518144 : for (_j = 0; _j < phi_size; _j++)
175 : {
176 471712 : RealEigenMatrix v = _JxW[_qp] * _coord[_qp] * computeQpOffDiagJacobian(jvar);
177 1415136 : _assembly.saveFullLocalArrayJacobian(
178 471712 : _local_ke, _i, _test.size(), _j, phi_size, _var.number(), jvar_num, v);
179 471712 : }
180 : }
181 :
182 1568 : accumulateTaggedLocalMatrix();
183 :
184 1568 : if (_has_diag_save_in && same_var)
185 : {
186 64 : DenseVector<Number> diag = _assembly.getJacobianDiagonal(_local_ke);
187 128 : for (const auto & var : _diag_save_in)
188 : {
189 64 : auto * avar = dynamic_cast<ArrayMooseVariable *>(var);
190 64 : if (avar)
191 64 : avar->addSolution(diag);
192 : else
193 0 : mooseError("Save-in variable for an array kernel must be an array variable");
194 : }
195 64 : }
196 : }
197 :
198 : RealEigenMatrix
199 471712 : ArrayIntegratedBC::computeQpOffDiagJacobian(const MooseVariableFEBase & jvar)
200 : {
201 471712 : if (jvar.number() == _var.number())
202 471712 : return computeQpJacobian().asDiagonal();
203 : else
204 0 : return RealEigenMatrix::Zero(_var.count(), jvar.count());
205 : }
206 :
207 : void
208 0 : ArrayIntegratedBC::computeOffDiagJacobianScalar(unsigned int jvar)
209 : {
210 0 : prepareMatrixTag(_assembly, _var.number(), jvar);
211 :
212 0 : const MooseVariableScalar & jv = _sys.getScalarVariable(_tid, jvar);
213 0 : for (_qp = 0; _qp < _qrule->n_points(); _qp++)
214 0 : for (_i = 0; _i < _test.size(); _i++)
215 : {
216 0 : RealEigenMatrix v = _JxW[_qp] * _coord[_qp] * computeQpOffDiagJacobianScalar(jv);
217 0 : _assembly.saveFullLocalArrayJacobian(
218 0 : _local_ke, _i, _test.size(), 0, 1, _var.number(), jvar, v);
219 0 : }
220 :
221 0 : accumulateTaggedLocalMatrix();
222 0 : }
223 :
224 : RealEigenMatrix
225 0 : ArrayIntegratedBC::computeQpOffDiagJacobianScalar(const MooseVariableScalar & jvar)
226 : {
227 0 : return RealEigenMatrix::Zero(_var.count(), (unsigned int)jvar.order() + 1);
228 : }
|