LCOV - code coverage report
Current view: top level - src/loops - ComputeFullJacobianThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 161 167 96.4 %
Date: 2026-05-29 20:35:17 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          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 "ComputeFullJacobianThread.h"
      11             : #include "NonlinearSystem.h"
      12             : #include "FEProblem.h"
      13             : #include "KernelBase.h"
      14             : #include "IntegratedBCBase.h"
      15             : #include "HDGKernel.h"
      16             : #include "DGKernel.h"
      17             : #include "InterfaceKernelBase.h"
      18             : #include "MooseVariableFE.h"
      19             : #include "MooseVariableScalar.h"
      20             : #include "NonlocalKernel.h"
      21             : #include "NonlocalIntegratedBC.h"
      22             : #include "FVElementalKernel.h"
      23             : #include "libmesh/threads.h"
      24             : 
      25       77770 : ComputeFullJacobianThread::ComputeFullJacobianThread(FEProblemBase & fe_problem,
      26       77770 :                                                      const std::set<TagID> & tags)
      27       77770 :   : ComputeJacobianThread(fe_problem, tags)
      28             : {
      29       77770 : }
      30             : 
      31             : // Splitting Constructor
      32        7267 : ComputeFullJacobianThread::ComputeFullJacobianThread(ComputeFullJacobianThread & x,
      33        7267 :                                                      Threads::split split)
      34        7267 :   : ComputeJacobianThread(x, split)
      35             : {
      36        7267 : }
      37             : 
      38       92180 : ComputeFullJacobianThread::~ComputeFullJacobianThread() {}
      39             : 
      40             : void
      41    14201338 : ComputeFullJacobianThread::computeOnElement()
      42             : {
      43    14201338 :   auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
      44    44314643 :   for (const auto & it : ce)
      45             :   {
      46    30113305 :     MooseVariableFieldBase & ivariable = *(it.first);
      47    30113305 :     MooseVariableFieldBase & jvariable = *(it.second);
      48             : 
      49    30113305 :     if (ivariable.isFV())
      50     2995296 :       continue;
      51             : 
      52    27118009 :     unsigned int ivar = ivariable.number();
      53    27118009 :     unsigned int jvar = jvariable.number();
      54             : 
      55    53023765 :     if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
      56    25905756 :         _tag_kernels->hasActiveVariableBlockObjects(ivar, _subdomain, _tid))
      57             :     {
      58             :       // only if there are dofs for j-variable (if it is subdomain restricted var, there may not be
      59             :       // any)
      60    24778274 :       const auto & kernels = _tag_kernels->getActiveVariableBlockObjects(ivar, _subdomain, _tid);
      61    75193816 :       for (const auto & kernel : kernels)
      62    50415542 :         if ((kernel->variable().number() == ivar) && kernel->isImplicit())
      63             :         {
      64    50372288 :           kernel->prepareShapes(jvar);
      65    50372288 :           kernel->computeOffDiagJacobian(jvar);
      66             :         }
      67             :     }
      68             :   }
      69             : 
      70             :   /// done only when nonlocal kernels exist in the system
      71    14201338 :   if (_fe_problem.checkNonlocalCouplingRequirement())
      72             :   {
      73        3792 :     auto & cne = _fe_problem.nonlocalCouplingEntries(_tid, _nl.number());
      74        7676 :     for (const auto & it : cne)
      75             :     {
      76        3884 :       MooseVariableFieldBase & ivariable = *(it.first);
      77        3884 :       MooseVariableFieldBase & jvariable = *(it.second);
      78             : 
      79        3884 :       if (ivariable.isFV())
      80           0 :         continue;
      81             : 
      82        3884 :       unsigned int ivar = ivariable.number();
      83        3884 :       unsigned int jvar = jvariable.number();
      84             : 
      85        7768 :       if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
      86        3884 :           _tag_kernels->hasActiveVariableBlockObjects(ivar, _subdomain, _tid))
      87             :       {
      88        3864 :         const auto & kernels = _tag_kernels->getActiveVariableBlockObjects(ivar, _subdomain, _tid);
      89        8216 :         for (const auto & kernel : kernels)
      90             :         {
      91             :           std::shared_ptr<NonlocalKernel> nonlocal_kernel =
      92        4352 :               std::dynamic_pointer_cast<NonlocalKernel>(kernel);
      93        4352 :           if (nonlocal_kernel)
      94         264 :             if ((kernel->variable().number() == ivar) && kernel->isImplicit())
      95             :             {
      96         264 :               kernel->prepareShapes(jvar);
      97         264 :               kernel->computeNonlocalOffDiagJacobian(jvar);
      98             :             }
      99        4352 :         }
     100             :       }
     101             :     }
     102             :   }
     103             : 
     104    14201338 :   const std::vector<MooseVariableScalar *> & scalar_vars = _nl.getScalarVariables(_tid);
     105    14201338 :   if (scalar_vars.size() > 0)
     106             :   {
     107             :     // go over nl-variables (non-scalar)
     108      142814 :     const std::vector<MooseVariableFieldBase *> & vars = _nl.getVariables(_tid);
     109      383196 :     for (const auto & ivariable : vars)
     110      473552 :       if (ivariable->activeOnSubdomain(_subdomain) > 0 &&
     111      233170 :           _tag_kernels->hasActiveVariableBlockObjects(ivariable->number(), _subdomain, _tid))
     112             :       {
     113             :         // for each variable get the list of active kernels
     114             :         const auto & kernels =
     115      226831 :             _tag_kernels->getActiveVariableBlockObjects(ivariable->number(), _subdomain, _tid);
     116      763689 :         for (const auto & kernel : kernels)
     117      536858 :           if (kernel->isImplicit())
     118             :           {
     119             :             // now, get the list of coupled scalar vars and compute their off-diag jacobians
     120      536858 :             const auto & coupled_scalar_vars = kernel->getCoupledMooseScalarVars();
     121             : 
     122             :             // Do: dvar / dscalar_var, only want to process only nl-variables (not aux ones)
     123      626994 :             for (const auto & jvariable : coupled_scalar_vars)
     124       90136 :               if (_nl.hasScalarVariable(jvariable->name()))
     125       90136 :                 kernel->computeOffDiagJacobianScalar(jvariable->number());
     126             :           }
     127             :       }
     128             :   }
     129             : 
     130    14201338 :   if (_fe_problem.haveFV())
     131     5036790 :     for (auto fv_kernel : _fv_kernels)
     132     2491683 :       if (fv_kernel->isImplicit())
     133     2491683 :         fv_kernel->computeOffDiagJacobian();
     134    14201338 : }
     135             : 
     136             : void
     137      188968 : ComputeFullJacobianThread::computeOnBoundary(BoundaryID bnd_id, const Elem * lower_d_elem)
     138             : {
     139      188968 :   auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     140      733473 :   for (const auto & it : ce)
     141             :   {
     142      544505 :     MooseVariableFieldBase & ivariable = *(it.first);
     143      544505 :     MooseVariableFieldBase & jvariable = *(it.second);
     144             : 
     145             :     // We don't currently support coupling with FV variables
     146      544505 :     if (ivariable.isFV() || jvariable.isFV())
     147        2568 :       continue;
     148             : 
     149      541937 :     const auto ivar = ivariable.number();
     150      541937 :     const auto jvar = jvariable.number();
     151             : 
     152      541937 :     if (!ivariable.activeOnSubdomain(_subdomain))
     153       77184 :       continue;
     154             : 
     155             :     // only if there are dofs for j-variable (if it is subdomain restricted var, there may not be
     156             :     // any)
     157      464753 :     if (lower_d_elem)
     158             :     {
     159       11896 :       auto lower_d_subdomain = lower_d_elem->subdomain_id();
     160       19528 :       if (!jvariable.activeOnSubdomain(_subdomain) &&
     161        7632 :           !jvariable.activeOnSubdomain(lower_d_subdomain))
     162        3584 :         continue;
     163             :     }
     164             :     else
     165             :     {
     166      452857 :       if (!jvariable.activeOnSubdomain(_subdomain))
     167       25584 :         continue;
     168             :     }
     169             : 
     170      435585 :     if (!_ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     171           0 :       continue;
     172             : 
     173      435585 :     const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     174      900729 :     for (const auto & bc : bcs)
     175      465144 :       if (bc->shouldApply() && bc->variable().number() == ivar && bc->isImplicit())
     176             :       {
     177      281950 :         bc->prepareShapes(jvar);
     178      281950 :         bc->computeOffDiagJacobian(jvar);
     179             :       }
     180             :   }
     181             : 
     182             :   /// done only when nonlocal integrated_bcs exist in the system
     183      188968 :   if (_fe_problem.checkNonlocalCouplingRequirement())
     184             :   {
     185         370 :     auto & cne = _fe_problem.nonlocalCouplingEntries(_tid, _nl.number());
     186         740 :     for (const auto & it : cne)
     187             :     {
     188         370 :       MooseVariableFieldBase & ivariable = *(it.first);
     189         370 :       MooseVariableFieldBase & jvariable = *(it.second);
     190             : 
     191         370 :       if (ivariable.isFV())
     192           0 :         continue;
     193             : 
     194         370 :       unsigned int ivar = ivariable.number();
     195         370 :       unsigned int jvar = jvariable.number();
     196             : 
     197         740 :       if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
     198         370 :           _ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     199             :       {
     200             :         const std::vector<std::shared_ptr<IntegratedBCBase>> & integrated_bcs =
     201         370 :             _ibc_warehouse->getBoundaryObjects(bnd_id, _tid);
     202         740 :         for (const auto & integrated_bc : integrated_bcs)
     203             :         {
     204             :           std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
     205         370 :               std::dynamic_pointer_cast<NonlocalIntegratedBC>(integrated_bc);
     206         370 :           if (nonlocal_integrated_bc)
     207         370 :             if ((integrated_bc->variable().number() == ivar) && integrated_bc->isImplicit())
     208             :             {
     209         370 :               integrated_bc->prepareShapes(jvar);
     210         370 :               integrated_bc->computeNonlocalOffDiagJacobian(jvar);
     211             :             }
     212         370 :         }
     213             :       }
     214             :     }
     215             :   }
     216             : 
     217      188968 :   const std::vector<MooseVariableScalar *> & scalar_vars = _nl.getScalarVariables(_tid);
     218      188968 :   if (scalar_vars.size() > 0)
     219             :   {
     220             :     // go over nl-variables (non-scalar)
     221       19262 :     const std::vector<MooseVariableFieldBase *> & vars = _nl.getVariables(_tid);
     222       57340 :     for (const auto & ivar : vars)
     223       76156 :       if (ivar->activeOnSubdomain(_subdomain) > 0 &&
     224       38078 :           _ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     225             :       {
     226             :         // for each variable get the list of active kernels
     227       38078 :         const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     228       76156 :         for (const auto & bc : bcs)
     229       38078 :           if (bc->variable().number() == ivar->number() && bc->isImplicit())
     230             :           {
     231             :             // now, get the list of coupled scalar vars and compute their off-diag jacobians
     232             :             const std::vector<MooseVariableScalar *> coupled_scalar_vars =
     233       19262 :                 bc->getCoupledMooseScalarVars();
     234             : 
     235             :             // Do: dvar / dscalar_var, only want to process only nl-variables (not aux ones)
     236       19308 :             for (const auto & jvar : coupled_scalar_vars)
     237          46 :               if (_nl.hasScalarVariable(jvar->name()))
     238          46 :                 bc->computeOffDiagJacobianScalar(jvar->number());
     239       19262 :           }
     240             :       }
     241             :   }
     242      188968 : }
     243             : 
     244             : void
     245        6614 : ComputeFullJacobianThread::computeOnInterface(BoundaryID bnd_id)
     246             : {
     247        6614 :   if (_ik_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     248             :   {
     249        6614 :     const auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     250       33271 :     for (const auto & it : ce)
     251             :     {
     252       26657 :       MooseVariableFieldBase & ivariable = *(it.first);
     253       26657 :       MooseVariableFieldBase & jvariable = *(it.second);
     254             : 
     255       26657 :       if (ivariable.isFV())
     256           0 :         continue;
     257             : 
     258       26657 :       unsigned int ivar = ivariable.number();
     259       26657 :       unsigned int jvar = jvariable.number();
     260             : 
     261       26657 :       const auto & int_ks = _ik_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     262       54130 :       for (const auto & interface_kernel : int_ks)
     263             :       {
     264       27473 :         if (!interface_kernel->isImplicit())
     265           0 :           continue;
     266             : 
     267       27473 :         interface_kernel->prepareShapes(jvar);
     268       27473 :         interface_kernel->prepareNeighborShapes(jvar);
     269             : 
     270       27473 :         if (interface_kernel->variable().number() == ivar)
     271       13675 :           interface_kernel->computeElementOffDiagJacobian(jvar);
     272             : 
     273       27473 :         if (interface_kernel->neighborVariable().number() == ivar)
     274       13675 :           interface_kernel->computeNeighborOffDiagJacobian(jvar);
     275             :       }
     276             :     }
     277             :   }
     278        6614 : }
     279             : 
     280             : void
     281       44720 : ComputeFullJacobianThread::computeOnInternalFace(const Elem * neighbor)
     282             : {
     283       44720 :   if (_dg_warehouse->hasActiveBlockObjects(_subdomain, _tid))
     284             :   {
     285       44720 :     const auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     286      132439 :     for (const auto & it : ce)
     287             :     {
     288       87719 :       MooseVariableFieldBase & ivariable = *(it.first);
     289       87719 :       MooseVariableFieldBase & jvariable = *(it.second);
     290             : 
     291       87719 :       if (ivariable.isFV())
     292           0 :         continue;
     293             : 
     294       87719 :       unsigned int ivar = ivariable.number();
     295       87719 :       unsigned int jvar = jvariable.number();
     296             : 
     297       87719 :       const auto & dgks = _dg_warehouse->getActiveBlockObjects(_subdomain, _tid);
     298      189576 :       for (const auto & dg : dgks)
     299             :       {
     300             :         // this check may skip some couplings...
     301      169698 :         if (dg->variable().number() == ivar && dg->isImplicit() &&
     302      236714 :             dg->hasBlocks(neighbor->subdomain_id()) &&
     303       67016 :             (jvariable.activeOnSubdomain(_subdomain) ||
     304        6048 :              jvariable.activeOnSubdomains(_fe_problem.mesh().interiorLowerDBlocks())))
     305             :         {
     306       64808 :           dg->prepareShapes(jvar);
     307       64808 :           dg->prepareNeighborShapes(jvar);
     308       64808 :           dg->computeOffDiagJacobian(jvar);
     309             :         }
     310             :       }
     311             :     }
     312             :   }
     313       44720 : }
     314             : 
     315             : void
     316      467787 : ComputeFullJacobianThread::computeOnInternalFace()
     317             : {
     318             :   mooseAssert(_hdg_warehouse->hasActiveBlockObjects(_subdomain, _tid),
     319             :               "We should not be called if we have no active HDG kernels");
     320     1000409 :   for (const auto & hdg_kernel : _hdg_warehouse->getActiveBlockObjects(_subdomain, _tid))
     321             :   {
     322             :     mooseAssert(
     323             :         hdg_kernel->hasBlocks(_subdomain),
     324             :         "We queried the warehouse for active blocks on this subdomain, so this better be active");
     325             :     mooseAssert(
     326             :         _neighbor_subdomain != Moose::INVALID_BLOCK_ID,
     327             :         "We should have set a valid neighbor subdomain ID if we made it in side this method");
     328      532622 :     if (hdg_kernel->hasBlocks(_neighbor_subdomain))
     329      532614 :       hdg_kernel->computeJacobianOnSide();
     330             :   }
     331      467787 : }

Generated by: LCOV version 1.14