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 325779 : NodalBC::validParams() 20 : { 21 325779 : InputParameters params = NodalBCBase::validParams(); 22 : 23 325779 : return params; 24 : } 25 : 26 69208 : 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 138400 : _var(*mooseVariable()), 34 69200 : _current_node(_var.node()), 35 138408 : _u(_var.dofValues()) 36 : { 37 69200 : addMooseVariableDependency(mooseVariable()); 38 : 39 69200 : _save_in.resize(_save_in_strings.size()); 40 69200 : _diag_save_in.resize(_diag_save_in_strings.size()); 41 : 42 69299 : for (unsigned int i = 0; i < _save_in_strings.size(); i++) 43 : { 44 99 : MooseVariable * var = &_subproblem.getStandardVariable(_tid, _save_in_strings[i]); 45 : 46 99 : 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 99 : _save_in[i] = var; 53 99 : var->sys().addVariableToZeroOnResidual(_save_in_strings[i]); 54 99 : addMooseVariableDependency(var); 55 : } 56 : 57 69200 : _has_save_in = _save_in.size() > 0; 58 : 59 69221 : for (unsigned int i = 0; i < _diag_save_in_strings.size(); i++) 60 : { 61 21 : MooseVariable * var = &_subproblem.getStandardVariable(_tid, _diag_save_in_strings[i]); 62 : 63 21 : 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 21 : _diag_save_in[i] = var; 70 21 : var->sys().addVariableToZeroOnJacobian(_diag_save_in_strings[i]); 71 21 : addMooseVariableDependency(var); 72 : } 73 : 74 69200 : _has_diag_save_in = _diag_save_in.size() > 0; 75 69200 : } 76 : 77 : void 78 62508692 : NodalBC::computeResidual() 79 : { 80 62508692 : if (_var.isNodalDefined()) 81 : { 82 60781139 : const Real res = computeQpResidual(); 83 60781139 : setResidual(_sys, res, _var); 84 : 85 60781139 : if (_has_save_in) 86 756 : for (unsigned int i = 0; i < _save_in.size(); i++) 87 378 : _save_in[i]->sys().solution().set(_save_in[i]->nodalDofIndex(), res); 88 : } 89 62508692 : } 90 : 91 : void 92 8806381 : 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 8806381 : if (_var.isNodalDefined()) 99 : { 100 8663141 : const Real cached_val = computeQpJacobian(); 101 8663141 : const dof_id_type cached_row = _var.nodalDofIndex(); 102 : 103 : // Cache the user's computeQpJacobian() value for later use. 104 8663141 : addJacobianElement(_fe_problem.assembly(0, _sys.number()), 105 : cached_val, 106 : cached_row, 107 : cached_row, 108 : /*scaling_factor=*/1); 109 : 110 8663141 : if (_has_diag_save_in) 111 102 : for (unsigned int i = 0; i < _diag_save_in.size(); i++) 112 51 : _diag_save_in[i]->sys().solution().set(_diag_save_in[i]->nodalDofIndex(), cached_val); 113 : } 114 8806381 : } 115 : 116 : void 117 8893085 : NodalBC::computeOffDiagJacobian(const unsigned int jvar_num) 118 : { 119 8893085 : if (jvar_num == _var.number()) 120 8806381 : computeJacobian(); 121 : else 122 : { 123 86704 : if (!_var.isNodalDefined()) 124 660 : return; 125 : 126 86044 : const Real cached_val = computeQpOffDiagJacobian(jvar_num); 127 : 128 86044 : 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 84023 : return; 132 : 133 2021 : const dof_id_type cached_row = _var.nodalDofIndex(); 134 : // Note: this only works for Lagrange variables... 135 2021 : 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 2021 : 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 8650550 : NodalBC::computeQpJacobian() 148 : { 149 8650550 : return 1.; 150 : } 151 : 152 : Real 153 83924 : NodalBC::computeQpOffDiagJacobian(unsigned int /*jvar*/) 154 : { 155 83924 : return 0.; 156 : } 157 : 158 : void 159 54 : NodalBC::computeResidualAndJacobian() 160 : { 161 54 : computeResidual(); 162 : 163 108 : for (const auto & [ivariable, jvariable] : _fe_problem.couplingEntries(_tid, _sys.number())) 164 : { 165 54 : const unsigned int ivar = ivariable->number(); 166 54 : const unsigned int jvar = jvariable->number(); 167 : 168 54 : if (ivar != _var.number()) 169 0 : continue; 170 : 171 54 : if (_is_implicit) 172 54 : computeOffDiagJacobian(jvar); 173 : } 174 : 175 : /// TODO: add nonlocal Jacobians and scalar Jacobians 176 54 : }