From 6ee628ff971acc53bdc466b1ac568951d17e6d5c Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Thu, 24 Oct 2024 09:05:58 -0600 Subject: [PATCH 01/16] Adding unchecked/unfinished LinearFV kernels for Boussinesq NC --- .../linearfvkernels/LinearFVEnergyAdvection.h | 0 .../LinearFVMomentumBoussinesq.h | 50 +++++++++ .../linearfvkernels/LinearFVEnergyAdvection.C | 101 ++++++++++++++++++ .../LinearFVMomentumBoussinesq.C | 79 ++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h create mode 100644 modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h create mode 100644 modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C create mode 100644 modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h new file mode 100644 index 000000000000..348bbb66545a --- /dev/null +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h @@ -0,0 +1,50 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "LinearFVElementalKernel.h" + +/** + * Kernel that adds the component of the pressure gradient in the momentum + * equations to the right hand side. + */ +class LinearFVMomentumBoussinesq : public LinearFVElementalKernel +{ +public: + static InputParameters validParams(); + + /** + * Class constructor. + * @param params The InputParameters for the kernel. + */ + LinearFVMomentumBoussinesq(const InputParameters & params); + + virtual Real computeMatrixContribution() override; + + virtual Real computeRightHandSideContribution() override; + +protected: + /// Fluid Temperature + MooseLinearVariableFV & getTemperatureVariable(const std::string & vname); + + /// Index x|y|z of the momentum equation component + const unsigned int _index; + /// Pointer to the linear finite volume temperature variable + MooseLinearVariableFV & _temperature_var; + /// The gravity vector + const RealVectorValue _gravity; + /// The thermal expansion coefficient + const Moose::Functor & _alpha; + /// Reference temperature at which the value of _rho was measured + const Real _ref_temperature; + /// the density + const Moose::Functor & _rho; + +}; diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C new file mode 100644 index 000000000000..176be7e83d5d --- /dev/null +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C @@ -0,0 +1,101 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "LinearFVAdvection.h" +#include "Assembly.h" +#include "SubProblem.h" +#include "LinearFVAdvectionDiffusionBC.h" + +registerMooseObject("MooseApp", LinearFVAdvection); + +InputParameters +LinearFVAdvection::validParams() +{ + InputParameters params = LinearFVFluxKernel::validParams(); + params.addClassDescription("Represents the matrix and right hand side contributions of an " + "advection term in a partial differential equation."); + params.addRequiredParam("velocity", "Constant advection velocity"); + params += Moose::FV::advectedInterpolationParameter(); + return params; +} + +LinearFVAdvection::LinearFVAdvection(const InputParameters & params) + : LinearFVFluxKernel(params), _velocity(getParam("velocity")) + +{ + Moose::FV::setInterpolationMethod(*this, _advected_interp_method, "advected_interp_method"); +} + +void +LinearFVAdvection::initialSetup() +{ + for (const auto bc : _var.getBoundaryConditionMap()) + if (!dynamic_cast(bc.second)) + mooseError( + bc.second->type(), " is not a compatible boundary condition with ", this->type(), "!"); +} + +Real +LinearFVAdvection::computeElemMatrixContribution() +{ + const Real face_flux = _velocity * _current_face_info->normal(); + const auto interp_coeffs = + interpCoeffs(_advected_interp_method, *_current_face_info, true, face_flux); + return interp_coeffs.first * face_flux * _current_face_area; +} + +Real +LinearFVAdvection::computeNeighborMatrixContribution() +{ + const Real face_flux = _velocity * _current_face_info->normal(); + const auto interp_coeffs = + interpCoeffs(_advected_interp_method, *_current_face_info, true, face_flux); + return interp_coeffs.second * face_flux * _current_face_area; +} + +Real +LinearFVAdvection::computeElemRightHandSideContribution() +{ + return 0.0; +} + +Real +LinearFVAdvection::computeNeighborRightHandSideContribution() +{ + return 0.0; +} + +Real +LinearFVAdvection::computeBoundaryMatrixContribution(const LinearFVBoundaryCondition & bc) +{ + const auto * const adv_bc = static_cast(&bc); + mooseAssert(adv_bc, "This should be a valid BC!"); + + const auto boundary_value_matrix_contrib = adv_bc->computeBoundaryValueMatrixContribution(); + + // We support internal boundaries too so we have to make sure the normal points always outward + const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0; + + return boundary_value_matrix_contrib * factor * (_velocity * _current_face_info->normal()) * + _current_face_area; +} + +Real +LinearFVAdvection::computeBoundaryRHSContribution(const LinearFVBoundaryCondition & bc) +{ + const auto * const adv_bc = static_cast(&bc); + mooseAssert(adv_bc, "This should be a valid BC!"); + + // We support internal boundaries too so we have to make sure the normal points always outward + const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0); + + const auto boundary_value_rhs_contrib = adv_bc->computeBoundaryValueRHSContribution(); + return -boundary_value_rhs_contrib * factor * (_velocity * _current_face_info->normal()) * + _current_face_area; +} diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C new file mode 100644 index 000000000000..5803884d96d2 --- /dev/null +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C @@ -0,0 +1,79 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "LinearFVMomentumBoussinesq.h" +#include "Assembly.h" +#include "SubProblem.h" +#include "NS.h" + +registerMooseObject("NavierStokesApp", LinearFVMomentumBoussinesq); + +InputParameters +LinearFVMomentumBoussinesq::validParams() +{ + InputParameters params = LinearFVElementalKernel::validParams(); + params.addClassDescription("Represents the Boussinesq term in the Navier Stokes momentum " + "equations, added to the right hand side."); + params.addParam(NS::T_fluid, + "The fluid temperature variable."); + params.addRequiredParam("gravity", "Direction of the gravity vector"); + params.addParam("alpha_name", + NS::alpha_boussinesq, + "The name of the thermal expansion coefficient" + "this is of the form rho = rho*(1-alpha (T-T_ref))"); + params.addRequiredParam("ref_temperature", "The value for the reference temperature."); + params.addRequiredParam(NS::density, "The value for the density"); + MooseEnum momentum_component("x=0 y=1 z=2"); + params.addRequiredParam( + "momentum_component", + momentum_component, + "The component of the momentum equation that this kernel applies to."); + params.addPrivateParam("_override_constant_check", false); + return params; +} + +LinearFVMomentumBoussinesq::LinearFVMomentumBoussinesq(const InputParameters & params) + : LinearFVElementalKernel(params), + _index(getParam("momentum_component")), + _temperature_var(getTemperatureVariable(NS::T_fluid)), + _gravity(getParam("gravity")), + _alpha(getFunctor("alpha_name")), + _ref_temperature(getParam("ref_temperature")), + _rho(getFunctor(NS::density)) +{ + if (!_rho.isConstant() && !getParam("_override_constant_check")) + paramError(NS::density, "The density in the boussinesq term is not constant!"); +} + +MooseLinearVariableFV & +LinearFVMomentumBoussinesq::getTemperatureVariable(const std::string & vname) +{ + auto * ptr = dynamic_cast *>( + &_fe_problem.getVariable(_tid, getParam(vname))); + + if (!ptr) + paramError(NS::T_fluid, "The fluid temperature variable should be of type MooseLinearVariableFVReal!"); + + return *ptr; +} + +Real +LinearFVMomentumBoussinesq::computeMatrixContribution() +{ + return 0.0; +} + +Real +LinearFVMomentumBoussinesq::computeRightHandSideContribution() +{ + const auto elem = makeElemArg(_current_elem_info->elem()); + const auto state = determineState(); + return -_alpha(elem, state) * _gravity(_index) * _rho(elem, state) * + (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature); +} From 4810035037dbaeabe29941c2a4ee6f7ac164c0d3 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Fri, 25 Oct 2024 14:09:35 -0600 Subject: [PATCH 02/16] Compileable kernels for Boussinesq and Energy advection, first iteration --- .../linearfvkernels/LinearFVEnergyAdvection.h | 57 +++++++++++++ .../LinearFVMomentumBoussinesq.h | 7 +- .../linearfvkernels/LinearFVEnergyAdvection.C | 82 ++++++++++--------- .../LinearFVMomentumBoussinesq.C | 14 ++-- 4 files changed, 111 insertions(+), 49 deletions(-) diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h index e69de29bb2d1..72af0030aec2 100644 --- a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h @@ -0,0 +1,57 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "LinearFVFluxKernel.h" +#include "RhieChowMassFlux.h" +#include "LinearFVAdvectionDiffusionBC.h" + +/** + * An advection kernel that implements the advection term for the enthalpy in the + * energy equation. + */ +class LinearFVEnergyAdvection : public LinearFVFluxKernel +{ +public: + static InputParameters validParams(); + LinearFVEnergyAdvection(const InputParameters & params); + + virtual Real computeElemMatrixContribution() override; + + virtual Real computeNeighborMatrixContribution() override; + + virtual Real computeElemRightHandSideContribution() override; + + virtual Real computeNeighborRightHandSideContribution() override; + + virtual Real computeBoundaryMatrixContribution(const LinearFVBoundaryCondition & bc) override; + + virtual Real computeBoundaryRHSContribution(const LinearFVBoundaryCondition & bc) override; + + virtual void setupFaceData(const FaceInfo * face_info) override; + +protected: + /// The advected heat quantity + const Moose::Functor & _adv_quant; + + /// The Rhie-Chow user object that provides us with the face velocity + const RhieChowMassFlux & _mass_flux_provider; + + /// Container for the current advected interpolation coefficients on the face to make sure + /// we don't compute it multiple times for different terms. + std::pair _advected_interp_coeffs; + + /// Container for the mass flux on the face which will be reused in the advection term's + /// matrix and right hand side contribution + Real _face_mass_flux; + + /// The interpolation method to use for the advected quantity + Moose::FV::InterpMethod _advected_interp_method; +}; diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h index 348bbb66545a..12ca2c7f281c 100644 --- a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h @@ -38,13 +38,12 @@ class LinearFVMomentumBoussinesq : public LinearFVElementalKernel const unsigned int _index; /// Pointer to the linear finite volume temperature variable MooseLinearVariableFV & _temperature_var; - /// The gravity vector + /// The gravity vector const RealVectorValue _gravity; /// The thermal expansion coefficient - const Moose::Functor & _alpha; + const Moose::Functor & _alpha; /// Reference temperature at which the value of _rho was measured const Real _ref_temperature; /// the density - const Moose::Functor & _rho; - + const Moose::Functor & _rho; }; diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C index 176be7e83d5d..6b0a48029036 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C @@ -7,72 +7,65 @@ //* Licensed under LGPL 2.1, please see LICENSE for details //* https://www.gnu.org/licenses/lgpl-2.1.html -#include "LinearFVAdvection.h" -#include "Assembly.h" -#include "SubProblem.h" -#include "LinearFVAdvectionDiffusionBC.h" +#include "LinearFVEnergyAdvection.h" +#include "MooseLinearVariableFV.h" +#include "NSFVUtils.h" +#include "NS.h" -registerMooseObject("MooseApp", LinearFVAdvection); +registerMooseObject("MooseApp", LinearFVEnergyAdvection); InputParameters -LinearFVAdvection::validParams() +LinearFVEnergyAdvection::validParams() { InputParameters params = LinearFVFluxKernel::validParams(); params.addClassDescription("Represents the matrix and right hand side contributions of an " - "advection term in a partial differential equation."); - params.addRequiredParam("velocity", "Constant advection velocity"); + "advection term for the energy e.g. h=cp*T. A user may still " + "override what quantity is advected, but the default is cp*T."); + params.addParam( + "advected_quantity", NS::specific_enthalpy, "The heat quantity to advect."); + params.addRequiredParam( + "rhie_chow_user_object", + "The rhie-chow user-object which is used to determine the face velocity."); params += Moose::FV::advectedInterpolationParameter(); return params; } -LinearFVAdvection::LinearFVAdvection(const InputParameters & params) - : LinearFVFluxKernel(params), _velocity(getParam("velocity")) - +LinearFVEnergyAdvection::LinearFVEnergyAdvection(const InputParameters & params) + : LinearFVFluxKernel(params), + _adv_quant(getFunctor("advected_quantity")), + _mass_flux_provider(getUserObject("rhie_chow_user_object")), + _advected_interp_coeffs(std::make_pair(0, 0)), + _face_mass_flux(0.0) { Moose::FV::setInterpolationMethod(*this, _advected_interp_method, "advected_interp_method"); } -void -LinearFVAdvection::initialSetup() -{ - for (const auto bc : _var.getBoundaryConditionMap()) - if (!dynamic_cast(bc.second)) - mooseError( - bc.second->type(), " is not a compatible boundary condition with ", this->type(), "!"); -} - Real -LinearFVAdvection::computeElemMatrixContribution() +LinearFVEnergyAdvection::computeElemMatrixContribution() { - const Real face_flux = _velocity * _current_face_info->normal(); - const auto interp_coeffs = - interpCoeffs(_advected_interp_method, *_current_face_info, true, face_flux); - return interp_coeffs.first * face_flux * _current_face_area; + return _advected_interp_coeffs.first * _face_mass_flux * _current_face_area; } Real -LinearFVAdvection::computeNeighborMatrixContribution() +LinearFVEnergyAdvection::computeNeighborMatrixContribution() { - const Real face_flux = _velocity * _current_face_info->normal(); - const auto interp_coeffs = - interpCoeffs(_advected_interp_method, *_current_face_info, true, face_flux); - return interp_coeffs.second * face_flux * _current_face_area; + return _advected_interp_coeffs.second * _face_mass_flux * _current_face_area; } Real -LinearFVAdvection::computeElemRightHandSideContribution() +LinearFVEnergyAdvection::computeElemRightHandSideContribution() { return 0.0; } Real -LinearFVAdvection::computeNeighborRightHandSideContribution() +LinearFVEnergyAdvection::computeNeighborRightHandSideContribution() { return 0.0; } Real -LinearFVAdvection::computeBoundaryMatrixContribution(const LinearFVBoundaryCondition & bc) +LinearFVEnergyAdvection::computeBoundaryMatrixContribution(const LinearFVBoundaryCondition & bc) { const auto * const adv_bc = static_cast(&bc); mooseAssert(adv_bc, "This should be a valid BC!"); @@ -82,12 +75,11 @@ LinearFVAdvection::computeBoundaryMatrixContribution(const LinearFVBoundaryCondi // We support internal boundaries too so we have to make sure the normal points always outward const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0; - return boundary_value_matrix_contrib * factor * (_velocity * _current_face_info->normal()) * - _current_face_area; + return boundary_value_matrix_contrib * factor * _face_mass_flux * _current_face_area; } Real -LinearFVAdvection::computeBoundaryRHSContribution(const LinearFVBoundaryCondition & bc) +LinearFVEnergyAdvection::computeBoundaryRHSContribution(const LinearFVBoundaryCondition & bc) { const auto * const adv_bc = static_cast(&bc); mooseAssert(adv_bc, "This should be a valid BC!"); @@ -96,6 +88,20 @@ LinearFVAdvection::computeBoundaryRHSContribution(const LinearFVBoundaryConditio const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0); const auto boundary_value_rhs_contrib = adv_bc->computeBoundaryValueRHSContribution(); - return -boundary_value_rhs_contrib * factor * (_velocity * _current_face_info->normal()) * - _current_face_area; + return -boundary_value_rhs_contrib * factor * _face_mass_flux * _current_face_area; +} + +void +LinearFVEnergyAdvection::setupFaceData(const FaceInfo * face_info) +{ + LinearFVFluxKernel::setupFaceData(face_info); + + // Caching the mass flux on the face which will be reused in the advection term's matrix and right + // hand side contributions + _face_mass_flux = _mass_flux_provider.getMassFlux(*face_info); + + // Caching the interpolation coefficients so they will be reused for the matrix and right hand + // side terms + _advected_interp_coeffs = + interpCoeffs(_advected_interp_method, *_current_face_info, true, _face_mass_flux); } diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C index 5803884d96d2..cf9248dbcca2 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C @@ -20,8 +20,7 @@ LinearFVMomentumBoussinesq::validParams() InputParameters params = LinearFVElementalKernel::validParams(); params.addClassDescription("Represents the Boussinesq term in the Navier Stokes momentum " "equations, added to the right hand side."); - params.addParam(NS::T_fluid, - "The fluid temperature variable."); + params.addParam(NS::T_fluid, "The fluid temperature variable."); params.addRequiredParam("gravity", "Direction of the gravity vector"); params.addParam("alpha_name", NS::alpha_boussinesq, @@ -43,12 +42,12 @@ LinearFVMomentumBoussinesq::LinearFVMomentumBoussinesq(const InputParameters & p _index(getParam("momentum_component")), _temperature_var(getTemperatureVariable(NS::T_fluid)), _gravity(getParam("gravity")), - _alpha(getFunctor("alpha_name")), + _alpha(getFunctor("alpha_name")), _ref_temperature(getParam("ref_temperature")), - _rho(getFunctor(NS::density)) + _rho(getFunctor(NS::density)) { if (!_rho.isConstant() && !getParam("_override_constant_check")) - paramError(NS::density, "The density in the boussinesq term is not constant!"); + paramError(NS::density, "The density in the boussinesq term is not constant!"); } MooseLinearVariableFV & @@ -58,7 +57,8 @@ LinearFVMomentumBoussinesq::getTemperatureVariable(const std::string & vname) &_fe_problem.getVariable(_tid, getParam(vname))); if (!ptr) - paramError(NS::T_fluid, "The fluid temperature variable should be of type MooseLinearVariableFVReal!"); + paramError(NS::T_fluid, + "The fluid temperature variable should be of type MooseLinearVariableFVReal!"); return *ptr; } @@ -75,5 +75,5 @@ LinearFVMomentumBoussinesq::computeRightHandSideContribution() const auto elem = makeElemArg(_current_elem_info->elem()); const auto state = determineState(); return -_alpha(elem, state) * _gravity(_index) * _rho(elem, state) * - (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature); + (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature); } From 84e92c8a9b5f9ef9437cd73a885934d9533d4da9 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Fri, 25 Oct 2024 16:06:24 -0600 Subject: [PATCH 03/16] Added scaling option to LinearFVSource term --- framework/include/linearfvkernels/LinearFVSource.h | 3 +++ framework/src/linearfvkernels/LinearFVSource.C | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/framework/include/linearfvkernels/LinearFVSource.h b/framework/include/linearfvkernels/LinearFVSource.h index 500dcf015a27..25dbecbd2119 100644 --- a/framework/include/linearfvkernels/LinearFVSource.h +++ b/framework/include/linearfvkernels/LinearFVSource.h @@ -33,4 +33,7 @@ class LinearFVSource : public LinearFVElementalKernel protected: /// The functor for the source density const Moose::Functor & _source_density; + + /// Scale factor + const Real & _scale; }; diff --git a/framework/src/linearfvkernels/LinearFVSource.C b/framework/src/linearfvkernels/LinearFVSource.C index b32fda7e382e..20e345f36f70 100644 --- a/framework/src/linearfvkernels/LinearFVSource.C +++ b/framework/src/linearfvkernels/LinearFVSource.C @@ -21,11 +21,14 @@ LinearFVSource::validParams() "Represents the matrix and right hand side contributions of a " "solution-independent source term in a partial differential equation."); params.addParam("source_density", 1.0, "The source density."); + params.addParam("scaling_factor", 1.0, "Coefficient to multiply by the body force term"); return params; } LinearFVSource::LinearFVSource(const InputParameters & params) - : LinearFVElementalKernel(params), _source_density(getFunctor("source_density")) + : LinearFVElementalKernel(params), + _source_density(getFunctor("source_density")), + _scale(getParam("scaling_factor")) { } @@ -41,6 +44,6 @@ Real LinearFVSource::computeRightHandSideContribution() { // The contribution to the right hand side is s_C*V_C - return _source_density(makeElemArg(_current_elem_info->elem()), determineState()) * + return _scale * _source_density(makeElemArg(_current_elem_info->elem()), determineState()) * _current_elem_volume; } From e6301e292d1fd5c43e5a586bcc1173f2b23f7f33 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Mon, 28 Oct 2024 13:29:50 -0600 Subject: [PATCH 04/16] Add energy solver to Linear Simple --- .../include/executioners/SIMPLE.h | 20 +++ .../navier_stokes/src/executioners/SIMPLE.C | 149 ++++++++++++++++-- 2 files changed, 158 insertions(+), 11 deletions(-) diff --git a/modules/navier_stokes/include/executioners/SIMPLE.h b/modules/navier_stokes/include/executioners/SIMPLE.h index 51bfad4decc7..7ffc5ee7d345 100644 --- a/modules/navier_stokes/include/executioners/SIMPLE.h +++ b/modules/navier_stokes/include/executioners/SIMPLE.h @@ -52,18 +52,38 @@ class SIMPLE : public SegregatedSolverBase /// the pressure equation. std::pair solvePressureCorrector(); + /// Solve an equation which contains an advection term that depends + /// on the solution of the segregated Navier-Stokes equations. + /// @param system_num The number of the system which is solved + /// @param system Reference to the system which is solved + /// @param relaxation_factor The relaxation factor for matrix relaxation + /// @param solver_config The solver configuration object for the linear solve + /// @param abs_tol The scaled absolute tolerance for the linear solve + /// @return The normalized residual norm of the equation. + std::pair solveAdvectedSystem(const unsigned int system_num, + LinearSystem & system, + const Real relaxation_factor, + SolverConfiguration & solver_config, + const Real abs_tol); + /// The number(s) of the system(s) corresponding to the momentum equation(s) std::vector _momentum_system_numbers; /// The number of the system corresponding to the pressure equation const unsigned int _pressure_sys_number; + /// The number of the system corresponding to the energy equation + const unsigned int _energy_sys_number; + /// Pointer(s) to the system(s) corresponding to the momentum equation(s) std::vector _momentum_systems; /// Reference to the nonlinear system corresponding to the pressure equation LinearSystem & _pressure_system; + /// Pointer to the nonlinear system corresponding to the fluid energy equation + LinearSystem * _energy_system; + /// Pointer to the segregated RhieChow interpolation object RhieChowMassFlux * _rc_uo; }; diff --git a/modules/navier_stokes/src/executioners/SIMPLE.C b/modules/navier_stokes/src/executioners/SIMPLE.C index f751e198ec12..44f290ee25dc 100644 --- a/modules/navier_stokes/src/executioners/SIMPLE.C +++ b/modules/navier_stokes/src/executioners/SIMPLE.C @@ -35,16 +35,16 @@ SIMPLE::validParams() /* * We suppress parameters which are not supported yet */ - params.suppressParameter("energy_system"); + // params.suppressParameter("energy_system"); params.suppressParameter("solid_energy_system"); params.suppressParameter>("passive_scalar_systems"); params.suppressParameter>("turbulence_systems"); - params.suppressParameter("energy_equation_relaxation"); + // params.suppressParameter("energy_equation_relaxation"); params.suppressParameter>("passive_scalar_equation_relaxation"); params.suppressParameter>("turbulence_equation_relaxation"); - params.suppressParameter("energy_petsc_options"); - params.suppressParameter("energy_petsc_options_iname"); - params.suppressParameter>("energy_petsc_options_value"); + // params.suppressParameter("energy_petsc_options"); + // params.suppressParameter("energy_petsc_options_iname"); + // params.suppressParameter>("energy_petsc_options_value"); params.suppressParameter("solid_energy_petsc_options"); params.suppressParameter("solid_energy_petsc_options_iname"); params.suppressParameter>("solid_energy_petsc_options_value"); @@ -54,13 +54,13 @@ SIMPLE::validParams() params.suppressParameter("turbulence_petsc_options"); params.suppressParameter("turbulence_petsc_options_iname"); params.suppressParameter>("turbulence_petsc_options_value"); - params.suppressParameter("energy_absolute_tolerance"); + // params.suppressParameter("energy_absolute_tolerance"); params.suppressParameter("solid_energy_absolute_tolerance"); params.suppressParameter>("passive_scalar_absolute_tolerance"); params.suppressParameter>("turbulence_absolute_tolerance"); - params.suppressParameter("energy_l_tol"); - params.suppressParameter("energy_l_abs_tol"); - params.suppressParameter("energy_l_max_its"); + // params.suppressParameter("energy_l_tol"); + // params.suppressParameter("energy_l_abs_tol"); + // params.suppressParameter("energy_l_max_its"); params.suppressParameter("solid_energy_l_tol"); params.suppressParameter("solid_energy_l_abs_tol"); params.suppressParameter("solid_energy_l_max_its"); @@ -77,7 +77,11 @@ SIMPLE::validParams() SIMPLE::SIMPLE(const InputParameters & parameters) : SegregatedSolverBase(parameters), _pressure_sys_number(_problem.linearSysNum(getParam("pressure_system"))), - _pressure_system(_problem.getLinearSystem(_pressure_sys_number)) + _energy_sys_number(_has_energy_system + ? _problem.linearSysNum(getParam("energy_system")) + : libMesh::invalid_uint), + _pressure_system(_problem.getLinearSystem(_pressure_sys_number)), + _energy_system(_has_energy_system ? &_problem.getLinearSystem(_energy_sys_number) : nullptr) { // We fetch the system numbers for the momentum components plus add vectors // for removing the contribution from the pressure gradient terms. @@ -253,6 +257,81 @@ SIMPLE::solvePressureCorrector() return std::make_pair(its_res_pair.first, pressure_solver.get_initial_residual() / norm_factor); } +std::pair +SIMPLE::solveAdvectedSystem(const unsigned int system_num, + LinearSystem & system, + const Real relaxation_factor, + SolverConfiguration & solver_config, + const Real absolute_tol) +{ + _problem.setCurrentLinearSystem(system_num); + + // We will need some members from the implicit linear system + LinearImplicitSystem & ni_system = libMesh::cast_ref(system.system()); + + // We will need the solution, the right hand side and the matrix + NumericVector & current_local_solution = *(ni_system.current_local_solution); + NumericVector & solution = *(ni_system.solution); + SparseMatrix & mmat = *(ni_system.matrix); + NumericVector & rhs = *(ni_system.rhs); + + mmat.zero(); + rhs.zero(); + + // We need a vector that stores the (diagonal_relaxed-original_diagonal) vector + auto diff_diagonal = solution.zero_clone(); + + // Fetch the linear solver from the system + PetscLinearSolver & linear_solver = + libMesh::cast_ref &>(*ni_system.get_linear_solver()); + + _problem.computeLinearSystemSys(ni_system, mmat, rhs, false); + + // We need a zero vector to be able to emulate the Ax=b system by evaluating the + // residual and jacobian. Unfortunately, this will leave us with the -b on the right hand side + // so we correct it by multiplying it with (-1) + // auto zero_solution = current_local_solution.zero_clone(); + //_problem.computeResidualAndJacobian(*zero_solution, rhs, mmat); + // rhs.scale(-1.0); + + // Go and relax the system matrix and the right hand side + relaxMatrix(mmat, relaxation_factor, *diff_diagonal); + relaxRightHandSide(rhs, solution, *diff_diagonal); + + if (_print_fields) + { + _console << system.name() << " system matrix" << std::endl; + mmat.print(); + } + + // We compute the normalization factors based on the fluxes + Real norm_factor = computeNormalizationFactor(solution, mmat, rhs); + + // We need the non-preconditioned norm to be consistent with the norm factor + LIBMESH_CHKERR(KSPSetNormType(linear_solver.ksp(), KSP_NORM_UNPRECONDITIONED)); + + // Setting the linear tolerances and maximum iteration counts + solver_config.real_valued_data["abs_tol"] = absolute_tol * norm_factor; + linear_solver.set_solver_configuration(solver_config); + + // Solve the system and update current local solution + auto its_res_pair = linear_solver.solve(mmat, mmat, solution, rhs); + ni_system.update(); + + if (_print_fields) + { + _console << " rhs when we solve " << system.name() << std::endl; + rhs.print(); + _console << system.name() << " solution " << std::endl; + solution.print(); + _console << " Norm factor " << norm_factor << std::endl; + } + + system.setSolution(current_local_solution); + + return std::make_pair(its_res_pair.first, linear_solver.get_initial_residual() / norm_factor); +} + void SIMPLE::execute() { @@ -307,15 +386,22 @@ SIMPLE::execute() unsigned int iteration_counter = 0; // Assign residuals to general residual vector - unsigned int no_systems = _momentum_systems.size() + 1; + unsigned int no_systems = _momentum_systems.size() + 1 + _has_energy_system; std::vector> ns_residuals(no_systems, std::make_pair(0, 1.0)); std::vector ns_abs_tols(_momentum_systems.size(), _momentum_absolute_tolerance); ns_abs_tols.push_back(_pressure_absolute_tolerance); + if (_has_energy_system) + { + ns_abs_tols.push_back(_energy_absolute_tolerance); + // if (_has_solid_energy_system) + // ns_abs_tols.push_back(_solid_energy_absolute_tolerance); + } // Loop until converged or hit the maximum allowed iteration number while (iteration_counter < _num_iterations && !converged(ns_residuals, ns_abs_tols)) { iteration_counter++; + size_t residual_index = 0; // We set the preconditioner/controllable parameters through petsc options. Linear // tolerances will be overridden within the solver. In case of a segregated momentum @@ -360,6 +446,33 @@ SIMPLE::execute() // Reconstruct the cell velocity as well to accelerate convergence _rc_uo->computeCellVelocity(); + // Update residual index + residual_index = momentum_residual.size(); + + // If we have an energy equation, solve it here. We assume the material properties in the + // Navier-Stokes equations depend on temperature, therefore we can not solve for temperature + // outside of the velocity-pressure loop + if (_has_energy_system) + { + // We set the preconditioner/controllable parameters through petsc options. Linear + // tolerances will be overridden within the solver. + Moose::PetscSupport::petscSetOptions(_energy_petsc_options, solver_params); + residual_index += 1; + ns_residuals[residual_index] = solveAdvectedSystem(_energy_sys_number, + *_energy_system, + _energy_equation_relaxation, + _energy_linear_control, + _energy_l_abs_tol); + + // if (_has_solid_energy_system) + //{ + // We set the preconditioner/controllable parameters through petsc options. Linear + // tolerances will be overridden within the solver. + // Moose::PetscSupport::petscSetOptions(_energy_petsc_options, solver_params); + // residual_index += 1; + // ns_its_residuals[residual_index] = solveSolidEnergySystem(); + //} + } // Printing residuals _console << "Iteration " << iteration_counter << " Initial residual norms:" << std::endl; for (auto system_i : index_range(_momentum_systems)) @@ -373,6 +486,20 @@ SIMPLE::execute() _console << " Pressure equation: " << COLOR_GREEN << ns_residuals[momentum_residual.size()].second << COLOR_DEFAULT << " Linear its: " << ns_residuals[momentum_residual.size()].first << std::endl; + residual_index = momentum_residual.size(); + + if (_has_energy_system) + { + residual_index += 1; + _console << " Energy equation: " << COLOR_GREEN << ns_residuals[residual_index].second + << COLOR_DEFAULT << std::endl; + // if (_has_solid_energy_system) + //{ + // residual_index += 1; + // _console << " Solid energy equation: " << COLOR_GREEN + // << ns_residuals[residual_index].second << COLOR_DEFAULT << std::endl; + // } + } } } From 24cb5ccd03ece88c7d4e86d19014c95aec5be0d6 Mon Sep 17 00:00:00 2001 From: Peter German Date: Wed, 30 Oct 2024 15:42:21 -0600 Subject: [PATCH 05/16] Modify advection kernel. (#28951) --- .../linearfvkernels/LinearFVEnergyAdvection.h | 6 +++--- .../linearfvkernels/LinearFVEnergyAdvection.C | 20 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h index 72af0030aec2..5769be69356b 100644 --- a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h @@ -38,12 +38,12 @@ class LinearFVEnergyAdvection : public LinearFVFluxKernel virtual void setupFaceData(const FaceInfo * face_info) override; protected: - /// The advected heat quantity - const Moose::Functor & _adv_quant; - /// The Rhie-Chow user object that provides us with the face velocity const RhieChowMassFlux & _mass_flux_provider; + const Real _cp; + +private: /// Container for the current advected interpolation coefficients on the face to make sure /// we don't compute it multiple times for different terms. std::pair _advected_interp_coeffs; diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C index 6b0a48029036..513439d4eb0f 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C @@ -18,11 +18,11 @@ InputParameters LinearFVEnergyAdvection::validParams() { InputParameters params = LinearFVFluxKernel::validParams(); - params.addClassDescription("Represents the matrix and right hand side contributions of an " - "advection term for the energy e.g. h=cp*T. A user may still " - "override what quantity is advected, but the default is cp*T."); - params.addParam( - "advected_quantity", NS::specific_enthalpy, "The heat quantity to advect."); + params.addClassDescription( + "Represents the matrix and right hand side contributions of an " + "advection term for the energy e.g. h=int(cp dT). A user may still " + "override what quantity is advected, but the default is specific enthalpy."); + params.addParam("cp", 1, "blabla"); params.addRequiredParam( "rhie_chow_user_object", "The rhie-chow user-object which is used to determine the face velocity."); @@ -32,8 +32,8 @@ LinearFVEnergyAdvection::validParams() LinearFVEnergyAdvection::LinearFVEnergyAdvection(const InputParameters & params) : LinearFVFluxKernel(params), - _adv_quant(getFunctor("advected_quantity")), _mass_flux_provider(getUserObject("rhie_chow_user_object")), + _cp(getParam("cp")), _advected_interp_coeffs(std::make_pair(0, 0)), _face_mass_flux(0.0) { @@ -43,13 +43,13 @@ LinearFVEnergyAdvection::LinearFVEnergyAdvection(const InputParameters & params) Real LinearFVEnergyAdvection::computeElemMatrixContribution() { - return _advected_interp_coeffs.first * _face_mass_flux * _current_face_area; + return _cp*_advected_interp_coeffs.first * _face_mass_flux * _current_face_area; } Real LinearFVEnergyAdvection::computeNeighborMatrixContribution() { - return _advected_interp_coeffs.second * _face_mass_flux * _current_face_area; + return _cp*_advected_interp_coeffs.second * _face_mass_flux * _current_face_area; } Real @@ -75,7 +75,7 @@ LinearFVEnergyAdvection::computeBoundaryMatrixContribution(const LinearFVBoundar // We support internal boundaries too so we have to make sure the normal points always outward const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0; - return boundary_value_matrix_contrib * factor * _face_mass_flux * _current_face_area; + return _cp*boundary_value_matrix_contrib * factor * _face_mass_flux * _current_face_area; } Real @@ -88,7 +88,7 @@ LinearFVEnergyAdvection::computeBoundaryRHSContribution(const LinearFVBoundaryCo const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0); const auto boundary_value_rhs_contrib = adv_bc->computeBoundaryValueRHSContribution(); - return -boundary_value_rhs_contrib * factor * _face_mass_flux * _current_face_area; + return -_cp*boundary_value_rhs_contrib * factor * _face_mass_flux * _current_face_area; } void From 723a3e82d87b635ca5c35ab58326c799f63556cc Mon Sep 17 00:00:00 2001 From: Peter German Date: Wed, 30 Oct 2024 15:44:56 -0600 Subject: [PATCH 06/16] Modify boussinesq kernel to respect pseudo hydrostatic pressure. (#28951) --- framework/src/linearfvkernels/LinearFVSource.C | 2 +- .../linearfvkernels/LinearFVMomentumBoussinesq.h | 2 +- .../src/linearfvkernels/LinearFVMomentumBoussinesq.C | 12 ++++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/framework/src/linearfvkernels/LinearFVSource.C b/framework/src/linearfvkernels/LinearFVSource.C index 20e345f36f70..080282cfddb7 100644 --- a/framework/src/linearfvkernels/LinearFVSource.C +++ b/framework/src/linearfvkernels/LinearFVSource.C @@ -21,7 +21,7 @@ LinearFVSource::validParams() "Represents the matrix and right hand side contributions of a " "solution-independent source term in a partial differential equation."); params.addParam("source_density", 1.0, "The source density."); - params.addParam("scaling_factor", 1.0, "Coefficient to multiply by the body force term"); + params.addParam("scaling_factor", 1.0, "Coefficient to multiply the body force term with."); return params; } diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h index 12ca2c7f281c..338bbd8365cf 100644 --- a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h @@ -12,7 +12,7 @@ #include "LinearFVElementalKernel.h" /** - * Kernel that adds the component of the pressure gradient in the momentum + * Kernel that adds the component of the Boussinesq term in the momentum * equations to the right hand side. */ class LinearFVMomentumBoussinesq : public LinearFVElementalKernel diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C index cf9248dbcca2..324cb3dc7a7d 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C @@ -46,6 +46,7 @@ LinearFVMomentumBoussinesq::LinearFVMomentumBoussinesq(const InputParameters & p _ref_temperature(getParam("ref_temperature")), _rho(getFunctor(NS::density)) { + _temperature_var.computeCellGradients(); if (!_rho.isConstant() && !getParam("_override_constant_check")) paramError(NS::density, "The density in the boussinesq term is not constant!"); } @@ -74,6 +75,13 @@ LinearFVMomentumBoussinesq::computeRightHandSideContribution() { const auto elem = makeElemArg(_current_elem_info->elem()); const auto state = determineState(); - return -_alpha(elem, state) * _gravity(_index) * _rho(elem, state) * - (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature); + // return -_alpha(elem, state) * _gravity(_index) * _rho(elem, state) * + // (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature); + // _console << _alpha(elem, state) * _rho(elem, state) * + // _temperature_var.gradSln(*_current_elem_info)(_index) / 300 * + // (_current_elem_info->centroid() * _gravity) + // << std::endl; + return -_alpha(elem, state) * _rho(elem, state) * + _temperature_var.gradSln(*_current_elem_info)(_index) * + (_current_elem_info->centroid() * _gravity); } From ab8d4d3080b822e924261f4a7421d86bd34f41f2 Mon Sep 17 00:00:00 2001 From: Peter German Date: Wed, 30 Oct 2024 15:45:50 -0600 Subject: [PATCH 07/16] Add execute command to SIMPLE at NONLINEAR. (#28951) --- .../navier_stokes/src/executioners/SIMPLE.C | 56 ++++--------------- 1 file changed, 12 insertions(+), 44 deletions(-) diff --git a/modules/navier_stokes/src/executioners/SIMPLE.C b/modules/navier_stokes/src/executioners/SIMPLE.C index 44f290ee25dc..d173dc00ce8e 100644 --- a/modules/navier_stokes/src/executioners/SIMPLE.C +++ b/modules/navier_stokes/src/executioners/SIMPLE.C @@ -35,16 +35,11 @@ SIMPLE::validParams() /* * We suppress parameters which are not supported yet */ - // params.suppressParameter("energy_system"); params.suppressParameter("solid_energy_system"); params.suppressParameter>("passive_scalar_systems"); params.suppressParameter>("turbulence_systems"); - // params.suppressParameter("energy_equation_relaxation"); params.suppressParameter>("passive_scalar_equation_relaxation"); params.suppressParameter>("turbulence_equation_relaxation"); - // params.suppressParameter("energy_petsc_options"); - // params.suppressParameter("energy_petsc_options_iname"); - // params.suppressParameter>("energy_petsc_options_value"); params.suppressParameter("solid_energy_petsc_options"); params.suppressParameter("solid_energy_petsc_options_iname"); params.suppressParameter>("solid_energy_petsc_options_value"); @@ -54,13 +49,9 @@ SIMPLE::validParams() params.suppressParameter("turbulence_petsc_options"); params.suppressParameter("turbulence_petsc_options_iname"); params.suppressParameter>("turbulence_petsc_options_value"); - // params.suppressParameter("energy_absolute_tolerance"); params.suppressParameter("solid_energy_absolute_tolerance"); params.suppressParameter>("passive_scalar_absolute_tolerance"); params.suppressParameter>("turbulence_absolute_tolerance"); - // params.suppressParameter("energy_l_tol"); - // params.suppressParameter("energy_l_abs_tol"); - // params.suppressParameter("energy_l_max_its"); params.suppressParameter("solid_energy_l_tol"); params.suppressParameter("solid_energy_l_abs_tol"); params.suppressParameter("solid_energy_l_max_its"); @@ -267,13 +258,13 @@ SIMPLE::solveAdvectedSystem(const unsigned int system_num, _problem.setCurrentLinearSystem(system_num); // We will need some members from the implicit linear system - LinearImplicitSystem & ni_system = libMesh::cast_ref(system.system()); + LinearImplicitSystem & li_system = libMesh::cast_ref(system.system()); // We will need the solution, the right hand side and the matrix - NumericVector & current_local_solution = *(ni_system.current_local_solution); - NumericVector & solution = *(ni_system.solution); - SparseMatrix & mmat = *(ni_system.matrix); - NumericVector & rhs = *(ni_system.rhs); + NumericVector & current_local_solution = *(li_system.current_local_solution); + NumericVector & solution = *(li_system.solution); + SparseMatrix & mmat = *(li_system.matrix); + NumericVector & rhs = *(li_system.rhs); mmat.zero(); rhs.zero(); @@ -283,16 +274,9 @@ SIMPLE::solveAdvectedSystem(const unsigned int system_num, // Fetch the linear solver from the system PetscLinearSolver & linear_solver = - libMesh::cast_ref &>(*ni_system.get_linear_solver()); + libMesh::cast_ref &>(*li_system.get_linear_solver()); - _problem.computeLinearSystemSys(ni_system, mmat, rhs, false); - - // We need a zero vector to be able to emulate the Ax=b system by evaluating the - // residual and jacobian. Unfortunately, this will leave us with the -b on the right hand side - // so we correct it by multiplying it with (-1) - // auto zero_solution = current_local_solution.zero_clone(); - //_problem.computeResidualAndJacobian(*zero_solution, rhs, mmat); - // rhs.scale(-1.0); + _problem.computeLinearSystemSys(li_system, mmat, rhs, true); // Go and relax the system matrix and the right hand side relaxMatrix(mmat, relaxation_factor, *diff_diagonal); @@ -316,7 +300,7 @@ SIMPLE::solveAdvectedSystem(const unsigned int system_num, // Solve the system and update current local solution auto its_res_pair = linear_solver.solve(mmat, mmat, solution, rhs); - ni_system.update(); + li_system.update(); if (_print_fields) { @@ -390,13 +374,9 @@ SIMPLE::execute() std::vector> ns_residuals(no_systems, std::make_pair(0, 1.0)); std::vector ns_abs_tols(_momentum_systems.size(), _momentum_absolute_tolerance); ns_abs_tols.push_back(_pressure_absolute_tolerance); - if (_has_energy_system) - { ns_abs_tols.push_back(_energy_absolute_tolerance); - // if (_has_solid_energy_system) - // ns_abs_tols.push_back(_solid_energy_absolute_tolerance); - } + // Loop until converged or hit the maximum allowed iteration number while (iteration_counter < _num_iterations && !converged(ns_residuals, ns_abs_tols)) { @@ -464,14 +444,7 @@ SIMPLE::execute() _energy_linear_control, _energy_l_abs_tol); - // if (_has_solid_energy_system) - //{ - // We set the preconditioner/controllable parameters through petsc options. Linear - // tolerances will be overridden within the solver. - // Moose::PetscSupport::petscSetOptions(_energy_petsc_options, solver_params); - // residual_index += 1; - // ns_its_residuals[residual_index] = solveSolidEnergySystem(); - //} + _problem.execute(EXEC_NONLINEAR); } // Printing residuals _console << "Iteration " << iteration_counter << " Initial residual norms:" << std::endl; @@ -492,13 +465,8 @@ SIMPLE::execute() { residual_index += 1; _console << " Energy equation: " << COLOR_GREEN << ns_residuals[residual_index].second - << COLOR_DEFAULT << std::endl; - // if (_has_solid_energy_system) - //{ - // residual_index += 1; - // _console << " Solid energy equation: " << COLOR_GREEN - // << ns_residuals[residual_index].second << COLOR_DEFAULT << std::endl; - // } + << COLOR_DEFAULT << " Linear its: " << ns_residuals[residual_index].first + << std::endl; } } } From 2aad0c1800dcef58753b34648b31620fac9e1a56 Mon Sep 17 00:00:00 2001 From: Peter German Date: Wed, 30 Oct 2024 15:46:22 -0600 Subject: [PATCH 08/16] Add channel test case with Boussinesq. (#28951) --- .../linear-segregated/2d/2d-boussinesq.i | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i new file mode 100644 index 000000000000..bdadc6c27f14 --- /dev/null +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i @@ -0,0 +1,266 @@ +mu = 2.6 +rho = 1.0 +advected_interp_method = 'average' +cp = 300 +k = 20 +alpha_b = 1e-4 + +[Mesh] + [mesh] + type = CartesianMeshGenerator + dim = 2 + dx = '1.5' + dy = '0.3' + ix = '80' + iy = '30' + [] +[] + +[Problem] + linear_sys_names = 'u_system v_system pressure_system energy_system' + previous_nl_solution_required = true +[] + +[UserObjects] + [rc] + type = RhieChowMassFlux + u = vel_x + v = vel_y + pressure = pressure + rho = ${rho} + p_diffusion_kernel = p_diffusion + [] +[] + +[Variables] + [vel_x] + type = MooseLinearVariableFVReal + initial_condition = 0.5 + solver_sys = u_system + [] + [vel_y] + type = MooseLinearVariableFVReal + solver_sys = v_system + initial_condition = 0.0 + [] + [pressure] + type = MooseLinearVariableFVReal + solver_sys = pressure_system + initial_condition = 0.2 + [] + [h] + type = MooseLinearVariableFVReal + solver_sys = energy_system + initial_condition = ${fparse 300*cp} + [] +[] + +[LinearFVKernels] + [u_advection_stress] + type = LinearWCNSFVMomentumFlux + variable = vel_x + advected_interp_method = ${advected_interp_method} + mu = ${mu} + u = vel_x + v = vel_y + momentum_component = 'x' + rhie_chow_user_object = 'rc' + use_nonorthogonal_correction = false + [] + [v_advection_stress] + type = LinearWCNSFVMomentumFlux + variable = vel_y + advected_interp_method = ${advected_interp_method} + mu = ${mu} + u = vel_x + v = vel_y + momentum_component = 'y' + rhie_chow_user_object = 'rc' + use_nonorthogonal_correction = false + [] + [u_pressure] + type = LinearFVMomentumPressure + variable = vel_x + pressure = pressure + momentum_component = 'x' + [] + [v_pressure] + type = LinearFVMomentumPressure + variable = vel_y + pressure = pressure + momentum_component = 'y' + [] + [u_boussinesq] + type = LinearFVMomentumBoussinesq + variable = vel_x + rho = ${rho} + gravity = '0 -9.81 0' + alpha_name = ${alpha_b} + ref_temperature = 300 + T_fluid = h + momentum_component = 'y' + [] + [v_boussinesq] + type = LinearFVMomentumBoussinesq + variable = vel_y + rho = ${rho} + gravity = '0 -9.81 0' + alpha_name = ${alpha_b} + ref_temperature = 300 + T_fluid = h + momentum_component = 'y' + [] + + [p_diffusion] + type = LinearFVAnisotropicDiffusion + variable = pressure + diffusion_tensor = Ainv + use_nonorthogonal_correction = false + [] + [HbyA_divergence] + type = LinearFVDivergence + variable = pressure + face_flux = HbyA + force_boundary_execution = true + [] + + [h_advection] + type = LinearFVEnergyAdvection + variable = h + advected_interp_method = ${advected_interp_method} + rhie_chow_user_object = 'rc' + [] + [conduction] + type = LinearFVDiffusion + variable = h + diffusion_coeff = ${fparse k/cp} + use_nonorthogonal_correction = true + [] +[] + +[AuxVariables] + [T_fluid] + type = MooseLinearVariableFVReal + solver_sys = energy_system + initial_condition = 300 + [] +[] + +[AuxKernels] + [enthalpy_to_temperature] + type = FunctorAux + variable = T_fluid + functor = enthalpy_to_temperature + execute_on = NONLINEAR + [] +[] + +[FunctorMaterials] + [constant_functors] + type = GenericFunctorMaterial + prop_names = 'cp alpha_b' + prop_values = '${cp} ${alpha_b}' + [] + [enthalpy_to_temperature] + type = ADParsedFunctorMaterial + property_name = enthalpy_to_temperature + functor_names = "h cp" + functor_symbols = "h cp" + expression = "h/cp" + [] +[] + +[LinearFVBCs] + [inlet-u] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + boundary = 'left' + variable = vel_x + functor = '1.1' + [] + [inlet-v] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + boundary = 'left' + variable = vel_y + functor = '0.0' + [] + [walls-u] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + boundary = 'top bottom' + variable = vel_x + functor = 0.0 + [] + [walls-v] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + boundary = 'top bottom' + variable = vel_y + functor = 0.0 + [] + [outlet_p] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + boundary = 'right' + variable = pressure + functor = 1.4 + [] + [outlet_u] + type = LinearFVAdvectionDiffusionOutflowBC + variable = vel_x + use_two_term_expansion = false + boundary = right + [] + [outlet_v] + type = LinearFVAdvectionDiffusionOutflowBC + variable = vel_y + use_two_term_expansion = false + boundary = right + [] + [inlet_top_T] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + variable = h + functor = ${fparse cp*300.0} + boundary = 'left top' + [] + [bottom_T] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + variable = h + functor = ${fparse cp*350.0} + boundary = bottom + [] + [outlet_T] + type = LinearFVAdvectionDiffusionOutflowBC + variable = h + use_two_term_expansion = false + boundary = right + [] +[] + +[Executioner] + type = SIMPLE + momentum_l_abs_tol = 1e-10 + pressure_l_abs_tol = 1e-10 + energy_l_abs_tol = 1e-10 + momentum_l_tol = 0 + pressure_l_tol = 0 + energy_l_tol = 0 + rhie_chow_user_object = 'rc' + momentum_systems = 'u_system v_system' + pressure_system = 'pressure_system' + energy_system = 'energy_system' + momentum_equation_relaxation = 0.8 + energy_equation_relaxation = 0.9 + pressure_variable_relaxation = 0.3 + num_iterations = 200 + pressure_absolute_tolerance = 1e-10 + momentum_absolute_tolerance = 1e-10 + energy_absolute_tolerance = 1e-10 + momentum_petsc_options_iname = '-pc_type -pc_hypre_type' + momentum_petsc_options_value = 'hypre boomeramg' + pressure_petsc_options_iname = '-pc_type -pc_hypre_type' + pressure_petsc_options_value = 'hypre boomeramg' + energy_petsc_options_iname = '-pc_type -pc_hypre_type' + energy_petsc_options_value = 'hypre boomeramg' + print_fields = false +[] + +[Outputs] + exodus = true +[] From 186e837774b1851555f6db91f588d64ad728e9c1 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Thu, 7 Nov 2024 10:15:45 -0700 Subject: [PATCH 09/16] Modify EnergyAdvection to solve for temperature --- .../linearfvkernels/LinearFVEnergyAdvection.C | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C index 513439d4eb0f..8f1c8cbe6fc8 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C @@ -18,11 +18,10 @@ InputParameters LinearFVEnergyAdvection::validParams() { InputParameters params = LinearFVFluxKernel::validParams(); - params.addClassDescription( - "Represents the matrix and right hand side contributions of an " - "advection term for the energy e.g. h=int(cp dT). A user may still " - "override what quantity is advected, but the default is specific enthalpy."); - params.addParam("cp", 1, "blabla"); + params.addClassDescription("Represents the matrix and right hand side contributions of an " + "advection term for the energy e.g. h=int(cp dT). A user may still " + "override what quantity is advected, but the default is temperature."); + params.addParam("cp", 1, "Specific heat value"); params.addRequiredParam( "rhie_chow_user_object", "The rhie-chow user-object which is used to determine the face velocity."); @@ -43,13 +42,13 @@ LinearFVEnergyAdvection::LinearFVEnergyAdvection(const InputParameters & params) Real LinearFVEnergyAdvection::computeElemMatrixContribution() { - return _cp*_advected_interp_coeffs.first * _face_mass_flux * _current_face_area; + return _cp * _advected_interp_coeffs.first * _face_mass_flux * _current_face_area; } Real LinearFVEnergyAdvection::computeNeighborMatrixContribution() { - return _cp*_advected_interp_coeffs.second * _face_mass_flux * _current_face_area; + return _cp * _advected_interp_coeffs.second * _face_mass_flux * _current_face_area; } Real @@ -75,7 +74,7 @@ LinearFVEnergyAdvection::computeBoundaryMatrixContribution(const LinearFVBoundar // We support internal boundaries too so we have to make sure the normal points always outward const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM) ? 1.0 : -1.0; - return _cp*boundary_value_matrix_contrib * factor * _face_mass_flux * _current_face_area; + return _cp * boundary_value_matrix_contrib * factor * _face_mass_flux * _current_face_area; } Real @@ -88,7 +87,7 @@ LinearFVEnergyAdvection::computeBoundaryRHSContribution(const LinearFVBoundaryCo const auto factor = (_current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0); const auto boundary_value_rhs_contrib = adv_bc->computeBoundaryValueRHSContribution(); - return -_cp*boundary_value_rhs_contrib * factor * _face_mass_flux * _current_face_area; + return -_cp * boundary_value_rhs_contrib * factor * _face_mass_flux * _current_face_area; } void From 7d0399f6291f7a0ef2d60a1a6f00acc73efbd20e Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Thu, 7 Nov 2024 10:16:21 -0700 Subject: [PATCH 10/16] Multiply the Boussinesq force by the element volume --- .../src/linearfvkernels/LinearFVMomentumBoussinesq.C | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C index 324cb3dc7a7d..d3f11c7f98c8 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C @@ -75,13 +75,7 @@ LinearFVMomentumBoussinesq::computeRightHandSideContribution() { const auto elem = makeElemArg(_current_elem_info->elem()); const auto state = determineState(); - // return -_alpha(elem, state) * _gravity(_index) * _rho(elem, state) * - // (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature); - // _console << _alpha(elem, state) * _rho(elem, state) * - // _temperature_var.gradSln(*_current_elem_info)(_index) / 300 * - // (_current_elem_info->centroid() * _gravity) - // << std::endl; - return -_alpha(elem, state) * _rho(elem, state) * - _temperature_var.gradSln(*_current_elem_info)(_index) * - (_current_elem_info->centroid() * _gravity); + return -_alpha(elem, state) * _gravity(_index) * _rho(elem, state) * + (_temperature_var.getElemValue(*_current_elem_info, state) - _ref_temperature) * + _current_elem_volume; } From d86750b87695ae9bae2b3228320028ff133b5247 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Thu, 7 Nov 2024 10:18:58 -0700 Subject: [PATCH 11/16] Adding tests for the Boussinesq buoyancy treatment #28951 --- .../linear-segregated/2d/2d-boussinesq.i | 61 ++--- .../channel-flow/linear-segregated/2d/tests | 14 +- .../diff_heated_cavity_linear_segregated.i | 250 ++++++++++++++++++ .../ins/natural_convection/tests | 10 +- 4 files changed, 289 insertions(+), 46 deletions(-) create mode 100644 modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i index bdadc6c27f14..bfb0490a476b 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i @@ -11,8 +11,8 @@ alpha_b = 1e-4 dim = 2 dx = '1.5' dy = '0.3' - ix = '80' - iy = '30' + ix = '55' + iy = '20' [] [] @@ -48,10 +48,10 @@ alpha_b = 1e-4 solver_sys = pressure_system initial_condition = 0.2 [] - [h] + [T] type = MooseLinearVariableFVReal solver_sys = energy_system - initial_condition = ${fparse 300*cp} + initial_condition = 300 [] [] @@ -96,9 +96,9 @@ alpha_b = 1e-4 rho = ${rho} gravity = '0 -9.81 0' alpha_name = ${alpha_b} - ref_temperature = 300 - T_fluid = h - momentum_component = 'y' + ref_temperature = 300.0 + T_fluid = T + momentum_component = 'x' [] [v_boussinesq] type = LinearFVMomentumBoussinesq @@ -106,8 +106,8 @@ alpha_b = 1e-4 rho = ${rho} gravity = '0 -9.81 0' alpha_name = ${alpha_b} - ref_temperature = 300 - T_fluid = h + ref_temperature = 300.0 + T_fluid = T momentum_component = 'y' [] @@ -126,32 +126,16 @@ alpha_b = 1e-4 [h_advection] type = LinearFVEnergyAdvection - variable = h + variable = T + cp = ${cp} advected_interp_method = ${advected_interp_method} rhie_chow_user_object = 'rc' [] [conduction] type = LinearFVDiffusion - variable = h - diffusion_coeff = ${fparse k/cp} - use_nonorthogonal_correction = true - [] -[] - -[AuxVariables] - [T_fluid] - type = MooseLinearVariableFVReal - solver_sys = energy_system - initial_condition = 300 - [] -[] - -[AuxKernels] - [enthalpy_to_temperature] - type = FunctorAux - variable = T_fluid - functor = enthalpy_to_temperature - execute_on = NONLINEAR + variable = T + diffusion_coeff = ${k} + # use_nonorthogonal_correction = true [] [] @@ -161,13 +145,6 @@ alpha_b = 1e-4 prop_names = 'cp alpha_b' prop_values = '${cp} ${alpha_b}' [] - [enthalpy_to_temperature] - type = ADParsedFunctorMaterial - property_name = enthalpy_to_temperature - functor_names = "h cp" - functor_symbols = "h cp" - expression = "h/cp" - [] [] [LinearFVBCs] @@ -215,19 +192,19 @@ alpha_b = 1e-4 [] [inlet_top_T] type = LinearFVAdvectionDiffusionFunctorDirichletBC - variable = h - functor = ${fparse cp*300.0} + variable = T + functor = ${fparse 300.0} boundary = 'left top' [] [bottom_T] type = LinearFVAdvectionDiffusionFunctorDirichletBC - variable = h - functor = ${fparse cp*350.0} + variable = T + functor = ${fparse 350.0} boundary = bottom [] [outlet_T] type = LinearFVAdvectionDiffusionOutflowBC - variable = h + variable = T use_two_term_expansion = false boundary = right [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests index 912c2b751882..2a03c5454712 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests @@ -1,6 +1,6 @@ [Tests] - issues = '#27280' - design = 'SIMPLE.md LinearFVDivergence.md LinearWCNSFVMomentumFlux.md LinearFVMomentumPressure.md' + issues = '#27280 #28951' + design = 'SIMPLE.md LinearFVDivergence.md LinearWCNSFVMomentumFlux.md LinearFVMomentumPressure.md LinearFVEnergyAdvection.md LinearFVMomentumBoussinesq' [momentum-pressure] type = 'Exodiff' input = 2d-velocity-pressure.i @@ -10,4 +10,14 @@ recover = false # we don't support recovery for SIMPLE yet max_threads = 1 # see libmesh issue #3808 [] + [energy_boussinesq] + type = 'Exodiff' + input = 2d-boussinesq.i + exodiff = 2d-boussinesq_out.e + requirement = "The system shall be able to solve the steady-state Navier-Stokes - energy-coupled " + "problem in a 2D channel using the Boussinesq approximation for fluid density " + "temperature variations with the SIMPLE algorithm using the linear finite volume system." + recover = false # we don't support recovery for SIMPLE yet + max_threads = 1 # see libmesh issue #3808 + [] [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i new file mode 100644 index 000000000000..1f4e17ba6510 --- /dev/null +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i @@ -0,0 +1,250 @@ +################################################################################ +# MATERIAL PROPERTIES +################################################################################ +rho = 3279. +T_0 = 875.0 +mu = 1. +k_cond = 38.0 +cp = 640. +alpha = 3.26e-4 + +walls = 'right left top bottom' + +[GlobalParams] + rhie_chow_user_object = 'ins_rhie_chow_interpolator' + advected_interp_method = 'upwind' + u = superficial_vel_x + v = superficial_vel_y +[] + +[Problem] + linear_sys_names = 'u_system v_system pressure_system energy_system' + previous_nl_solution_required = true +[] + +################################################################################ +# GEOMETRY +################################################################################ + +[Mesh] + [gen] + type = GeneratedMeshGenerator + dim = 2 + xmin = 0 + xmax = 1 + ymin = 0 + ymax = 1 + nx = 40 + ny = 40 + [] +[] + +################################################################################ +# EQUATIONS: VARIABLES, KERNELS & BCS +################################################################################ + +[UserObjects] + [ins_rhie_chow_interpolator] + type = RhieChowMassFlux + u = superficial_vel_x + v = superficial_vel_y + pressure = pressure + rho = ${rho} + p_diffusion_kernel = p_diffusion + [] +[] + +[Variables] + [superficial_vel_x] + type = MooseLinearVariableFVReal + solver_sys = u_system + [] + [superficial_vel_y] + type = MooseLinearVariableFVReal + solver_sys = v_system + [] + [pressure] + type = MooseLinearVariableFVReal + initial_condition = 0 + solver_sys = pressure_system + [] + [T_fluid] + type = MooseLinearVariableFVReal + solver_sys = energy_system + initial_condition = ${fparse 875} + [] +[] + +[LinearFVKernels] + [u_advection_stress] + type = LinearWCNSFVMomentumFlux + variable = superficial_vel_x + mu = ${mu} + momentum_component = 'x' + use_nonorthogonal_correction = true + [] + [u_pressure] + type = LinearFVMomentumPressure + variable = superficial_vel_x + pressure = pressure + momentum_component = 'x' + [] + [u_buoyancy] + type = LinearFVMomentumBoussinesq + variable = superficial_vel_x + T_fluid = T_fluid + gravity = '0 -9.81 0' + rho = ${rho} + ref_temperature = ${T_0} + alpha_name = ${alpha} + momentum_component = 'x' + [] + + [v_advection_stress] + type = LinearWCNSFVMomentumFlux + variable = superficial_vel_y + mu = ${mu} + momentum_component = 'y' + use_nonorthogonal_correction = true + [] + [v_pressure] + type = LinearFVMomentumPressure + variable = superficial_vel_y + pressure = pressure + momentum_component = 'y' + [] + [v_buoyancy] + type = LinearFVMomentumBoussinesq + variable = superficial_vel_y + T_fluid = T_fluid + gravity = '0 -9.81 0' + rho = ${rho} + ref_temperature = ${T_0} + alpha_name = ${alpha} + momentum_component = 'y' + [] + + [p_diffusion] + type = LinearFVAnisotropicDiffusion + variable = pressure + diffusion_tensor = Ainv + use_nonorthogonal_correction = true + [] + [HbyA_divergence] + type = LinearFVDivergence + variable = pressure + face_flux = HbyA + force_boundary_execution = true + [] + + ####### FUEL ENERGY EQUATION ####### + + [heat_advection] + type = LinearFVEnergyAdvection + variable = T_fluid + cp = ${cp} + [] + [conduction] + type = LinearFVDiffusion + variable = T_fluid + diffusion_coeff = ${fparse k_cond} + [] +[] + + +[LinearFVBCs] + [no-slip-u] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + variable = superficial_vel_x + boundary = ${walls} + functor = 0 + [] + [no-slip-v] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + variable = superficial_vel_y + boundary = ${walls} + functor = 0 + [] + [T_cold] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + variable = T_fluid + boundary = 'right' + functor = ${fparse 870.0} + [] + [T_hot] + type = LinearFVAdvectionDiffusionFunctorDirichletBC + variable = T_fluid + boundary = 'left' + functor = ${fparse 880.0} + [] + [T_all] + type = LinearFVAdvectionDiffusionExtrapolatedBC + variable = T_fluid + boundary = 'top bottom' + use_two_term_expansion = false + [] + [pressure-extrapolation] + type = LinearFVExtrapolatedPressureBC + boundary = ${walls} + variable = pressure + use_two_term_expansion = false + [] +[] + +[FunctorMaterials] + [constant_functors] + type = GenericFunctorMaterial + prop_names = 'cp alpha_b' + prop_values = '${cp} ${alpha}' + [] +[] + +################################################################################ +# EXECUTION / SOLVE +################################################################################ + +[Executioner] + type = SIMPLE + momentum_l_abs_tol = 1e-11 + pressure_l_abs_tol = 1e-11 + energy_l_abs_tol = 1e-11 + momentum_l_tol = 0 + pressure_l_tol = 0 + energy_l_tol = 0 + rhie_chow_user_object = 'ins_rhie_chow_interpolator' + momentum_systems = 'u_system v_system' + pressure_system = 'pressure_system' + energy_system = 'energy_system' + momentum_equation_relaxation = 0.3 + pressure_variable_relaxation = 0.7 + energy_equation_relaxation = 0.95 + num_iterations = 3000 + pressure_absolute_tolerance = 1e-8 + momentum_absolute_tolerance = 1e-8 + energy_absolute_tolerance = 1e-6 + print_fields = false + momentum_l_max_its = 300 + + pin_pressure = true + pressure_pin_value = 0.0 + pressure_pin_point = '0.5 0.0 0.0' + + # momentum_petsc_options = '-ksp_monitor' + momentum_petsc_options_iname = '-pc_type -pc_hypre_type' + momentum_petsc_options_value = 'hypre boomeramg' + + pressure_petsc_options_iname = '-pc_type -pc_hypre_type' + pressure_petsc_options_value = 'hypre boomeramg' + + energy_petsc_options_iname = '-pc_type -pc_hypre_type' + energy_petsc_options_value = 'hypre boomeramg' +[] + +################################################################################ +# SIMULATION OUTPUTS +################################################################################ + +[Outputs] + exodus = true +[] + diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests index b7668e178d96..0a7ddd588bb5 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests @@ -1,6 +1,6 @@ [Tests] - design = 'NSFVAction.md' - issues = '#21380 #24662' + design = 'NSFVAction.md LinearFVEnergyAdvection.md LinearFVMomentumBoussinesq.md' + issues = '#21380 #24662 #28951' [natural_circulation_dogleg] type = 'Exodiff' input = 'natural_circulation_dogleg.i' @@ -15,4 +15,10 @@ rel_err = 1.0E-7 method = opt [] + [diff_heated_cavity_linear_segregated] + type = 'Exodiff' + input = 'diff_heated_cavity_linear_segregated.i' + exodiff = 'diff_heated_cavity_linear_segregated_out.e' + requirement = 'The system shall be able to use the density Boussinesq approximation to solve for a differentially heated 2D cavity.' + [] [] From 962666aa32204da1d225d31c77c7acdd11753c3b Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Thu, 7 Nov 2024 10:19:54 -0700 Subject: [PATCH 12/16] Add documentation for the Linear FV Kernels for energy advection and Boussinesq buoyancy force treatment #28951 --- .../LinearFVEnergyAdvection.md | 23 +++++++++++++++++++ .../LinearFVMomentumBoussinesq.md | 14 +++++++++++ 2 files changed, 37 insertions(+) create mode 100644 modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md create mode 100644 modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md diff --git a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md new file mode 100644 index 000000000000..6f34867568bf --- /dev/null +++ b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md @@ -0,0 +1,23 @@ +# LinearFVEnergyAdvection + +This kernel adds the contributions of the energy advection term to the matrix and right hand side of the energy equation system for the finite volume SIMPLE segregated solver [SIMPLE.md]. + +This term is described by $\nabla \cdot \left(\rho\vec{u} c_p T \right)$ present in the energy equation conservation for an incompressible/weakly-compressible formulation. Currently, the kernel only supports constant specific heat values for $c_p$ and solves for a temperature variable. The specific heat value needs to be prescribed, otherwise it will default to its default value of $c_p=1$. + +For FV, the integral of the advection term over a cell can be expressed as: + +\begin{equation} +\int\limits_{V_C} \nabla \cdot \left(\rho\vec{u} c_p T \right) dV \approx \sum\limits_f (\rho \vec{u}\cdot \vec{n})_{RC} c_p T_f |S_f| \, +\end{equation} + +where $T_f$ is a face temperature. The temperature acts as the advected quantity and an interpolation scheme (e.g. upwind) can be used to copmute the face value. This kernel adds the face contribution for each face $f$ to the right hand side and matrix. + +The face mass flux $(\rho \vec{u}\cdot \vec{n})_{RC}$ is provided by the [RhieChowMassFlux.md] object which uses pressure +gradients and the discrete momentum equation to compute face velocities and mass fluxes. +For more information on the expression that is used, see [SIMPLE.md]. + +!syntax parameters /LinearFVKernels/LinearFVEnergyAdvection + +!syntax inputs /LinearFVKernels/LinearFVEnergyAdvection + +!syntax children /LinearFVKernels/LinearFVEnergyAdvection diff --git a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md new file mode 100644 index 000000000000..987131e71197 --- /dev/null +++ b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md @@ -0,0 +1,14 @@ +# LinearFVMomentumBoussinesq + +This kernel adds the contributions of the Boussinesq buoyancy treatment for density through a force/source term to the right hand side of the momentum equation system for the finite volume SIMPLE segregated solver [SIMPLE.md]. + +This term is described by $-\rho_{ref}\alpha\vec{g}(T - T_{ref})$ present in the momentum equation conservation when describing an incompressible fluid, where $\rho_0$ is the reference density, $\alpha$ is the thermal expansion coefficient, $\vec{g}$ is the gravity vector, $T$ is the temperature, and $T_{ref}$ is a reference temperature. The Boussinesq buoyancy model assumes the changes in density as a function of temperature are linear and relevant only in the buoyant force term of the equation system. The Boussinesq kernel allows for modeling natural convection. + +This term deals only with the force due to the variation in density $\Delta \rho \vec{g}$, with the fluid density being $\rho = \rho_0+\Delta\rho$. Thus, with no extra added terms to the conventional incompressible Navier Stokes equations, the system will solve for dynamic pressure. +For natural convection simulations, it is advisable to compute relevant dimensionless numbers such as the Rayleigh number or the Richardson number to decide on the need for turbulence models, mesh refinement and stability considerations. + +!syntax parameters /LinearFVKernels/LinearFVMomentumBoussinesq + +!syntax inputs /LinearFVKernels/LinearFVMomentumBoussinesq + +!syntax children /LinearFVKernels/LinearFVMomentumBoussinesq From fef203881a441f643bd7e4b7e2073cf4cfca59f6 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Fri, 8 Nov 2024 13:54:31 -0700 Subject: [PATCH 13/16] Fix Documentation location #28951 --- .../content/source/linearfvkernels/LinearFVEnergyAdvection.md | 0 .../finite_volume/ins/channel-flow/linear-segregated/2d/tests | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {modules/navier_stokes => framework}/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md (100%) diff --git a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md b/framework/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md similarity index 100% rename from modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md rename to framework/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests index 2a03c5454712..063db7f201c3 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests @@ -1,6 +1,6 @@ [Tests] issues = '#27280 #28951' - design = 'SIMPLE.md LinearFVDivergence.md LinearWCNSFVMomentumFlux.md LinearFVMomentumPressure.md LinearFVEnergyAdvection.md LinearFVMomentumBoussinesq' + design = 'SIMPLE.md LinearFVDivergence.md LinearWCNSFVMomentumFlux.md LinearFVMomentumPressure.md LinearFVEnergyAdvection.md LinearFVMomentumBoussinesq.md' [momentum-pressure] type = 'Exodiff' input = 2d-velocity-pressure.i From 597925ac60d5cef7f030e6d4a2437f59c66d58dd Mon Sep 17 00:00:00 2001 From: freiler <54753719+freiler@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:32:54 -0700 Subject: [PATCH 14/16] Apply suggestions from code review Co-authored-by: Peter German <31662443+grmnptr@users.noreply.github.com> Apply suggestions from code review Co-authored-by: Peter German <31662443+grmnptr@users.noreply.github.com> --- .../source/linearfvkernels/LinearFVMomentumBoussinesq.md | 4 ++-- .../include/linearfvkernels/LinearFVEnergyAdvection.h | 1 + modules/navier_stokes/src/executioners/SIMPLE.C | 2 +- .../src/linearfvkernels/LinearFVMomentumBoussinesq.C | 6 +++--- .../ins/channel-flow/linear-segregated/2d/2d-boussinesq.i | 2 +- .../ins/channel-flow/linear-segregated/2d/tests | 4 +--- .../diff_heated_cavity_linear_segregated.i | 8 ++++---- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md index 987131e71197..2d9860f1bbc5 100644 --- a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md +++ b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md @@ -2,9 +2,9 @@ This kernel adds the contributions of the Boussinesq buoyancy treatment for density through a force/source term to the right hand side of the momentum equation system for the finite volume SIMPLE segregated solver [SIMPLE.md]. -This term is described by $-\rho_{ref}\alpha\vec{g}(T - T_{ref})$ present in the momentum equation conservation when describing an incompressible fluid, where $\rho_0$ is the reference density, $\alpha$ is the thermal expansion coefficient, $\vec{g}$ is the gravity vector, $T$ is the temperature, and $T_{ref}$ is a reference temperature. The Boussinesq buoyancy model assumes the changes in density as a function of temperature are linear and relevant only in the buoyant force term of the equation system. The Boussinesq kernel allows for modeling natural convection. +This term is described by $-\rho_{ref}\alpha\vec{g}(T - T_{ref})$ present in the momentum equation conservation when describing an incompressible fluid, where $\rho_{ref}$ is the reference density, $\alpha$ is the thermal expansion coefficient, $\vec{g}$ is the gravity vector, $T$ is the temperature, and $T_{ref}$ is a reference temperature. The Boussinesq buoyancy model assumes the changes in density as a function of temperature are linear and relevant only in the buoyant force term of the equation system. The Boussinesq kernel allows for modeling natural convection. -This term deals only with the force due to the variation in density $\Delta \rho \vec{g}$, with the fluid density being $\rho = \rho_0+\Delta\rho$. Thus, with no extra added terms to the conventional incompressible Navier Stokes equations, the system will solve for dynamic pressure. +This term deals only with the force due to the variation in density $\Delta \rho \vec{g}$, with the fluid density being $\rho = \rho_{ref}+\Delta\rho$. Thus, with no extra added terms to the conventional incompressible Navier Stokes equations, the system will solve for dynamic pressure. For natural convection simulations, it is advisable to compute relevant dimensionless numbers such as the Rayleigh number or the Richardson number to decide on the need for turbulence models, mesh refinement and stability considerations. !syntax parameters /LinearFVKernels/LinearFVMomentumBoussinesq diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h index 5769be69356b..b315e78e878f 100644 --- a/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVEnergyAdvection.h @@ -41,6 +41,7 @@ class LinearFVEnergyAdvection : public LinearFVFluxKernel /// The Rhie-Chow user object that provides us with the face velocity const RhieChowMassFlux & _mass_flux_provider; + /// The constant specific heat value const Real _cp; private: diff --git a/modules/navier_stokes/src/executioners/SIMPLE.C b/modules/navier_stokes/src/executioners/SIMPLE.C index d173dc00ce8e..3ff9393790b2 100644 --- a/modules/navier_stokes/src/executioners/SIMPLE.C +++ b/modules/navier_stokes/src/executioners/SIMPLE.C @@ -444,8 +444,8 @@ SIMPLE::execute() _energy_linear_control, _energy_l_abs_tol); - _problem.execute(EXEC_NONLINEAR); } + _problem.execute(EXEC_NONLINEAR); // Printing residuals _console << "Iteration " << iteration_counter << " Initial residual norms:" << std::endl; for (auto system_i : index_range(_momentum_systems)) diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C index d3f11c7f98c8..9cc5dfab622d 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C @@ -21,11 +21,11 @@ LinearFVMomentumBoussinesq::validParams() params.addClassDescription("Represents the Boussinesq term in the Navier Stokes momentum " "equations, added to the right hand side."); params.addParam(NS::T_fluid, "The fluid temperature variable."); - params.addRequiredParam("gravity", "Direction of the gravity vector"); + params.addRequiredParam("gravity", "Gravitational acceleration vector."); params.addParam("alpha_name", NS::alpha_boussinesq, "The name of the thermal expansion coefficient" - "this is of the form rho = rho*(1-alpha (T-T_ref))"); + "this is of the form rho = rho_ref*(1-alpha (T-T_ref))"); params.addRequiredParam("ref_temperature", "The value for the reference temperature."); params.addRequiredParam(NS::density, "The value for the density"); MooseEnum momentum_component("x=0 y=1 z=2"); @@ -47,7 +47,7 @@ LinearFVMomentumBoussinesq::LinearFVMomentumBoussinesq(const InputParameters & p _rho(getFunctor(NS::density)) { _temperature_var.computeCellGradients(); - if (!_rho.isConstant() && !getParam("_override_constant_check")) + if (!_rho.isConstant()) paramError(NS::density, "The density in the boussinesq term is not constant!"); } diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i index bfb0490a476b..ace77fd44eaf 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i @@ -135,7 +135,7 @@ alpha_b = 1e-4 type = LinearFVDiffusion variable = T diffusion_coeff = ${k} - # use_nonorthogonal_correction = true + use_nonorthogonal_correction = false [] [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests index 063db7f201c3..e83237a2b0a3 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests @@ -14,9 +14,7 @@ type = 'Exodiff' input = 2d-boussinesq.i exodiff = 2d-boussinesq_out.e - requirement = "The system shall be able to solve the steady-state Navier-Stokes - energy-coupled " - "problem in a 2D channel using the Boussinesq approximation for fluid density " - "temperature variations with the SIMPLE algorithm using the linear finite volume system." + requirement = "The system shall be able to solve the steady-state Navier-Stokes equations with coupled fluid energy equations in a 2D channel using the Boussinesq approximation for buoyancy with the SIMPLE algorithm using the linear finite volume system." recover = false # we don't support recovery for SIMPLE yet max_threads = 1 # see libmesh issue #3808 [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i index 1f4e17ba6510..7dd08fff1bb5 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i @@ -71,7 +71,7 @@ walls = 'right left top bottom' [T_fluid] type = MooseLinearVariableFVReal solver_sys = energy_system - initial_condition = ${fparse 875} + initial_condition = 875 [] [] @@ -137,7 +137,7 @@ walls = 'right left top bottom' force_boundary_execution = true [] - ####### FUEL ENERGY EQUATION ####### + ####### FUEL ENERGY EQUATION ####### [heat_advection] type = LinearFVEnergyAdvection @@ -169,13 +169,13 @@ walls = 'right left top bottom' type = LinearFVAdvectionDiffusionFunctorDirichletBC variable = T_fluid boundary = 'right' - functor = ${fparse 870.0} + functor = 870.0 [] [T_hot] type = LinearFVAdvectionDiffusionFunctorDirichletBC variable = T_fluid boundary = 'left' - functor = ${fparse 880.0} + functor = 880.0 [] [T_all] type = LinearFVAdvectionDiffusionExtrapolatedBC From c87f4f0f6b845840cf7f6f1c52d1bffd899744e2 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Fri, 8 Nov 2024 15:49:41 -0700 Subject: [PATCH 15/16] Address Peter's reviews- tests and doc #28951 --- .../include/linearfvkernels/LinearFVSource.h | 2 +- .../linearfvkernels/LinearFVEnergyAdvection.md | 4 ++-- .../LinearFVMomentumBoussinesq.md | 4 ++-- .../LinearFVMomentumBoussinesq.h | 6 +++--- .../navier_stokes/src/executioners/SIMPLE.C | 1 - .../linearfvkernels/LinearFVEnergyAdvection.C | 2 +- .../LinearFVMomentumBoussinesq.C | 4 +--- .../linear-segregated/2d/2d-boussinesq.i | 8 ++++---- .../2d/gold/2d-boussinesq_out.e | Bin 0 -> 94784 bytes .../channel-flow/linear-segregated/2d/tests | 2 ++ .../2d}/diff_heated_cavity_linear_segregated.i | 6 +++--- .../diff_heated_cavity_linear_segregated_out.e | Bin 0 -> 181196 bytes .../linear_segregated/2d/tests | 12 ++++++++++++ .../finite_volume/ins/natural_convection/tests | 6 ------ 14 files changed, 31 insertions(+), 26 deletions(-) rename {framework => modules/navier_stokes}/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md (82%) create mode 100644 modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/gold/2d-boussinesq_out.e rename modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/{ => linear_segregated/2d}/diff_heated_cavity_linear_segregated.i (99%) create mode 100644 modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/gold/diff_heated_cavity_linear_segregated_out.e create mode 100644 modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests diff --git a/framework/include/linearfvkernels/LinearFVSource.h b/framework/include/linearfvkernels/LinearFVSource.h index 25dbecbd2119..60ccdebfe28b 100644 --- a/framework/include/linearfvkernels/LinearFVSource.h +++ b/framework/include/linearfvkernels/LinearFVSource.h @@ -35,5 +35,5 @@ class LinearFVSource : public LinearFVElementalKernel const Moose::Functor & _source_density; /// Scale factor - const Real & _scale; + const Real _scale; }; diff --git a/framework/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md similarity index 82% rename from framework/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md rename to modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md index 6f34867568bf..cf8564ea4405 100644 --- a/framework/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md +++ b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVEnergyAdvection.md @@ -2,7 +2,7 @@ This kernel adds the contributions of the energy advection term to the matrix and right hand side of the energy equation system for the finite volume SIMPLE segregated solver [SIMPLE.md]. -This term is described by $\nabla \cdot \left(\rho\vec{u} c_p T \right)$ present in the energy equation conservation for an incompressible/weakly-compressible formulation. Currently, the kernel only supports constant specific heat values for $c_p$ and solves for a temperature variable. The specific heat value needs to be prescribed, otherwise it will default to its default value of $c_p=1$. +This term is described by $\nabla \cdot \left(\rho\vec{u} c_p T \right)$ present in the energy equation conservation for an incompressible/weakly-compressible formulation. Currently, the kernel only supports +constant specific heat values+ for $c_p$ and solves for a temperature variable. The specific heat value needs to be prescribed, otherwise it will default to its default value of $c_p=1$. For FV, the integral of the advection term over a cell can be expressed as: @@ -10,7 +10,7 @@ For FV, the integral of the advection term over a cell can be expressed as: \int\limits_{V_C} \nabla \cdot \left(\rho\vec{u} c_p T \right) dV \approx \sum\limits_f (\rho \vec{u}\cdot \vec{n})_{RC} c_p T_f |S_f| \, \end{equation} -where $T_f$ is a face temperature. The temperature acts as the advected quantity and an interpolation scheme (e.g. upwind) can be used to copmute the face value. This kernel adds the face contribution for each face $f$ to the right hand side and matrix. +where $T_f$ is a face temperature. The temperature acts as the advected quantity and an interpolation scheme (e.g. upwind) can be used to compute the face value. This kernel adds the face contribution for each face $f$ to the right hand side and matrix. The face mass flux $(\rho \vec{u}\cdot \vec{n})_{RC}$ is provided by the [RhieChowMassFlux.md] object which uses pressure gradients and the discrete momentum equation to compute face velocities and mass fluxes. diff --git a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md index 2d9860f1bbc5..f74feca039f6 100644 --- a/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md +++ b/modules/navier_stokes/doc/content/source/linearfvkernels/LinearFVMomentumBoussinesq.md @@ -1,10 +1,10 @@ # LinearFVMomentumBoussinesq -This kernel adds the contributions of the Boussinesq buoyancy treatment for density through a force/source term to the right hand side of the momentum equation system for the finite volume SIMPLE segregated solver [SIMPLE.md]. +This kernel adds the contributions of the Boussinesq buoyancy treatment for density through a force/source term to the right hand side of the momentum equation system for the finite volume SIMPLE segregated solver [SIMPLE.md]. The Boussinesq buoyancy treatment is applicable for low changes in density, and assumes constant density value in all other equation terms. This term is described by $-\rho_{ref}\alpha\vec{g}(T - T_{ref})$ present in the momentum equation conservation when describing an incompressible fluid, where $\rho_{ref}$ is the reference density, $\alpha$ is the thermal expansion coefficient, $\vec{g}$ is the gravity vector, $T$ is the temperature, and $T_{ref}$ is a reference temperature. The Boussinesq buoyancy model assumes the changes in density as a function of temperature are linear and relevant only in the buoyant force term of the equation system. The Boussinesq kernel allows for modeling natural convection. -This term deals only with the force due to the variation in density $\Delta \rho \vec{g}$, with the fluid density being $\rho = \rho_{ref}+\Delta\rho$. Thus, with no extra added terms to the conventional incompressible Navier Stokes equations, the system will solve for dynamic pressure. +This term deals only with the force due to the variation in density $\Delta \rho \vec{g}$, with the fluid density being $\rho = \rho_{ref}+\Delta\rho$. Thus, with no extra added terms to the conventional incompressible Navier Stokes equations, the system will solve for the total pressure minus the hydrostatic pressure. For natural convection simulations, it is advisable to compute relevant dimensionless numbers such as the Rayleigh number or the Richardson number to decide on the need for turbulence models, mesh refinement and stability considerations. !syntax parameters /LinearFVKernels/LinearFVMomentumBoussinesq diff --git a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h index 338bbd8365cf..8722cae3b40c 100644 --- a/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h +++ b/modules/navier_stokes/include/linearfvkernels/LinearFVMomentumBoussinesq.h @@ -32,17 +32,17 @@ class LinearFVMomentumBoussinesq : public LinearFVElementalKernel protected: /// Fluid Temperature - MooseLinearVariableFV & getTemperatureVariable(const std::string & vname); + const MooseLinearVariableFV & getTemperatureVariable(const std::string & vname); /// Index x|y|z of the momentum equation component const unsigned int _index; /// Pointer to the linear finite volume temperature variable - MooseLinearVariableFV & _temperature_var; + const MooseLinearVariableFV & _temperature_var; /// The gravity vector const RealVectorValue _gravity; /// The thermal expansion coefficient const Moose::Functor & _alpha; - /// Reference temperature at which the value of _rho was measured + /// Reference temperature at which the reference value of the density (_rho) was measured const Real _ref_temperature; /// the density const Moose::Functor & _rho; diff --git a/modules/navier_stokes/src/executioners/SIMPLE.C b/modules/navier_stokes/src/executioners/SIMPLE.C index 3ff9393790b2..214c7e5baa8c 100644 --- a/modules/navier_stokes/src/executioners/SIMPLE.C +++ b/modules/navier_stokes/src/executioners/SIMPLE.C @@ -443,7 +443,6 @@ SIMPLE::execute() _energy_equation_relaxation, _energy_linear_control, _energy_l_abs_tol); - } _problem.execute(EXEC_NONLINEAR); // Printing residuals diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C index 8f1c8cbe6fc8..a8fb51986640 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVEnergyAdvection.C @@ -12,7 +12,7 @@ #include "NSFVUtils.h" #include "NS.h" -registerMooseObject("MooseApp", LinearFVEnergyAdvection); +registerMooseObject("NavierStokesApp", LinearFVEnergyAdvection); InputParameters LinearFVEnergyAdvection::validParams() diff --git a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C index 9cc5dfab622d..2bfd4533a2f3 100644 --- a/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C +++ b/modules/navier_stokes/src/linearfvkernels/LinearFVMomentumBoussinesq.C @@ -33,7 +33,6 @@ LinearFVMomentumBoussinesq::validParams() "momentum_component", momentum_component, "The component of the momentum equation that this kernel applies to."); - params.addPrivateParam("_override_constant_check", false); return params; } @@ -46,12 +45,11 @@ LinearFVMomentumBoussinesq::LinearFVMomentumBoussinesq(const InputParameters & p _ref_temperature(getParam("ref_temperature")), _rho(getFunctor(NS::density)) { - _temperature_var.computeCellGradients(); if (!_rho.isConstant()) paramError(NS::density, "The density in the boussinesq term is not constant!"); } -MooseLinearVariableFV & +const MooseLinearVariableFV & LinearFVMomentumBoussinesq::getTemperatureVariable(const std::string & vname) { auto * ptr = dynamic_cast *>( diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i index ace77fd44eaf..d4ed4dfd09b0 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/2d-boussinesq.i @@ -9,10 +9,10 @@ alpha_b = 1e-4 [mesh] type = CartesianMeshGenerator dim = 2 - dx = '1.5' - dy = '0.3' - ix = '55' - iy = '20' + dx = '1.' + dy = '0.2' + ix = '10' + iy = '5' [] [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/gold/2d-boussinesq_out.e b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/gold/2d-boussinesq_out.e new file mode 100644 index 0000000000000000000000000000000000000000..f12a320c14b42fecb732865c183079df4b6b1149 GIT binary patch literal 94784 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 N^{T5cyJy;`{};sI(&+#I literal 0 HcmV?d00001 diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests index e83237a2b0a3..261269687237 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/channel-flow/linear-segregated/2d/tests @@ -17,5 +17,7 @@ requirement = "The system shall be able to solve the steady-state Navier-Stokes equations with coupled fluid energy equations in a 2D channel using the Boussinesq approximation for buoyancy with the SIMPLE algorithm using the linear finite volume system." recover = false # we don't support recovery for SIMPLE yet max_threads = 1 # see libmesh issue #3808 + abs_zero = 1e-5 + rel_err = 1e-5 [] [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/diff_heated_cavity_linear_segregated.i similarity index 99% rename from modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i rename to modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/diff_heated_cavity_linear_segregated.i index 7dd08fff1bb5..cfc2104c0b8c 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/diff_heated_cavity_linear_segregated.i +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/diff_heated_cavity_linear_segregated.i @@ -34,8 +34,8 @@ walls = 'right left top bottom' xmax = 1 ymin = 0 ymax = 1 - nx = 40 - ny = 40 + nx = 30 + ny = 30 [] [] @@ -221,7 +221,7 @@ walls = 'right left top bottom' num_iterations = 3000 pressure_absolute_tolerance = 1e-8 momentum_absolute_tolerance = 1e-8 - energy_absolute_tolerance = 1e-6 + energy_absolute_tolerance = 1e-8 print_fields = false momentum_l_max_its = 300 diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/gold/diff_heated_cavity_linear_segregated_out.e b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/gold/diff_heated_cavity_linear_segregated_out.e new file mode 100644 index 0000000000000000000000000000000000000000..f4a0ac45798f63d09a7fbd69cc4e6f014f49dc2e GIT binary patch literal 181196 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 XRPugphi`+@1MarDj7l%4YFqMu@g`j+ literal 0 HcmV?d00001 diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests new file mode 100644 index 000000000000..d77f8d565cce --- /dev/null +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests @@ -0,0 +1,12 @@ +[Tests] + design = 'LinearFVEnergyAdvection.md LinearFVMomentumBoussinesq.md' + issues = '#28951' + [diff_heated_cavity_linear_segregated] + type = 'Exodiff' + input = 'diff_heated_cavity_linear_segregated.i' + exodiff = 'diff_heated_cavity_linear_segregated_out.e' + abs_zero = 1e-5 + rel_err = 1e-3 + requirement = 'The system shall be able to use the density Boussinesq approximation to solve for a differentially heated 2D cavity.' + [] +[] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests index 0a7ddd588bb5..7f1758aa063d 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests @@ -15,10 +15,4 @@ rel_err = 1.0E-7 method = opt [] - [diff_heated_cavity_linear_segregated] - type = 'Exodiff' - input = 'diff_heated_cavity_linear_segregated.i' - exodiff = 'diff_heated_cavity_linear_segregated_out.e' - requirement = 'The system shall be able to use the density Boussinesq approximation to solve for a differentially heated 2D cavity.' - [] [] From f67967a6e397fff1a187c254a9eba9c37025fdf3 Mon Sep 17 00:00:00 2001 From: Ramiro Freile Date: Wed, 13 Nov 2024 15:15:20 -0700 Subject: [PATCH 16/16] Max threads=1 for linearFV variables in tests. --- .../ins/natural_convection/linear_segregated/2d/tests | 1 + .../test/tests/finite_volume/ins/natural_convection/tests | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests index d77f8d565cce..21c43ef37d68 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/linear_segregated/2d/tests @@ -7,6 +7,7 @@ exodiff = 'diff_heated_cavity_linear_segregated_out.e' abs_zero = 1e-5 rel_err = 1e-3 + max_threads = 1 requirement = 'The system shall be able to use the density Boussinesq approximation to solve for a differentially heated 2D cavity.' [] [] diff --git a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests index 7f1758aa063d..b7668e178d96 100644 --- a/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests +++ b/modules/navier_stokes/test/tests/finite_volume/ins/natural_convection/tests @@ -1,6 +1,6 @@ [Tests] - design = 'NSFVAction.md LinearFVEnergyAdvection.md LinearFVMomentumBoussinesq.md' - issues = '#21380 #24662 #28951' + design = 'NSFVAction.md' + issues = '#21380 #24662' [natural_circulation_dogleg] type = 'Exodiff' input = 'natural_circulation_dogleg.i'