Skip to content

Commit

Permalink
Merge pull request idaholab#21255 from hugary1995/adCoupledNeighborGr…
Browse files Browse the repository at this point in the history
…adient

Provide a method in `NeighborCoupleable` to get `adCoupledNeighborGradient`
  • Loading branch information
GiudGiud committed Jun 10, 2022
2 parents 8543682 + 63a7439 commit 5f2c210
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 0 deletions.
8 changes: 8 additions & 0 deletions framework/include/interfaces/NeighborCoupleable.h
Expand Up @@ -75,6 +75,14 @@ class NeighborCoupleable : public Coupleable
unsigned int comp = 0) const;
virtual const VariableGradient & coupledNeighborGradientOlder(const std::string & var_name,
unsigned int comp = 0) const;

/**
* Get the coupled neighbor variable gradient for \p var_name with derivative information for
* automatic differentiation objects
*/
virtual const ADVariableGradient & adCoupledNeighborGradient(const std::string & var_name,
unsigned int comp = 0) const;

virtual const VectorVariableGradient & coupledVectorNeighborGradient(const std::string & var_name,
unsigned int comp = 0) const;
virtual const VectorVariableGradient &
Expand Down
15 changes: 15 additions & 0 deletions framework/src/interfaces/NeighborCoupleable.C
Expand Up @@ -196,6 +196,21 @@ NeighborCoupleable::coupledNeighborGradientOlder(const std::string & var_name,
mooseError("Older values not available for explicit schemes");
}

const ADVariableGradient &
NeighborCoupleable::adCoupledNeighborGradient(const std::string & var_name, unsigned int comp) const
{
if (_neighbor_nodal)
mooseError("Nodal variables do not have gradients");
if (!_c_is_implicit)
mooseError(
"adCoupledNeighborGradient returns a data structure with derivatives. Explicit schemes "
"use old solution data which do not have derivatives so adCoupledNeighborGradient is "
"not appropriate. Please use coupledNeighborGradient instead");

const auto * var = getVarHelper<MooseVariableField<Real>>(var_name, comp);
return var->adGradSlnNeighbor();
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradient(const std::string & var_name,
unsigned int comp) const
Expand Down
33 changes: 33 additions & 0 deletions test/include/interfacekernels/ADCoupledInterfacialSourceGradient.h
@@ -0,0 +1,33 @@
//* 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 "ADInterfaceKernel.h"

/**
* Diffusion with a source depending on the gradient jump of the coupled variable,
* using the automatic differentiation system to calculate the Jacobian.
*/
class ADCoupledInterfacialSourceGradient : public ADInterfaceKernel
{
public:
static InputParameters validParams();

ADCoupledInterfacialSourceGradient(const InputParameters & parameters);

protected:
virtual ADReal computeQpResidual(Moose::DGResidualType type) override;

const MaterialProperty<Real> & _D;
const MaterialProperty<Real> & _D_neighbor;

const ADVariableGradient & _grad_var;
const ADVariableGradient & _grad_var_neighbor;
};
56 changes: 56 additions & 0 deletions test/src/interfacekernels/ADCoupledInterfacialSourceGradient.C
@@ -0,0 +1,56 @@
//* 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 "ADCoupledInterfacialSourceGradient.h"

registerMooseObject("MooseTestApp", ADCoupledInterfacialSourceGradient);

InputParameters
ADCoupledInterfacialSourceGradient::validParams()
{
InputParameters params = ADInterfaceKernel::validParams();
params.addParam<MaterialPropertyName>("D", "D", "The diffusion coefficient.");
params.addParam<MaterialPropertyName>(
"D_neighbor", "D_neighbor", "The neighboring diffusion coefficient.");
params.addRequiredCoupledVar(
"var_source", "A variable whose gradient jump serves as the source term at the interface");
return params;
}

ADCoupledInterfacialSourceGradient::ADCoupledInterfacialSourceGradient(
const InputParameters & parameters)
: ADInterfaceKernel(parameters),
_D(getMaterialProperty<Real>("D")),
_D_neighbor(getNeighborMaterialProperty<Real>("D_neighbor")),
_grad_var(adCoupledGradient("var_source")),
_grad_var_neighbor(adCoupledNeighborGradient("var_source"))
{
}

ADReal
ADCoupledInterfacialSourceGradient::computeQpResidual(Moose::DGResidualType type)
{
ADReal gradient_jump = (_grad_var[_qp] - _grad_var_neighbor[_qp]) * _normals[_qp];

ADReal r = 0;

switch (type)
{
case Moose::Element:
r = -_test[_i][_qp] *
(_D_neighbor[_qp] * _grad_neighbor_value[_qp] * _normals[_qp] + gradient_jump);
break;

case Moose::Neighbor:
r = _test_neighbor[_i][_qp] * (_D[_qp] * _grad_u[_qp] * _normals[_qp] - gradient_jump);
break;
}

return r;
}
108 changes: 108 additions & 0 deletions test/tests/interfacekernels/ad_coupled_gradient/coupled.i
@@ -0,0 +1,108 @@
[Mesh]
[gen]
type = GeneratedMeshGenerator
dim = 1
nx = 20
xmax = 2
[]
[subdomain1]
input = gen
type = SubdomainBoundingBoxGenerator
bottom_left = '1.0 0 0'
block_id = 1
top_right = '2.0 1.0 0'
[]
[interface]
input = subdomain1
type = SideSetsBetweenSubdomainsGenerator
primary_block = '0'
paired_block = '1'
new_boundary = 'primary0_interface'
[]
[]

[Variables]
[u]
block = '0'
[]
[v]
block = '1'
[]
[w]
[]
[]

[Kernels]
[diff_u]
type = Diffusion
variable = u
block = 0
[]
[diff_v]
type = Diffusion
variable = v
block = 1
[]
[diff_w]
type = Diffusion
variable = w
[]
[react_w]
type = Reaction
variable = w
[]
[]

[InterfaceKernels]
[interface]
type = ADCoupledInterfacialSourceGradient
variable = u
neighbor_var = v
var_source = w
boundary = primary0_interface
D = 1
D_neighbor = 1
[]
[]

[BCs]
[left]
type = DirichletBC
variable = u
boundary = 'left'
value = 0
[]
[right]
type = DirichletBC
variable = v
boundary = 'right'
value = 10
[]
[middle]
type = MatchedValueBC
variable = v
boundary = 'primary0_interface'
v = u
[]
[w_left]
type = DirichletBC
variable = w
boundary = 'left'
value = 0
[]
[w_right]
type = DirichletBC
variable = w
boundary = 'right'
value = 4
[]
[]

[Executioner]
type = Steady
solve_type = NEWTON
[]

[Outputs]
exodus = true
[]
Binary file not shown.
19 changes: 19 additions & 0 deletions test/tests/interfacekernels/ad_coupled_gradient/tests
@@ -0,0 +1,19 @@
[Tests]
design = 'automatic_differentiation/index.md'
issues = '#15307'
[exo]
type = 'Exodiff'
input = 'coupled.i'
exodiff = 'coupled_out.e'
requirement = 'The system shall be able to solve a simple interfacial source problem using '
'automatic differentiation in which the source term depends on the gradient jump '
'of a coupled variable.'
[]
[jac]
type = 'PetscJacobianTester'
input = 'coupled.i'
difference_tol = 1e-6
requirement = 'The system shall be able to couple variable gradients at interfaces and have an '
'accurate Jacobian provided through automatic differentiation.'
[]
[]

0 comments on commit 5f2c210

Please sign in to comment.