From 6a69f37cdde0698e55d71146461f2dd4cf958f07 Mon Sep 17 00:00:00 2001 From: Alex Lindsay Date: Tue, 22 Aug 2023 15:30:26 -0700 Subject: [PATCH] Allow preset vector AD Dirichlet BCs Closes #25271 --- framework/include/bcs/ADDirichletBC.h | 4 +- framework/include/bcs/ADDirichletBCBase.h | 13 +--- .../include/bcs/ADDirichletBCBaseTempl.h | 45 +++++++++++ framework/include/bcs/ADFunctionDirichletBC.h | 4 +- framework/include/bcs/ADNodalBC.h | 28 +++++-- framework/include/bcs/ADPresetNodalBC.h | 27 ------- .../include/bcs/ADVectorFunctionDirichletBC.h | 6 +- framework/src/bcs/ADDirichletBC.C | 4 +- framework/src/bcs/ADDirichletBCBase.C | 22 +----- framework/src/bcs/ADDirichletBCBaseTempl.C | 66 ++++++++++++++++ framework/src/bcs/ADFunctionDirichletBC.C | 4 +- framework/src/bcs/ADNodalBC.C | 75 ++++++++++++------- framework/src/bcs/ADPresetNodalBC.C | 30 -------- .../src/bcs/ADVectorFunctionDirichletBC.C | 9 +-- 14 files changed, 200 insertions(+), 137 deletions(-) create mode 100644 framework/include/bcs/ADDirichletBCBaseTempl.h delete mode 100644 framework/include/bcs/ADPresetNodalBC.h create mode 100644 framework/src/bcs/ADDirichletBCBaseTempl.C delete mode 100644 framework/src/bcs/ADPresetNodalBC.C diff --git a/framework/include/bcs/ADDirichletBC.h b/framework/include/bcs/ADDirichletBC.h index 388078aee37e..397db43711b1 100644 --- a/framework/include/bcs/ADDirichletBC.h +++ b/framework/include/bcs/ADDirichletBC.h @@ -9,14 +9,14 @@ #pragma once -#include "ADDirichletBCBase.h" +#include "ADDirichletBCBaseTempl.h" /** * Boundary condition of a Dirichlet type * * Sets the values of a nodal variable at nodes */ -class ADDirichletBC : public ADDirichletBCBase +class ADDirichletBC : public ADDirichletBCBaseTempl { public: static InputParameters validParams(); diff --git a/framework/include/bcs/ADDirichletBCBase.h b/framework/include/bcs/ADDirichletBCBase.h index 02330a522014..f7bd11636d34 100644 --- a/framework/include/bcs/ADDirichletBCBase.h +++ b/framework/include/bcs/ADDirichletBCBase.h @@ -9,12 +9,12 @@ #pragma once -#include "ADNodalBC.h" +#include "NodalBCBase.h" /** * Base class for automatic differentiation Dirichlet BCs */ -class ADDirichletBCBase : public ADNodalBC +class ADDirichletBCBase : public NodalBCBase { public: ADDirichletBCBase(const InputParameters & parameters); @@ -22,20 +22,13 @@ class ADDirichletBCBase : public ADNodalBC /** * Method to preset the nodal value if applicable */ - void computeValue(NumericVector & current_solution); + virtual void computeValue(NumericVector & current_solution) = 0; static InputParameters validParams(); bool preset() const { return _preset; } protected: - virtual ADReal computeQpResidual() override; - - /** - * Compute the value of the Dirichlet BC at the current quadrature point - */ - virtual ADReal computeQpValue() = 0; - /// Whether or not the value is to be preset const bool _preset; }; diff --git a/framework/include/bcs/ADDirichletBCBaseTempl.h b/framework/include/bcs/ADDirichletBCBaseTempl.h new file mode 100644 index 000000000000..3342fc84da78 --- /dev/null +++ b/framework/include/bcs/ADDirichletBCBaseTempl.h @@ -0,0 +1,45 @@ +//* 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 "ADDirichletBCBase.h" +#include "ADNodalBC.h" + +/** + * Base class for automatic differentiation Dirichlet BCs + */ +template +class ADDirichletBCBaseTempl : public ADNodalBCTempl +{ +public: + ADDirichletBCBaseTempl(const InputParameters & parameters); + + /** + * Method to preset the nodal value if applicable + */ + virtual void computeValue(NumericVector & current_solution) override; + + static InputParameters validParams(); + +protected: + virtual typename Moose::ADType::type computeQpResidual() override; + + /** + * Compute the value of the Dirichlet BC at the current quadrature point + */ + virtual typename Moose::ADType::type computeQpValue() = 0; + + using ADNodalBCTempl::_var; + using ADNodalBCTempl::_sys; + using ADNodalBCTempl::_current_node; + using ADNodalBCTempl::_u; + using ADNodalBCTempl::_t; + using ADNodalBCTempl::shouldSetComp; +}; diff --git a/framework/include/bcs/ADFunctionDirichletBC.h b/framework/include/bcs/ADFunctionDirichletBC.h index bef34284722a..7f1cd950a719 100644 --- a/framework/include/bcs/ADFunctionDirichletBC.h +++ b/framework/include/bcs/ADFunctionDirichletBC.h @@ -9,14 +9,14 @@ #pragma once -#include "ADDirichletBCBase.h" +#include "ADDirichletBCBaseTempl.h" /** * Boundary condition of a Dirichlet type * * Sets the values of a nodal variable at nodes to values specified by a function */ -class ADFunctionDirichletBC : public ADDirichletBCBase +class ADFunctionDirichletBC : public ADDirichletBCBaseTempl { public: static InputParameters validParams(); diff --git a/framework/include/bcs/ADNodalBC.h b/framework/include/bcs/ADNodalBC.h index 9b67918efdb4..b2597f6cc012 100644 --- a/framework/include/bcs/ADNodalBC.h +++ b/framework/include/bcs/ADNodalBC.h @@ -9,14 +9,15 @@ #pragma once -#include "NodalBCBase.h" #include "MooseVariableInterface.h" +#include "NodalBCBase.h" +#include "ADDirichletBCBase.h" /** * Base class for deriving any automatic differentiation boundary condition of a integrated type */ -template -class ADNodalBCTempl : public NodalBCBase, public MooseVariableInterface +template +class ADNodalBCTempl : public Base, public MooseVariableInterface { public: static InputParameters validParams(); @@ -25,6 +26,8 @@ class ADNodalBCTempl : public NodalBCBase, public MooseVariableInterface const MooseVariableFE & variable() const override { return _var; } + bool shouldSetComp(unsigned short i) const { return _set_components[i]; } + protected: /** * Compute this NodalBC's contribution to the residual at the current quadrature point @@ -45,6 +48,14 @@ class ADNodalBCTempl : public NodalBCBase, public MooseVariableInterface const std::array _set_components; + using Base::_fe_problem; + using Base::_subproblem; + using Base::_sys; + using Base::_tid; + using Base::addJacobian; + using Base::addMooseVariableDependency; + using Base::setResidual; + private: void computeResidual() override final; void computeJacobian() override final; @@ -58,7 +69,6 @@ class ADNodalBCTempl : public NodalBCBase, public MooseVariableInterface template void addResidual(const ADResidual & residual, const std::vector & dof_indices); - using NodalBCBase::addJacobian; /** * process the Jacobian into the global data structures */ @@ -70,5 +80,11 @@ class ADNodalBCTempl : public NodalBCBase, public MooseVariableInterface Assembly & _undisplaced_assembly; }; -using ADNodalBC = ADNodalBCTempl; -using ADVectorNodalBC = ADNodalBCTempl; +template <> +InputParameters ADNodalBCTempl::validParams(); + +template <> +InputParameters ADNodalBCTempl::validParams(); + +using ADNodalBC = ADNodalBCTempl; +using ADVectorNodalBC = ADNodalBCTempl; diff --git a/framework/include/bcs/ADPresetNodalBC.h b/framework/include/bcs/ADPresetNodalBC.h deleted file mode 100644 index a2c5aac541c0..000000000000 --- a/framework/include/bcs/ADPresetNodalBC.h +++ /dev/null @@ -1,27 +0,0 @@ -//* 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 "ADDirichletBCBase.h" - -/** - * Base class for automatic differentiation nodal BCs that (pre)set the solution - * vector entries. - * - * Depcreated: inherit from ADDirichletBCBase instead and set the parameter - * preset = true for the same behavior. - */ -class ADPresetNodalBC : public ADDirichletBCBase -{ -public: - ADPresetNodalBC(const InputParameters & parameters); - - static InputParameters validParams(); -}; diff --git a/framework/include/bcs/ADVectorFunctionDirichletBC.h b/framework/include/bcs/ADVectorFunctionDirichletBC.h index 04bd74351de2..9a82ef13bf2c 100644 --- a/framework/include/bcs/ADVectorFunctionDirichletBC.h +++ b/framework/include/bcs/ADVectorFunctionDirichletBC.h @@ -9,14 +9,14 @@ #pragma once -#include "ADNodalBC.h" +#include "ADDirichletBCBaseTempl.h" /** * Boundary condition of a Dirichlet type * * Sets the values of a LAGRANGE_VEC variable at nodes to values specified by functions */ -class ADVectorFunctionDirichletBC : public ADVectorNodalBC +class ADVectorFunctionDirichletBC : public ADDirichletBCBaseTempl { public: static InputParameters validParams(); @@ -24,7 +24,7 @@ class ADVectorFunctionDirichletBC : public ADVectorNodalBC ADVectorFunctionDirichletBC(const InputParameters & parameters); protected: - virtual ADRealVectorValue computeQpResidual() override; + virtual ADRealVectorValue computeQpValue() override; /// Optional vectorValue function const Function * const _function; diff --git a/framework/src/bcs/ADDirichletBC.C b/framework/src/bcs/ADDirichletBC.C index 439e845f79b7..61702a7003b1 100644 --- a/framework/src/bcs/ADDirichletBC.C +++ b/framework/src/bcs/ADDirichletBC.C @@ -14,7 +14,7 @@ registerMooseObject("MooseApp", ADDirichletBC); InputParameters ADDirichletBC::validParams() { - InputParameters params = ADDirichletBCBase::validParams(); + InputParameters params = ADDirichletBCBaseTempl::validParams(); params.addRequiredParam("value", "Value of the BC"); params.declareControllable("value"); params.addClassDescription("Imposes the essential boundary condition $u=g$, where $g$ " @@ -23,7 +23,7 @@ ADDirichletBC::validParams() } ADDirichletBC::ADDirichletBC(const InputParameters & parameters) - : ADDirichletBCBase(parameters), _value(getParam("value")) + : ADDirichletBCBaseTempl(parameters), _value(getParam("value")) { } diff --git a/framework/src/bcs/ADDirichletBCBase.C b/framework/src/bcs/ADDirichletBCBase.C index b4dfa553456c..56008da73287 100644 --- a/framework/src/bcs/ADDirichletBCBase.C +++ b/framework/src/bcs/ADDirichletBCBase.C @@ -12,31 +12,13 @@ InputParameters ADDirichletBCBase::validParams() { - InputParameters params = ADNodalBC::validParams(); + InputParameters params = NodalBCBase::validParams(); params.addParam( "preset", true, "Whether or not to preset the BC (apply the value before the solve begins)."); return params; } ADDirichletBCBase::ADDirichletBCBase(const InputParameters & parameters) - : ADNodalBC(parameters), _preset(getParam("preset")) + : NodalBCBase(parameters), _preset(getParam("preset")) { } - -void -ADDirichletBCBase::computeValue(NumericVector & current_solution) -{ - mooseAssert(_preset, "BC is not preset"); - - if (_var.isNodalDefined()) - { - const auto dof_idx = _var.nodalDofIndex(); - current_solution.set(dof_idx, MetaPhysicL::raw_value(computeQpValue())); - } -} - -ADReal -ADDirichletBCBase::computeQpResidual() -{ - return _u - computeQpValue(); -} diff --git a/framework/src/bcs/ADDirichletBCBaseTempl.C b/framework/src/bcs/ADDirichletBCBaseTempl.C new file mode 100644 index 000000000000..c8dbecdeb9c5 --- /dev/null +++ b/framework/src/bcs/ADDirichletBCBaseTempl.C @@ -0,0 +1,66 @@ +//* 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 "ADDirichletBCBaseTempl.h" +#include "MooseVariableFE.h" +#include "SystemBase.h" +#include "libmesh/node.h" + +template +InputParameters +ADDirichletBCBaseTempl::validParams() +{ + InputParameters params = ADNodalBCTempl::validParams(); + params.addParam( + "preset", true, "Whether or not to preset the BC (apply the value before the solve begins)."); + return params; +} + +template +ADDirichletBCBaseTempl::ADDirichletBCBaseTempl(const InputParameters & parameters) + : ADNodalBCTempl(parameters) +{ +} + +template +void +ADDirichletBCBaseTempl::computeValue(NumericVector & current_solution) +{ + mooseAssert(this->_preset, "BC is not preset"); + + if (_var.isNodalDefined()) + { + const auto n_comp = _current_node->n_comp(_sys.number(), _var.number()); + const auto value = MetaPhysicL::raw_value(computeQpValue()); + for (const auto i : make_range(n_comp)) + { + const auto dof_idx = _current_node->dof_number(_sys.number(), _var.number(), i); + if constexpr (std::is_same::value) + { + mooseAssert(n_comp == 1, "This should only be unity"); + current_solution.set(dof_idx, value); + } + else + { + if (shouldSetComp(i)) + current_solution.set(dof_idx, value(i)); + } + } + } +} + +template +typename Moose::ADType::type +ADDirichletBCBaseTempl::computeQpResidual() +{ + return _u - computeQpValue(); +} + +template class ADDirichletBCBaseTempl; +template class ADDirichletBCBaseTempl; diff --git a/framework/src/bcs/ADFunctionDirichletBC.C b/framework/src/bcs/ADFunctionDirichletBC.C index 46009aded76f..f0c154e8c51c 100644 --- a/framework/src/bcs/ADFunctionDirichletBC.C +++ b/framework/src/bcs/ADFunctionDirichletBC.C @@ -17,7 +17,7 @@ registerMooseObject("MooseApp", ADFunctionDirichletBC); InputParameters ADFunctionDirichletBC::validParams() { - InputParameters params = ADDirichletBCBase::validParams(); + InputParameters params = ADDirichletBCBaseTempl::validParams(); params.addClassDescription("Imposes the essential boundary condition $u=g$, where $g$ " "is calculated by a function."); params.addParam("function", 0, "The function describing the Dirichlet condition"); @@ -25,7 +25,7 @@ ADFunctionDirichletBC::validParams() } ADFunctionDirichletBC::ADFunctionDirichletBC(const InputParameters & parameters) - : ADDirichletBCBase(parameters), _function(getFunction("function")) + : ADDirichletBCBaseTempl(parameters), _function(getFunction("function")) { } diff --git a/framework/src/bcs/ADNodalBC.C b/framework/src/bcs/ADNodalBC.C index 08a4c0982f55..a86655459d90 100644 --- a/framework/src/bcs/ADNodalBC.C +++ b/framework/src/bcs/ADNodalBC.C @@ -8,6 +8,8 @@ //* https://www.gnu.org/licenses/lgpl-2.1.html #include "ADNodalBC.h" +#include "NodalBCBase.h" +#include "ADDirichletBCBase.h" // MOOSE includes #include "Assembly.h" @@ -18,16 +20,16 @@ #include "libmesh/quadrature.h" -template +template InputParameters -ADNodalBCTempl::validParams() +ADNodalBCTempl::validParams() { - return NodalBCBase::validParams(); + return Base::validParams(); } template <> InputParameters -ADNodalBCTempl::validParams() +ADNodalBCTempl::validParams() { InputParameters params = NodalBCBase::validParams(); // The below parameters are useful for vector Nodal BCs @@ -37,9 +39,21 @@ ADNodalBCTempl::validParams() return params; } -template -ADNodalBCTempl::ADNodalBCTempl(const InputParameters & parameters) - : NodalBCBase(parameters), +template <> +InputParameters +ADNodalBCTempl::validParams() +{ + InputParameters params = ADDirichletBCBase::validParams(); + // The below parameters are useful for vector Nodal BCs + params.addParam("set_x_comp", true, "Whether to set the x-component of the variable"); + params.addParam("set_y_comp", true, "Whether to set the y-component of the variable"); + params.addParam("set_z_comp", true, "Whether to set the z-component of the variable"); + return params; +} + +template +ADNodalBCTempl::ADNodalBCTempl(const InputParameters & parameters) + : Base(parameters), MooseVariableInterface(this, true, "variable", @@ -50,9 +64,12 @@ ADNodalBCTempl::ADNodalBCTempl(const InputParameters & parameters) _current_node(_var.node()), _u(_var.adNodalValue()), _set_components( - {std::is_same::value ? getParam("set_x_comp") : true, - std::is_same::value ? getParam("set_y_comp") : true, - std::is_same::value ? getParam("set_z_comp") : true}), + {std::is_same::value ? this->template getParam("set_x_comp") + : true, + std::is_same::value ? this->template getParam("set_y_comp") + : true, + std::is_same::value ? this->template getParam("set_z_comp") + : true}), _undisplaced_assembly(_fe_problem.assembly(_tid, _sys.number())) { _subproblem.haveADObjects(true); @@ -75,11 +92,11 @@ conversionHelper(const libMesh::VectorValue & value, const unsigned int } } -template +template template void -ADNodalBCTempl::addResidual(const ADResidual & residual, - const std::vector & dof_indices) +ADNodalBCTempl::addResidual(const ADResidual & residual, + const std::vector & dof_indices) { mooseAssert(dof_indices.size() <= _set_components.size(), "The number of dof indices must be less than the number of settable components"); @@ -89,11 +106,11 @@ ADNodalBCTempl::addResidual(const ADResidual & residual, setResidual(_sys, raw_value(conversionHelper(residual, i)), dof_indices[i]); } -template +template template void -ADNodalBCTempl::addJacobian(const ADResidual & residual, - const std::vector & dof_indices) +ADNodalBCTempl::addJacobian(const ADResidual & residual, + const std::vector & dof_indices) { mooseAssert(dof_indices.size() <= _set_components.size(), "The number of dof indices must be less than the number of settable components"); @@ -108,9 +125,9 @@ ADNodalBCTempl::addJacobian(const ADResidual & residual, /*scaling_factor=*/1); } -template +template void -ADNodalBCTempl::computeResidual() +ADNodalBCTempl::computeResidual() { const std::vector & dof_indices = _var.dofIndices(); if (dof_indices.empty()) @@ -121,9 +138,9 @@ ADNodalBCTempl::computeResidual() addResidual(residual, dof_indices); } -template +template void -ADNodalBCTempl::computeJacobian() +ADNodalBCTempl::computeJacobian() { const std::vector & dof_indices = _var.dofIndices(); if (dof_indices.empty()) @@ -134,9 +151,9 @@ ADNodalBCTempl::computeJacobian() addJacobian(residual, dof_indices); } -template +template void -ADNodalBCTempl::computeResidualAndJacobian() +ADNodalBCTempl::computeResidualAndJacobian() { const std::vector & dof_indices = _var.dofIndices(); if (dof_indices.empty()) @@ -148,21 +165,23 @@ ADNodalBCTempl::computeResidualAndJacobian() addJacobian(residual, dof_indices); } -template +template void -ADNodalBCTempl::computeOffDiagJacobian(const unsigned int jvar_num) +ADNodalBCTempl::computeOffDiagJacobian(const unsigned int jvar_num) { // Only need to do this once because AD does all the derivatives at once if (jvar_num == _var.number()) computeJacobian(); } -template +template void -ADNodalBCTempl::computeOffDiagJacobianScalar(unsigned int) +ADNodalBCTempl::computeOffDiagJacobianScalar(unsigned int) { // scalar coupling will have been included in the all-at-once handling in computeOffDiagJacobian } -template class ADNodalBCTempl; -template class ADNodalBCTempl; +template class ADNodalBCTempl; +template class ADNodalBCTempl; +template class ADNodalBCTempl; +template class ADNodalBCTempl; diff --git a/framework/src/bcs/ADPresetNodalBC.C b/framework/src/bcs/ADPresetNodalBC.C deleted file mode 100644 index c1fa29ab4293..000000000000 --- a/framework/src/bcs/ADPresetNodalBC.C +++ /dev/null @@ -1,30 +0,0 @@ -//* 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 "ADPresetNodalBC.h" - -InputParameters -ADPresetNodalBC::validParams() -{ - InputParameters params = ADNodalBC::validParams(); - - params.addClassDescription( - "Nodal boundary condition base class with preset solution vector values."); - - // Utilize the new ADDirichletBCBase with preset, set true and don't let the user change it - params.set("preset") = true; - params.suppressParameter("preset"); - - return params; -} - -ADPresetNodalBC::ADPresetNodalBC(const InputParameters & parameters) : ADDirichletBCBase(parameters) -{ - mooseDeprecated("Inherit from ADDirichletBCBase with preset = true instead of ADPresetNodalBC"); -} diff --git a/framework/src/bcs/ADVectorFunctionDirichletBC.C b/framework/src/bcs/ADVectorFunctionDirichletBC.C index 7151547e5743..c9b20dcd6ac1 100644 --- a/framework/src/bcs/ADVectorFunctionDirichletBC.C +++ b/framework/src/bcs/ADVectorFunctionDirichletBC.C @@ -15,7 +15,7 @@ registerMooseObject("MooseApp", ADVectorFunctionDirichletBC); InputParameters ADVectorFunctionDirichletBC::validParams() { - InputParameters params = ADVectorNodalBC::validParams(); + InputParameters params = ADDirichletBCBaseTempl::validParams(); params.addClassDescription( "Imposes the essential boundary condition $\\vec{u}=\\vec{g}$, where $\\vec{g}$ " "components are calculated with functions."); @@ -29,7 +29,7 @@ ADVectorFunctionDirichletBC::validParams() } ADVectorFunctionDirichletBC::ADVectorFunctionDirichletBC(const InputParameters & parameters) - : ADVectorNodalBC(parameters), + : ADDirichletBCBaseTempl(parameters), _function(isParamValid("function") ? &getFunction("function") : nullptr), _function_x(getFunction("function_x")), _function_y(getFunction("function_y")), @@ -44,7 +44,7 @@ ADVectorFunctionDirichletBC::ADVectorFunctionDirichletBC(const InputParameters & } ADRealVectorValue -ADVectorFunctionDirichletBC::computeQpResidual() +ADVectorFunctionDirichletBC::computeQpValue() { if (_function) _values = _function->vectorValue(_t, *_current_node); @@ -52,6 +52,5 @@ ADVectorFunctionDirichletBC::computeQpResidual() _values = RealVectorValue(_function_x.value(_t, *_current_node), _function_y.value(_t, *_current_node), _function_z.value(_t, *_current_node)); - - return _u - _values; + return _values; }