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 "ComputeNodalKernelBCJacobiansThread.h" 11 : 12 : // MOOSE includes 13 : #include "Assembly.h" 14 : #include "AuxiliarySystem.h" 15 : #include "FEProblem.h" 16 : #include "MooseVariableFE.h" 17 : #include "NodalKernelBase.h" 18 : #include "NonlinearSystemBase.h" 19 : 20 : #include "libmesh/threads.h" 21 : 22 53 : ComputeNodalKernelBCJacobiansThread::ComputeNodalKernelBCJacobiansThread( 23 : FEProblemBase & fe_problem, 24 : NonlinearSystemBase & nl, 25 : MooseObjectTagWarehouse<NodalKernelBase> & nodal_kernels, 26 53 : const std::set<TagID> & tags) 27 : : ThreadedNodeLoop<ConstBndNodeRange, ConstBndNodeRange::const_iterator>(fe_problem), 28 53 : _fe_problem(fe_problem), 29 53 : _nl(nl), 30 106 : _aux_sys(fe_problem.getAuxiliarySystem()), 31 53 : _tags(tags), 32 53 : _nodal_kernels(nodal_kernels), 33 53 : _num_cached(0) 34 : { 35 53 : } 36 : 37 : // Splitting Constructor 38 5 : ComputeNodalKernelBCJacobiansThread::ComputeNodalKernelBCJacobiansThread( 39 5 : ComputeNodalKernelBCJacobiansThread & x, Threads::split split) 40 : : ThreadedNodeLoop<ConstBndNodeRange, ConstBndNodeRange::const_iterator>(x, split), 41 5 : _fe_problem(x._fe_problem), 42 5 : _nl(x._nl), 43 5 : _aux_sys(x._aux_sys), 44 5 : _tags(x._tags), 45 5 : _nodal_kernels(x._nodal_kernels), 46 5 : _num_cached(0) 47 : { 48 5 : } 49 : 50 : void 51 58 : ComputeNodalKernelBCJacobiansThread::pre() 52 : { 53 58 : _num_cached = 0; 54 : 55 58 : if (!_tags.size() || _tags.size() == _fe_problem.numMatrixTags()) 56 58 : _nkernel_warehouse = &_nodal_kernels; 57 0 : else if (_tags.size() == 1) 58 0 : _nkernel_warehouse = &(_nodal_kernels.getMatrixTagObjectWarehouse(*(_tags.begin()), _tid)); 59 : else 60 0 : _nkernel_warehouse = &(_nodal_kernels.getMatrixTagsObjectWarehouse(_tags, _tid)); 61 58 : } 62 : 63 : void 64 1644 : ComputeNodalKernelBCJacobiansThread::onNode(ConstBndNodeRange::const_iterator & node_it) 65 : { 66 1644 : const BndNode * bnode = *node_it; 67 : 68 1644 : BoundaryID boundary_id = bnode->_bnd_id; 69 : 70 1644 : auto & ce = _fe_problem.couplingEntries(_tid, _nl.number()); 71 3846 : for (const auto & it : ce) 72 : { 73 2202 : MooseVariableFEBase & ivariable = *(it.first); 74 2202 : MooseVariableFEBase & jvariable = *(it.second); 75 : 76 2202 : unsigned int ivar = ivariable.number(); 77 2202 : unsigned int jvar = jvariable.number(); 78 : 79 : // The NodalKernels that are active and are coupled to the jvar in question 80 2202 : std::vector<std::shared_ptr<NodalKernelBase>> active_involved_kernels; 81 : 82 2202 : if (_nkernel_warehouse->hasActiveBoundaryObjects(boundary_id, _tid)) 83 : { 84 : // Loop over each NodalKernel to see if it's involved with the jvar 85 1590 : const auto & objects = _nkernel_warehouse->getActiveBoundaryObjects(boundary_id, _tid); 86 3372 : for (const auto & nodal_kernel : objects) 87 : { 88 1782 : if (nodal_kernel->variable().number() == ivar) 89 : { 90 : // If this NodalKernel is acting on the jvar add it to the list and short-circuit the 91 : // loop 92 1590 : if (nodal_kernel->variable().number() == jvar) 93 : { 94 1494 : active_involved_kernels.push_back(nodal_kernel); 95 1494 : continue; 96 : } 97 : 98 : // See if this NodalKernel is coupled to the jvar 99 : const std::vector<MooseVariableFEBase *> & coupled_vars = 100 96 : nodal_kernel->getCoupledMooseVars(); 101 96 : for (const auto & var : coupled_vars) 102 : { 103 0 : if (var->number() == jvar) 104 : { 105 0 : active_involved_kernels.push_back(nodal_kernel); 106 0 : break; // It only takes one 107 : } 108 : } 109 : } 110 : } 111 : } 112 : 113 : // Did we find any NodalKernels coupled to this jvar? 114 2202 : if (!active_involved_kernels.empty()) 115 : { 116 : // prepare variables 117 1494 : for (auto * var : _aux_sys._nodal_vars[_tid]) 118 0 : var->prepareAux(); 119 : 120 1494 : if (_nkernel_warehouse->hasActiveBoundaryObjects(boundary_id, _tid)) 121 : { 122 1494 : Node * node = bnode->_node; 123 1494 : if (node->processor_id() == _fe_problem.processor_id()) 124 : { 125 1168 : _fe_problem.reinitNodeFace(node, boundary_id, _tid); 126 2336 : for (const auto & nodal_kernel : active_involved_kernels) 127 : { 128 1168 : nodal_kernel->setSubdomains(Moose::NodeArg::undefined_subdomain_connection); 129 1168 : nodal_kernel->computeOffDiagJacobian(jvar); 130 : } 131 : 132 1168 : _num_cached++; 133 : } 134 : } 135 : 136 1494 : if (_num_cached == 20) // cache 20 nodes worth before adding into the jacobian 137 : { 138 48 : _num_cached = 0; 139 : // vectors are thread-safe, but matrices are not yet 140 48 : Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); 141 48 : _fe_problem.addCachedJacobian(_tid); 142 48 : } 143 : } 144 2202 : } 145 1644 : } 146 : 147 : void 148 5 : ComputeNodalKernelBCJacobiansThread::join(const ComputeNodalKernelBCJacobiansThread & /*y*/) 149 : { 150 5 : } 151 : 152 : void 153 58 : ComputeNodalKernelBCJacobiansThread::printGeneralExecutionInformation() const 154 : { 155 58 : if (!_fe_problem.shouldPrintExecution(_tid) || !_nkernel_warehouse->hasActiveBoundaryObjects()) 156 48 : return; 157 : 158 10 : const auto & console = _fe_problem.console(); 159 10 : const auto & execute_on = _fe_problem.getCurrentExecuteOnFlag(); 160 : console << "[DBG] Computing nodal kernel & boundary conditions contribution to the Jacobian on " 161 10 : "boundary nodes on " 162 10 : << execute_on << std::endl; 163 10 : console << "[DBG] Ordering on boundaries they are defined on:" << std::endl; 164 10 : console << _nkernel_warehouse->activeObjectsToFormattedString() << std::endl; 165 : }