LCOV - code coverage report
Current view: top level - src/loops - ComputeLinearFVGreenGaussGradientFaceThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 67 79 84.8 %
Date: 2025-07-17 01:28:37 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        9865 : ComputeLinearFVGreenGaussGradientFaceThread::ComputeLinearFVGreenGaussGradientFaceThread(
      17        9865 :     FEProblemBase & fe_problem, const unsigned int linear_system_num)
      18        9865 :   : _fe_problem(fe_problem),
      19        9865 :     _dim(_fe_problem.mesh().dimension()),
      20        9865 :     _linear_system_number(linear_system_num),
      21        9865 :     _linear_system(libMesh::cast_ref<libMesh::LinearImplicitSystem &>(
      22        9865 :         _fe_problem.getLinearSystem(_linear_system_number).system())),
      23        9865 :     _system_number(_linear_system.number()),
      24        9865 :     _new_gradient(_fe_problem.getLinearSystem(_linear_system_number).newGradientContainer())
      25             : {
      26        9865 : }
      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        9865 : ComputeLinearFVGreenGaussGradientFaceThread::operator()(const FaceInfoRange & range)
      43             : {
      44        9865 :   ParallelUniqueId puid;
      45        9865 :   _tid = puid.id;
      46             : 
      47        9865 :   unsigned int size = 0;
      48             : 
      49        9865 :   for (const auto & variable :
      50       29595 :        _fe_problem.getLinearSystem(_linear_system_number).getVariables(_tid))
      51             :   {
      52        9865 :     _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        9865 :     if (_current_var->needsGradientVectorStorage())
      57             :     {
      58        8038 :       if (!size)
      59        8038 :         size = range.size();
      60             : 
      61        8038 :       std::vector<std::vector<Real>> new_values_elem(_new_gradient.size(),
      62        8038 :                                                      std::vector<Real>(size, 0.0));
      63        8038 :       std::vector<std::vector<Real>> new_values_neighbor(_new_gradient.size(),
      64        8038 :                                                          std::vector<Real>(size, 0.0));
      65        8038 :       std::vector<dof_id_type> dof_indices_elem(size, 0);
      66        8038 :       std::vector<dof_id_type> dof_indices_neighbor(size, 0);
      67             : 
      68             :       {
      69        8038 :         PetscVectorReader solution_reader(*_linear_system.current_local_solution);
      70             : 
      71             :         // Iterate over all the face infos in the range
      72        8038 :         auto face_iterator = range.begin();
      73     4360482 :         for (const auto & face_i : make_range(size))
      74             :         {
      75     4352444 :           const auto & face_info = *face_iterator;
      76             : 
      77             :           const auto current_face_type =
      78     4352444 :               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     4352444 :           if (current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
      83             :           {
      84     4049620 :             dof_indices_elem[face_i] =
      85     4049620 :                 face_info->elemInfo()->dofIndices()[_system_number][_current_var->number()];
      86     4049620 :             dof_indices_neighbor[face_i] =
      87     4049620 :                 face_info->neighborInfo()->dofIndices()[_system_number][_current_var->number()];
      88             : 
      89             :             const auto face_value =
      90     4049620 :                 Moose::FV::linearInterpolation(solution_reader(dof_indices_elem[face_i]),
      91     4049620 :                                                solution_reader(dof_indices_neighbor[face_i]),
      92             :                                                *face_info,
      93     4049620 :                                                true);
      94             : 
      95             :             const auto contribution =
      96     4049620 :                 face_info->normal() * face_info->faceArea() * face_info->faceCoord() * face_value;
      97             : 
      98    12112136 :             for (const auto i : make_range(_dim))
      99             :             {
     100     8062516 :               new_values_elem[i][face_i] = contribution(i);
     101     8062516 :               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      302824 :           else if (current_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
     108             :                    current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR)
     109             :           {
     110             :             auto * bc_pointer =
     111      302824 :                 _current_var->getBoundaryCondition(*face_info->boundaryIDs().begin());
     112             : 
     113      302824 :             if (bc_pointer)
     114      289704 :               bc_pointer->setupFaceData(face_info, current_face_type);
     115             : 
     116             :             const auto * const elem_info = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
     117      302824 :                                                ? 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      302824 :             const auto multiplier =
     123      302824 :                 current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0;
     124      302824 :             auto & dof_id_container = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
     125             :                                           ? dof_indices_elem
     126             :                                           : dof_indices_neighbor;
     127      302824 :             auto & contribution_container = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
     128             :                                                 ? new_values_elem
     129             :                                                 : new_values_neighbor;
     130             : 
     131      302824 :             dof_id_container[face_i] =
     132      302824 :                 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      302824 :             const auto contribution = multiplier * face_info->normal() * face_info->faceArea() *
     137      605648 :                                       face_info->faceCoord() *
     138      315944 :                                       (bc_pointer ? bc_pointer->computeBoundaryValue()
     139      315944 :                                                   : solution_reader(dof_id_container[face_i]));
     140      904368 :             for (const auto i : make_range(_dim))
     141      601544 :               contribution_container[i][face_i] = contribution(i);
     142             :           }
     143     4352444 :           face_iterator++;
     144             :         }
     145        8038 :       }
     146       21914 :       for (const auto i : make_range(_dim))
     147             :       {
     148       13876 :         _new_gradient[i]->add_vector(new_values_elem[i].data(), dof_indices_elem);
     149       13876 :         _new_gradient[i]->add_vector(new_values_neighbor[i].data(), dof_indices_neighbor);
     150             :       }
     151        8038 :     }
     152             :   }
     153        9865 : }
     154             : 
     155             : void
     156           0 : ComputeLinearFVGreenGaussGradientFaceThread::join(
     157             :     const ComputeLinearFVGreenGaussGradientFaceThread & /*y*/)
     158             : {
     159           0 : }

Generated by: LCOV version 1.14