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 167794 : NodalBC::validParams() 20 : { 21 167794 : InputParameters params = NodalBCBase::validParams(); 22 : 23 167794 : return params; 24 : } 25 : 26 63274 : 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 126536 : _var(*mooseVariable()), 34 63268 : _current_node(_var.node()), 35 253081 : _u(_var.dofValues()) 36 : { 37 63268 : addMooseVariableDependency(mooseVariable()); 38 : 39 63268 : _save_in.resize(_save_in_strings.size()); 40 63268 : _diag_save_in.resize(_diag_save_in_strings.size()); 41 : 42 63358 : for (unsigned int i = 0; i < _save_in_strings.size(); i++) 43 : { 44 90 : MooseVariable * var = &_subproblem.getStandardVariable(_tid, _save_in_strings[i]); 45 : 46 90 : 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 90 : _save_in[i] = var; 53 90 : var->sys().addVariableToZeroOnResidual(_save_in_strings[i]); 54 90 : addMooseVariableDependency(var); 55 : } 56 : 57 63268 : _has_save_in = _save_in.size() > 0; 58 : 59 63286 : for (unsigned int i = 0; i < _diag_save_in_strings.size(); i++) 60 : { 61 18 : MooseVariable * var = &_subproblem.getStandardVariable(_tid, _diag_save_in_strings[i]); 62 : 63 18 : 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 18 : _diag_save_in[i] = var; 70 18 : var->sys().addVariableToZeroOnJacobian(_diag_save_in_strings[i]); 71 18 : addMooseVariableDependency(var); 72 : } 73 : 74 63268 : _has_diag_save_in = _diag_save_in.size() > 0; 75 63268 : } 76 : 77 : void 78 57190544 : NodalBC::computeResidual() 79 : { 80 57190544 : if (_var.isNodalDefined()) 81 : { 82 55354742 : const Real res = computeQpResidual(); 83 55354742 : setResidual(_sys, res, _var); 84 : 85 55354742 : 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 57190544 : } 90 : 91 : void 92 7879801 : 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 7879801 : if (_var.isNodalDefined()) 99 : { 100 7715021 : const Real cached_val = computeQpJacobian(); 101 7715021 : const dof_id_type cached_row = _var.nodalDofIndex(); 102 : 103 : // Cache the user's computeQpJacobian() value for later use. 104 7715021 : addJacobianElement(_fe_problem.assembly(0, _sys.number()), 105 : cached_val, 106 : cached_row, 107 : cached_row, 108 : /*scaling_factor=*/1); 109 : 110 7715021 : 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 7879801 : } 115 : 116 : void 117 7955653 : NodalBC::computeOffDiagJacobian(const unsigned int jvar_num) 118 : { 119 7955653 : if (jvar_num == _var.number()) 120 7879801 : computeJacobian(); 121 : else 122 : { 123 75852 : if (!_var.isNodalDefined()) 124 564 : return; 125 : 126 75288 : const Real cached_val = computeQpOffDiagJacobian(jvar_num); 127 : 128 75288 : 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 73492 : return; 132 : 133 1796 : const dof_id_type cached_row = _var.nodalDofIndex(); 134 : // Note: this only works for Lagrange variables... 135 1796 : 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 1796 : 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 7703829 : NodalBC::computeQpJacobian() 148 : { 149 7703829 : return 1.; 150 : } 151 : 152 : Real 153 73404 : NodalBC::computeQpOffDiagJacobian(unsigned int /*jvar*/) 154 : { 155 73404 : 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 : }