LCOV - code coverage report
Current view: top level - src/loops - ComputeFullJacobianThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 161 167 96.4 %
Date: 2025-07-17 01:28:37 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       82895 : ComputeFullJacobianThread::ComputeFullJacobianThread(FEProblemBase & fe_problem,
      26       82895 :                                                      const std::set<TagID> & tags)
      27       82895 :   : ComputeJacobianThread(fe_problem, tags)
      28             : {
      29       82895 : }
      30             : 
      31             : // Splitting Constructor
      32        6359 : ComputeFullJacobianThread::ComputeFullJacobianThread(ComputeFullJacobianThread & x,
      33        6359 :                                                      Threads::split split)
      34        6359 :   : ComputeJacobianThread(x, split)
      35             : {
      36        6359 : }
      37             : 
      38       95496 : ComputeFullJacobianThread::~ComputeFullJacobianThread() {}
      39             : 
      40             : void
      41    15954634 : ComputeFullJacobianThread::computeOnElement()
      42             : {
      43    15954634 :   auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
      44    52266475 :   for (const auto & it : ce)
      45             :   {
      46    36311841 :     MooseVariableFieldBase & ivariable = *(it.first);
      47    36311841 :     MooseVariableFieldBase & jvariable = *(it.second);
      48             : 
      49    36311841 :     if (ivariable.isFV())
      50     6437403 :       continue;
      51             : 
      52    29874438 :     unsigned int ivar = ivariable.number();
      53    29874438 :     unsigned int jvar = jvariable.number();
      54             : 
      55    58191116 :     if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
      56    28316678 :         _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    26067159 :       const auto & kernels = _tag_kernels->getActiveVariableBlockObjects(ivar, _subdomain, _tid);
      61    78686525 :       for (const auto & kernel : kernels)
      62    52619366 :         if ((kernel->variable().number() == ivar) && kernel->isImplicit())
      63             :         {
      64    52572108 :           kernel->prepareShapes(jvar);
      65    52572108 :           kernel->computeOffDiagJacobian(jvar);
      66             :         }
      67             :     }
      68             :   }
      69             : 
      70             :   /// done only when nonlocal kernels exist in the system
      71    15954634 :   if (_fe_problem.checkNonlocalCouplingRequirement())
      72             :   {
      73        4452 :     auto & cne = _fe_problem.nonlocalCouplingEntries(_tid, _nl.number());
      74        9016 :     for (const auto & it : cne)
      75             :     {
      76        4564 :       MooseVariableFieldBase & ivariable = *(it.first);
      77        4564 :       MooseVariableFieldBase & jvariable = *(it.second);
      78             : 
      79        4564 :       if (ivariable.isFV())
      80           0 :         continue;
      81             : 
      82        4564 :       unsigned int ivar = ivariable.number();
      83        4564 :       unsigned int jvar = jvariable.number();
      84             : 
      85        9128 :       if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
      86        4564 :           _tag_kernels->hasActiveVariableBlockObjects(ivar, _subdomain, _tid))
      87             :       {
      88        4536 :         const auto & kernels = _tag_kernels->getActiveVariableBlockObjects(ivar, _subdomain, _tid);
      89        9688 :         for (const auto & kernel : kernels)
      90             :         {
      91             :           std::shared_ptr<NonlocalKernel> nonlocal_kernel =
      92        5152 :               std::dynamic_pointer_cast<NonlocalKernel>(kernel);
      93        5152 :           if (nonlocal_kernel)
      94         336 :             if ((kernel->variable().number() == ivar) && kernel->isImplicit())
      95             :             {
      96         336 :               kernel->prepareShapes(jvar);
      97         336 :               kernel->computeNonlocalOffDiagJacobian(jvar);
      98             :             }
      99        5152 :         }
     100             :       }
     101             :     }
     102             :   }
     103             : 
     104    15954634 :   const std::vector<MooseVariableScalar *> & scalar_vars = _nl.getScalarVariables(_tid);
     105    15954634 :   if (scalar_vars.size() > 0)
     106             :   {
     107             :     // go over nl-variables (non-scalar)
     108      141204 :     const std::vector<MooseVariableFieldBase *> & vars = _nl.getVariables(_tid);
     109      379733 :     for (const auto & ivariable : vars)
     110      470062 :       if (ivariable->activeOnSubdomain(_subdomain) > 0 &&
     111      231533 :           _tag_kernels->hasActiveVariableBlockObjects(ivariable->number(), _subdomain, _tid))
     112             :       {
     113             :         // for each variable get the list of active kernels
     114             :         const auto & kernels =
     115      225299 :             _tag_kernels->getActiveVariableBlockObjects(ivariable->number(), _subdomain, _tid);
     116      759092 :         for (const auto & kernel : kernels)
     117      533793 :           if (kernel->isImplicit())
     118             :           {
     119             :             // now, get the list of coupled scalar vars and compute their off-diag jacobians
     120      533793 :             const auto & coupled_scalar_vars = kernel->getCoupledMooseScalarVars();
     121             : 
     122             :             // Do: dvar / dscalar_var, only want to process only nl-variables (not aux ones)
     123      623971 :             for (const auto & jvariable : coupled_scalar_vars)
     124       90178 :               if (_nl.hasScalarVariable(jvariable->name()))
     125       90178 :                 kernel->computeOffDiagJacobianScalar(jvariable->number());
     126             :           }
     127             :       }
     128             :   }
     129             : 
     130    15954634 :   if (_fe_problem.haveFV())
     131     8471954 :     for (auto fv_kernel : _fv_kernels)
     132     4667078 :       if (fv_kernel->isImplicit())
     133     4667078 :         fv_kernel->computeOffDiagJacobian();
     134    15954634 : }
     135             : 
     136             : void
     137      197635 : ComputeFullJacobianThread::computeOnBoundary(BoundaryID bnd_id, const Elem * lower_d_elem)
     138             : {
     139      197635 :   auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     140      882511 :   for (const auto & it : ce)
     141             :   {
     142      684876 :     MooseVariableFieldBase & ivariable = *(it.first);
     143      684876 :     MooseVariableFieldBase & jvariable = *(it.second);
     144             : 
     145             :     // We don't currently support coupling with FV variables
     146      684876 :     if (ivariable.isFV() || jvariable.isFV())
     147         864 :       continue;
     148             : 
     149      684012 :     const auto ivar = ivariable.number();
     150      684012 :     const auto jvar = jvariable.number();
     151             : 
     152      684012 :     if (!ivariable.activeOnSubdomain(_subdomain))
     153       77190 :       continue;
     154             : 
     155             :     // only if there are dofs for j-variable (if it is subdomain restricted var, there may not be
     156             :     // any)
     157      606822 :     if (lower_d_elem)
     158             :     {
     159       11728 :       auto lower_d_subdomain = lower_d_elem->subdomain_id();
     160       19264 :       if (!jvariable.activeOnSubdomain(_subdomain) &&
     161        7536 :           !jvariable.activeOnSubdomain(lower_d_subdomain))
     162        3552 :         continue;
     163             :     }
     164             :     else
     165             :     {
     166      595094 :       if (!jvariable.activeOnSubdomain(_subdomain))
     167       25731 :         continue;
     168             :     }
     169             : 
     170      577539 :     if (!_ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     171           0 :       continue;
     172             : 
     173      577539 :     const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     174     1229767 :     for (const auto & bc : bcs)
     175      652228 :       if (bc->shouldApply() && bc->variable().number() == ivar && bc->isImplicit())
     176             :       {
     177      347758 :         bc->prepareShapes(jvar);
     178      347758 :         bc->computeOffDiagJacobian(jvar);
     179             :       }
     180             :   }
     181             : 
     182             :   /// done only when nonlocal integrated_bcs exist in the system
     183      197635 :   if (_fe_problem.checkNonlocalCouplingRequirement())
     184             :   {
     185         434 :     auto & cne = _fe_problem.nonlocalCouplingEntries(_tid, _nl.number());
     186         868 :     for (const auto & it : cne)
     187             :     {
     188         434 :       MooseVariableFieldBase & ivariable = *(it.first);
     189         434 :       MooseVariableFieldBase & jvariable = *(it.second);
     190             : 
     191         434 :       if (ivariable.isFV())
     192           0 :         continue;
     193             : 
     194         434 :       unsigned int ivar = ivariable.number();
     195         434 :       unsigned int jvar = jvariable.number();
     196             : 
     197         868 :       if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
     198         434 :           _ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     199             :       {
     200             :         const std::vector<std::shared_ptr<IntegratedBCBase>> & integrated_bcs =
     201         434 :             _ibc_warehouse->getBoundaryObjects(bnd_id, _tid);
     202         868 :         for (const auto & integrated_bc : integrated_bcs)
     203             :         {
     204             :           std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
     205         434 :               std::dynamic_pointer_cast<NonlocalIntegratedBC>(integrated_bc);
     206         434 :           if (nonlocal_integrated_bc)
     207         434 :             if ((integrated_bc->variable().number() == ivar) && integrated_bc->isImplicit())
     208             :             {
     209         434 :               integrated_bc->prepareShapes(jvar);
     210         434 :               integrated_bc->computeNonlocalOffDiagJacobian(jvar);
     211             :             }
     212         434 :         }
     213             :       }
     214             :     }
     215             :   }
     216             : 
     217      197635 :   const std::vector<MooseVariableScalar *> & scalar_vars = _nl.getScalarVariables(_tid);
     218      197635 :   if (scalar_vars.size() > 0)
     219             :   {
     220             :     // go over nl-variables (non-scalar)
     221       19320 :     const std::vector<MooseVariableFieldBase *> & vars = _nl.getVariables(_tid);
     222       57456 :     for (const auto & ivar : vars)
     223       76272 :       if (ivar->activeOnSubdomain(_subdomain) > 0 &&
     224       38136 :           _ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     225             :       {
     226             :         // for each variable get the list of active kernels
     227       38136 :         const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     228       76272 :         for (const auto & bc : bcs)
     229       38136 :           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       19320 :                 bc->getCoupledMooseScalarVars();
     234             : 
     235             :             // Do: dvar / dscalar_var, only want to process only nl-variables (not aux ones)
     236       19384 :             for (const auto & jvar : coupled_scalar_vars)
     237          64 :               if (_nl.hasScalarVariable(jvar->name()))
     238          64 :                 bc->computeOffDiagJacobianScalar(jvar->number());
     239       19320 :           }
     240             :       }
     241             :   }
     242      197635 : }
     243             : 
     244             : void
     245        6646 : ComputeFullJacobianThread::computeOnInterface(BoundaryID bnd_id)
     246             : {
     247        6646 :   if (_ik_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     248             :   {
     249        6646 :     const auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     250       33434 :     for (const auto & it : ce)
     251             :     {
     252       26788 :       MooseVariableFieldBase & ivariable = *(it.first);
     253       26788 :       MooseVariableFieldBase & jvariable = *(it.second);
     254             : 
     255       26788 :       if (ivariable.isFV())
     256           0 :         continue;
     257             : 
     258       26788 :       unsigned int ivar = ivariable.number();
     259       26788 :       unsigned int jvar = jvariable.number();
     260             : 
     261       26788 :       const auto & int_ks = _ik_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     262       54396 :       for (const auto & interface_kernel : int_ks)
     263             :       {
     264       27608 :         if (!interface_kernel->isImplicit())
     265           0 :           continue;
     266             : 
     267       27608 :         interface_kernel->prepareShapes(jvar);
     268       27608 :         interface_kernel->prepareNeighborShapes(jvar);
     269             : 
     270       27608 :         if (interface_kernel->variable().number() == ivar)
     271       13740 :           interface_kernel->computeElementOffDiagJacobian(jvar);
     272             : 
     273       27608 :         if (interface_kernel->neighborVariable().number() == ivar)
     274       13740 :           interface_kernel->computeNeighborOffDiagJacobian(jvar);
     275             :       }
     276             :     }
     277             :   }
     278        6646 : }
     279             : 
     280             : void
     281       41110 : ComputeFullJacobianThread::computeOnInternalFace(const Elem * neighbor)
     282             : {
     283       41110 :   if (_dg_warehouse->hasActiveBlockObjects(_subdomain, _tid))
     284             :   {
     285       41110 :     const auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     286      124235 :     for (const auto & it : ce)
     287             :     {
     288       83125 :       MooseVariableFieldBase & ivariable = *(it.first);
     289       83125 :       MooseVariableFieldBase & jvariable = *(it.second);
     290             : 
     291       83125 :       if (ivariable.isFV())
     292           0 :         continue;
     293             : 
     294       83125 :       unsigned int ivar = ivariable.number();
     295       83125 :       unsigned int jvar = jvariable.number();
     296             : 
     297       83125 :       const auto & dgks = _dg_warehouse->getActiveBlockObjects(_subdomain, _tid);
     298      176357 :       for (const auto & dg : dgks)
     299             :       {
     300             :         // this check may skip some couplings...
     301      153080 :         if (dg->variable().number() == ivar && dg->isImplicit() &&
     302      212004 :             dg->hasBlocks(neighbor->subdomain_id()) &&
     303       58924 :             (jvariable.activeOnSubdomain(_subdomain) ||
     304        6060 :              jvariable.activeOnSubdomains(_fe_problem.mesh().interiorLowerDBlocks())))
     305             :         {
     306       56716 :           dg->prepareShapes(jvar);
     307       56716 :           dg->prepareNeighborShapes(jvar);
     308       56716 :           dg->computeOffDiagJacobian(jvar);
     309             :         }
     310             :       }
     311             :     }
     312             :   }
     313       41110 : }
     314             : 
     315             : void
     316     1501152 : ComputeFullJacobianThread::computeOnInternalFace()
     317             : {
     318             :   mooseAssert(_hdg_warehouse->hasActiveBlockObjects(_subdomain, _tid),
     319             :               "We should not be called if we have no active HDG kernels");
     320     3617016 :   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     2115864 :     if (hdg_kernel->hasBlocks(_neighbor_subdomain))
     329     2115856 :       hdg_kernel->computeJacobianOnSide();
     330             :   }
     331     1501152 : }

Generated by: LCOV version 1.14