https://mooseframework.inl.gov
PolycrystalDiffusivityTensorBase.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "libmesh/quadrature.h"
12 
14 
17 {
19  params.addClassDescription("Generates a diffusion tensor to distinguish between the bulk, grain "
20  "boundaries, and surfaces");
22  "v", "var_name_base", "op_num", "Array of coupled variables");
23  params.addCoupledVar("T", "Temperature variable in Kelvin");
24  params.addRequiredParam<Real>("D0", "Diffusion prefactor for vacancies in m^2/s");
25  params.addRequiredParam<Real>("Em", "Vacancy migration energy in eV");
26  params.addRequiredCoupledVar("c", "Vacancy phase variable");
27  params.addParam<std::string>(
28  "diffusivity_name", "D", "Name for the diffusivity material property");
29  params.addParam<Real>("surfindex", 1.0, "Surface diffusion index weight");
30  params.addParam<Real>("gbindex", 1.0, "Grain boundary diffusion index weight");
31  params.addParam<Real>("bulkindex", 1.0, "Bulk diffusion index weight");
32  return params;
33 }
34 
36  const InputParameters & parameters)
38  _T(coupledValue("T")),
39  _c(coupledValue("c")),
40  _grad_c(coupledGradient("c")),
41  _c_name(coupledName("c", 0)),
42  _diffusivity_name(getParam<std::string>("diffusivity_name")),
43  _D(declareProperty<RealTensorValue>(_diffusivity_name)),
44  _dDdc(isCoupledConstant("_c_name")
45  ? nullptr
46  : &declarePropertyDerivative<RealTensorValue>(_diffusivity_name, _c_name)),
47  _dDdgradc(isCoupledConstant("_c_name")
48  ? nullptr
49  : &declarePropertyDerivative<RankThreeTensor>(_diffusivity_name, "gradc")),
50  _D0(getParam<Real>("D0")),
51  _Em(getParam<Real>("Em")),
52  _s_index(getParam<Real>("surfindex")),
53  _gb_index(getParam<Real>("gbindex")),
54  _b_index(getParam<Real>("bulkindex")),
55  _kb(8.617343e-5), // Boltzmann constant in eV/K
56  _op_num(coupledComponents("v")),
57  _vals_name(_op_num),
58  _dDdeta(_op_num)
59 {
60  if (_op_num == 0)
61  mooseError("Model requires op_num > 0");
62 
63  _vals.resize(_op_num);
64  _grad_vals.resize(_op_num);
65  for (unsigned int i = 0; i < _op_num; ++i)
66  {
67  _vals[i] = &coupledValue("v", i);
68  _grad_vals[i] = &coupledGradient("v", i);
69  _vals_name[i] = coupledName("v", i);
71  _dDdeta[i] = &declarePropertyDerivative<RealTensorValue>(_diffusivity_name, _vals_name[i]);
72  }
73 }
74 
75 void
77 {
78  RealTensorValue I(1, 0, 0, 0, 1, 0, 0, 0, 1);
79 
80  for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
81  {
82  Real c = _c[_qp];
83  Real mc = 1.0 - c;
84 
85  // Compute grain boundary diffusivity and derivatives wrt order parameters
86  RealTensorValue Dgb(0.0);
87  std::vector<RealTensorValue> dDgbdeta(_op_num);
88 
89  for (unsigned int i = 0; i < _op_num; ++i)
90  for (unsigned int j = i + 1; j < _op_num; ++j)
91  {
92  RealGradient ngb = (*_grad_vals[i])[_qp] - (*_grad_vals[j])[_qp];
93  if (ngb.norm() > 1.0e-10)
94  ngb /= ngb.norm();
95  else
96  ngb = 0.0;
97 
98  RealTensorValue Tgb;
99  for (unsigned int a = 0; a < 3; ++a)
100  for (unsigned int b = a; b < 3; ++b)
101  {
102  Tgb(a, b) = I(a, b) - ngb(a) * ngb(b);
103  Tgb(b, a) = I(b, a) - ngb(b) * ngb(a);
104  }
105 
106  Dgb += (*_vals[i])[_qp] * (*_vals[j])[_qp] * Tgb;
107  Dgb += (*_vals[j])[_qp] * (*_vals[i])[_qp] * Tgb;
108  dDgbdeta[i] += 2.0 * (*_vals[j])[_qp] * Tgb;
109  dDgbdeta[j] += 2.0 * (*_vals[i])[_qp] * Tgb;
110  }
111 
112  // Compute surface diffusivity matrix
113  RealGradient ns(0);
114  if (_grad_c[_qp].norm() > 1.0e-10)
115  ns = _grad_c[_qp] / _grad_c[_qp].norm();
116 
117  RealTensorValue Ts;
118  for (unsigned int a = 0; a < 3; ++a)
119  for (unsigned int b = 0; b < 3; ++b)
120  {
121  Ts(a, b) = I(a, b) - ns(a) * ns(b);
122  }
123 
124  RankThreeTensor dTs;
125  if (_grad_c[_qp].norm() > 1.0e-10)
126  {
127  Real dcx = _grad_c[_qp](0);
128  Real dcy = _grad_c[_qp](1);
129  Real dcz = _grad_c[_qp](2);
130  Real norm4 = pow(_grad_c[_qp].norm(), 4.0);
131  // Derivatives wrt dc/dx
132  dTs(0, 0, 0) = -2.0 * dcx * (dcy * dcy + dcz * dcz) / norm4;
133  dTs(1, 0, 0) = dTs(0, 1, 0) = (dcx * dcx * dcy - dcy * dcy * dcy - dcy * dcz * dcz) / norm4;
134  dTs(1, 1, 0) = 2.0 * dcx * dcy * dcy / norm4;
135  dTs(2, 0, 0) = dTs(0, 2, 0) = (dcx * dcx * dcz - dcy * dcy * dcz - dcz * dcz * dcz) / norm4;
136  dTs(2, 1, 0) = dTs(1, 2, 0) = 2.0 * dcx * dcy * dcz / norm4;
137  dTs(2, 2, 0) = 2.0 * dcx * dcz * dcz / norm4;
138 
139  // Derivatives wrt dc/dy
140  dTs(0, 0, 1) = 2.0 * dcx * dcx * dcy / norm4;
141  dTs(1, 0, 1) = dTs(0, 1, 1) = (-dcx * dcx * dcx + dcx * dcy * dcy - dcx * dcz * dcz) / norm4;
142  dTs(1, 1, 1) = -2.0 * dcy * (dcx * dcx + dcz * dcz) / norm4;
143  dTs(2, 0, 1) = dTs(0, 2, 1) = 2.0 * dcx * dcy * dcz / norm4;
144  dTs(2, 1, 1) = dTs(1, 2, 1) = (dcy * dcy * dcz - dcx * dcx * dcz - dcz * dcz * dcz) / norm4;
145  dTs(2, 2, 1) = 2.0 * dcy * dcz * dcz / norm4;
146 
147  // Derivatives wrt dc/dz
148  dTs(0, 0, 2) = 2.0 * dcx * dcx * dcz / norm4;
149  dTs(1, 0, 2) = dTs(0, 1, 2) = 2.0 * dcx * dcy * dcz / norm4;
150  dTs(1, 1, 2) = 2.0 * dcy * dcy * dcz / norm4;
151  dTs(2, 0, 2) = dTs(0, 2, 2) = (dcx * dcz * dcz - dcx * dcx * dcx - dcy * dcy * dcx) / norm4;
152  dTs(2, 1, 2) = dTs(1, 2, 2) = (dcy * dcz * dcz - dcx * dcx * dcy - dcy * dcy * dcy) / norm4;
153  dTs(2, 2, 2) = -2.0 * dcz * (dcx * dcx + dcy * dcy) / norm4;
154  }
155 
156  RealTensorValue Dsurf = c * c * mc * mc * Ts;
157  RealTensorValue dDsurfdc = (2.0 * c * mc * mc - 2.0 * c * c * mc) * Ts;
158  RankThreeTensor dDsurfdgradc = c * c * mc * mc * dTs;
159 
160  // Compute bulk properties
161  _Dbulk = _D0 * std::exp(-_Em / _kb / _T[_qp]);
162  const Real mult_bulk = 1.0;
163  const Real dmult_bulk = 0.0;
164 
165  // Compute diffusion tensor
166  _D[_qp] = _Dbulk * (_b_index * mult_bulk * I + _gb_index * Dgb + _s_index * Dsurf);
167  if (_dDdc)
168  (*_dDdc)[_qp] = _Dbulk * (_b_index * dmult_bulk * I + _s_index * dDsurfdc);
169  if (_dDdgradc)
170  (*_dDdgradc)[_qp] = _Dbulk * _s_index * dDsurfdgradc;
171  for (unsigned int i = 0; i < _op_num; ++i)
172  if (_dDdeta[i])
173  (*_dDdeta[i])[_qp] = _Dbulk * _gb_index * dDgbdeta[i];
174  }
175 }
Generates a diffusion tensor to distinguish between the bulk, grain boundary, and surface diffusion r...
virtual bool isCoupledConstant(const std::string &var_name) const
auto norm() const -> decltype(std::norm(Real()))
std::vector< const VariableGradient * > _grad_vals
VariableName coupledName(const std::string &var_name, unsigned int comp=0) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< const VariableValue * > _vals
MaterialProperty< RealTensorValue > & _D
std::vector< NonlinearVariableName > _vals_name
solid phase order parameters
virtual const VariableGradient & coupledGradient(const std::string &var_name, unsigned int comp=0) const
MaterialProperty< RankThreeTensor > * _dDdgradc
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual const VariableValue & coupledValue(const std::string &var_name, unsigned int comp=0) const
TensorValue< Real > RealTensorValue
static InputParameters validParams()
std::vector< MaterialProperty< RealTensorValue > * > _dDdeta
auto norm(const T &a) -> decltype(std::abs(a))
void addCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
PolycrystalDiffusivityTensorBase(const InputParameters &parameters)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void addRequiredCoupledVarWithAutoBuild(const std::string &name, const std::string &base_name, const std::string &num_name, const std::string &doc_string)
registerMooseObject("PhaseFieldApp", PolycrystalDiffusivityTensorBase)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
MaterialProperty< RealTensorValue > * _dDdc