LCOV - code coverage report
Current view: top level - src/loops - ComputeLinearFVGreenGaussGradientFaceThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 67 79 84.8 %
Date: 2025-08-08 20:01:16 Functions: 2 4 50.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 "ComputeLinearFVGreenGaussGradientFaceThread.h"
      11             : #include "LinearSystem.h"
      12             : #include "LinearFVBoundaryCondition.h"
      13             : #include "PetscVectorReader.h"
      14             : #include "FEProblemBase.h"
      15             : 
      16       10678 : ComputeLinearFVGreenGaussGradientFaceThread::ComputeLinearFVGreenGaussGradientFaceThread(
      17       10678 :     FEProblemBase & fe_problem, const unsigned int linear_system_num)
      18       10678 :   : _fe_problem(fe_problem),
      19       10678 :     _dim(_fe_problem.mesh().dimension()),
      20       10678 :     _linear_system_number(linear_system_num),
      21       10678 :     _linear_system(libMesh::cast_ref<libMesh::LinearImplicitSystem &>(
      22       10678 :         _fe_problem.getLinearSystem(_linear_system_number).system())),
      23       10678 :     _system_number(_linear_system.number()),
      24       10678 :     _new_gradient(_fe_problem.getLinearSystem(_linear_system_number).newGradientContainer())
      25             : {
      26       10678 : }
      27             : 
      28           0 : ComputeLinearFVGreenGaussGradientFaceThread::ComputeLinearFVGreenGaussGradientFaceThread(
      29           0 :     ComputeLinearFVGreenGaussGradientFaceThread & x, Threads::split /*split*/)
      30           0 :   : _fe_problem(x._fe_problem),
      31           0 :     _dim(x._dim),
      32           0 :     _linear_system_number(x._linear_system_number),
      33           0 :     _linear_system(x._linear_system),
      34           0 :     _system_number(x._system_number),
      35             :     // This will be the vector we work on since the old gradient might still be needed
      36             :     // to compute extrapolated boundary conditions for example.
      37           0 :     _new_gradient(x._new_gradient)
      38             : {
      39           0 : }
      40             : 
      41             : void
      42       10678 : ComputeLinearFVGreenGaussGradientFaceThread::operator()(const FaceInfoRange & range)
      43             : {
      44       10678 :   ParallelUniqueId puid;
      45       10678 :   _tid = puid.id;
      46             : 
      47       10678 :   unsigned int size = 0;
      48             : 
      49       10678 :   for (const auto & variable :
      50       32034 :        _fe_problem.getLinearSystem(_linear_system_number).getVariables(_tid))
      51             :   {
      52       10678 :     _current_var = dynamic_cast<MooseLinearVariableFV<Real> *>(variable);
      53             :     mooseAssert(_current_var,
      54             :                 "This should be a linear FV variable, did we somehow add a nonlinear variable to "
      55             :                 "the linear system?");
      56       10678 :     if (_current_var->needsGradientVectorStorage())
      57             :     {
      58        9320 :       if (!size)
      59        9320 :         size = range.size();
      60             : 
      61        9320 :       std::vector<std::vector<Real>> new_values_elem(_new_gradient.size(),
      62        9320 :                                                      std::vector<Real>(size, 0.0));
      63        9320 :       std::vector<std::vector<Real>> new_values_neighbor(_new_gradient.size(),
      64        9320 :                                                          std::vector<Real>(size, 0.0));
      65        9320 :       std::vector<dof_id_type> dof_indices_elem(size, 0);
      66        9320 :       std::vector<dof_id_type> dof_indices_neighbor(size, 0);
      67             : 
      68             :       {
      69        9320 :         PetscVectorReader solution_reader(*_linear_system.current_local_solution);
      70             : 
      71             :         // Iterate over all the face infos in the range
      72        9320 :         auto face_iterator = range.begin();
      73     4700710 :         for (const auto & face_i : make_range(size))
      74             :         {
      75     4691390 :           const auto & face_info = *face_iterator;
      76             : 
      77             :           const auto current_face_type =
      78     4691390 :               face_info->faceType(std::make_pair(_current_var->number(), _system_number));
      79             : 
      80             :           // First we check if this face is internal to the variable, if yes, contribute to both
      81             :           // sides
      82     4691390 :           if (current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
      83             :           {
      84     4349474 :             dof_indices_elem[face_i] =
      85     4349474 :                 face_info->elemInfo()->dofIndices()[_system_number][_current_var->number()];
      86     4349474 :             dof_indices_neighbor[face_i] =
      87     4349474 :                 face_info->neighborInfo()->dofIndices()[_system_number][_current_var->number()];
      88             : 
      89             :             const auto face_value =
      90     4349474 :                 Moose::FV::linearInterpolation(solution_reader(dof_indices_elem[face_i]),
      91     4349474 :                                                solution_reader(dof_indices_neighbor[face_i]),
      92             :                                                *face_info,
      93     4349474 :                                                true);
      94             : 
      95             :             const auto contribution =
      96     4349474 :                 face_info->normal() * face_info->faceArea() * face_info->faceCoord() * face_value;
      97             : 
      98    13007268 :             for (const auto i : make_range(_dim))
      99             :             {
     100     8657794 :               new_values_elem[i][face_i] = contribution(i);
     101     8657794 :               new_values_neighbor[i][face_i] = -contribution(i);
     102             :             }
     103             :           }
     104             :           // If this face is on the boundary of the block where the variable is defined, we
     105             :           // check for boundary conditions. If we don't find any we use an automatic one-term
     106             :           // expansion to compute the face value.
     107      341916 :           else if (current_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
     108             :                    current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR)
     109             :           {
     110             :             auto * bc_pointer =
     111      341916 :                 _current_var->getBoundaryCondition(*face_info->boundaryIDs().begin());
     112             : 
     113      341916 :             if (bc_pointer)
     114      326956 :               bc_pointer->setupFaceData(face_info, current_face_type);
     115             : 
     116             :             const auto * const elem_info = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
     117      341916 :                                                ? face_info->elemInfo()
     118           0 :                                                : face_info->neighborInfo();
     119             : 
     120             :             // We have to account for cases when this face is an internal boundary and the normal
     121             :             // points in the wrong direction
     122      341916 :             const auto multiplier =
     123      341916 :                 current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0;
     124      341916 :             auto & dof_id_container = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
     125             :                                           ? dof_indices_elem
     126             :                                           : dof_indices_neighbor;
     127      341916 :             auto & contribution_container = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
     128             :                                                 ? new_values_elem
     129             :                                                 : new_values_neighbor;
     130             : 
     131      341916 :             dof_id_container[face_i] =
     132      341916 :                 elem_info->dofIndices()[_system_number][_current_var->number()];
     133             : 
     134             :             // If we don't have a boundary condition, then it's a natural condition. We'll use a
     135             :             // one-term expansion approximation in that case
     136      341916 :             const auto contribution = multiplier * face_info->normal() * face_info->faceArea() *
     137      683832 :                                       face_info->faceCoord() *
     138      356876 :                                       (bc_pointer ? bc_pointer->computeBoundaryValue()
     139      356876 :                                                   : solution_reader(dof_id_container[face_i]));
     140     1020984 :             for (const auto i : make_range(_dim))
     141      679068 :               contribution_container[i][face_i] = contribution(i);
     142             :           }
     143     4691390 :           face_iterator++;
     144             :         }
     145        9320 :       }
     146       25430 :       for (const auto i : make_range(_dim))
     147             :       {
     148       16110 :         _new_gradient[i]->add_vector(new_values_elem[i].data(), dof_indices_elem);
     149       16110 :         _new_gradient[i]->add_vector(new_values_neighbor[i].data(), dof_indices_neighbor);
     150             :       }
     151        9320 :     }
     152             :   }
     153       10678 : }
     154             : 
     155             : void
     156           0 : ComputeLinearFVGreenGaussGradientFaceThread::join(
     157             :     const ComputeLinearFVGreenGaussGradientFaceThread & /*y*/)
     158             : {
     159           0 : }

Generated by: LCOV version 1.14