LCOV - code coverage report
Current view: top level - src/fvkernels - FVPorousFlowDispersiveFlux.C (source / functions) Hit Total Coverage
Test: idaholab/moose porous_flow: #31405 (292dce) with base fef103 Lines: 90 96 93.8 %
Date: 2025-09-04 07:55:56 Functions: 3 3 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 "FVPorousFlowDispersiveFlux.h"
      11             : #include "PorousFlowDictator.h"
      12             : #include "MooseUtils.h"
      13             : 
      14             : registerADMooseObject("PorousFlowApp", FVPorousFlowDispersiveFlux);
      15             : 
      16             : InputParameters
      17         246 : FVPorousFlowDispersiveFlux::validParams()
      18             : {
      19         246 :   InputParameters params = FVFluxKernel::validParams();
      20         246 :   params += FVDiffusionInterpolationInterface::validParams();
      21             :   RealVectorValue g(0, 0, -9.81);
      22         492 :   params.addParam<RealVectorValue>("gravity", g, "Gravity vector. Defaults to (0, 0, -9.81)");
      23         492 :   params.addRequiredParam<UserObjectName>("PorousFlowDictator",
      24             :                                           "The PorousFlowDictator UserObject");
      25         492 :   params.addParam<unsigned int>("fluid_component", 0, "The fluid component");
      26         492 :   params.addRequiredParam<std::vector<Real>>(
      27             :       "disp_long", "Vector of longitudinal dispersion coefficients for each phase");
      28         492 :   params.addRequiredParam<std::vector<Real>>(
      29             :       "disp_trans", "Vector of transverse dispersion coefficients for each phase");
      30         246 :   params.addClassDescription(
      31             :       "Dispersive and diffusive flux of the component given by fluid_component in all phases");
      32         246 :   params.set<unsigned short>("ghost_layers") = 2;
      33             : 
      34             :   // We add the relationship manager here, this will select the right number of
      35             :   // ghosting layers depending on the chosen interpolation method
      36         492 :   params.addRelationshipManager(
      37             :       "ElementSideNeighborLayers",
      38             :       Moose::RelationshipManagerType::GEOMETRIC | Moose::RelationshipManagerType::ALGEBRAIC |
      39             :           Moose::RelationshipManagerType::COUPLING,
      40             :       [](const InputParameters & obj_params, InputParameters & rm_params)
      41         342 :       { FVRelationshipManagerInterface::setRMParamsDiffusion(obj_params, rm_params, 3); });
      42             : 
      43         246 :   params.addClassDescription("Advective Darcy flux");
      44         246 :   return params;
      45           0 : }
      46             : 
      47         132 : FVPorousFlowDispersiveFlux::FVPorousFlowDispersiveFlux(const InputParameters & params)
      48             :   : FVFluxKernel(params),
      49             :     FVDiffusionInterpolationInterface(params),
      50         132 :     _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
      51         132 :     _num_phases(_dictator.numPhases()),
      52         264 :     _fluid_component(getParam<unsigned int>("fluid_component")),
      53         264 :     _density(getADMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_qp")),
      54         264 :     _viscosity(getADMaterialProperty<std::vector<Real>>("PorousFlow_viscosity_qp")),
      55         132 :     _viscosity_neighbor(
      56         132 :         getNeighborADMaterialProperty<std::vector<Real>>("PorousFlow_viscosity_qp")),
      57         264 :     _relperm(getADMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_qp")),
      58         132 :     _relperm_neighbor(
      59         132 :         getNeighborADMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_qp")),
      60         132 :     _mass_fractions(
      61         132 :         getADMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_qp")),
      62         132 :     _mass_fractions_neighbor(
      63         132 :         getNeighborADMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_qp")),
      64         264 :     _grad_mass_frac(getADMaterialProperty<std::vector<std::vector<RealGradient>>>(
      65             :         "PorousFlow_grad_mass_frac_qp")),
      66         264 :     _permeability(getADMaterialProperty<RealTensorValue>("PorousFlow_permeability_qp")),
      67         132 :     _permeability_neighbor(
      68         132 :         getNeighborADMaterialProperty<RealTensorValue>("PorousFlow_permeability_qp")),
      69         264 :     _pressure(getADMaterialProperty<std::vector<Real>>("PorousFlow_porepressure_qp")),
      70         132 :     _pressure_neighbor(
      71         132 :         getNeighborADMaterialProperty<std::vector<Real>>("PorousFlow_porepressure_qp")),
      72         264 :     _grad_p(getADMaterialProperty<std::vector<RealGradient>>("PorousFlow_grad_porepressure_qp")),
      73         264 :     _porosity(getADMaterialProperty<Real>("PorousFlow_porosity_qp")),
      74         264 :     _porosity_neighbor(getNeighborADMaterialProperty<Real>("PorousFlow_porosity_qp")),
      75         264 :     _tortuosity(getADMaterialProperty<std::vector<Real>>("PorousFlow_tortuosity_qp")),
      76         132 :     _tortuosity_neighbor(
      77         132 :         getNeighborADMaterialProperty<std::vector<Real>>("PorousFlow_tortuosity_qp")),
      78         132 :     _diffusion_coeff(
      79         132 :         getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_diffusion_coeff_qp")),
      80         264 :     _diffusion_coeff_neighbor(getNeighborMaterialProperty<std::vector<std::vector<Real>>>(
      81             :         "PorousFlow_diffusion_coeff_qp")),
      82         264 :     _gravity(getParam<RealVectorValue>("gravity")),
      83         132 :     _identity_tensor(ADRankTwoTensor::initIdentity),
      84         264 :     _disp_long(getParam<std::vector<Real>>("disp_long")),
      85         396 :     _disp_trans(getParam<std::vector<Real>>("disp_trans"))
      86             : {
      87         132 :   if (_fluid_component >= _dictator.numComponents())
      88           0 :     paramError(
      89             :         "fluid_component",
      90             :         "The Dictator proclaims that the maximum fluid component index in this simulation is ",
      91           0 :         _dictator.numComponents() - 1,
      92             :         " whereas you have used ",
      93           0 :         _fluid_component,
      94             :         ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
      95             : 
      96             :   // Check that sufficient values of the dispersion coefficients have been entered
      97         132 :   if (_disp_long.size() != _num_phases)
      98           0 :     paramError(
      99             :         "disp_long",
     100             :         "The number of longitudinal dispersion coefficients is not equal to the number of phases");
     101             : 
     102         132 :   if (_disp_trans.size() != _num_phases)
     103           0 :     paramError("disp_trans",
     104             :                "The number of transverse dispersion coefficients disp_trans is not equal to the "
     105             :                "number of phases");
     106         132 : }
     107             : 
     108             : ADReal
     109      194708 : FVPorousFlowDispersiveFlux::computeQpResidual()
     110             : {
     111      194708 :   ADReal flux = 0.0;
     112      194708 :   ADRankTwoTensor dispersion;
     113             :   ADReal diffusion;
     114             : 
     115      551616 :   for (unsigned int p = 0; p < _num_phases; ++p)
     116             :   {
     117             :     // Diffusive component
     118             :     ADRealGradient gradX;
     119             : 
     120      356908 :     const auto state = determineState();
     121      356908 :     const auto dudn = gradUDotNormal(state, _correct_skewness);
     122             : 
     123             :     // If we are on a boundary face, use the reconstructed gradient computed in _grad_mass_frac
     124      356908 :     if (onBoundary(*_face_info))
     125             :     {
     126        3096 :       gradX = -1 * _grad_mass_frac[_qp][p][_fluid_component];
     127        6192 :       diffusion = _porosity[_qp] * _tortuosity[_qp][p] * _density[_qp][p] *
     128        6192 :                   _diffusion_coeff[_qp][p][_fluid_component];
     129             :     }
     130             :     else
     131             :     {
     132             :       // If we are on an internal face, calculate the gradient explicitly
     133      353812 :       const auto & X_elem = _mass_fractions[_qp][p][_fluid_component];
     134      353812 :       const auto & X_neighbor = _mass_fractions_neighbor[_qp][p][_fluid_component];
     135             : 
     136      707624 :       gradX = (X_elem - X_neighbor) * _face_info->eCN() / _face_info->dCNMag();
     137             : 
     138             :       const auto coeff =
     139      353812 :           _porosity[_qp] * _tortuosity[_qp][p] * _diffusion_coeff[_qp][p][_fluid_component];
     140             : 
     141      353812 :       const auto coeff_neighbor = _porosity_neighbor[_qp] * _tortuosity_neighbor[_qp][p] *
     142      353812 :                                   _diffusion_coeff_neighbor[_qp][p][_fluid_component];
     143             : 
     144      353812 :       interpolate(
     145      353812 :           Moose::FV::InterpMethod::Average, diffusion, coeff, coeff_neighbor, *_face_info, true);
     146             :     }
     147             : 
     148             :     // Dispersive component. Calculate Darcy velocity
     149             :     ADRealGradient gradp;
     150             :     ADRealTensorValue mobility;
     151             : 
     152             :     // If we are on a boundary face, use the gradient computed in _grad_p
     153      356908 :     if (onBoundary(*_face_info))
     154             :     {
     155        3096 :       gradp = -_grad_p[_qp][p] + _density[_qp][p] * _gravity;
     156        6192 :       mobility = _relperm[_qp][p] * _permeability[_qp] * _density[_qp][p] / _viscosity[_qp][p];
     157             :     }
     158             :     else
     159             :     {
     160             :       // If we are on an internal face, calculate the gradient explicitly
     161      353812 :       const auto & p_elem = _pressure[_qp][p];
     162      353812 :       const auto & p_neighbor = _pressure_neighbor[_qp][p];
     163             : 
     164      707624 :       gradp = (p_elem - p_neighbor) * _face_info->eCN() / _face_info->dCNMag() +
     165      353812 :               _density[_qp][p] * _gravity;
     166             : 
     167      353812 :       const auto mobility_element = _relperm[_qp][p] * _permeability[_qp] / _viscosity[_qp][p];
     168             : 
     169             :       const auto mobility_neighbor =
     170      353812 :           _relperm_neighbor[_qp][p] * _permeability_neighbor[_qp] / _viscosity_neighbor[_qp][p];
     171             : 
     172      353812 :       interpolate(Moose::FV::InterpMethod::Upwind,
     173             :                   mobility,
     174             :                   mobility_element,
     175             :                   mobility_neighbor,
     176             :                   gradp,
     177      353812 :                   *_face_info,
     178             :                   true);
     179             :     }
     180             : 
     181      356908 :     const auto velocity = mobility * gradp;
     182      356908 :     const auto velocity_abs = MetaPhysicL::raw_value(velocity).norm();
     183             : 
     184      356908 :     if (!MooseUtils::isZero(velocity_abs))
     185             :     {
     186      194284 :       const auto v2 = ADRankTwoTensor::selfOuterProduct(velocity);
     187             : 
     188             :       // Add longitudinal dispersion to diffusive component
     189      194284 :       diffusion += _disp_trans[p] * velocity_abs;
     190      388568 :       dispersion = (_disp_long[p] - _disp_trans[p]) * v2 / velocity_abs;
     191             :     }
     192             : 
     193      356908 :     flux += (diffusion * _identity_tensor + dispersion) * _density[_qp][p] * gradX * _normal;
     194             :   }
     195             : 
     196      194708 :   return flux;
     197             : }

Generated by: LCOV version 1.14