From 6d0f6c8e88ae6603c8934b4af5b6549ba024715d Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Fri, 8 Sep 2023 17:20:46 -0700 Subject: [PATCH 1/8] FSI additions - Interface kernel for coupling scalar field displacments to vector fluid velocity field - Create ConvectedMeshPSPG so that we can have one-to-one comparison between INS and INSAD in the FSI module - Fix mesh convection residual for INSAD. The multiplication order needs to be switched to match the regular advection term Closes #23680 --- .../interfacekernels/ADInterfaceKernel.h | 11 +- .../interfacekernels/InterfaceKernel.h | 7 +- .../interfacekernels/InterfaceKernelBase.h | 20 -- .../ADPenaltyVelocityContinuity.md | 15 + .../content/source/kernels/ConvectedMesh.md | 8 +- .../source/kernels/ConvectedMeshPSPG.md | 22 ++ .../ADPenaltyVelocityContinuity.h | 59 ++++ modules/fsi/include/kernels/ConvectedMesh.h | 21 +- .../fsi/include/kernels/ConvectedMeshPSPG.h | 48 +++ .../ADPenaltyVelocityContinuity.C | 149 +++++++++ modules/fsi/src/kernels/ConvectedMesh.C | 83 +++++- modules/fsi/src/kernels/ConvectedMeshPSPG.C | 127 ++++++++ .../ad-fsi-flat-channel.i | 282 ++++++++++++++++++ .../2d-small-strain-transient/custom.cmp | 43 +++ .../fsi_flat_channel.i | 59 ++-- .../gold/ad-fsi-flat-channel_out.e | 1 + .../gold/fsi_flat_channel_out.e | Bin 159684 -> 202828 bytes .../tests/2d-small-strain-transient/tests | 58 +++- .../src/materials/INSADMaterial.C | 3 +- 19 files changed, 942 insertions(+), 74 deletions(-) create mode 100644 modules/fsi/doc/content/source/interfacekernels/ADPenaltyVelocityContinuity.md create mode 100644 modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md create mode 100644 modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h create mode 100644 modules/fsi/include/kernels/ConvectedMeshPSPG.h create mode 100644 modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C create mode 100644 modules/fsi/src/kernels/ConvectedMeshPSPG.C create mode 100644 modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i create mode 100644 modules/fsi/test/tests/2d-small-strain-transient/custom.cmp create mode 120000 modules/fsi/test/tests/2d-small-strain-transient/gold/ad-fsi-flat-channel_out.e diff --git a/framework/include/interfacekernels/ADInterfaceKernel.h b/framework/include/interfacekernels/ADInterfaceKernel.h index bfcce5c3ba12..208fe21c4cce 100644 --- a/framework/include/interfacekernels/ADInterfaceKernel.h +++ b/framework/include/interfacekernels/ADInterfaceKernel.h @@ -35,28 +35,27 @@ class ADInterfaceKernelTempl : public InterfaceKernelBase, public NeighborMooseV * Using the passed DGResidual type, selects the correct test function space and residual block, * and then calls computeQpResidual */ - void computeElemNeighResidual(Moose::DGResidualType type) override final; + void computeElemNeighResidual(Moose::DGResidualType type); /** * Using the passed DGJacobian type, selects the correct test function and trial function spaces * and * jacobian block, and then calls computeQpJacobian */ - void computeElemNeighJacobian(Moose::DGJacobianType type) override final; + void computeElemNeighJacobian(Moose::DGJacobianType type); /** * Using the passed DGJacobian type, selects the correct test function and trial function spaces * and * jacobian block, and then calls computeQpOffDiagJacobian with the passed jvar */ - void computeOffDiagElemNeighJacobian(Moose::DGJacobianType type, - unsigned int jvar) override final; + void computeOffDiagElemNeighJacobian(Moose::DGJacobianType type, unsigned int jvar); /// Selects the correct Jacobian type and routine to call for the primary variable jacobian - void computeElementOffDiagJacobian(unsigned int jvar) override final; + virtual void computeElementOffDiagJacobian(unsigned int jvar) override final; /// Selects the correct Jacobian type and routine to call for the secondary variable jacobian - void computeNeighborOffDiagJacobian(unsigned int jvar) override final; + virtual void computeNeighborOffDiagJacobian(unsigned int jvar) override final; /// Computes the residual for the current side. void computeResidual() override final; diff --git a/framework/include/interfacekernels/InterfaceKernel.h b/framework/include/interfacekernels/InterfaceKernel.h index 5093628c5d2a..071186ef23c9 100644 --- a/framework/include/interfacekernels/InterfaceKernel.h +++ b/framework/include/interfacekernels/InterfaceKernel.h @@ -48,22 +48,21 @@ class InterfaceKernelTempl : public InterfaceKernelBase, public NeighborMooseVar * Using the passed DGResidual type, selects the correct test function space and residual block, * and then calls computeQpResidual */ - virtual void computeElemNeighResidual(Moose::DGResidualType type) override; + virtual void computeElemNeighResidual(Moose::DGResidualType type); /** * Using the passed DGJacobian type, selects the correct test function and trial function spaces * and * jacobian block, and then calls computeQpJacobian */ - virtual void computeElemNeighJacobian(Moose::DGJacobianType type) override; + virtual void computeElemNeighJacobian(Moose::DGJacobianType type); /** * Using the passed DGJacobian type, selects the correct test function and trial function spaces * and * jacobian block, and then calls computeQpOffDiagJacobian with the passed jvar */ - virtual void computeOffDiagElemNeighJacobian(Moose::DGJacobianType type, - unsigned int jvar) override; + virtual void computeOffDiagElemNeighJacobian(Moose::DGJacobianType type, unsigned int jvar); /// Selects the correct Jacobian type and routine to call for the primary variable jacobian virtual void computeElementOffDiagJacobian(unsigned int jvar) override; diff --git a/framework/include/interfacekernels/InterfaceKernelBase.h b/framework/include/interfacekernels/InterfaceKernelBase.h index af70367dd128..c499cac15f2b 100644 --- a/framework/include/interfacekernels/InterfaceKernelBase.h +++ b/framework/include/interfacekernels/InterfaceKernelBase.h @@ -35,26 +35,6 @@ class InterfaceKernelBase : public NeighborResidualObject, /// The neighbor variable number that this interface kernel operates on virtual const MooseVariableFEBase & neighborVariable() const = 0; - /** - * Using the passed DGResidual type, selects the correct test function space and residual block, - * and then calls computeQpResidual - */ - virtual void computeElemNeighResidual(Moose::DGResidualType type) = 0; - - /** - * Using the passed DGJacobian type, selects the correct test function and trial function spaces - * and - * jacobian block, and then calls computeQpJacobian - */ - virtual void computeElemNeighJacobian(Moose::DGJacobianType type) = 0; - - /** - * Using the passed DGJacobian type, selects the correct test function and trial function spaces - * and - * jacobian block, and then calls computeQpOffDiagJacobian with the passed jvar - */ - virtual void computeOffDiagElemNeighJacobian(Moose::DGJacobianType type, unsigned int jvar) = 0; - /// Selects the correct Jacobian type and routine to call for the primary variable jacobian virtual void computeElementOffDiagJacobian(unsigned int jvar) = 0; diff --git a/modules/fsi/doc/content/source/interfacekernels/ADPenaltyVelocityContinuity.md b/modules/fsi/doc/content/source/interfacekernels/ADPenaltyVelocityContinuity.md new file mode 100644 index 000000000000..8c493d9c47ea --- /dev/null +++ b/modules/fsi/doc/content/source/interfacekernels/ADPenaltyVelocityContinuity.md @@ -0,0 +1,15 @@ +# ADPenaltyVelocityContinuity + +!syntax description /InterfaceKernels/ADPenaltyVelocityContinuity + +This object is meant for use in coupling the Navier-Stokes fluid equations with +solid mechanics equations at a fluid-structure interface. In that context this +object imposes both continuity of stress and continuity of material velocity via +a penalty condition. For more information on the error of penalty methods, +please see [CoupledPenaltyInterfaceDiffusion.md]. + +!syntax parameters /InterfaceKernels/ADPenaltyVelocityContinuity + +!syntax inputs /InterfaceKernels/ADPenaltyVelocityContinuity + +!syntax children /InterfaceKernels/ADPenaltyVelocityContinuity diff --git a/modules/fsi/doc/content/source/kernels/ConvectedMesh.md b/modules/fsi/doc/content/source/kernels/ConvectedMesh.md index 6a27801953af..4e4638955353 100644 --- a/modules/fsi/doc/content/source/kernels/ConvectedMesh.md +++ b/modules/fsi/doc/content/source/kernels/ConvectedMesh.md @@ -1,6 +1,6 @@ # ConvectedMesh -## Description +!syntax description /Kernels/ConvectedMesh `ConvectedMesh` implements the corresponding weak form for the components of the term: @@ -13,3 +13,9 @@ where $\rho$ is the density, $\vec{d_m}$ is the fluid mesh displacements, and $\vec{u}$ is the fluid velocity. This term is essential for obtaining the correct convective derivative of the fluid in cases where the fluid mesh is dynamic, e.g. in simulations of fluid-structure interaction. + +!syntax parameters /Kernels/ConvectedMesh + +!syntax inputs /Kernels/ConvectedMesh + +!syntax children /Kernels/ConvectedMesh diff --git a/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md b/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md new file mode 100644 index 000000000000..4c83a0b23656 --- /dev/null +++ b/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md @@ -0,0 +1,22 @@ +# ConvectedMeshPSPG + +!syntax description /Kernels/ConvectedMeshPSPG + +This object adds the pressure-stabilized Petrov-Galerkin term to the pressure +equation corresponding to the [ConvectedMesh.md] object. It implements the +weak form + +\begin{equation} +\int \nabla \psi \dot \left(\tau \dot{\vec{d}}\right) dV +\end{equation} + +where $\nabla \psi$ is the gradient of the pressure test function, $\tau$ is a +stabilization parameter computed automatically by the `navier_stokes` base class +`INSBase`, and $\dot{\vec{d}}$ is the time derivative of the displacement +vector. + +!syntax parameters /Kernels/ConvectedMeshPSPG + +!syntax inputs /Kernels/ConvectedMeshPSPG + +!syntax children /Kernels/ConvectedMeshPSPG diff --git a/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h b/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h new file mode 100644 index 000000000000..fb5ec1533fde --- /dev/null +++ b/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h @@ -0,0 +1,59 @@ +///* 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 "InterfaceKernelBase.h" + +/** + * Interface kernel for enforcing continuity of stress and velocity + */ +class ADPenaltyVelocityContinuity : public InterfaceKernelBase +{ +public: + static InputParameters validParams(); + + ADPenaltyVelocityContinuity(const InputParameters & parameters); + + virtual void computeResidual() override; + virtual void computeResidualAndJacobian() override; + virtual void computeJacobian() override; + virtual void computeElementOffDiagJacobian(unsigned int jvar) override; + virtual void computeNeighborOffDiagJacobian(unsigned int jvar) override; + virtual const MooseVariableFieldBase & variable() const override; + virtual const MooseVariableFieldBase & neighborVariable() const override; + +protected: + /// The penalty factor + const Real _penalty; + + /// Fluid velocity variable + const VectorMooseVariable * const _velocity_var; + + /// Fluid velocity values + const ADVectorVariableValue & _velocity; + + /// Solid velocity values + std::vector _solid_velocities; + + /// Displacement variables + std::vector _displacements; + + /// JxW with displacement derivatives + const MooseArray & _ad_JxW; + + /// Coordinate transformation with displacement derivatives + const MooseArray & _ad_coord; + + /// Residuals data member to avoid constant heap allocation + std::vector _residuals; + + /// Jump data member to avoid constant heap allocations + std::vector _qp_jumps; +}; diff --git a/modules/fsi/include/kernels/ConvectedMesh.h b/modules/fsi/include/kernels/ConvectedMesh.h index 8b953d79e7de..d288f0ece028 100644 --- a/modules/fsi/include/kernels/ConvectedMesh.h +++ b/modules/fsi/include/kernels/ConvectedMesh.h @@ -9,12 +9,12 @@ #pragma once -#include "Kernel.h" +#include "INSBase.h" /** * This calculates the time derivative for a coupled variable **/ -class ConvectedMesh : public Kernel +class ConvectedMesh : public INSBase { public: static InputParameters validParams(); @@ -26,6 +26,17 @@ class ConvectedMesh : public Kernel virtual Real computeQpJacobian() override; virtual Real computeQpOffDiagJacobian(unsigned int jvar) override; + /** + * Compute the Jacobian of the Petrov-Galerkin stabilization addition with respect to the provided + * velocity component + */ + Real computePGVelocityJacobian(unsigned short component); + + /** + * Compute the strong residual, e.g. -rho * ddisp/dt * grad(u) + */ + Real strongResidual(); + const VariableValue & _disp_x_dot; const VariableValue & _d_disp_x_dot; const unsigned int _disp_x_id; @@ -37,4 +48,10 @@ class ConvectedMesh : public Kernel const unsigned int _disp_z_id; const MaterialProperty & _rho; + + /// Whether this kernel should include Streamline-Upwind Petrov-Galerkin stabilization + const bool _supg; + + /// The velocity component this kernel is acting on + unsigned short _component; }; diff --git a/modules/fsi/include/kernels/ConvectedMeshPSPG.h b/modules/fsi/include/kernels/ConvectedMeshPSPG.h new file mode 100644 index 000000000000..98ca4f0e7e99 --- /dev/null +++ b/modules/fsi/include/kernels/ConvectedMeshPSPG.h @@ -0,0 +1,48 @@ +//* 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 "INSBase.h" + +/** + * This calculates the time derivative for a coupled variable + **/ +class ConvectedMeshPSPG : public INSBase +{ +public: + static InputParameters validParams(); + + ConvectedMeshPSPG(const InputParameters & parameters); + +protected: + virtual Real computeQpResidual() override; + virtual Real computeQpJacobian() override; + virtual Real computeQpOffDiagJacobian(unsigned int jvar) override; + + RealVectorValue dStrongResidualDDisp(unsigned short component); + RealVectorValue dStrongResidualDVel(unsigned short component); + + /** + * Compute the strong residual, e.g. -rho * ddisp/dt * grad(u) + */ + RealVectorValue strongResidual(); + + const VariableValue & _disp_x_dot; + const VariableValue & _d_disp_x_dot; + const unsigned int _disp_x_id; + const VariableValue & _disp_y_dot; + const VariableValue & _d_disp_y_dot; + const unsigned int _disp_y_id; + const VariableValue & _disp_z_dot; + const VariableValue & _d_disp_z_dot; + const unsigned int _disp_z_id; + + const MaterialProperty & _rho; +}; diff --git a/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C b/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C new file mode 100644 index 000000000000..bdf99341a19f --- /dev/null +++ b/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C @@ -0,0 +1,149 @@ +//* 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 "ADPenaltyVelocityContinuity.h" +#include "Assembly.h" + +registerMooseObject("FsiApp", ADPenaltyVelocityContinuity); + +InputParameters +ADPenaltyVelocityContinuity::validParams() +{ + InputParameters params = InterfaceKernelBase::validParams(); + params.addClassDescription( + "Enforces continuity of flux and continuity of solution via penalty across an interface."); + params.addRequiredParam( + "penalty", + "The penalty that penalizes jump between primary and neighbor secondary variables."); + params.addRequiredCoupledVar("fluid_velocity", "The fluid velocity"); + params.renameCoupledVar("neighbor_var", "displacements", "All the displacement variables"); + params.addRequiredCoupledVar("solid_velocities", "The solid velocity components"); + return params; +} + +ADPenaltyVelocityContinuity::ADPenaltyVelocityContinuity(const InputParameters & parameters) + : InterfaceKernelBase(parameters), + _penalty(getParam("penalty")), + _velocity_var(getVectorVar("fluid_velocity", 0)), + _velocity(adCoupledVectorValue("fluid_velocity")), + _ad_JxW(_assembly.adJxWFace()), + _ad_coord(_assembly.adCoordTransformation()) +{ + if (isCoupledConstant("fluid_velocity")) + paramError("fluid_velocity", "The fluid velocity must be an actual variable"); + + _solid_velocities.resize(coupledComponents("solid_velocities")); + for (const auto i : index_range(_solid_velocities)) + _solid_velocities[i] = &adCoupledNeighborValue("solid_velocities", i); + + _displacements.resize(coupledComponents("displacements")); + for (const auto i : index_range(_displacements)) + _displacements[i] = getVar("displacements", i); +} + +void +ADPenaltyVelocityContinuity::computeResidual() +{ + _qp_jumps.resize(_qrule->n_points()); + for (auto & qp_jump : _qp_jumps) + qp_jump = 0; + + const auto solid_velocity = [&](const auto qp) + { + ADRealVectorValue ret; + for (const auto i : index_range(_solid_velocities)) + if (_solid_velocities[i]) + ret(i) = (*_solid_velocities[i])[qp]; + + return ret; + }; + + for (const auto qp : make_range(_qrule->n_points())) + _qp_jumps[qp] = _ad_JxW[qp] * _ad_coord[qp] * _penalty * (_velocity[qp] - solid_velocity(qp)); + + // Fluid velocity residuals + { + const auto & phi = _velocity_var->phiFace(); + const auto & dof_indices = _velocity_var->dofIndices(); + mooseAssert(phi.size() == dof_indices.size(), "These should be the same"); + + _residuals.resize(phi.size()); + for (auto & r : _residuals) + r = 0; + + for (const auto qp : make_range(_qrule->n_points())) + for (const auto i : index_range(phi)) + _residuals[i] += phi[i][qp] * _qp_jumps[qp]; + + addResidualsAndJacobian(_assembly, _residuals, dof_indices, _velocity_var->scalingFactor()); + } + + // Displacement residuals + for (const auto dim : index_range(_displacements)) + { + const auto * const disp_var = _displacements[dim]; + if (disp_var) + { + const auto & phi = disp_var->phiFaceNeighbor(); + const auto & dof_indices = disp_var->dofIndicesNeighbor(); + mooseAssert(phi.size() == dof_indices.size(), "These should be the same"); + + _residuals.resize(phi.size()); + for (auto & r : _residuals) + r = 0; + + for (const auto qp : make_range(_qrule->n_points())) + for (const auto i : index_range(phi)) + _residuals[i] -= phi[i][qp] * _qp_jumps[qp](dim); + + addResidualsAndJacobian(_assembly, _residuals, dof_indices, disp_var->scalingFactor()); + } + } +} + +void +ADPenaltyVelocityContinuity::computeJacobian() +{ + computeResidual(); +} + +void +ADPenaltyVelocityContinuity::computeResidualAndJacobian() +{ + computeResidual(); +} + +void +ADPenaltyVelocityContinuity::computeElementOffDiagJacobian(const unsigned int jvar) +{ + if (jvar == _velocity_var->number()) + // Only need to do this once because AD does everything all at once + computeResidual(); +} + +void +ADPenaltyVelocityContinuity::computeNeighborOffDiagJacobian(unsigned int) +{ +} + +const MooseVariableFieldBase & +ADPenaltyVelocityContinuity::variable() const +{ + return *_velocity_var; +} + +const MooseVariableFieldBase & +ADPenaltyVelocityContinuity::neighborVariable() const +{ + if (_displacements.empty() || !_displacements.front()) + mooseError("The 'neighborVariable' method was called which requires that displacements be " + "actual variables."); + + return *_displacements.front(); +} diff --git a/modules/fsi/src/kernels/ConvectedMesh.C b/modules/fsi/src/kernels/ConvectedMesh.C index da66fe028942..5d3ecec413f1 100644 --- a/modules/fsi/src/kernels/ConvectedMesh.C +++ b/modules/fsi/src/kernels/ConvectedMesh.C @@ -14,18 +14,20 @@ registerMooseObject("FsiApp", ConvectedMesh); InputParameters ConvectedMesh::validParams() { - InputParameters params = Kernel::validParams(); + InputParameters params = INSBase::validParams(); params.addClassDescription( "Corrects the convective derivative for situations in which the fluid mesh is dynamic."); params.addRequiredCoupledVar("disp_x", "The x displacement"); params.addCoupledVar("disp_y", "The y displacement"); params.addCoupledVar("disp_z", "The z displacement"); params.addParam("rho_name", "rho", "The name of the density"); + params.addParam( + "supg", false, "Whether to perform SUPG stabilization of the momentum residuals"); return params; } ConvectedMesh::ConvectedMesh(const InputParameters & parameters) - : Kernel(parameters), + : INSBase(parameters), _disp_x_dot(coupledDot("disp_x")), _d_disp_x_dot(coupledDotDu("disp_x")), _disp_x_id(coupled("disp_x")), @@ -35,33 +37,94 @@ ConvectedMesh::ConvectedMesh(const InputParameters & parameters) _disp_z_dot(isCoupled("disp_z") ? coupledDot("disp_z") : _zero), _d_disp_z_dot(isCoupled("disp_z") ? coupledDotDu("disp_z") : _zero), _disp_z_id(coupled("disp_z")), - _rho(getMaterialProperty("rho_name")) + _rho(getMaterialProperty("rho_name")), + _supg(getParam("supg")) { + if (_var.number() == _u_vel_var_number) + _component = 0; + else if (_var.number() == _v_vel_var_number) + _component = 1; + else if (_var.number() == _w_vel_var_number) + _component = 2; + else + paramError("variable", "The variable must match one of the velocity variables."); +} + +Real +ConvectedMesh::strongResidual() +{ + return -_rho[_qp] * RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]) * + _grad_u[_qp]; } Real ConvectedMesh::computeQpResidual() { - return _test[_i][_qp] * -_rho[_qp] * - RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]) * _grad_u[_qp]; + auto test = _test[_i][_qp]; + if (_supg) + test += tau() * _grad_test[_i][_qp] * RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + return test * strongResidual(); +} + +Real +ConvectedMesh::computePGVelocityJacobian(const unsigned short component) +{ + return strongResidual() * ((dTauDUComp(component) * _grad_test[_i][_qp] * + RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp])) + + (tau() * _grad_test[_i][_qp](component) * _phi[_j][_qp])); } Real ConvectedMesh::computeQpJacobian() { - return _test[_i][_qp] * -_rho[_qp] * - RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]) * _grad_phi[_j][_qp]; + auto test = _test[_i][_qp]; + if (_supg) + test += tau() * _grad_test[_i][_qp] * RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + auto jac = test * -_rho[_qp] * + RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]) * + _grad_phi[_j][_qp]; + if (_supg) + jac += computePGVelocityJacobian(_component); + + return jac; } Real ConvectedMesh::computeQpOffDiagJacobian(unsigned int jvar) { + mooseAssert(jvar != _var.number(), "Making sure I understand how old hand-coded Jacobians work."); + + auto test = _test[_i][_qp]; + if (_supg) + test += tau() * _grad_test[_i][_qp] * RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + if (jvar == _disp_x_id) - return _test[_i][_qp] * -_rho[_qp] * _phi[_j][_qp] * _d_disp_x_dot[_qp] * _grad_u[_qp](0); + return test * -_rho[_qp] * _phi[_j][_qp] * _d_disp_x_dot[_qp] * _grad_u[_qp](0); else if (jvar == _disp_y_id) - return _test[_i][_qp] * -_rho[_qp] * _phi[_j][_qp] * _d_disp_y_dot[_qp] * _grad_u[_qp](1); + return test * -_rho[_qp] * _phi[_j][_qp] * _d_disp_y_dot[_qp] * _grad_u[_qp](1); else if (jvar == _disp_z_id) - return _test[_i][_qp] * -_rho[_qp] * _phi[_j][_qp] * _d_disp_z_dot[_qp] * _grad_u[_qp](2); + return test * -_rho[_qp] * _phi[_j][_qp] * _d_disp_z_dot[_qp] * _grad_u[_qp](2); + else if (jvar == _u_vel_var_number) + { + if (_supg) + return computePGVelocityJacobian(0); + else + return 0; + } + else if (jvar == _v_vel_var_number) + { + if (_supg) + return computePGVelocityJacobian(1); + else + return 0; + } + else if (jvar == _w_vel_var_number) + { + if (_supg) + return computePGVelocityJacobian(2); + else + return 0; + } else return 0.0; } diff --git a/modules/fsi/src/kernels/ConvectedMeshPSPG.C b/modules/fsi/src/kernels/ConvectedMeshPSPG.C new file mode 100644 index 000000000000..e8da5f120ae3 --- /dev/null +++ b/modules/fsi/src/kernels/ConvectedMeshPSPG.C @@ -0,0 +1,127 @@ +//* 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 "ConvectedMeshPSPG.h" + +registerMooseObject("FsiApp", ConvectedMeshPSPG); + +InputParameters +ConvectedMeshPSPG::validParams() +{ + InputParameters params = INSBase::validParams(); + params.addClassDescription( + "Corrects the convective derivative for situations in which the fluid mesh is dynamic."); + params.addRequiredCoupledVar("disp_x", "The x displacement"); + params.addCoupledVar("disp_y", "The y displacement"); + params.addCoupledVar("disp_z", "The z displacement"); + params.addParam("rho_name", "rho", "The name of the density"); + return params; +} + +ConvectedMeshPSPG::ConvectedMeshPSPG(const InputParameters & parameters) + : INSBase(parameters), + _disp_x_dot(coupledDot("disp_x")), + _d_disp_x_dot(coupledDotDu("disp_x")), + _disp_x_id(coupled("disp_x")), + _disp_y_dot(isCoupled("disp_y") ? coupledDot("disp_y") : _zero), + _d_disp_y_dot(isCoupled("disp_y") ? coupledDotDu("disp_y") : _zero), + _disp_y_id(coupled("disp_y")), + _disp_z_dot(isCoupled("disp_z") ? coupledDot("disp_z") : _zero), + _d_disp_z_dot(isCoupled("disp_z") ? coupledDotDu("disp_z") : _zero), + _disp_z_id(coupled("disp_z")), + _rho(getMaterialProperty("rho_name")) +{ +} + +RealVectorValue +ConvectedMeshPSPG::strongResidual() +{ + const auto minus_rho_ddisp_dt = + -_rho[_qp] * RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]); + return RealVectorValue(minus_rho_ddisp_dt * _grad_u_vel[_qp], + minus_rho_ddisp_dt * _grad_v_vel[_qp], + minus_rho_ddisp_dt * _grad_w_vel[_qp]); +} + +RealVectorValue +ConvectedMeshPSPG::dStrongResidualDDisp(const unsigned short component) +{ + const auto & ddisp_dot = [&]() -> const VariableValue & + { + switch (component) + { + case 0: + return _d_disp_x_dot; + case 1: + return _d_disp_y_dot; + case 2: + return _d_disp_z_dot; + default: + mooseError("Invalid component"); + } + }(); + + // Only non-zero component will be from 'component' + RealVectorValue ddisp_dt; + ddisp_dt(component) = _phi[_j][_qp] * ddisp_dot[_qp]; + + const auto minus_rho_ddisp_dt = -_rho[_qp] * ddisp_dt; + return RealVectorValue(minus_rho_ddisp_dt * _grad_u_vel[_qp], + minus_rho_ddisp_dt * _grad_v_vel[_qp], + minus_rho_ddisp_dt * _grad_w_vel[_qp]); +} + +RealVectorValue +ConvectedMeshPSPG::dStrongResidualDVel(const unsigned short component) +{ + const auto minus_rho_ddisp_dt = + -_rho[_qp] * RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]); + + // Only non-zero component will be from 'component' + RealVectorValue ret; + ret(component) = minus_rho_ddisp_dt * _grad_phi[_j][_qp]; + return ret; +} + +Real +ConvectedMeshPSPG::computeQpResidual() +{ + return -tau() / _rho[_qp] * _grad_test[_i][_qp] * strongResidual(); +} + +Real +ConvectedMeshPSPG::computeQpJacobian() +{ + // No derivative with respect to pressure + return 0; +} + +Real +ConvectedMeshPSPG::computeQpOffDiagJacobian(unsigned int jvar) +{ + mooseAssert(jvar != _var.number(), "Making sure I understand how old hand-coded Jacobians work."); + + if (jvar == _disp_x_id) + return -tau() / _rho[_qp] * _grad_test[_i][_qp] * dStrongResidualDDisp(0); + else if (jvar == _disp_y_id) + return -tau() / _rho[_qp] * _grad_test[_i][_qp] * dStrongResidualDDisp(1); + else if (jvar == _disp_z_id) + return -tau() / _rho[_qp] * _grad_test[_i][_qp] * dStrongResidualDDisp(2); + else if (jvar == _u_vel_var_number) + return -dTauDUComp(0) / _rho[_qp] * _grad_test[_i][_qp] * strongResidual() - + tau() / _rho[_qp] * _grad_test[_i][_qp] * dStrongResidualDVel(0); + else if (jvar == _v_vel_var_number) + return -dTauDUComp(1) / _rho[_qp] * _grad_test[_i][_qp] * strongResidual() - + tau() / _rho[_qp] * _grad_test[_i][_qp] * dStrongResidualDVel(1); + else if (jvar == _w_vel_var_number) + return -dTauDUComp(2) / _rho[_qp] * _grad_test[_i][_qp] * strongResidual() - + tau() / _rho[_qp] * _grad_test[_i][_qp] * dStrongResidualDVel(2); + else + return 0.0; +} diff --git a/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i b/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i new file mode 100644 index 000000000000..f34a4420c7b8 --- /dev/null +++ b/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i @@ -0,0 +1,282 @@ +[GlobalParams] + displacements = 'disp_x disp_y' + order = FIRST + preset = false + use_displaced_mesh = true +[] + +[Mesh] + [gmg] + type = GeneratedMeshGenerator + dim = 2 + xmin = 0 + xmax = 3.0 + ymin = 0 + ymax = 1.0 + nx = 10 + ny = 15 + elem_type = QUAD4 + [] + [subdomain1] + type = SubdomainBoundingBoxGenerator + bottom_left = '0.0 0.5 0' + block_id = 1 + top_right = '3.0 1.0 0' + input = gmg + [] + [interface] + type = SideSetsBetweenSubdomainsGenerator + primary_block = '0' + paired_block = '1' + new_boundary = 'master0_interface' + input = subdomain1 + [] + [break_boundary] + type = BreakBoundaryOnSubdomainGenerator + input = interface + [] +[] + +[Variables] + [vel] + block = 0 + family = LAGRANGE_VEC + [] + [p] + block = 0 + order = FIRST + [] + [disp_x] + [] + [disp_y] + [] + [vel_x_solid] + block = 1 + [] + [vel_y_solid] + block = 1 + [] +[] + +[Kernels] + [mass] + type = INSADMass + variable = p + block = 0 + [] + [mass_pspg] + type = INSADMassPSPG + variable = p + block = 0 + [] + [momentum_time] + type = INSADMomentumTimeDerivative + variable = vel + block = 0 + [] + [momentum_convection] + type = INSADMomentumAdvection + variable = vel + block = 0 + [] + [momentum_viscous] + type = INSADMomentumViscous + variable = vel + block = 0 + [] + [momentum_pressure] + type = INSADMomentumPressure + variable = vel + pressure = p + integrate_p_by_parts = true + block = 0 + [] + [momentum_supg] + type = INSADMomentumSUPG + variable = vel + velocity = vel + block = 0 + [] + [momentum_mesh] + type = INSADMomentumMeshAdvection + variable = vel + disp_x = 'disp_x' + disp_y = 'disp_y' + block = 0 + [] + [disp_x_fluid] + type = Diffusion + variable = disp_x + block = 0 + use_displaced_mesh = false + [] + [disp_y_fluid] + type = Diffusion + variable = disp_y + block = 0 + use_displaced_mesh = false + [] + [accel_tensor_x] + type = CoupledTimeDerivative + variable = disp_x + v = vel_x_solid + block = 1 + use_displaced_mesh = false + [] + [accel_tensor_y] + type = CoupledTimeDerivative + variable = disp_y + v = vel_y_solid + block = 1 + use_displaced_mesh = false + [] + [vxs_time_derivative_term] + type = CoupledTimeDerivative + variable = vel_x_solid + v = disp_x + block = 1 + use_displaced_mesh = false + [] + [vys_time_derivative_term] + type = CoupledTimeDerivative + variable = vel_y_solid + v = disp_y + block = 1 + use_displaced_mesh = false + [] + [source_vxs] + type = MatReaction + variable = vel_x_solid + block = 1 + mob_name = 1 + use_displaced_mesh = false + [] + [source_vys] + type = MatReaction + variable = vel_y_solid + block = 1 + mob_name = 1 + use_displaced_mesh = false + [] +[] + +[InterfaceKernels] + [penalty] + type = ADPenaltyVelocityContinuity + variable = vel + fluid_velocity = vel + displacements = 'disp_x disp_y' + solid_velocities = 'vel_x_solid vel_y_solid' + boundary = master0_interface + penalty = 1e6 + [] +[] + +[Modules/TensorMechanics/Master] + [solid_domain] + strain = SMALL + incremental = false + # generate_output = 'strain_xx strain_yy strain_zz' ## Not at all necessary, but nice + block = '1' + [] +[] + +[Materials] + [elasticity_tensor] + type = ComputeIsotropicElasticityTensor + youngs_modulus = 1e2 + poissons_ratio = 0.3 + block = '1' + use_displaced_mesh = false + [] + [small_stress] + type = ComputeLinearElasticStress + block = 1 + [] + [const] + type = ADGenericConstantMaterial + block = 0 + prop_names = 'rho mu' + prop_values = '1 1' + [] + [ins_mat] + type = INSADTauMaterial + velocity = vel + pressure = p + block = 0 + [] +[] + +[BCs] + [fluid_bottom] + type = ADVectorFunctionDirichletBC + variable = vel + boundary = 'bottom' + function_x = 0 + function_y = 0 + [] + [fluid_left] + type = ADVectorFunctionDirichletBC + variable = vel + boundary = 'left_to_0' + function_x = 'inlet_func' + function_y = 0 + # The displacements actually affect the result of the function evaluation so in order to eliminate the impact + # on the Jacobian we set 'use_displaced_mesh = false' here + use_displaced_mesh = false + [] + [no_disp_x] + type = DirichletBC + variable = disp_x + boundary = 'bottom top left_to_1 right_to_1 left_to_0 right_to_0' + value = 0 + [] + [no_disp_y] + type = DirichletBC + variable = disp_y + boundary = 'bottom top left_to_1 right_to_1 left_to_0 right_to_0' + value = 0 + [] + [solid_x_no_slip] + type = DirichletBC + variable = vel_x_solid + boundary = 'top left_to_1 right_to_1' + value = 0.0 + [] + [solid_y_no_slip] + type = DirichletBC + variable = vel_y_solid + boundary = 'top left_to_1 right_to_1' + value = 0.0 + [] +[] + +[Preconditioning] + [SMP] + type = SMP + full = true + [] +[] + +[Executioner] + type = Transient + num_steps = 5 + # num_steps = 60 + dt = 0.1 + dtmin = 0.1 + solve_type = 'NEWTON' + petsc_options_iname = '-pc_type -pc_factor_shift_type' + petsc_options_value = 'lu NONZERO' + line_search = none +[] + +[Outputs] + exodus = true +[] + +[Functions] + [inlet_func] + type = ParsedFunction + expression = '(-16 * (y - 0.25)^2 + 1) * (1 + cos(t))' + [] +[] diff --git a/modules/fsi/test/tests/2d-small-strain-transient/custom.cmp b/modules/fsi/test/tests/2d-small-strain-transient/custom.cmp new file mode 100644 index 000000000000..5933c52784c2 --- /dev/null +++ b/modules/fsi/test/tests/2d-small-strain-transient/custom.cmp @@ -0,0 +1,43 @@ + +# ***************************************************************** +# EXODIFF (Version: 2.90) Modified: 2018-02-15 +# Authors: Richard Drake, rrdrake@sandia.gov +# Greg Sjaardema, gdsjaar@sandia.gov +# Run on 2023/04/26 11:42:41 PDT +# ***************************************************************** + +# FILE 1: /home/lindad/projects/moose/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel_out.e +# Title: ad-fsi-flat-channel_out.e +# Dim = 2, Blocks = 2, Nodes = 35, Elements = 6, Nodesets = 12, Sidesets = 12 +# Vars: Global = 0, Nodal = 7, Element = 0, Nodeset = 0, Sideset = 0, Times = 2 + + +# ============================================================== +# NOTE: All node and element ids are reported as global ids. + +# NOTES: - The min/max values are reporting the min/max in absolute value. +# - Time values (t) are 1-offset time step numbers. +# - Element block numbers are the block ids. +# - Node(n) and element(e) numbers are 1-offset. + +COORDINATES absolute 1.e-6 # min separation not calculated + +TIME STEPS relative 1.e-6 floor 0.0 # min: 0 @ t1 max: 0.1 @ t2 + + +# No GLOBAL VARIABLES + +NODAL VARIABLES relative 5.5e-6 floor 1e-10 + disp_x # min: 0 @ t1,n1 max: 0.035855951 @ t2,n7 + disp_y # min: 0 @ t1,n1 max: 0.065177301 @ t2,n7 + p # min: 0 @ t1,n1 max: 38.023022 @ t2,n4 + vel_x # min: 0 @ t1,n1 max: 1.773337 @ t2,n4 + vel_x_solid # min: 0 @ t1,n1 max: 0.35855951 @ t2,n7 + vel_y # min: 0 @ t1,n1 max: 0.65179 @ t2,n7 + vel_y_solid # min: 0 @ t1,n1 max: 0.65177301 @ t2,n7 + +# No ELEMENT VARIABLES + +# No NODESET VARIABLES + +# No SIDESET VARIABLES diff --git a/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i b/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i index 41e9b6875613..9e21c69ac5a2 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i +++ b/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i @@ -5,20 +5,24 @@ convective_term = true transient_term = true pspg = true + supg = true displacements = 'disp_x disp_y' + preset = false + order = FIRST + use_displaced_mesh = true [] [Mesh] [gmg] - type = GeneratedMeshGenerator - dim = 2 - xmin = 0 - xmax = 3.0 - ymin = 0 - ymax = 1.0 - nx = 10 - ny = 15 - elem_type = QUAD4 + type = GeneratedMeshGenerator + dim = 2 + xmin = 0 + xmax = 3.0 + ymin = 0 + ymax = 1.0 + nx = 10 + ny = 15 + elem_type = QUAD4 [] [subdomain1] @@ -70,13 +74,11 @@ type = INSMomentumTimeDerivative variable = vel_x block = 0 - use_displaced_mesh = true [../] [./vel_y_time] type = INSMomentumTimeDerivative variable = vel_y block = 0 - use_displaced_mesh = true [../] [./mass] type = INSMass @@ -85,7 +87,6 @@ v = vel_y pressure = p block = 0 - use_displaced_mesh = true [../] [./x_momentum_space] type = INSMomentumLaplaceForm @@ -95,7 +96,6 @@ pressure = p component = 0 block = 0 - use_displaced_mesh = true [../] [./y_momentum_space] type = INSMomentumLaplaceForm @@ -105,69 +105,90 @@ pressure = p component = 1 block = 0 - use_displaced_mesh = true [../] [./vel_x_mesh] type = ConvectedMesh disp_x = disp_x disp_y = disp_y variable = vel_x + u = vel_x + v = vel_y + pressure = p block = 0 - use_displaced_mesh = true [../] [./vel_y_mesh] type = ConvectedMesh disp_x = disp_x disp_y = disp_y variable = vel_y + u = vel_x + v = vel_y + pressure = p + block = 0 + [../] + [./p_mesh] + type = ConvectedMeshPSPG + disp_x = disp_x + disp_y = disp_y + variable = p + u = vel_x + v = vel_y + pressure = p block = 0 - use_displaced_mesh = true [../] [./disp_x_fluid] type = Diffusion variable = disp_x block = 0 + use_displaced_mesh = false [../] [./disp_y_fluid] type = Diffusion variable = disp_y block = 0 + use_displaced_mesh = false [../] [./accel_tensor_x] type = CoupledTimeDerivative variable = disp_x v = vel_x_solid block = 1 + use_displaced_mesh = false [../] [./accel_tensor_y] type = CoupledTimeDerivative variable = disp_y v = vel_y_solid block = 1 + use_displaced_mesh = false [../] [./vxs_time_derivative_term] type = CoupledTimeDerivative variable = vel_x_solid v = disp_x block = 1 + use_displaced_mesh = false [../] [./vys_time_derivative_term] type = CoupledTimeDerivative variable = vel_y_solid v = disp_y block = 1 + use_displaced_mesh = false [../] [./source_vxs] type = MatReaction variable = vel_x_solid block = 1 mob_name = 1 + use_displaced_mesh = false [../] [./source_vys] type = MatReaction variable = vel_y_solid block = 1 mob_name = 1 + use_displaced_mesh = false [../] [] @@ -205,6 +226,7 @@ youngs_modulus = 1e2 poissons_ratio = 0.3 block = '1' + use_displaced_mesh = false [../] [./small_stress] type = ComputeLinearElasticStress @@ -215,6 +237,7 @@ block = 0 prop_names = 'rho mu' prop_values = '1 1' + use_displaced_mesh = false [../] [] @@ -277,8 +300,8 @@ dt = 0.1 dtmin = 0.1 solve_type = 'PJFNK' - petsc_options_iname = '-pc_type' - petsc_options_value = 'lu' + petsc_options_iname = '-pc_type -pc_factor_shift_type' + petsc_options_value = 'lu NONZERO' line_search = none [] diff --git a/modules/fsi/test/tests/2d-small-strain-transient/gold/ad-fsi-flat-channel_out.e b/modules/fsi/test/tests/2d-small-strain-transient/gold/ad-fsi-flat-channel_out.e new file mode 120000 index 000000000000..ffa472d109a3 --- /dev/null +++ b/modules/fsi/test/tests/2d-small-strain-transient/gold/ad-fsi-flat-channel_out.e @@ -0,0 +1 @@ +fsi_flat_channel_out.e \ No newline at end of file diff --git a/modules/fsi/test/tests/2d-small-strain-transient/gold/fsi_flat_channel_out.e b/modules/fsi/test/tests/2d-small-strain-transient/gold/fsi_flat_channel_out.e index 0d72cc5b1c88fcb907475df505b58de4cc8ed25d..dc3418a9f894eda2432be4640cebc24a3cbb334e 100644 GIT binary patch literal 202828 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 diff --git a/modules/fsi/test/tests/2d-small-strain-transient/tests b/modules/fsi/test/tests/2d-small-strain-transient/tests index 92074d61b10f..9497a8b3f865 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/tests +++ b/modules/fsi/test/tests/2d-small-strain-transient/tests @@ -1,14 +1,50 @@ [Tests] design = 'modules/fsi/index.md' - - [./fsi] - type = 'Exodiff' - input = 'fsi_flat_channel.i' - exodiff = 'fsi_flat_channel_out.e' - requirement = 'We shall be able to combine navier-stokes and tensor-mechanics simulation capabilities to do some basic fluid-structure interaction simulations' - issues = '#12462' - # vel_x_solid is not accurate - # We mmay improve that in the future - rel_err = 1e-4 - [../] + issues = '#12462' + [fsi] + requirement = 'We shall be able to combine navier-stokes and tensor-mechanics simulation capabilities to do some basic fluid-structure interaction simulations and produce equivalent results when the Navier-Stokes equations are implemented using' + [INS] + type = 'Exodiff' + input = 'fsi_flat_channel.i' + exodiff = 'fsi_flat_channel_out.e' + detail = 'scalar field variables for velocity components and hand-coded Jacobians,' + # vel_x_solid is not accurate + # We mmay improve that in the future + rel_err = 1e-4 + [] + [INSAD] + type = 'Exodiff' + input = 'ad-fsi-flat-channel.i' + exodiff = 'ad-fsi-flat-channel_out.e' + detail = 'and a vector field variable for velocity and a Jacobian computed using automatic differentation. Additionally,' + # vel_x_solid is not accurate + # We mmay improve that in the future + rel_err = 1e-4 + [] + [INSAD_displaced_jac] + type = 'PetscJacobianTester' + input = 'ad-fsi-flat-channel.i' + ratio_tol = 1e-6 + difference_tol = 1 + run_sim = True + cli_args = 'Mesh/gmg/nx=2 Mesh/gmg/ny=3 Executioner/num_steps=1' + detail = 'the automatic differentation Jacobian shall be (nearly) perfect when the fluid domain equations are run on the displaced mesh, and' + [] + [INSAD_undisplaced_jac] + type = 'PetscJacobianTester' + input = 'ad-fsi-flat-channel.i' + difference_tol = 1 + run_sim = True + cli_args = 'Mesh/gmg/nx=2 Mesh/gmg/ny=3 Executioner/num_steps=1 GlobalParams/use_displaced_mesh=false' + detail = 'perfect when the fluid domain equations are run on the undisplaced mesh, and' + [] + [INS_undisplaced_jac] + type = 'PetscJacobianTester' + input = 'fsi_flat_channel.i' + difference_tol = 1 + run_sim = True + cli_args = 'Mesh/gmg/nx=2 Mesh/gmg/ny=3 Executioner/num_steps=1 GlobalParams/use_displaced_mesh=false' + detail = 'the hand-coded Jacobian shall be perfect when the simulation is run entirely undisplaced.' + [] + [] [] diff --git a/modules/navier_stokes/src/materials/INSADMaterial.C b/modules/navier_stokes/src/materials/INSADMaterial.C index ae7b48313275..e4f14ba735a6 100644 --- a/modules/navier_stokes/src/materials/INSADMaterial.C +++ b/modules/navier_stokes/src/materials/INSADMaterial.C @@ -218,8 +218,7 @@ INSADMaterial::computeQpProperties() _mesh_velocity[_qp](1) = (*_disp_y_dot)[_qp]; if (_disp_z_dot) _mesh_velocity[_qp](2) = (*_disp_z_dot)[_qp]; - _convected_mesh_strong_residual[_qp] = - -_rho[_qp] * _grad_velocity[_qp].left_multiply(_mesh_velocity[_qp]); + _convected_mesh_strong_residual[_qp] = -_rho[_qp] * _grad_velocity[_qp] * _mesh_velocity[_qp]; } if (_has_coupled_force) From 938e593598775d137fa6308c0d4751cfaa186846 Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 3 Oct 2023 15:45:43 -0700 Subject: [PATCH 2/8] Make FSI coverage requirement less strict --- .coverage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.coverage b/.coverage index 2f6f19017d77..67a7614684dc 100644 --- a/.coverage +++ b/.coverage @@ -36,7 +36,7 @@ require_total = 85 require_total = 84 [fsi] -require_total = 90 +require_total = 85 [functional_expansion_tools] require_total = 82 From f59feff7afe35a3f2dc75925af2d338258cbbe44 Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 10 Oct 2023 12:03:24 -0700 Subject: [PATCH 3/8] More convected -> advected language change --- .../include/kernels/INSADEnergyMeshAdvection.h | 2 +- .../include/kernels/INSADMomentumMeshAdvection.h | 4 ++-- modules/navier_stokes/include/materials/INSAD3Eqn.h | 2 +- .../navier_stokes/include/materials/INSADMaterial.h | 6 +++--- .../include/materials/INSADStabilized3Eqn.h | 9 --------- .../include/materials/INSADTauMaterial.h | 8 ++++---- .../src/kernels/INSADEnergyMeshAdvection.C | 6 +++--- .../src/kernels/INSADMomentumMeshAdvection.C | 6 +++--- modules/navier_stokes/src/materials/INSAD3Eqn.C | 8 ++++---- modules/navier_stokes/src/materials/INSADMaterial.C | 11 +++++------ .../navier_stokes/src/materials/INSADStabilized3Eqn.C | 4 ++-- .../src/userobjects/INSADObjectTracker.C | 6 +++--- 12 files changed, 31 insertions(+), 41 deletions(-) diff --git a/modules/navier_stokes/include/kernels/INSADEnergyMeshAdvection.h b/modules/navier_stokes/include/kernels/INSADEnergyMeshAdvection.h index 736fa1a9ed37..533fa314fbc1 100644 --- a/modules/navier_stokes/include/kernels/INSADEnergyMeshAdvection.h +++ b/modules/navier_stokes/include/kernels/INSADEnergyMeshAdvection.h @@ -25,7 +25,7 @@ class INSADEnergyMeshAdvection : public ADKernelValue protected: virtual ADReal precomputeQpResidual() override; - const ADMaterialProperty & _temperature_convected_mesh_strong_residual; + const ADMaterialProperty & _temperature_advected_mesh_strong_residual; friend class INSADMomentumMeshAdvection; }; diff --git a/modules/navier_stokes/include/kernels/INSADMomentumMeshAdvection.h b/modules/navier_stokes/include/kernels/INSADMomentumMeshAdvection.h index 39e7d376260b..c42bac014416 100644 --- a/modules/navier_stokes/include/kernels/INSADMomentumMeshAdvection.h +++ b/modules/navier_stokes/include/kernels/INSADMomentumMeshAdvection.h @@ -30,7 +30,7 @@ class INSADMomentumMeshAdvection : public ADVectorKernelValue /// The strong residual for this object, computed by material classes to eliminate computation /// duplication in simulations in which we have stabilization - const ADMaterialProperty & _convected_mesh_strong_residual; + const ADMaterialProperty & _advected_mesh_strong_residual; }; template @@ -57,7 +57,7 @@ INSADMomentumMeshAdvection::setDisplacementParams(T & mesh_convection_obj) "ins_ad_object_tracker"); for (const auto block_id : mesh_convection_obj.blockIDs()) { - obj_tracker.set("has_convected_mesh", true, block_id); + obj_tracker.set("has_advected_mesh", true, block_id); obj_tracker.set("disp_x", mesh_convection_obj.coupledName("disp_x"), block_id); if (mesh_convection_obj.isParamValid("disp_y")) obj_tracker.set("disp_y", mesh_convection_obj.coupledName("disp_y"), block_id); diff --git a/modules/navier_stokes/include/materials/INSAD3Eqn.h b/modules/navier_stokes/include/materials/INSAD3Eqn.h index e29adea79233..2bd76f6461c3 100644 --- a/modules/navier_stokes/include/materials/INSAD3Eqn.h +++ b/modules/navier_stokes/include/materials/INSAD3Eqn.h @@ -39,7 +39,7 @@ class INSAD3Eqn : public INSADMaterial /// The strong residual for the temperature transport term corresponding to mesh velocity in an /// ALE simulation - ADMaterialProperty & _temperature_convected_mesh_strong_residual; + ADMaterialProperty & _temperature_advected_mesh_strong_residual; bool _has_ambient_convection; Real _ambient_convection_alpha; diff --git a/modules/navier_stokes/include/materials/INSADMaterial.h b/modules/navier_stokes/include/materials/INSADMaterial.h index f8f68f2255df..2c4d1ebda1a8 100644 --- a/modules/navier_stokes/include/materials/INSADMaterial.h +++ b/modules/navier_stokes/include/materials/INSADMaterial.h @@ -65,8 +65,8 @@ class INSADMaterial : public Material /// The mesh velocity ADMaterialProperty & _mesh_velocity; - /// Strong residual corresponding to convected mesh term - ADMaterialProperty & _convected_mesh_strong_residual; + /// Strong residual corresponding to advected mesh term + ADMaterialProperty & _advected_mesh_strong_residual; // /// Future addition pending addition of INSADMMSKernel. // /// Strong residual corresponding to the mms function term @@ -124,7 +124,7 @@ class INSADMaterial : public Material std::vector _coupled_force_vector_function; /// Whether we have mesh convection - bool _has_convected_mesh; + bool _has_advected_mesh; /// The time derivative with respect to x-displacement const ADVariableValue * _disp_x_dot; diff --git a/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h b/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h index 338fd8de8bbe..c119fba070ee 100644 --- a/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h +++ b/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h @@ -42,13 +42,4 @@ class INSADStabilized3Eqn : public INSADTauMaterialTempl ADMaterialProperty & _tau_energy; ADMaterialProperty & _temperature_strong_residual; - - using INSADTauMaterialTempl::_cp; - using INSADTauMaterialTempl::_temperature_advective_strong_residual; - using INSADTauMaterialTempl::_temperature_td_strong_residual; - using INSADTauMaterialTempl::_temperature_ambient_convection_strong_residual; - using INSADTauMaterialTempl::_temperature_source_strong_residual; - using INSADTauMaterialTempl::_has_ambient_convection; - using INSADTauMaterialTempl::_has_heat_source; - using INSADTauMaterialTempl::_has_energy_transient; }; diff --git a/modules/navier_stokes/include/materials/INSADTauMaterial.h b/modules/navier_stokes/include/materials/INSADTauMaterial.h index 9f6f1e8f2255..8eeb15391dea 100644 --- a/modules/navier_stokes/include/materials/INSADTauMaterial.h +++ b/modules/navier_stokes/include/materials/INSADTauMaterial.h @@ -91,10 +91,10 @@ class INSADTauMaterialTempl : public T const unsigned int _vel_sys_number; using T::_ad_q_point; + using T::_advected_mesh_strong_residual; using T::_advective_strong_residual; using T::_assembly; using T::_boussinesq_strong_residual; - using T::_convected_mesh_strong_residual; using T::_coord_sys; using T::_coupled_force_strong_residual; using T::_current_elem; @@ -109,8 +109,8 @@ class INSADTauMaterialTempl : public T using T::_grad_p; using T::_grad_velocity; using T::_gravity_strong_residual; + using T::_has_advected_mesh; using T::_has_boussinesq; - using T::_has_convected_mesh; using T::_has_coupled_force; using T::_has_gravity; using T::_has_transient; @@ -351,8 +351,8 @@ INSADTauMaterialTempl::computeQpProperties() if (_has_boussinesq) _momentum_strong_residual[_qp] += _boussinesq_strong_residual[_qp]; - if (_has_convected_mesh) - _momentum_strong_residual[_qp] += _convected_mesh_strong_residual[_qp]; + if (_has_advected_mesh) + _momentum_strong_residual[_qp] += _advected_mesh_strong_residual[_qp]; if (_has_coupled_force) _momentum_strong_residual[_qp] += _coupled_force_strong_residual[_qp]; diff --git a/modules/navier_stokes/src/kernels/INSADEnergyMeshAdvection.C b/modules/navier_stokes/src/kernels/INSADEnergyMeshAdvection.C index 3e87e1c1c56d..66764089f25f 100644 --- a/modules/navier_stokes/src/kernels/INSADEnergyMeshAdvection.C +++ b/modules/navier_stokes/src/kernels/INSADEnergyMeshAdvection.C @@ -24,8 +24,8 @@ INSADEnergyMeshAdvection::validParams() INSADEnergyMeshAdvection::INSADEnergyMeshAdvection(const InputParameters & parameters) : ADKernelValue(parameters), - _temperature_convected_mesh_strong_residual( - getADMaterialProperty("temperature_convected_mesh_strong_residual")) + _temperature_advected_mesh_strong_residual( + getADMaterialProperty("temperature_advected_mesh_strong_residual")) { INSADMomentumMeshAdvection::setDisplacementParams(*this); } @@ -33,5 +33,5 @@ INSADEnergyMeshAdvection::INSADEnergyMeshAdvection(const InputParameters & param ADReal INSADEnergyMeshAdvection::precomputeQpResidual() { - return _temperature_convected_mesh_strong_residual[_qp]; + return _temperature_advected_mesh_strong_residual[_qp]; } diff --git a/modules/navier_stokes/src/kernels/INSADMomentumMeshAdvection.C b/modules/navier_stokes/src/kernels/INSADMomentumMeshAdvection.C index 2173720f247b..bcdbe0d12f4d 100644 --- a/modules/navier_stokes/src/kernels/INSADMomentumMeshAdvection.C +++ b/modules/navier_stokes/src/kernels/INSADMomentumMeshAdvection.C @@ -34,8 +34,8 @@ INSADMomentumMeshAdvection::validParams() INSADMomentumMeshAdvection::INSADMomentumMeshAdvection(const InputParameters & parameters) : ADVectorKernelValue(parameters), - _convected_mesh_strong_residual( - getADMaterialProperty("convected_mesh_strong_residual")) + _advected_mesh_strong_residual( + getADMaterialProperty("advected_mesh_strong_residual")) { setDisplacementParams(*this); } @@ -43,5 +43,5 @@ INSADMomentumMeshAdvection::INSADMomentumMeshAdvection(const InputParameters & p ADRealVectorValue INSADMomentumMeshAdvection::precomputeQpResidual() { - return _convected_mesh_strong_residual[_qp]; + return _advected_mesh_strong_residual[_qp]; } diff --git a/modules/navier_stokes/src/materials/INSAD3Eqn.C b/modules/navier_stokes/src/materials/INSAD3Eqn.C index e64a5671f171..f5cd5d7f3c4a 100644 --- a/modules/navier_stokes/src/materials/INSAD3Eqn.C +++ b/modules/navier_stokes/src/materials/INSAD3Eqn.C @@ -36,8 +36,8 @@ INSAD3Eqn::INSAD3Eqn(const InputParameters & parameters) declareADProperty("temperature_ambient_convection_strong_residual")), _temperature_source_strong_residual( declareADProperty("temperature_source_strong_residual")), - _temperature_convected_mesh_strong_residual( - declareADProperty("temperature_convected_mesh_strong_residual")) + _temperature_advected_mesh_strong_residual( + declareADProperty("temperature_advected_mesh_strong_residual")) { } @@ -127,7 +127,7 @@ INSAD3Eqn::computeQpProperties() } } - if (_has_convected_mesh) - _temperature_convected_mesh_strong_residual[_qp] = + if (_has_advected_mesh) + _temperature_advected_mesh_strong_residual[_qp] = -_rho[_qp] * _cp[_qp] * _mesh_velocity[_qp] * _grad_temperature[_qp]; } diff --git a/modules/navier_stokes/src/materials/INSADMaterial.C b/modules/navier_stokes/src/materials/INSADMaterial.C index e4f14ba735a6..9b1ff8c74d3a 100644 --- a/modules/navier_stokes/src/materials/INSADMaterial.C +++ b/modules/navier_stokes/src/materials/INSADMaterial.C @@ -50,8 +50,8 @@ INSADMaterial::INSADMaterial(const InputParameters & parameters) _coupled_force_strong_residual( declareADProperty("coupled_force_strong_residual")), _mesh_velocity(declareADProperty("mesh_velocity")), - _convected_mesh_strong_residual( - declareADProperty("convected_mesh_strong_residual")), + _advected_mesh_strong_residual( + declareADProperty("advected_mesh_strong_residual")), // _mms_function_strong_residual(declareProperty("mms_function_strong_residual")), _use_displaced_mesh(getParam("use_displaced_mesh")), _ad_q_point(_bnd ? _assembly.adQPointsFace() : _assembly.adQPoints()), @@ -112,8 +112,7 @@ INSADMaterial::subdomainSetup() // Setup data for Arbitrary Lagrangian Eulerian (ALE) simulations in which the simulation domain // is displacing. We will need to subtract the mesh velocity from the velocity solution in order // to get the correct material velocity for the momentum convection term. - if ((_has_convected_mesh = - _object_tracker->get("has_convected_mesh", _current_subdomain_id))) + if ((_has_advected_mesh = _object_tracker->get("has_advected_mesh", _current_subdomain_id))) { auto & disp_x = _subproblem.getStandardVariable( _tid, _object_tracker->get("disp_x", _current_subdomain_id)); @@ -211,14 +210,14 @@ INSADMaterial::computeQpProperties() _boussinesq_strong_residual[_qp] = (*_boussinesq_alpha)[_qp] * _gravity_vector * _rho[_qp] * ((*_temperature)[_qp] - (*_ref_temp)[_qp]); - if (_has_convected_mesh) + if (_has_advected_mesh) { _mesh_velocity[_qp](0) = (*_disp_x_dot)[_qp]; if (_disp_y_dot) _mesh_velocity[_qp](1) = (*_disp_y_dot)[_qp]; if (_disp_z_dot) _mesh_velocity[_qp](2) = (*_disp_z_dot)[_qp]; - _convected_mesh_strong_residual[_qp] = -_rho[_qp] * _grad_velocity[_qp] * _mesh_velocity[_qp]; + _advected_mesh_strong_residual[_qp] = -_rho[_qp] * _grad_velocity[_qp] * _mesh_velocity[_qp]; } if (_has_coupled_force) diff --git a/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C b/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C index e6690d7e3d9b..e42ad7517ce0 100644 --- a/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C +++ b/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C @@ -69,6 +69,6 @@ INSADStabilized3Eqn::computeQpProperties() if (_has_heat_source) _temperature_strong_residual[_qp] += _temperature_source_strong_residual[_qp]; - if (_has_convected_mesh) - _temperature_strong_residual[_qp] += _temperature_convected_mesh_strong_residual[_qp]; + if (_has_advected_mesh) + _temperature_strong_residual[_qp] += _temperature_advected_mesh_strong_residual[_qp]; } diff --git a/modules/navier_stokes/src/userobjects/INSADObjectTracker.C b/modules/navier_stokes/src/userobjects/INSADObjectTracker.C index 0eef5ca4a39f..746cab509dbf 100644 --- a/modules/navier_stokes/src/userobjects/INSADObjectTracker.C +++ b/modules/navier_stokes/src/userobjects/INSADObjectTracker.C @@ -62,14 +62,14 @@ INSADObjectTracker::validTrackerParams() params.addParam>("coupled_force_vector_function", "The function(s) standing in as a coupled force(s)"); - params.addParam("has_convected_mesh", + params.addParam("has_advected_mesh", false, "Whether the fluid domain is undergoing displacement in which case we must " - "add a convecting mesh term to correct the material velocity."); + "add an advecting mesh term to correct the material velocity."); params.addParam("disp_x", "The x displacement"); params.addParam("disp_y", "The y displacement"); params.addParam("disp_z", "The z displacement"); - params.addParamNamesToGroup("has_convected_mesh disp_x disp_y disp_z", "Moving mesh"); + params.addParamNamesToGroup("has_advected_mesh disp_x disp_y disp_z", "Moving mesh"); return params; } From 1a98e2884bdd989cdba161e45e9dbd1596ca74a0 Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 10 Oct 2023 13:07:50 -0700 Subject: [PATCH 4/8] Use relative velocity for SUPG velocity and tau computation --- framework/src/kernels/ADKernelSUPG.C | 9 +++++++-- .../2d-small-strain-transient/ad-fsi-flat-channel.i | 2 +- modules/navier_stokes/examples/laser-welding/3d.i | 2 +- .../navier_stokes/include/materials/INSADMaterial.h | 3 +++ .../include/materials/INSADStabilized3Eqn.h | 13 ------------- .../include/materials/INSADTauMaterial.h | 9 +++++++-- modules/navier_stokes/src/materials/INSADMaterial.C | 3 +++ .../src/materials/INSADStabilized3Eqn.C | 3 +-- 8 files changed, 23 insertions(+), 21 deletions(-) diff --git a/framework/src/kernels/ADKernelSUPG.C b/framework/src/kernels/ADKernelSUPG.C index 00f41a1c7c09..ec397112f765 100644 --- a/framework/src/kernels/ADKernelSUPG.C +++ b/framework/src/kernels/ADKernelSUPG.C @@ -21,7 +21,9 @@ ADKernelSUPGTempl::validParams() InputParameters params = ADKernelStabilizedTempl::validParams(); params.addParam( "tau_name", "tau", "The name of the stabilization parameter tau."); - params.addRequiredCoupledVar("velocity", "The velocity variable."); + params.addCoupledVar("velocity", "The velocity variable."); + params.addParam("material_velocity", + "A material property describing the velocity"); return params; } @@ -29,7 +31,10 @@ template ADKernelSUPGTempl::ADKernelSUPGTempl(const InputParameters & parameters) : ADKernelStabilizedTempl(parameters), _tau(this->template getADMaterialProperty("tau_name")), - _velocity(this->adCoupledVectorValue("velocity")) + _velocity( + this->isParamValid("velocity") + ? this->adCoupledVectorValue("velocity") + : this->template getADMaterialProperty("material_velocity").get()) { } diff --git a/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i b/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i index f34a4420c7b8..71c78ff37f8c 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i +++ b/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i @@ -94,7 +94,7 @@ [momentum_supg] type = INSADMomentumSUPG variable = vel - velocity = vel + material_velocity = relative_velocity block = 0 [] [momentum_mesh] diff --git a/modules/navier_stokes/examples/laser-welding/3d.i b/modules/navier_stokes/examples/laser-welding/3d.i index 2000fbb842d1..70a140f2496a 100644 --- a/modules/navier_stokes/examples/laser-welding/3d.i +++ b/modules/navier_stokes/examples/laser-welding/3d.i @@ -104,7 +104,7 @@ sb=5.67e-8 [momentum_supg] type = INSADMomentumSUPG variable = vel - velocity = vel + material_velocity = relative_velocity use_displaced_mesh = true [] [temperature_time] diff --git a/modules/navier_stokes/include/materials/INSADMaterial.h b/modules/navier_stokes/include/materials/INSADMaterial.h index 2c4d1ebda1a8..bc24d98add76 100644 --- a/modules/navier_stokes/include/materials/INSADMaterial.h +++ b/modules/navier_stokes/include/materials/INSADMaterial.h @@ -65,6 +65,9 @@ class INSADMaterial : public Material /// The mesh velocity ADMaterialProperty & _mesh_velocity; + /// The relative velocity, e.g. velocity - mesh_velocity + ADMaterialProperty & _relative_velocity; + /// Strong residual corresponding to advected mesh term ADMaterialProperty & _advected_mesh_strong_residual; diff --git a/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h b/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h index c119fba070ee..359fdfeb1c69 100644 --- a/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h +++ b/modules/navier_stokes/include/materials/INSADStabilized3Eqn.h @@ -9,19 +9,6 @@ #pragma once -#include "InputParameters.h" -#include "NonlinearSystemBase.h" -#include "FEProblemBase.h" -#include "MaterialProperty.h" -#include "MooseArray.h" - -#include "libmesh/elem.h" - -#include - -class INSADMaterial; -class INSAD3Eqn; - #include "INSADTauMaterial.h" #include "INSAD3Eqn.h" diff --git a/modules/navier_stokes/include/materials/INSADTauMaterial.h b/modules/navier_stokes/include/materials/INSADTauMaterial.h index 8eeb15391dea..bcec8f6308c2 100644 --- a/modules/navier_stokes/include/materials/INSADTauMaterial.h +++ b/modules/navier_stokes/include/materials/INSADTauMaterial.h @@ -90,6 +90,10 @@ class INSADTauMaterialTempl : public T /// The velocity system number const unsigned int _vel_sys_number; + /// The speed of the medium. This is the norm of the relative velocity, e.g. the velocity minus + /// the mesh velocity + ADReal _speed; + using T::_ad_q_point; using T::_advected_mesh_strong_residual; using T::_advective_strong_residual; @@ -120,6 +124,7 @@ class INSADTauMaterialTempl : public T using T::_q_point; using T::_qp; using T::_qrule; + using T::_relative_velocity; using T::_rho; using T::_rz_axial_coord; using T::_rz_radial_coord; @@ -335,8 +340,8 @@ INSADTauMaterialTempl::computeQpProperties() const auto nu = _mu[_qp] / _rho[_qp]; const auto transient_part = _has_transient ? 4. / (_dt * _dt) : 0.; - const auto speed = NS::computeSpeed(_velocity[_qp]); - _tau[_qp] = _alpha / std::sqrt(transient_part + (2. * speed / _hmax) * (2. * speed / _hmax) + + _speed = NS::computeSpeed(_relative_velocity[_qp]); + _tau[_qp] = _alpha / std::sqrt(transient_part + (2. * _speed / _hmax) * (2. * _speed / _hmax) + 9. * (4. * nu / (_hmax * _hmax)) * (4. * nu / (_hmax * _hmax))); _momentum_strong_residual[_qp] = diff --git a/modules/navier_stokes/src/materials/INSADMaterial.C b/modules/navier_stokes/src/materials/INSADMaterial.C index 9b1ff8c74d3a..72a4291035c0 100644 --- a/modules/navier_stokes/src/materials/INSADMaterial.C +++ b/modules/navier_stokes/src/materials/INSADMaterial.C @@ -50,6 +50,7 @@ INSADMaterial::INSADMaterial(const InputParameters & parameters) _coupled_force_strong_residual( declareADProperty("coupled_force_strong_residual")), _mesh_velocity(declareADProperty("mesh_velocity")), + _relative_velocity(declareADProperty("relative_velocity")), _advected_mesh_strong_residual( declareADProperty("advected_mesh_strong_residual")), // _mms_function_strong_residual(declareProperty("mms_function_strong_residual")), @@ -209,6 +210,7 @@ INSADMaterial::computeQpProperties() if (_has_boussinesq) _boussinesq_strong_residual[_qp] = (*_boussinesq_alpha)[_qp] * _gravity_vector * _rho[_qp] * ((*_temperature)[_qp] - (*_ref_temp)[_qp]); + _relative_velocity[_qp] = _velocity[_qp]; if (_has_advected_mesh) { @@ -217,6 +219,7 @@ INSADMaterial::computeQpProperties() _mesh_velocity[_qp](1) = (*_disp_y_dot)[_qp]; if (_disp_z_dot) _mesh_velocity[_qp](2) = (*_disp_z_dot)[_qp]; + _relative_velocity[_qp] -= _mesh_velocity[_qp]; _advected_mesh_strong_residual[_qp] = -_rho[_qp] * _grad_velocity[_qp] * _mesh_velocity[_qp]; } diff --git a/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C b/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C index e42ad7517ce0..02e383d60082 100644 --- a/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C +++ b/modules/navier_stokes/src/materials/INSADStabilized3Eqn.C @@ -46,9 +46,8 @@ INSADStabilized3Eqn::computeQpProperties() const auto dissipation_coefficient = _k[_qp] / (_rho[_qp] * _cp[_qp]); const auto transient_part = _has_energy_transient ? 4. / (_dt * _dt) : 0.; - const auto speed = NS::computeSpeed(_velocity[_qp]); _tau_energy[_qp] = - _alpha / std::sqrt(transient_part + (2. * speed / _hmax) * (2. * speed / _hmax) + + _alpha / std::sqrt(transient_part + (2. * _speed / _hmax) * (2. * _speed / _hmax) + 9. * (4. * dissipation_coefficient / (_hmax * _hmax)) * (4. * dissipation_coefficient / (_hmax * _hmax))); From 7d89aaa69e11ea348648c7a549b46ef4e1470341 Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 10 Oct 2023 14:04:33 -0700 Subject: [PATCH 5/8] Modify INS to use relative velocity in SUPG/tau computations INS and INSAD now match again --- modules/fsi/src/kernels/ConvectedMesh.C | 13 +++++--- .../ad-fsi-flat-channel.i | 2 ++ .../fsi_flat_channel.i | 8 +++++ .../gold/fsi_flat_channel_out.e | Bin 202828 -> 204040 bytes .../navier_stokes/include/kernels/INSBase.h | 17 ++++++++-- modules/navier_stokes/src/kernels/INSBase.C | 26 +++++++++++++--- .../src/kernels/INSMomentumBase.C | 29 +++++++++--------- 7 files changed, 69 insertions(+), 26 deletions(-) diff --git a/modules/fsi/src/kernels/ConvectedMesh.C b/modules/fsi/src/kernels/ConvectedMesh.C index 5d3ecec413f1..43832bdc951c 100644 --- a/modules/fsi/src/kernels/ConvectedMesh.C +++ b/modules/fsi/src/kernels/ConvectedMesh.C @@ -61,16 +61,17 @@ Real ConvectedMesh::computeQpResidual() { auto test = _test[_i][_qp]; + const auto U = relativeVelocity(); if (_supg) - test += tau() * _grad_test[_i][_qp] * RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + test += tau() * _grad_test[_i][_qp] * U; return test * strongResidual(); } Real ConvectedMesh::computePGVelocityJacobian(const unsigned short component) { - return strongResidual() * ((dTauDUComp(component) * _grad_test[_i][_qp] * - RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp])) + + const auto U = relativeVelocity(); + return strongResidual() * ((dTauDUComp(component) * _grad_test[_i][_qp] * U) + (tau() * _grad_test[_i][_qp](component) * _phi[_j][_qp])); } @@ -78,8 +79,9 @@ Real ConvectedMesh::computeQpJacobian() { auto test = _test[_i][_qp]; + const auto U = relativeVelocity(); if (_supg) - test += tau() * _grad_test[_i][_qp] * RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + test += tau() * _grad_test[_i][_qp] * U; auto jac = test * -_rho[_qp] * RealVectorValue(_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]) * _grad_phi[_j][_qp]; @@ -95,8 +97,9 @@ ConvectedMesh::computeQpOffDiagJacobian(unsigned int jvar) mooseAssert(jvar != _var.number(), "Making sure I understand how old hand-coded Jacobians work."); auto test = _test[_i][_qp]; + const auto U = relativeVelocity(); if (_supg) - test += tau() * _grad_test[_i][_qp] * RealVectorValue(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + test += tau() * _grad_test[_i][_qp] * U; if (jvar == _disp_x_id) return test * -_rho[_qp] * _phi[_j][_qp] * _d_disp_x_dot[_qp] * _grad_u[_qp](0); diff --git a/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i b/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i index 71c78ff37f8c..a605cbb299fe 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i +++ b/modules/fsi/test/tests/2d-small-strain-transient/ad-fsi-flat-channel.i @@ -268,6 +268,8 @@ petsc_options_iname = '-pc_type -pc_factor_shift_type' petsc_options_value = 'lu NONZERO' line_search = none + nl_rel_tol = 1e-50 + nl_abs_tol = 1e-10 [] [Outputs] diff --git a/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i b/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i index 9e21c69ac5a2..81b65334510f 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i +++ b/modules/fsi/test/tests/2d-small-strain-transient/fsi_flat_channel.i @@ -87,6 +87,8 @@ v = vel_y pressure = p block = 0 + disp_x = disp_x + disp_y = disp_y [../] [./x_momentum_space] type = INSMomentumLaplaceForm @@ -96,6 +98,8 @@ pressure = p component = 0 block = 0 + disp_x = disp_x + disp_y = disp_y [../] [./y_momentum_space] type = INSMomentumLaplaceForm @@ -105,6 +109,8 @@ pressure = p component = 1 block = 0 + disp_x = disp_x + disp_y = disp_y [../] [./vel_x_mesh] type = ConvectedMesh @@ -303,6 +309,8 @@ petsc_options_iname = '-pc_type -pc_factor_shift_type' petsc_options_value = 'lu NONZERO' line_search = none + nl_rel_tol = 1e-50 + nl_abs_tol = 1e-10 [] [Outputs] diff --git a/modules/fsi/test/tests/2d-small-strain-transient/gold/fsi_flat_channel_out.e b/modules/fsi/test/tests/2d-small-strain-transient/gold/fsi_flat_channel_out.e index dc3418a9f894eda2432be4640cebc24a3cbb334e..9678cb1f2d63f7251f07edfc25f67423d951a332 100644 GIT binary patch delta 32028 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 delta 32046 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 diff --git a/modules/navier_stokes/include/kernels/INSBase.h b/modules/navier_stokes/include/kernels/INSBase.h index 2efa3a85598a..aef78d1c44ad 100644 --- a/modules/navier_stokes/include/kernels/INSBase.h +++ b/modules/navier_stokes/include/kernels/INSBase.h @@ -11,8 +11,6 @@ #include "Kernel.h" -// Forward Declarations - /** * This class computes strong and weak components of the INS governing * equations. These terms can then be assembled in child classes @@ -60,6 +58,12 @@ class INSBase : public Kernel /// Provides tau which yields superconvergence for 1D advection-diffusion virtual Real tauNodal(); + /** + * Compute the velocity. If displacements are provided, then this routine will subtract the time + * derivative of the displacements, e.g. the mesh velocity + */ + RealVectorValue relativeVelocity() const; + /// second derivatives of the shape function const VariablePhiSecond & _second_phi; @@ -106,4 +110,13 @@ class INSBase : public Kernel bool _laplace; bool _convective_term; bool _transient_term; + + /// Whether displacements are provided + const bool _disps_provided; + /// Time derivative of the x-displacement + const VariableValue & _disp_x_dot; + /// Time derivative of the y-displacement + const VariableValue & _disp_y_dot; + /// Time derivative of the z-displacement + const VariableValue & _disp_z_dot; }; diff --git a/modules/navier_stokes/src/kernels/INSBase.C b/modules/navier_stokes/src/kernels/INSBase.C index 4a182a542746..ffd096191a26 100644 --- a/modules/navier_stokes/src/kernels/INSBase.C +++ b/modules/navier_stokes/src/kernels/INSBase.C @@ -38,6 +38,9 @@ INSBase::validParams() params.addParam("transient_term", false, "Whether there should be a transient term in the momentum residuals."); + params.addCoupledVar("disp_x", "The x displacement"); + params.addCoupledVar("disp_y", "The y displacement"); + params.addCoupledVar("disp_z", "The z displacement"); return params; } @@ -88,10 +91,25 @@ INSBase::INSBase(const InputParameters & parameters) _alpha(getParam("alpha")), _laplace(getParam("laplace")), _convective_term(getParam("convective_term")), - _transient_term(getParam("transient_term")) + _transient_term(getParam("transient_term")), + + // Displacements for mesh velocity for ALE simulations + _disps_provided(isParamValid("disp_x")), + _disp_x_dot(isParamValid("disp_x") ? coupledDot("disp_x") : _zero), + _disp_y_dot(isParamValid("disp_y") ? coupledDot("disp_y") : _zero), + _disp_z_dot(isParamValid("disp_z") ? coupledDot("disp_z") : _zero) { } +RealVectorValue +INSBase::relativeVelocity() const +{ + RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + if (_disps_provided) + U -= RealVectorValue{_disp_x_dot[_qp], _disp_y_dot[_qp], _disp_z_dot[_qp]}; + return U; +} + RealVectorValue INSBase::convectiveTerm() { @@ -270,7 +288,7 @@ Real INSBase::tau() { Real nu = _mu[_qp] / _rho[_qp]; - RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + const auto U = relativeVelocity(); Real h = _current_elem->hmax(); Real transient_part = _transient_term ? 4. / (_dt * _dt) : 0.; return _alpha / std::sqrt(transient_part + (2. * U.norm() / h) * (2. * U.norm() / h) + @@ -281,7 +299,7 @@ Real INSBase::tauNodal() { Real nu = _mu[_qp] / _rho[_qp]; - RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + const auto U = relativeVelocity(); Real h = _current_elem->hmax(); Real xi; if (nu < std::numeric_limits::epsilon()) @@ -298,7 +316,7 @@ Real INSBase::dTauDUComp(unsigned comp) { Real nu = _mu[_qp] / _rho[_qp]; - RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + const auto U = relativeVelocity(); Real h = _current_elem->hmax(); Real transient_part = _transient_term ? 4. / (_dt * _dt) : 0.; return -_alpha / 2. * diff --git a/modules/navier_stokes/src/kernels/INSMomentumBase.C b/modules/navier_stokes/src/kernels/INSMomentumBase.C index 59ea047a5794..35c605cdcc25 100644 --- a/modules/navier_stokes/src/kernels/INSMomentumBase.C +++ b/modules/navier_stokes/src/kernels/INSMomentumBase.C @@ -65,13 +65,11 @@ INSMomentumBase::computeQpResidual() Real INSMomentumBase::computeQpPGResidual() { - RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + const auto U = relativeVelocity(); - RealVectorValue convective_term = _convective_term ? convectiveTerm() : RealVectorValue(0, 0, 0); - RealVectorValue viscous_term = - _laplace ? strongViscousTermLaplace() : strongViscousTermTraction(); - RealVectorValue transient_term = - _transient_term ? timeDerivativeTerm() : RealVectorValue(0, 0, 0); + const auto convective_term = _convective_term ? convectiveTerm() : RealVectorValue(0, 0, 0); + const auto viscous_term = _laplace ? strongViscousTermLaplace() : strongViscousTermTraction(); + const auto transient_term = _transient_term ? timeDerivativeTerm() : RealVectorValue(0, 0, 0); return tau() * U * _grad_test[_i][_qp] * ((convective_term + viscous_term + transient_term + strongPressureTerm() + @@ -109,18 +107,19 @@ INSMomentumBase::computeQpJacobian() Real INSMomentumBase::computeQpPGJacobian(unsigned comp) { - RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + const auto U = relativeVelocity(); RealVectorValue d_U_d_U_comp(0, 0, 0); d_U_d_U_comp(comp) = _phi[_j][_qp]; - Real convective_term = _convective_term ? convectiveTerm()(_component) : 0; - Real d_convective_term_d_u_comp = _convective_term ? dConvecDUComp(comp)(_component) : 0; - Real viscous_term = + const Real convective_term = _convective_term ? convectiveTerm()(_component) : 0; + const Real d_convective_term_d_u_comp = _convective_term ? dConvecDUComp(comp)(_component) : 0; + const Real viscous_term = _laplace ? strongViscousTermLaplace()(_component) : strongViscousTermTraction()(_component); - Real d_viscous_term_d_u_comp = _laplace ? dStrongViscDUCompLaplace(comp)(_component) - : dStrongViscDUCompTraction(comp)(_component); - Real transient_term = _transient_term ? timeDerivativeTerm()(_component) : 0; - Real d_transient_term_d_u_comp = _transient_term ? dTimeDerivativeDUComp(comp)(_component) : 0; + const Real d_viscous_term_d_u_comp = _laplace ? dStrongViscDUCompLaplace(comp)(_component) + : dStrongViscDUCompTraction(comp)(_component); + const Real transient_term = _transient_term ? timeDerivativeTerm()(_component) : 0; + const Real d_transient_term_d_u_comp = + _transient_term ? dTimeDerivativeDUComp(comp)(_component) : 0; return dTauDUComp(comp) * U * _grad_test[_i][_qp] * (convective_term + viscous_term + strongPressureTerm()(_component) + @@ -182,7 +181,7 @@ INSMomentumBase::computeQpOffDiagJacobian(unsigned jvar) if (_supg) { - RealVectorValue U(_u_vel[_qp], _v_vel[_qp], _w_vel[_qp]); + const auto U = relativeVelocity(); jac += tau() * U * _grad_test[_i][_qp] * dStrongPressureDPressure()(_component); } From 165061fa08b7311e14175029f4c03621623bec7a Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 10 Oct 2023 14:13:36 -0700 Subject: [PATCH 6/8] Remove INS Jacobian test Using the relative velocity as the advecting velocity in SUPG and in calculations of tau introduced new dependence on the displacements that I don't want to spend time coding the Jacobians for --- modules/fsi/test/tests/2d-small-strain-transient/tests | 8 -------- 1 file changed, 8 deletions(-) diff --git a/modules/fsi/test/tests/2d-small-strain-transient/tests b/modules/fsi/test/tests/2d-small-strain-transient/tests index 9497a8b3f865..509941f1416f 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/tests +++ b/modules/fsi/test/tests/2d-small-strain-transient/tests @@ -38,13 +38,5 @@ cli_args = 'Mesh/gmg/nx=2 Mesh/gmg/ny=3 Executioner/num_steps=1 GlobalParams/use_displaced_mesh=false' detail = 'perfect when the fluid domain equations are run on the undisplaced mesh, and' [] - [INS_undisplaced_jac] - type = 'PetscJacobianTester' - input = 'fsi_flat_channel.i' - difference_tol = 1 - run_sim = True - cli_args = 'Mesh/gmg/nx=2 Mesh/gmg/ny=3 Executioner/num_steps=1 GlobalParams/use_displaced_mesh=false' - detail = 'the hand-coded Jacobian shall be perfect when the simulation is run entirely undisplaced.' - [] [] [] From 3ee3baaaafe28954126c4fc3bdf80b31c0a5a33e Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 17 Oct 2023 17:59:15 -0700 Subject: [PATCH 7/8] Try to address Max's markdown comment --- .../doc/content/source/kernels/ConvectedMesh.md | 1 + .../content/source/kernels/ConvectedMeshPSPG.md | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/modules/fsi/doc/content/source/kernels/ConvectedMesh.md b/modules/fsi/doc/content/source/kernels/ConvectedMesh.md index 4e4638955353..b1218d9ac01a 100644 --- a/modules/fsi/doc/content/source/kernels/ConvectedMesh.md +++ b/modules/fsi/doc/content/source/kernels/ConvectedMesh.md @@ -6,6 +6,7 @@ the term: \begin{equation} +\label{convection} -\rho \left(\frac{\partial\vec{d_m}}{\partial t} \cdot \nabla\right) \vec{u} \end{equation} diff --git a/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md b/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md index 4c83a0b23656..292f3d99303c 100644 --- a/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md +++ b/modules/fsi/doc/content/source/kernels/ConvectedMeshPSPG.md @@ -7,13 +7,22 @@ equation corresponding to the [ConvectedMesh.md] object. It implements the weak form \begin{equation} -\int \nabla \psi \dot \left(\tau \dot{\vec{d}}\right) dV +\label{pspg} +\int \nabla \psi \cdot \left(\tau\frac{\partial\vec{d_m}}{\partial t}\cdot\nabla\vec{u}\right) dV \end{equation} where $\nabla \psi$ is the gradient of the pressure test function, $\tau$ is a stabilization parameter computed automatically by the `navier_stokes` base class -`INSBase`, and $\dot{\vec{d}}$ is the time derivative of the displacement -vector. +`INSBase`, $\vec{d_m}$ is the fluid mesh displacements, and +$\vec{u}$ is the fluid velocity. Note that when comparing [pspg] with +[!eqref](ConvectedMesh.md#convection) that the minus sign and density $\rho$ have +disappeared. This is because the form of PSPG stabilization is + +\begin{equation} +\int \nabla \psi \cdot \left(-\frac{\tau}{\rho}\vec{R}\right) +\end{equation} + +where $\vec{R}$ denotes the strong form of the momentum residuals. !syntax parameters /Kernels/ConvectedMeshPSPG From fd7f724d99f564542177559125579f5309db0b3f Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Fri, 27 Oct 2023 12:56:09 -0700 Subject: [PATCH 8/8] Apply suggestions from code review - Better doxygen for ConvectedMeshPSPG - Typo fix - Better doxygen for _speed member - Inline short methods in the header - More doxygen for disp dot members in INSBase - Switch i and qp loop order Co-authored-by: Guillaume Giudicelli --- .../ADPenaltyVelocityContinuity.h | 42 +++++++++++++++++ .../fsi/include/kernels/ConvectedMeshPSPG.h | 2 +- .../ADPenaltyVelocityContinuity.C | 45 +------------------ .../tests/2d-small-strain-transient/tests | 2 +- .../navier_stokes/include/kernels/INSBase.h | 6 +-- .../include/materials/INSADTauMaterial.h | 2 +- 6 files changed, 50 insertions(+), 49 deletions(-) diff --git a/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h b/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h index fb5ec1533fde..3611710689f6 100644 --- a/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h +++ b/modules/fsi/include/interfacekernels/ADPenaltyVelocityContinuity.h @@ -10,6 +10,7 @@ #pragma once #include "InterfaceKernelBase.h" +#include "MooseVariableFE.h" /** * Interface kernel for enforcing continuity of stress and velocity @@ -57,3 +58,44 @@ class ADPenaltyVelocityContinuity : public InterfaceKernelBase /// Jump data member to avoid constant heap allocations std::vector _qp_jumps; }; + +inline void +ADPenaltyVelocityContinuity::computeJacobian() +{ + computeResidual(); +} + +inline void +ADPenaltyVelocityContinuity::computeResidualAndJacobian() +{ + computeResidual(); +} + +inline void +ADPenaltyVelocityContinuity::computeElementOffDiagJacobian(const unsigned int jvar) +{ + if (jvar == _velocity_var->number()) + // Only need to do this once because AD does everything all at once + computeResidual(); +} + +inline void +ADPenaltyVelocityContinuity::computeNeighborOffDiagJacobian(unsigned int) +{ +} + +inline const MooseVariableFieldBase & +ADPenaltyVelocityContinuity::variable() const +{ + return *_velocity_var; +} + +inline const MooseVariableFieldBase & +ADPenaltyVelocityContinuity::neighborVariable() const +{ + if (_displacements.empty() || !_displacements.front()) + mooseError("The 'neighborVariable' method was called which requires that displacements be " + "actual variables."); + + return *_displacements.front(); +} diff --git a/modules/fsi/include/kernels/ConvectedMeshPSPG.h b/modules/fsi/include/kernels/ConvectedMeshPSPG.h index 98ca4f0e7e99..617caeeb54cb 100644 --- a/modules/fsi/include/kernels/ConvectedMeshPSPG.h +++ b/modules/fsi/include/kernels/ConvectedMeshPSPG.h @@ -12,7 +12,7 @@ #include "INSBase.h" /** - * This calculates the time derivative for a coupled variable + * Computes residual and Jacobian contributions for the PSPG stabilization term for mesh advection **/ class ConvectedMeshPSPG : public INSBase { diff --git a/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C b/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C index bdf99341a19f..bd44f5906126 100644 --- a/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C +++ b/modules/fsi/src/interfacekernels/ADPenaltyVelocityContinuity.C @@ -77,8 +77,8 @@ ADPenaltyVelocityContinuity::computeResidual() for (auto & r : _residuals) r = 0; - for (const auto qp : make_range(_qrule->n_points())) - for (const auto i : index_range(phi)) + for (const auto i : index_range(phi)) + for (const auto qp : make_range(_qrule->n_points())) _residuals[i] += phi[i][qp] * _qp_jumps[qp]; addResidualsAndJacobian(_assembly, _residuals, dof_indices, _velocity_var->scalingFactor()); @@ -106,44 +106,3 @@ ADPenaltyVelocityContinuity::computeResidual() } } } - -void -ADPenaltyVelocityContinuity::computeJacobian() -{ - computeResidual(); -} - -void -ADPenaltyVelocityContinuity::computeResidualAndJacobian() -{ - computeResidual(); -} - -void -ADPenaltyVelocityContinuity::computeElementOffDiagJacobian(const unsigned int jvar) -{ - if (jvar == _velocity_var->number()) - // Only need to do this once because AD does everything all at once - computeResidual(); -} - -void -ADPenaltyVelocityContinuity::computeNeighborOffDiagJacobian(unsigned int) -{ -} - -const MooseVariableFieldBase & -ADPenaltyVelocityContinuity::variable() const -{ - return *_velocity_var; -} - -const MooseVariableFieldBase & -ADPenaltyVelocityContinuity::neighborVariable() const -{ - if (_displacements.empty() || !_displacements.front()) - mooseError("The 'neighborVariable' method was called which requires that displacements be " - "actual variables."); - - return *_displacements.front(); -} diff --git a/modules/fsi/test/tests/2d-small-strain-transient/tests b/modules/fsi/test/tests/2d-small-strain-transient/tests index 509941f1416f..71037c3d3e4f 100644 --- a/modules/fsi/test/tests/2d-small-strain-transient/tests +++ b/modules/fsi/test/tests/2d-small-strain-transient/tests @@ -9,7 +9,7 @@ exodiff = 'fsi_flat_channel_out.e' detail = 'scalar field variables for velocity components and hand-coded Jacobians,' # vel_x_solid is not accurate - # We mmay improve that in the future + # We may improve that in the future rel_err = 1e-4 [] [INSAD] diff --git a/modules/navier_stokes/include/kernels/INSBase.h b/modules/navier_stokes/include/kernels/INSBase.h index aef78d1c44ad..1e34c800f52b 100644 --- a/modules/navier_stokes/include/kernels/INSBase.h +++ b/modules/navier_stokes/include/kernels/INSBase.h @@ -113,10 +113,10 @@ class INSBase : public Kernel /// Whether displacements are provided const bool _disps_provided; - /// Time derivative of the x-displacement + /// Time derivative of the x-displacement, mesh velocity in the x-direction const VariableValue & _disp_x_dot; - /// Time derivative of the y-displacement + /// Time derivative of the y-displacement, mesh velocity in the y-direction const VariableValue & _disp_y_dot; - /// Time derivative of the z-displacement + /// Time derivative of the z-displacement, mesh velocity in the z-direction const VariableValue & _disp_z_dot; }; diff --git a/modules/navier_stokes/include/materials/INSADTauMaterial.h b/modules/navier_stokes/include/materials/INSADTauMaterial.h index bcec8f6308c2..78994614ee87 100644 --- a/modules/navier_stokes/include/materials/INSADTauMaterial.h +++ b/modules/navier_stokes/include/materials/INSADTauMaterial.h @@ -91,7 +91,7 @@ class INSADTauMaterialTempl : public T const unsigned int _vel_sys_number; /// The speed of the medium. This is the norm of the relative velocity, e.g. the velocity minus - /// the mesh velocity + /// the mesh velocity, at the current _qp ADReal _speed; using T::_ad_q_point;