LCOV - code coverage report
Current view: top level - src/loops - ComputeFullJacobianThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 161 167 96.4 %
Date: 2025-08-08 20:01:16 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       89114 : ComputeFullJacobianThread::ComputeFullJacobianThread(FEProblemBase & fe_problem,
      26       89114 :                                                      const std::set<TagID> & tags)
      27       89114 :   : ComputeJacobianThread(fe_problem, tags)
      28             : {
      29       89114 : }
      30             : 
      31             : // Splitting Constructor
      32        6288 : ComputeFullJacobianThread::ComputeFullJacobianThread(ComputeFullJacobianThread & x,
      33        6288 :                                                      Threads::split split)
      34        6288 :   : ComputeJacobianThread(x, split)
      35             : {
      36        6288 : }
      37             : 
      38      101574 : ComputeFullJacobianThread::~ComputeFullJacobianThread() {}
      39             : 
      40             : void
      41    17721464 : ComputeFullJacobianThread::computeOnElement()
      42             : {
      43    17721464 :   auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
      44    57454006 :   for (const auto & it : ce)
      45             :   {
      46    39732542 :     MooseVariableFieldBase & ivariable = *(it.first);
      47    39732542 :     MooseVariableFieldBase & jvariable = *(it.second);
      48             : 
      49    39732542 :     if (ivariable.isFV())
      50     6755163 :       continue;
      51             : 
      52    32977379 :     unsigned int ivar = ivariable.number();
      53    32977379 :     unsigned int jvar = jvariable.number();
      54             : 
      55    64279297 :     if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
      56    31301918 :         _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    28984982 :       const auto & kernels = _tag_kernels->getActiveVariableBlockObjects(ivar, _subdomain, _tid);
      61    87628580 :       for (const auto & kernel : kernels)
      62    58643598 :         if ((kernel->variable().number() == ivar) && kernel->isImplicit())
      63             :         {
      64    58594318 :           kernel->prepareShapes(jvar);
      65    58594318 :           kernel->computeOffDiagJacobian(jvar);
      66             :         }
      67             :     }
      68             :   }
      69             : 
      70             :   /// done only when nonlocal kernels exist in the system
      71    17721464 :   if (_fe_problem.checkNonlocalCouplingRequirement())
      72             :   {
      73        5064 :     auto & cne = _fe_problem.nonlocalCouplingEntries(_tid, _nl.number());
      74       10252 :     for (const auto & it : cne)
      75             :     {
      76        5188 :       MooseVariableFieldBase & ivariable = *(it.first);
      77        5188 :       MooseVariableFieldBase & jvariable = *(it.second);
      78             : 
      79        5188 :       if (ivariable.isFV())
      80           0 :         continue;
      81             : 
      82        5188 :       unsigned int ivar = ivariable.number();
      83        5188 :       unsigned int jvar = jvariable.number();
      84             : 
      85       10376 :       if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
      86        5188 :           _tag_kernels->hasActiveVariableBlockObjects(ivar, _subdomain, _tid))
      87             :       {
      88        5160 :         const auto & kernels = _tag_kernels->getActiveVariableBlockObjects(ivar, _subdomain, _tid);
      89       10984 :         for (const auto & kernel : kernels)
      90             :         {
      91             :           std::shared_ptr<NonlocalKernel> nonlocal_kernel =
      92        5824 :               std::dynamic_pointer_cast<NonlocalKernel>(kernel);
      93        5824 :           if (nonlocal_kernel)
      94         360 :             if ((kernel->variable().number() == ivar) && kernel->isImplicit())
      95             :             {
      96         360 :               kernel->prepareShapes(jvar);
      97         360 :               kernel->computeNonlocalOffDiagJacobian(jvar);
      98             :             }
      99        5824 :         }
     100             :       }
     101             :     }
     102             :   }
     103             : 
     104    17721464 :   const std::vector<MooseVariableScalar *> & scalar_vars = _nl.getScalarVariables(_tid);
     105    17721464 :   if (scalar_vars.size() > 0)
     106             :   {
     107             :     // go over nl-variables (non-scalar)
     108      159204 :     const std::vector<MooseVariableFieldBase *> & vars = _nl.getVariables(_tid);
     109      427665 :     for (const auto & ivariable : vars)
     110      529258 :       if (ivariable->activeOnSubdomain(_subdomain) > 0 &&
     111      260797 :           _tag_kernels->hasActiveVariableBlockObjects(ivariable->number(), _subdomain, _tid))
     112             :       {
     113             :         // for each variable get the list of active kernels
     114             :         const auto & kernels =
     115      253861 :             _tag_kernels->getActiveVariableBlockObjects(ivariable->number(), _subdomain, _tid);
     116      855228 :         for (const auto & kernel : kernels)
     117      601367 :           if (kernel->isImplicit())
     118             :           {
     119             :             // now, get the list of coupled scalar vars and compute their off-diag jacobians
     120      601367 :             const auto & coupled_scalar_vars = kernel->getCoupledMooseScalarVars();
     121             : 
     122             :             // Do: dvar / dscalar_var, only want to process only nl-variables (not aux ones)
     123      702805 :             for (const auto & jvariable : coupled_scalar_vars)
     124      101438 :               if (_nl.hasScalarVariable(jvariable->name()))
     125      101438 :                 kernel->computeOffDiagJacobianScalar(jvariable->number());
     126             :           }
     127             :       }
     128             :   }
     129             : 
     130    17721464 :   if (_fe_problem.haveFV())
     131     9008699 :     for (auto fv_kernel : _fv_kernels)
     132     4918731 :       if (fv_kernel->isImplicit())
     133     4918731 :         fv_kernel->computeOffDiagJacobian();
     134    17721464 : }
     135             : 
     136             : void
     137      216599 : ComputeFullJacobianThread::computeOnBoundary(BoundaryID bnd_id, const Elem * lower_d_elem)
     138             : {
     139      216599 :   auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     140      953897 :   for (const auto & it : ce)
     141             :   {
     142      737298 :     MooseVariableFieldBase & ivariable = *(it.first);
     143      737298 :     MooseVariableFieldBase & jvariable = *(it.second);
     144             : 
     145             :     // We don't currently support coupling with FV variables
     146      737298 :     if (ivariable.isFV() || jvariable.isFV())
     147        1107 :       continue;
     148             : 
     149      736191 :     const auto ivar = ivariable.number();
     150      736191 :     const auto jvar = jvariable.number();
     151             : 
     152      736191 :     if (!ivariable.activeOnSubdomain(_subdomain))
     153       86076 :       continue;
     154             : 
     155             :     // only if there are dofs for j-variable (if it is subdomain restricted var, there may not be
     156             :     // any)
     157      650115 :     if (lower_d_elem)
     158             :     {
     159       13200 :       auto lower_d_subdomain = lower_d_elem->subdomain_id();
     160       21666 :       if (!jvariable.activeOnSubdomain(_subdomain) &&
     161        8466 :           !jvariable.activeOnSubdomain(lower_d_subdomain))
     162        3974 :         continue;
     163             :     }
     164             :     else
     165             :     {
     166      636915 :       if (!jvariable.activeOnSubdomain(_subdomain))
     167       28638 :         continue;
     168             :     }
     169             : 
     170      617503 :     if (!_ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     171           0 :       continue;
     172             : 
     173      617503 :     const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     174     1310871 :     for (const auto & bc : bcs)
     175      693368 :       if (bc->shouldApply() && bc->variable().number() == ivar && bc->isImplicit())
     176             :       {
     177      374440 :         bc->prepareShapes(jvar);
     178      374440 :         bc->computeOffDiagJacobian(jvar);
     179             :       }
     180             :   }
     181             : 
     182             :   /// done only when nonlocal integrated_bcs exist in the system
     183      216599 :   if (_fe_problem.checkNonlocalCouplingRequirement())
     184             :   {
     185         494 :     auto & cne = _fe_problem.nonlocalCouplingEntries(_tid, _nl.number());
     186         988 :     for (const auto & it : cne)
     187             :     {
     188         494 :       MooseVariableFieldBase & ivariable = *(it.first);
     189         494 :       MooseVariableFieldBase & jvariable = *(it.second);
     190             : 
     191         494 :       if (ivariable.isFV())
     192           0 :         continue;
     193             : 
     194         494 :       unsigned int ivar = ivariable.number();
     195         494 :       unsigned int jvar = jvariable.number();
     196             : 
     197         988 :       if (ivariable.activeOnSubdomain(_subdomain) && jvariable.activeOnSubdomain(_subdomain) &&
     198         494 :           _ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     199             :       {
     200             :         const std::vector<std::shared_ptr<IntegratedBCBase>> & integrated_bcs =
     201         494 :             _ibc_warehouse->getBoundaryObjects(bnd_id, _tid);
     202         988 :         for (const auto & integrated_bc : integrated_bcs)
     203             :         {
     204             :           std::shared_ptr<NonlocalIntegratedBC> nonlocal_integrated_bc =
     205         494 :               std::dynamic_pointer_cast<NonlocalIntegratedBC>(integrated_bc);
     206         494 :           if (nonlocal_integrated_bc)
     207         494 :             if ((integrated_bc->variable().number() == ivar) && integrated_bc->isImplicit())
     208             :             {
     209         494 :               integrated_bc->prepareShapes(jvar);
     210         494 :               integrated_bc->computeNonlocalOffDiagJacobian(jvar);
     211             :             }
     212         494 :         }
     213             :       }
     214             :     }
     215             :   }
     216             : 
     217      216599 :   const std::vector<MooseVariableScalar *> & scalar_vars = _nl.getScalarVariables(_tid);
     218      216599 :   if (scalar_vars.size() > 0)
     219             :   {
     220             :     // go over nl-variables (non-scalar)
     221       21728 :     const std::vector<MooseVariableFieldBase *> & vars = _nl.getVariables(_tid);
     222       64624 :     for (const auto & ivar : vars)
     223       85792 :       if (ivar->activeOnSubdomain(_subdomain) > 0 &&
     224       42896 :           _ibc_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     225             :       {
     226             :         // for each variable get the list of active kernels
     227       42896 :         const auto & bcs = _ibc_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     228       85792 :         for (const auto & bc : bcs)
     229       42896 :           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       21728 :                 bc->getCoupledMooseScalarVars();
     234             : 
     235             :             // Do: dvar / dscalar_var, only want to process only nl-variables (not aux ones)
     236       21800 :             for (const auto & jvar : coupled_scalar_vars)
     237          72 :               if (_nl.hasScalarVariable(jvar->name()))
     238          72 :                 bc->computeOffDiagJacobianScalar(jvar->number());
     239       21728 :           }
     240             :       }
     241             :   }
     242      216599 : }
     243             : 
     244             : void
     245        7476 : ComputeFullJacobianThread::computeOnInterface(BoundaryID bnd_id)
     246             : {
     247        7476 :   if (_ik_warehouse->hasActiveBoundaryObjects(bnd_id, _tid))
     248             :   {
     249        7476 :     const auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     250       37599 :     for (const auto & it : ce)
     251             :     {
     252       30123 :       MooseVariableFieldBase & ivariable = *(it.first);
     253       30123 :       MooseVariableFieldBase & jvariable = *(it.second);
     254             : 
     255       30123 :       if (ivariable.isFV())
     256           0 :         continue;
     257             : 
     258       30123 :       unsigned int ivar = ivariable.number();
     259       30123 :       unsigned int jvar = jvariable.number();
     260             : 
     261       30123 :       const auto & int_ks = _ik_warehouse->getActiveBoundaryObjects(bnd_id, _tid);
     262       61166 :       for (const auto & interface_kernel : int_ks)
     263             :       {
     264       31043 :         if (!interface_kernel->isImplicit())
     265           0 :           continue;
     266             : 
     267       31043 :         interface_kernel->prepareShapes(jvar);
     268       31043 :         interface_kernel->prepareNeighborShapes(jvar);
     269             : 
     270       31043 :         if (interface_kernel->variable().number() == ivar)
     271       15453 :           interface_kernel->computeElementOffDiagJacobian(jvar);
     272             : 
     273       31043 :         if (interface_kernel->neighborVariable().number() == ivar)
     274       15453 :           interface_kernel->computeNeighborOffDiagJacobian(jvar);
     275             :       }
     276             :     }
     277             :   }
     278        7476 : }
     279             : 
     280             : void
     281       45956 : ComputeFullJacobianThread::computeOnInternalFace(const Elem * neighbor)
     282             : {
     283       45956 :   if (_dg_warehouse->hasActiveBlockObjects(_subdomain, _tid))
     284             :   {
     285       45956 :     const auto & ce = _fe_problem.couplingEntries(_tid, _nl.number());
     286      140209 :     for (const auto & it : ce)
     287             :     {
     288       94253 :       MooseVariableFieldBase & ivariable = *(it.first);
     289       94253 :       MooseVariableFieldBase & jvariable = *(it.second);
     290             : 
     291       94253 :       if (ivariable.isFV())
     292           0 :         continue;
     293             : 
     294       94253 :       unsigned int ivar = ivariable.number();
     295       94253 :       unsigned int jvar = jvariable.number();
     296             : 
     297       94253 :       const auto & dgks = _dg_warehouse->getActiveBlockObjects(_subdomain, _tid);
     298      199820 :       for (const auto & dg : dgks)
     299             :       {
     300             :         // this check may skip some couplings...
     301      172918 :         if (dg->variable().number() == ivar && dg->isImplicit() &&
     302      239341 :             dg->hasBlocks(neighbor->subdomain_id()) &&
     303       66423 :             (jvariable.activeOnSubdomain(_subdomain) ||
     304        6818 :              jvariable.activeOnSubdomains(_fe_problem.mesh().interiorLowerDBlocks())))
     305             :         {
     306       63939 :           dg->prepareShapes(jvar);
     307       63939 :           dg->prepareNeighborShapes(jvar);
     308       63939 :           dg->computeOffDiagJacobian(jvar);
     309             :         }
     310             :       }
     311             :     }
     312             :   }
     313       45956 : }
     314             : 
     315             : void
     316     1508335 : ComputeFullJacobianThread::computeOnInternalFace()
     317             : {
     318             :   mooseAssert(_hdg_warehouse->hasActiveBlockObjects(_subdomain, _tid),
     319             :               "We should not be called if we have no active HDG kernels");
     320     3631382 :   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     2123047 :     if (hdg_kernel->hasBlocks(_neighbor_subdomain))
     329     2123038 :       hdg_kernel->computeJacobianOnSide();
     330             :   }
     331     1508335 : }

Generated by: LCOV version 1.14