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 "NodalBC.h" 11 : 12 : #include "Assembly.h" 13 : #include "MooseVariableFE.h" 14 : #include "SystemBase.h" 15 : #include "NonlinearSystemBase.h" 16 : #include "FEProblemBase.h" 17 : 18 : InputParameters 19 315986 : NodalBC::validParams() 20 : { 21 315986 : InputParameters params = NodalBCBase::validParams(); 22 : 23 315986 : return params; 24 : } 25 : 26 64323 : NodalBC::NodalBC(const InputParameters & parameters) 27 : : NodalBCBase(parameters), 28 : MooseVariableInterface<Real>(this, 29 : true, 30 : "variable", 31 : Moose::VarKindType::VAR_SOLVER, 32 : Moose::VarFieldType::VAR_FIELD_STANDARD), 33 128630 : _var(*mooseVariable()), 34 64315 : _current_node(_var.node()), 35 128638 : _u(_var.dofValues()) 36 : { 37 64315 : addMooseVariableDependency(mooseVariable()); 38 : 39 64315 : _save_in.resize(_save_in_strings.size()); 40 64315 : _diag_save_in.resize(_diag_save_in_strings.size()); 41 : 42 64407 : for (unsigned int i = 0; i < _save_in_strings.size(); i++) 43 : { 44 92 : MooseVariable * var = &_subproblem.getStandardVariable(_tid, _save_in_strings[i]); 45 : 46 92 : if (var->feType() != _var.feType()) 47 0 : paramError( 48 : "save_in", 49 : "saved-in auxiliary variable is incompatible with the object's nonlinear variable: ", 50 0 : moose::internal::incompatVarMsg(*var, _var)); 51 : 52 92 : _save_in[i] = var; 53 92 : var->sys().addVariableToZeroOnResidual(_save_in_strings[i]); 54 92 : addMooseVariableDependency(var); 55 : } 56 : 57 64315 : _has_save_in = _save_in.size() > 0; 58 : 59 64335 : for (unsigned int i = 0; i < _diag_save_in_strings.size(); i++) 60 : { 61 20 : MooseVariable * var = &_subproblem.getStandardVariable(_tid, _diag_save_in_strings[i]); 62 : 63 20 : if (var->feType() != _var.feType()) 64 0 : paramError( 65 : "diag_save_in", 66 : "saved-in auxiliary variable is incompatible with the object's nonlinear variable: ", 67 0 : moose::internal::incompatVarMsg(*var, _var)); 68 : 69 20 : _diag_save_in[i] = var; 70 20 : var->sys().addVariableToZeroOnJacobian(_diag_save_in_strings[i]); 71 20 : addMooseVariableDependency(var); 72 : } 73 : 74 64315 : _has_diag_save_in = _diag_save_in.size() > 0; 75 64315 : } 76 : 77 : void 78 55984841 : NodalBC::computeResidual() 79 : { 80 55984841 : if (_var.isNodalDefined()) 81 : { 82 54483529 : const Real res = computeQpResidual(); 83 54483529 : setResidual(_sys, res, _var); 84 : 85 54483529 : if (_has_save_in) 86 672 : for (unsigned int i = 0; i < _save_in.size(); i++) 87 336 : _save_in[i]->sys().solution().set(_save_in[i]->nodalDofIndex(), res); 88 : } 89 55984841 : } 90 : 91 : void 92 7859273 : NodalBC::computeJacobian() 93 : { 94 : // We call the user's computeQpJacobian() function and store the 95 : // results in the _assembly object. We can't store them directly in 96 : // the element stiffness matrix, as they will only be inserted after 97 : // all the assembly is done. 98 7859273 : if (_var.isNodalDefined()) 99 : { 100 7737767 : const Real cached_val = computeQpJacobian(); 101 7737767 : const dof_id_type cached_row = _var.nodalDofIndex(); 102 : 103 : // Cache the user's computeQpJacobian() value for later use. 104 7737767 : addJacobianElement(_fe_problem.assembly(0, _sys.number()), 105 : cached_val, 106 : cached_row, 107 : cached_row, 108 : /*scaling_factor=*/1); 109 : 110 7737767 : if (_has_diag_save_in) 111 90 : for (unsigned int i = 0; i < _diag_save_in.size(); i++) 112 45 : _diag_save_in[i]->sys().solution().set(_diag_save_in[i]->nodalDofIndex(), cached_val); 113 : } 114 7859273 : } 115 : 116 : void 117 7939251 : NodalBC::computeOffDiagJacobian(const unsigned int jvar_num) 118 : { 119 7939251 : if (jvar_num == _var.number()) 120 7859273 : computeJacobian(); 121 : else 122 : { 123 79978 : if (!_var.isNodalDefined()) 124 660 : return; 125 : 126 79318 : const Real cached_val = computeQpOffDiagJacobian(jvar_num); 127 : 128 79318 : if (cached_val == 0.) 129 : // there's no reason to cache this if it's zero, and it can even lead to new nonzero 130 : // allocations 131 77520 : return; 132 : 133 1798 : const dof_id_type cached_row = _var.nodalDofIndex(); 134 : // Note: this only works for Lagrange variables... 135 1798 : const dof_id_type cached_col = _current_node->dof_number(_sys.number(), jvar_num, 0); 136 : 137 : // Cache the user's computeQpJacobian() value for later use. 138 1798 : addJacobianElement(_fe_problem.assembly(0, _sys.number()), 139 : cached_val, 140 : cached_row, 141 : cached_col, 142 : /*scaling_factor=*/1); 143 : } 144 : } 145 : 146 : Real 147 7726575 : NodalBC::computeQpJacobian() 148 : { 149 7726575 : return 1.; 150 : } 151 : 152 : Real 153 77432 : NodalBC::computeQpOffDiagJacobian(unsigned int /*jvar*/) 154 : { 155 77432 : return 0.; 156 : } 157 : 158 : void 159 48 : NodalBC::computeResidualAndJacobian() 160 : { 161 48 : computeResidual(); 162 : 163 96 : for (const auto & [ivariable, jvariable] : _fe_problem.couplingEntries(_tid, _sys.number())) 164 : { 165 48 : const unsigned int ivar = ivariable->number(); 166 48 : const unsigned int jvar = jvariable->number(); 167 : 168 48 : if (ivar != _var.number()) 169 0 : continue; 170 : 171 48 : if (_is_implicit) 172 48 : computeOffDiagJacobian(jvar); 173 : } 174 : 175 : /// TODO: add nonlocal Jacobians and scalar Jacobians 176 48 : }