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 "BoundaryIntegralValueConstraint.h" 11 : 12 : #include "MooseVariableScalar.h" 13 : 14 : #include <array> 15 : 16 : registerMooseObject("MooseApp", BoundaryIntegralValueConstraint); 17 : 18 : InputParameters 19 3237 : BoundaryIntegralValueConstraint::validParams() 20 : { 21 3237 : InputParameters params = IntegratedBC::validParams(); 22 6474 : params.addClassDescription( 23 : "Enforces a prescribed average value for a finite element variable on a boundary using a " 24 : "scalar Lagrange multiplier."); 25 12948 : params.addParam<PostprocessorName>("phi0", "0", "The value that the constraint will enforce."); 26 9711 : params.addRequiredCoupledVar("lambda", "Lagrange multiplier scalar variable"); 27 3237 : return params; 28 0 : } 29 : 30 92 : BoundaryIntegralValueConstraint::BoundaryIntegralValueConstraint(const InputParameters & parameters) 31 : : IntegratedBC(parameters), 32 92 : _phi0(getPostprocessorValue("phi0")), 33 184 : _lambda_var(*getScalarVar("lambda", 0)), 34 276 : _lambda(coupledScalarValue("lambda")) 35 : { 36 92 : if (_lambda_var.order() != 1) 37 0 : paramError("lambda", "The lambda variable must be a first-order scalar variable."); 38 92 : } 39 : 40 : std::set<std::string> 41 84 : BoundaryIntegralValueConstraint::additionalROVariables() 42 : { 43 252 : return {_lambda_var.name()}; 44 84 : } 45 : 46 : Real 47 25856 : BoundaryIntegralValueConstraint::computeQpResidual() 48 : { 49 25856 : return _lambda[0] * _test[_i][_qp]; 50 : } 51 : 52 : void 53 3232 : BoundaryIntegralValueConstraint::computeResidual() 54 : { 55 3232 : IntegratedBC::computeResidual(); 56 3232 : computeScalarResidual(); 57 3232 : } 58 : 59 : void 60 112 : BoundaryIntegralValueConstraint::computeOffDiagJacobian(const unsigned int jvar) 61 : { 62 112 : if (jvar == _var.number()) 63 112 : computeScalarFieldJacobian(); 64 112 : } 65 : 66 : void 67 112 : BoundaryIntegralValueConstraint::computeOffDiagJacobianScalar(const unsigned int jvar) 68 : { 69 112 : if (jvar == _lambda_var.number()) 70 : { 71 112 : computeScalarJacobian(); 72 112 : computeFieldScalarJacobian(); 73 : } 74 112 : } 75 : 76 : void 77 1616 : BoundaryIntegralValueConstraint::computeResidualAndJacobian() 78 : { 79 1616 : computeResidual(); 80 : 81 1616 : if (_is_implicit) 82 : { 83 1616 : prepareShapes(_var.number()); 84 1616 : IntegratedBC::computeJacobian(); 85 1616 : computeScalarJacobian(); 86 : 87 : // The residual-and-Jacobian-together path bypasses ComputeFullJacobianThread, so assemble the 88 : // scalar off-diagonal blocks here. 89 1616 : computeFieldScalarJacobian(); 90 1616 : computeScalarFieldJacobian(); 91 : } 92 1616 : } 93 : 94 : void 95 3232 : BoundaryIntegralValueConstraint::computeScalarResidual() 96 : { 97 : mooseAssert(_lambda_var.dofIndices().size() == 1, "The lambda variable should have one dof"); 98 : 99 3232 : std::array<Real, 1> residual{{0.0}}; 100 : 101 9696 : for (_qp = 0; _qp < _qrule->n_points(); _qp++) 102 6464 : residual[0] += _JxW[_qp] * _coord[_qp] * (_u[_qp] - _phi0); 103 : 104 3232 : addResiduals(_assembly, residual, _lambda_var.dofIndices(), _lambda_var.scalingFactor()); 105 3232 : } 106 : 107 : void 108 1728 : BoundaryIntegralValueConstraint::computeScalarJacobian() 109 : { 110 : mooseAssert(_lambda_var.dofIndices().size() == 1, "The lambda variable should have one dof"); 111 : 112 1728 : DenseMatrix<Real> zero(1, 1); 113 1728 : addJacobian(_assembly, 114 : zero, 115 1728 : _lambda_var.dofIndices(), 116 1728 : _lambda_var.dofIndices(), 117 1728 : _lambda_var.scalingFactor()); 118 1728 : } 119 : 120 : void 121 1728 : BoundaryIntegralValueConstraint::computeFieldScalarJacobian() 122 : { 123 : mooseAssert(_lambda_var.dofIndices().size() == 1, "The lambda variable should have one dof"); 124 : 125 1728 : DenseMatrix<Real> jacobian(_test.size(), 1); 126 : 127 5184 : for (_qp = 0; _qp < _qrule->n_points(); _qp++) 128 17280 : for (_i = 0; _i < _test.size(); _i++) 129 13824 : jacobian(_i, 0) += _JxW[_qp] * _coord[_qp] * _test[_i][_qp]; 130 : 131 1728 : addJacobian( 132 1728 : _assembly, jacobian, _var.dofIndices(), _lambda_var.dofIndices(), _var.scalingFactor()); 133 1728 : } 134 : 135 : void 136 1728 : BoundaryIntegralValueConstraint::computeScalarFieldJacobian() 137 : { 138 : mooseAssert(_lambda_var.dofIndices().size() == 1, "The lambda variable should have one dof"); 139 : 140 1728 : DenseMatrix<Real> jacobian(1, _phi.size()); 141 : 142 5184 : for (_qp = 0; _qp < _qrule->n_points(); _qp++) 143 17280 : for (_j = 0; _j < _phi.size(); _j++) 144 13824 : jacobian(0, _j) += _JxW[_qp] * _coord[_qp] * _phi[_j][_qp]; 145 : 146 1728 : addJacobian(_assembly, 147 : jacobian, 148 1728 : _lambda_var.dofIndices(), 149 1728 : _var.dofIndices(), 150 1728 : _lambda_var.scalingFactor()); 151 1728 : }