LCOV - code coverage report
Current view: top level - src/userobjects - INSFVRhieChowInterpolatorSegregated.C (source / functions) Hit Total Coverage
Test: idaholab/moose navier_stokes: 9fc4b0 Lines: 192 228 84.2 %
Date: 2025-08-14 10:14:56 Functions: 11 17 64.7 %
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 "INSFVRhieChowInterpolatorSegregated.h"
      11             : #include "INSFVAttributes.h"
      12             : #include "SubProblem.h"
      13             : #include "MooseMesh.h"
      14             : #include "NS.h"
      15             : #include "Assembly.h"
      16             : #include "INSFVVelocityVariable.h"
      17             : #include "INSFVPressureVariable.h"
      18             : #include "PiecewiseByBlockLambdaFunctor.h"
      19             : #include "VectorCompositeFunctor.h"
      20             : #include "SIMPLENonlinearAssembly.h"
      21             : 
      22             : #include "libmesh/mesh_base.h"
      23             : #include "libmesh/elem_range.h"
      24             : #include "metaphysicl/dualsemidynamicsparsenumberarray.h"
      25             : 
      26             : #include "NonlinearSystem.h"
      27             : #include "libmesh/petsc_matrix.h"
      28             : #include "libmesh/petsc_vector.h"
      29             : 
      30             : using namespace libMesh;
      31             : 
      32             : registerMooseObject("NavierStokesApp", INSFVRhieChowInterpolatorSegregated);
      33             : 
      34             : InputParameters
      35        1484 : INSFVRhieChowInterpolatorSegregated::validParams()
      36             : {
      37        1484 :   auto params = RhieChowInterpolatorBase::validParams();
      38             : 
      39        1484 :   params.addClassDescription("Computes H/A and 1/A together with face velocities for segregated "
      40             :                              "momentum-pressure equations.");
      41             : 
      42             :   // We disable the execution of this, should only provide functions
      43             :   // for the SIMPLENonlinearAssembly executioner
      44        1484 :   ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true);
      45        1484 :   exec_enum.addAvailableFlags(EXEC_NONE);
      46        4452 :   exec_enum = {EXEC_NONE};
      47        1484 :   params.suppressParameter<ExecFlagEnum>("execute_on");
      48             : 
      49        1484 :   return params;
      50        1484 : }
      51             : 
      52         742 : INSFVRhieChowInterpolatorSegregated::INSFVRhieChowInterpolatorSegregated(
      53         742 :     const InputParameters & params)
      54             :   : RhieChowInterpolatorBase(params),
      55        1484 :     _HbyA(_moose_mesh, blockIDs(), "HbyA"),
      56         742 :     _Ainv(_moose_mesh, blockIDs(), "Ainv", false),
      57         742 :     _vel(std::make_unique<PiecewiseByBlockLambdaFunctor<ADRealVectorValue>>(
      58             :         name(),
      59     1132014 :         [this](const auto & r, const auto & t) -> ADRealVectorValue
      60             :         {
      61     2262544 :           ADRealVectorValue velocity((*_u)(r, t));
      62     1131272 :           if (_dim >= 2)
      63     1131272 :             velocity(1) = (*_v)(r, t);
      64     1131272 :           if (_dim >= 3)
      65      439349 :             velocity(2) = (*_w)(r, t);
      66     1131272 :           return velocity;
      67             :         },
      68        2226 :         std::set<ExecFlagType>({EXEC_ALWAYS}),
      69             :         _moose_mesh,
      70             :         blockIDs())),
      71        2226 :     _face_velocity(_moose_mesh, blockIDs(), "face_values")
      72             : {
      73         742 :   if (_displaced)
      74           0 :     paramError("use_displaced_mesh",
      75             :                "The segregated Rhie-Chow user object does not currently support operation on a "
      76             :                "displaced mesh");
      77             : 
      78             :   // Register the elemental/face functors which will be queried in the pressure equation
      79        1599 :   for (const auto tid : make_range(libMesh::n_threads()))
      80             :   {
      81         857 :     UserObject::_subproblem.addFunctor("Ainv", _Ainv, tid);
      82        1714 :     UserObject::_subproblem.addFunctor("HbyA", _HbyA, tid);
      83             :   }
      84             : 
      85         742 :   if (_velocity_interp_method == Moose::FV::InterpMethod::Average)
      86           0 :     paramError("velocity_interp_method",
      87             :                "Segregated momentum-pressure solvers do not allow average interpolation methods!");
      88             : 
      89         742 :   if (!dynamic_cast<SIMPLENonlinearAssembly *>(getMooseApp().getExecutioner()))
      90           0 :     mooseError(this->name(), " should only be used with a segregated thermal-hydraulics solver!");
      91        1484 : }
      92             : 
      93             : void
      94         742 : INSFVRhieChowInterpolatorSegregated::linkMomentumSystem(
      95             :     std::vector<NonlinearSystemBase *> momentum_systems,
      96             :     const std::vector<unsigned int> & momentum_system_numbers,
      97             :     const TagID pressure_gradient_tag)
      98             : {
      99         742 :   _momentum_systems = momentum_systems;
     100         742 :   _momentum_system_numbers = momentum_system_numbers;
     101         742 :   _pressure_gradient_tag = pressure_gradient_tag;
     102             : 
     103         742 :   _momentum_implicit_systems.clear();
     104        2283 :   for (auto & system : _momentum_systems)
     105             :     _momentum_implicit_systems.push_back(
     106        1541 :         dynamic_cast<NonlinearImplicitSystem *>(&system->system()));
     107         742 : }
     108             : 
     109             : void
     110           0 : INSFVRhieChowInterpolatorSegregated::meshChanged()
     111             : {
     112             :   _HbyA.clear();
     113             :   _Ainv.clear();
     114             :   _face_velocity.clear();
     115           0 : }
     116             : 
     117             : void
     118           0 : INSFVRhieChowInterpolatorSegregated::initialize()
     119             : {
     120           0 :   for (const auto & pair : _HbyA)
     121           0 :     _HbyA[pair.first] = 0;
     122             : 
     123           0 :   for (const auto & pair : _Ainv)
     124           0 :     _Ainv[pair.first] = 0;
     125           0 : }
     126             : 
     127             : void
     128         742 : INSFVRhieChowInterpolatorSegregated::initFaceVelocities()
     129             : {
     130      130514 :   for (auto & fi : _fe_problem.mesh().faceInfo())
     131             :   {
     132      130567 :     if (hasBlocks(fi->elemPtr()->subdomain_id()) ||
     133        1802 :         (fi->neighborPtr() && hasBlocks(fi->neighborPtr()->subdomain_id())))
     134             :     {
     135             :       // On internal face we do a regular interpoaltion with geometric weights
     136      128773 :       if (_u->isInternalFace(*fi))
     137             :       {
     138      106914 :         const Moose::FaceArg face{
     139      106914 :             fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
     140             : 
     141      213828 :         _face_velocity[fi->id()] = MetaPhysicL::raw_value((*_vel)(face, Moose::currentState()));
     142             :       }
     143             :       // On the boundary, we just take the boundary values
     144             :       else
     145             :       {
     146             :         const Elem * const boundary_elem =
     147       21859 :             hasBlocks(fi->elemPtr()->subdomain_id()) ? fi->elemPtr() : fi->neighborPtr();
     148             : 
     149       21859 :         const Moose::FaceArg boundary_face{
     150       21859 :             fi, Moose::FV::LimiterType::CentralDifference, true, false, boundary_elem, nullptr};
     151             : 
     152       21859 :         _face_velocity[fi->id()] =
     153       43718 :             MetaPhysicL::raw_value((*_vel)(boundary_face, Moose::currentState()));
     154             :       }
     155             :     }
     156             :   }
     157         742 : }
     158             : 
     159             : VectorValue<ADReal>
     160    13460960 : INSFVRhieChowInterpolatorSegregated::getVelocity(const Moose::FV::InterpMethod m,
     161             :                                                  const FaceInfo & fi,
     162             :                                                  const Moose::StateArg & /*time*/,
     163             :                                                  const THREAD_ID /*tid*/,
     164             :                                                  const bool /*subtract_mesh_velocity*/) const
     165             : {
     166    13460960 :   if (m != Moose::FV::InterpMethod::RhieChow)
     167           0 :     mooseError("Segregated solution algorithms only support Rhie-Chow interpolation!");
     168    13460960 :   return _face_velocity.evaluate(&fi);
     169             : }
     170             : 
     171             : void
     172       43563 : INSFVRhieChowInterpolatorSegregated::computeFaceVelocity()
     173             : {
     174       43563 :   const auto time_arg = Moose::currentState();
     175             : 
     176     6447382 :   for (auto & fi : _fe_problem.mesh().faceInfo())
     177             :   {
     178     6465505 :     if (hasBlocks(fi->elemPtr()->subdomain_id()) ||
     179      142477 :         (fi->neighborPtr() && hasBlocks(fi->neighborPtr()->subdomain_id())))
     180             :     {
     181             :       // On internal face we just use the interpolated H/A and the pressure face gradient
     182             :       // So u_f = -(H/A)_f - (1/A)_f*grad(p)_f
     183             :       // Notice the (-) sign on H/A which is because we use the Jacobian/Residual
     184             :       // computations and we get -H instead of H.
     185     6324022 :       if (_u->isInternalFace(*fi))
     186             :       {
     187     5008774 :         const Moose::FaceArg face{
     188     5008774 :             fi, Moose::FV::LimiterType::CentralDifference, true, false, nullptr, nullptr};
     189             : 
     190             :         RealVectorValue Ainv;
     191     5008774 :         RealVectorValue HbyA = MetaPhysicL::raw_value(_HbyA(face, time_arg));
     192             : 
     193     5008774 :         interpolate(Moose::FV::InterpMethod::Average,
     194             :                     Ainv,
     195     5008774 :                     _Ainv(makeElemArg(fi->elemPtr()), time_arg),
     196    10017548 :                     _Ainv(makeElemArg(fi->neighborPtr()), time_arg),
     197             :                     *fi,
     198             :                     true);
     199             : 
     200     5008774 :         RealVectorValue grad_p = MetaPhysicL::raw_value(_p->gradient(face, time_arg));
     201    15725403 :         for (const auto comp_index : make_range(_dim))
     202    10716629 :           _face_velocity[fi->id()](comp_index) =
     203    10716629 :               -HbyA(comp_index) - Ainv(comp_index) * grad_p(comp_index);
     204             :       }
     205             :       else
     206             :       {
     207             :         const Elem * const boundary_elem =
     208     1315248 :             hasBlocks(fi->elemPtr()->subdomain_id()) ? fi->elemPtr() : fi->neighborPtr();
     209     1315248 :         const Moose::FaceArg boundary_face{
     210     1315248 :             fi, Moose::FV::LimiterType::CentralDifference, true, false, boundary_elem, nullptr};
     211             : 
     212             :         // If we have a dirichlet boundary conditions, this sill give us the exact value of the
     213             :         // velocity on the face as expected (see populateHbyA())
     214     1315248 :         if (_u->isDirichletBoundaryFace(*fi, boundary_elem, time_arg))
     215     1791170 :           _face_velocity[fi->id()] = -MetaPhysicL::raw_value(_HbyA(boundary_face, time_arg));
     216             :         else
     217             :         {
     218      419663 :           const RealVectorValue & Ainv = MetaPhysicL::raw_value(_Ainv(boundary_face, time_arg));
     219      419663 :           const RealVectorValue & HbyA = MetaPhysicL::raw_value(_HbyA(boundary_face, time_arg));
     220             :           const RealVectorValue & grad_p =
     221      419663 :               MetaPhysicL::raw_value(_p->gradient(boundary_face, time_arg));
     222     1288392 :           for (const auto comp_index : make_range(_dim))
     223      868729 :             _face_velocity[fi->id()](comp_index) =
     224      868729 :                 -HbyA(comp_index) - Ainv(comp_index) * grad_p(comp_index);
     225             :         }
     226             :       }
     227             :     }
     228             :   }
     229       43563 : }
     230             : 
     231             : void
     232       43563 : INSFVRhieChowInterpolatorSegregated::computeCellVelocity()
     233             : {
     234       43563 :   std::vector<unsigned int> var_nums = {_momentum_implicit_systems[0]->variable_number(_u->name())};
     235       43563 :   if (_v)
     236       43563 :     var_nums.push_back(_momentum_implicit_systems[1]->variable_number(_v->name()));
     237       43563 :   if (_w)
     238        5082 :     var_nums.push_back(_momentum_implicit_systems[2]->variable_number(_w->name()));
     239             : 
     240       43563 :   const auto time_arg = Moose::currentState();
     241             : 
     242             :   for (auto & elem :
     243     5412363 :        as_range(_mesh.active_local_elements_begin(), _mesh.active_local_elements_end()))
     244             :   {
     245     2640837 :     if (hasBlocks(elem->subdomain_id()))
     246             :     {
     247     2603296 :       const auto elem_arg = makeElemArg(elem);
     248     2603296 :       const RealVectorValue Ainv = _Ainv(elem_arg, time_arg);
     249     2603296 :       const RealVectorValue & grad_p = raw_value(_p->gradient(elem_arg, time_arg));
     250             : 
     251     8101974 :       for (auto comp_index : make_range(_dim))
     252             :       {
     253             :         // If we are doing segregated momentum components we need to access different vector
     254             :         // components otherwise everything is in the same vector (with different variable names)
     255     5498678 :         const unsigned int system_number = _momentum_implicit_systems[comp_index]->number();
     256     5498678 :         const auto index = elem->dof_number(system_number, var_nums[comp_index], 0);
     257             : 
     258             :         // We set the dof value in the solution vector the same logic applies:
     259             :         // u_C = -(H/A)_C - (1/A)_C*grad(p)_C where C is the cell index
     260    10997356 :         _momentum_implicit_systems[comp_index]->solution->set(
     261     5498678 :             index, -(*_HbyA_raw[comp_index])(index)-Ainv(comp_index) * grad_p(comp_index));
     262             :       }
     263             :     }
     264       43563 :   }
     265             : 
     266      135771 :   for (auto system_i : index_range(_momentum_implicit_systems))
     267             :   {
     268       92208 :     _momentum_implicit_systems[system_i]->solution->close();
     269       92208 :     _momentum_implicit_systems[system_i]->update();
     270       92208 :     _momentum_systems[system_i]->setSolution(
     271       92208 :         *_momentum_implicit_systems[system_i]->current_local_solution);
     272             :   }
     273       43563 : }
     274             : 
     275             : void
     276       43563 : INSFVRhieChowInterpolatorSegregated::populateHbyA(
     277             :     const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_hbya,
     278             :     const std::vector<unsigned int> & var_nums)
     279             : {
     280     6447382 :   for (auto & fi : _fe_problem.mesh().faceInfo())
     281             :   {
     282     6465505 :     if (hasBlocks(fi->elemPtr()->subdomain_id()) ||
     283      142477 :         (fi->neighborPtr() && hasBlocks(fi->neighborPtr()->subdomain_id())))
     284             :     {
     285             :       // If we are on an internal face, we just interpolate the values to the faces.
     286             :       // Otherwise, depending on the boundary type, we take the velocity value or
     287             :       // extrapolated HbyA values.
     288     6324022 :       if (_u->isInternalFace(*fi))
     289             :       {
     290     5008774 :         const Elem * elem = fi->elemPtr();
     291             :         const Elem * neighbor = fi->neighborPtr();
     292    15725403 :         for (auto comp_index : make_range(_dim))
     293             :         {
     294    10716629 :           unsigned int system_number = _momentum_implicit_systems[comp_index]->number();
     295    10716629 :           const auto dof_index_elem = elem->dof_number(system_number, var_nums[comp_index], 0);
     296             :           const auto dof_index_neighbor =
     297    10716629 :               neighbor->dof_number(system_number, var_nums[comp_index], 0);
     298             : 
     299    10716629 :           interpolate(Moose::FV::InterpMethod::Average,
     300    21433258 :                       _HbyA[fi->id()](comp_index),
     301    10716629 :                       (*raw_hbya[comp_index])(dof_index_elem),
     302    21433258 :                       (*raw_hbya[comp_index])(dof_index_neighbor),
     303             :                       *fi,
     304             :                       true);
     305             :         }
     306             :       }
     307             :       else
     308             :       {
     309             :         const Elem * const boundary_elem =
     310     1315248 :             hasBlocks(fi->elemPtr()->subdomain_id()) ? fi->elemPtr() : fi->neighborPtr();
     311             : 
     312     1315248 :         const Moose::FaceArg boundary_face{
     313     1315248 :             fi, Moose::FV::LimiterType::CentralDifference, true, false, boundary_elem, nullptr};
     314             : 
     315     1315248 :         if (_u->isDirichletBoundaryFace(*fi, boundary_elem, Moose::currentState()))
     316     1791170 :           _HbyA[fi->id()] = -MetaPhysicL::raw_value((*_vel)(boundary_face, Moose::currentState()));
     317             :         else
     318     1288392 :           for (const auto comp_index : make_range(_dim))
     319             :           {
     320      868729 :             unsigned int system_number = _momentum_implicit_systems[comp_index]->number();
     321             :             const auto dof_index_elem =
     322      868729 :                 boundary_elem->dof_number(system_number, var_nums[comp_index], 0);
     323      868729 :             _HbyA[fi->id()](comp_index) = (*raw_hbya[comp_index])(dof_index_elem);
     324             :           }
     325             :       }
     326             :     }
     327             :   }
     328       43563 : }
     329             : 
     330             : void
     331       43563 : INSFVRhieChowInterpolatorSegregated::computeHbyA(bool verbose)
     332             : {
     333       43563 :   if (verbose)
     334             :   {
     335           0 :     _console << "************************************" << std::endl;
     336           0 :     _console << "Computing HbyA" << std::endl;
     337           0 :     _console << "************************************" << std::endl;
     338             :   }
     339             :   mooseAssert(_momentum_implicit_systems.size() && _momentum_implicit_systems[0],
     340             :               "The momentum system shall be linked before calling this function!");
     341             : 
     342             :   NonlinearImplicitSystem * momentum_system = _momentum_implicit_systems[0];
     343             : 
     344       43563 :   std::vector<unsigned int> var_nums = {_momentum_implicit_systems[0]->variable_number(_u->name())};
     345       43563 :   if (_v)
     346       43563 :     var_nums.push_back(_momentum_implicit_systems[1]->variable_number(_v->name()));
     347       43563 :   if (_w)
     348        5082 :     var_nums.push_back(_momentum_implicit_systems[2]->variable_number(_w->name()));
     349             : 
     350       43563 :   _HbyA_raw.clear();
     351      135771 :   for (auto system_i : index_range(_momentum_systems))
     352             :   {
     353       92208 :     _fe_problem.setCurrentNonlinearSystem(_momentum_system_numbers[system_i]);
     354             : 
     355       92208 :     momentum_system = _momentum_implicit_systems[system_i];
     356             : 
     357       92208 :     NumericVector<Number> & rhs = *(momentum_system->rhs);
     358             :     NumericVector<Number> & current_local_solution = *(momentum_system->current_local_solution);
     359             :     NumericVector<Number> & solution = *(momentum_system->solution);
     360       92208 :     PetscMatrix<Number> * mmat = dynamic_cast<PetscMatrix<Number> *>(momentum_system->matrix);
     361             :     mooseAssert(mmat,
     362             :                 "The matrices used in the segregated INSFVRhieChow objects need to be convertable "
     363             :                 "to PetscMAtrix!");
     364             : 
     365       92208 :     if (verbose)
     366             :     {
     367           0 :       _console << "Matrix in rc object" << std::endl;
     368           0 :       mmat->print();
     369             :     }
     370             : 
     371       92208 :     auto Ainv = current_local_solution.zero_clone();
     372       92208 :     PetscVector<Number> * Ainv_petsc = dynamic_cast<PetscVector<Number> *>(Ainv.get());
     373             : 
     374       92208 :     mmat->get_diagonal(*Ainv_petsc);
     375             : 
     376       92208 :     auto working_vector = momentum_system->current_local_solution->zero_clone();
     377             :     PetscVector<Number> * working_vector_petsc =
     378       92208 :         dynamic_cast<PetscVector<Number> *>(working_vector.get());
     379             :     mooseAssert(working_vector_petsc,
     380             :                 "The vectors used in the segregated INSFVRhieChow objects need to be convertable "
     381             :                 "to PetscVectors!");
     382             : 
     383       92208 :     *working_vector_petsc = 1.0;
     384       92208 :     Ainv_petsc->pointwise_divide(*working_vector_petsc, *Ainv_petsc);
     385             : 
     386      184416 :     _HbyA_raw.push_back(current_local_solution.zero_clone());
     387             :     NumericVector<Number> & HbyA = *(_HbyA_raw.back());
     388             : 
     389       92208 :     if (verbose)
     390             :     {
     391           0 :       _console << "Velocity solution in H(u)" << std::endl;
     392           0 :       solution.print();
     393             :     }
     394             : 
     395             :     // We fill the 1/A functor
     396             :     auto active_local_begin =
     397       92208 :         _mesh.evaluable_elements_begin(momentum_system->get_dof_map(), var_nums[system_i]);
     398             :     auto active_local_end =
     399       92208 :         _mesh.evaluable_elements_end(momentum_system->get_dof_map(), var_nums[system_i]);
     400             : 
     401       92208 :     const auto & state = Moose::currentState();
     402    13868740 :     for (auto it = active_local_begin; it != active_local_end; ++it)
     403             :     {
     404     6888266 :       const Elem * elem = *it;
     405     6888266 :       if (this->hasBlocks(elem->subdomain_id()))
     406             :       {
     407     6779088 :         const Moose::ElemArg & elem_arg = makeElemArg(elem);
     408             :         Real coord_multiplier;
     409     6779088 :         const auto coord_type = _fe_problem.getCoordSystem(elem->subdomain_id());
     410             :         const unsigned int rz_radial_coord =
     411     6779088 :             Moose::COORD_RZ ? _fe_problem.getAxisymmetricRadialCoord() : libMesh::invalid_uint;
     412             : 
     413     6779088 :         MooseMeshUtils::coordTransformFactor(
     414     6779088 :             elem->vertex_average(), coord_multiplier, coord_type, rz_radial_coord);
     415             : 
     416     6779088 :         const Real volume = _moose_mesh.elemInfo(elem->id()).volume();
     417     6779088 :         const auto dof_index = elem->dof_number(momentum_system->number(), var_nums[system_i], 0);
     418    13558176 :         _Ainv[elem->id()](system_i) = MetaPhysicL::raw_value(epsilon(_tid)(elem_arg, state)) *
     419     6779088 :                                       (*Ainv_petsc)(dof_index)*volume * coord_multiplier;
     420             :       }
     421             :     }
     422             : 
     423             :     // Now we set the diagonal of our system matrix to 0 so we can create H*u
     424             :     // TODO: Add a function for this in libmesh
     425       92208 :     *working_vector_petsc = 0.0;
     426       92208 :     LibmeshPetscCall(MatDiagonalSet(mmat->mat(), working_vector_petsc->vec(), INSERT_VALUES));
     427             : 
     428       92208 :     if (verbose)
     429             :     {
     430           0 :       _console << "H" << std::endl;
     431           0 :       mmat->print();
     432             :     }
     433             : 
     434             :     // We need to subtract the contribution of the pressure gradient from the residual (right hand
     435             :     // side). We plug working_vector=0 in here to get the right hand side contribution
     436       92208 :     _fe_problem.computeResidualTag(*working_vector, HbyA, _pressure_gradient_tag);
     437             : 
     438             :     // Now we reorganize the association between tags and vectors to make sure
     439             :     // that the next solve is perfect
     440       92208 :     _momentum_systems[system_i]->associateVectorToTag(
     441      184416 :         momentum_system->get_vector(_fe_problem.vectorTagName(0)), 0);
     442       92208 :     _momentum_systems[system_i]->associateVectorToTag(
     443      184416 :         momentum_system->get_vector(_fe_problem.vectorTagName(_pressure_gradient_tag)),
     444             :         _pressure_gradient_tag);
     445       92208 :     _momentum_systems[system_i]->setSolution(current_local_solution);
     446             : 
     447       92208 :     if (verbose)
     448             :     {
     449           0 :       _console << "total RHS" << std::endl;
     450           0 :       rhs.print();
     451           0 :       _console << "pressure RHS" << std::endl;
     452           0 :       HbyA.print();
     453             :     }
     454             : 
     455             :     // We correct the right hand side to exclude the pressure contribution
     456       92208 :     HbyA.scale(-1.0);
     457       92208 :     HbyA.add(-1.0, rhs);
     458             : 
     459       92208 :     if (verbose)
     460             :     {
     461           0 :       _console << "H RHS" << std::endl;
     462           0 :       HbyA.print();
     463             :     }
     464             : 
     465             :     // Create H(u)
     466       92208 :     mmat->vector_mult(*working_vector_petsc, solution);
     467             : 
     468       92208 :     if (verbose)
     469             :     {
     470           0 :       _console << " H(u)" << std::endl;
     471           0 :       working_vector_petsc->print();
     472             :     }
     473             : 
     474             :     // Create H(u) - RHS
     475       92208 :     HbyA.add(*working_vector_petsc);
     476             : 
     477       92208 :     if (verbose)
     478             :     {
     479           0 :       _console << " H(u)-rhs-relaxation_source" << std::endl;
     480           0 :       HbyA.print();
     481             :     }
     482             : 
     483             :     // Create 1/A*(H(u)-RHS)
     484       92208 :     HbyA.pointwise_mult(HbyA, *Ainv);
     485             : 
     486       92208 :     if (verbose)
     487             :     {
     488           0 :       _console << " (H(u)-rhs)/A" << std::endl;
     489           0 :       HbyA.print();
     490             :     }
     491       92208 :   }
     492             : 
     493       43563 :   populateHbyA(_HbyA_raw, var_nums);
     494             : 
     495       43563 :   if (verbose)
     496             :   {
     497           0 :     _console << "************************************" << std::endl;
     498           0 :     _console << "DONE Computing HbyA " << std::endl;
     499           0 :     _console << "************************************" << std::endl;
     500             :   }
     501       43563 : }

Generated by: LCOV version 1.14