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  _dDdgradeta(_op_num)
60 {
61  if (_op_num == 0)
62  mooseError("Model requires op_num > 0");
63 
64  _vals.resize(_op_num);
65  _grad_vals.resize(_op_num);
66  for (unsigned int i = 0; i < _op_num; ++i)
67  {
68  _vals[i] = &coupledValue("v", i);
69  _grad_vals[i] = &coupledGradient("v", i);
70  _vals_name[i] = coupledName("v", i);
72  _dDdeta[i] = &declarePropertyDerivative<RealTensorValue>(_diffusivity_name, _vals_name[i]);
74  _dDdgradeta[i] =
75  &declarePropertyDerivative<RankThreeTensor>(_diffusivity_name, ("grad" + _vals_name[i]));
76  }
77 }
78 
79 void
81 {
82  RealTensorValue I(1, 0, 0, 0, 1, 0, 0, 0, 1);
83 
84  for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
85  {
86  Real c = _c[_qp];
87  Real mc = 1.0 - c;
88 
89  // Compute grain boundary diffusivity and derivatives wrt order parameters
90  RealTensorValue Dgb(0.0);
91  std::vector<RealTensorValue> dDgbdeta(_op_num);
92  std::vector<RankThreeTensor> dDgbdgradeta(_op_num);
93 
94  for (unsigned int i = 0; i < _op_num; ++i)
95  for (unsigned int j = i + 1; j < _op_num; ++j)
96  {
97  RealGradient ngb = (*_grad_vals[i])[_qp] - (*_grad_vals[j])[_qp];
98  if (ngb.norm() > 1.0e-10)
99  ngb /= ngb.norm();
100  else
101  ngb = 0.0;
102 
103  RealTensorValue Tgb;
104  for (unsigned int a = 0; a < 3; ++a)
105  for (unsigned int b = a; b < 3; ++b)
106  {
107  Tgb(a, b) = I(a, b) - ngb(a) * ngb(b);
108  Tgb(b, a) = I(b, a) - ngb(b) * ngb(a);
109  }
110 
111  RankThreeTensor dTgbi, dTgbj;
112  if (((*_grad_vals[i])[_qp] - (*_grad_vals[j])[_qp]).norm() > 1.0e-10)
113  {
114  Real detax = (*_grad_vals[i])[_qp](0) - (*_grad_vals[j])[_qp](0);
115  Real detay = (*_grad_vals[i])[_qp](1) - (*_grad_vals[j])[_qp](1);
116  Real detaz = (*_grad_vals[i])[_qp](2) - (*_grad_vals[j])[_qp](2);
117  Real norm4 = pow(((*_grad_vals[i])[_qp] - (*_grad_vals[j])[_qp]).norm(), 4.0);
118  // Derivatives wrt detai/dx
119  dTgbi(0, 0, 0) = -2.0 * detax * (detay * detay + detaz * detaz) / norm4;
120  dTgbi(1, 0, 0) = dTgbi(0, 1, 0) =
121  (detax * detax * detay - detay * detay * detay - detay * detaz * detaz) / norm4;
122  dTgbi(1, 1, 0) = 2.0 * detax * detay * detay / norm4;
123  dTgbi(2, 0, 0) = dTgbi(0, 2, 0) =
124  (detax * detax * detaz - detay * detay * detaz - detaz * detaz * detaz) / norm4;
125  dTgbi(2, 1, 0) = dTgbi(1, 2, 0) = 2.0 * detax * detay * detaz / norm4;
126  dTgbi(2, 2, 0) = 2.0 * detax * detaz * detaz / norm4;
127  // Derivatives wrt detai/dy
128  dTgbi(0, 0, 1) = 2.0 * detax * detax * detay / norm4;
129  dTgbi(1, 0, 1) = dTgbi(0, 1, 1) =
130  (-detax * detax * detax + detax * detay * detay - detax * detaz * detaz) / norm4;
131  dTgbi(1, 1, 1) = -2.0 * detay * (detax * detax + detaz * detaz) / norm4;
132  dTgbi(2, 0, 1) = dTgbi(0, 2, 1) = 2.0 * detax * detay * detaz / norm4;
133  dTgbi(2, 1, 1) = dTgbi(1, 2, 1) =
134  (detay * detay * detaz - detax * detax * detaz - detaz * detaz * detaz) / norm4;
135  dTgbi(2, 2, 1) = 2.0 * detay * detaz * detaz / norm4;
136 
137  // Derivatives wrt detai/dz
138  dTgbi(0, 0, 2) = 2.0 * detax * detax * detaz / norm4;
139  dTgbi(1, 0, 2) = dTgbi(0, 1, 2) = 2.0 * detax * detay * detaz / norm4;
140  dTgbi(1, 1, 2) = 2.0 * detay * detay * detaz / norm4;
141  dTgbi(2, 0, 2) = dTgbi(0, 2, 2) =
142  (detax * detaz * detaz - detax * detax * detax - detay * detay * detax) / norm4;
143  dTgbi(2, 1, 2) = dTgbi(1, 2, 2) =
144  (detay * detaz * detaz - detax * detax * detay - detay * detay * detay) / norm4;
145  dTgbi(2, 2, 2) = -2.0 * detaz * (detax * detax + detay * detay) / norm4;
146 
147  dTgbj = -dTgbi;
148  }
149 
150  Dgb += (*_vals[i])[_qp] * (*_vals[j])[_qp] * Tgb;
151  Dgb += (*_vals[j])[_qp] * (*_vals[i])[_qp] * Tgb;
152  dDgbdeta[i] += 2.0 * (*_vals[j])[_qp] * Tgb;
153  dDgbdeta[j] += 2.0 * (*_vals[i])[_qp] * Tgb;
154  dDgbdgradeta[i] += 2.0 * (*_vals[i])[_qp] * (*_vals[j])[_qp] * dTgbi;
155  dDgbdgradeta[j] += 2.0 * (*_vals[i])[_qp] * (*_vals[j])[_qp] * dTgbj;
156  }
157 
158  // Compute surface diffusivity matrix
159  RealGradient ns(0);
160  if (_grad_c[_qp].norm() > 1.0e-10)
161  ns = _grad_c[_qp] / _grad_c[_qp].norm();
162 
163  RealTensorValue Ts;
164  for (unsigned int a = 0; a < 3; ++a)
165  for (unsigned int b = 0; b < 3; ++b)
166  {
167  Ts(a, b) = I(a, b) - ns(a) * ns(b);
168  }
169 
170  RankThreeTensor dTs;
171  if (_grad_c[_qp].norm() > 1.0e-10)
172  {
173  Real dcx = _grad_c[_qp](0);
174  Real dcy = _grad_c[_qp](1);
175  Real dcz = _grad_c[_qp](2);
176  Real norm4 = pow(_grad_c[_qp].norm(), 4.0);
177  // Derivatives wrt dc/dx
178  dTs(0, 0, 0) = -2.0 * dcx * (dcy * dcy + dcz * dcz) / norm4;
179  dTs(1, 0, 0) = dTs(0, 1, 0) = (dcx * dcx * dcy - dcy * dcy * dcy - dcy * dcz * dcz) / norm4;
180  dTs(1, 1, 0) = 2.0 * dcx * dcy * dcy / norm4;
181  dTs(2, 0, 0) = dTs(0, 2, 0) = (dcx * dcx * dcz - dcy * dcy * dcz - dcz * dcz * dcz) / norm4;
182  dTs(2, 1, 0) = dTs(1, 2, 0) = 2.0 * dcx * dcy * dcz / norm4;
183  dTs(2, 2, 0) = 2.0 * dcx * dcz * dcz / norm4;
184 
185  // Derivatives wrt dc/dy
186  dTs(0, 0, 1) = 2.0 * dcx * dcx * dcy / norm4;
187  dTs(1, 0, 1) = dTs(0, 1, 1) = (-dcx * dcx * dcx + dcx * dcy * dcy - dcx * dcz * dcz) / norm4;
188  dTs(1, 1, 1) = -2.0 * dcy * (dcx * dcx + dcz * dcz) / norm4;
189  dTs(2, 0, 1) = dTs(0, 2, 1) = 2.0 * dcx * dcy * dcz / norm4;
190  dTs(2, 1, 1) = dTs(1, 2, 1) = (dcy * dcy * dcz - dcx * dcx * dcz - dcz * dcz * dcz) / norm4;
191  dTs(2, 2, 1) = 2.0 * dcy * dcz * dcz / norm4;
192 
193  // Derivatives wrt dc/dz
194  dTs(0, 0, 2) = 2.0 * dcx * dcx * dcz / norm4;
195  dTs(1, 0, 2) = dTs(0, 1, 2) = 2.0 * dcx * dcy * dcz / norm4;
196  dTs(1, 1, 2) = 2.0 * dcy * dcy * dcz / norm4;
197  dTs(2, 0, 2) = dTs(0, 2, 2) = (dcx * dcz * dcz - dcx * dcx * dcx - dcy * dcy * dcx) / norm4;
198  dTs(2, 1, 2) = dTs(1, 2, 2) = (dcy * dcz * dcz - dcx * dcx * dcy - dcy * dcy * dcy) / norm4;
199  dTs(2, 2, 2) = -2.0 * dcz * (dcx * dcx + dcy * dcy) / norm4;
200  }
201 
202  RealTensorValue Dsurf = c * c * mc * mc * Ts;
203  RealTensorValue dDsurfdc = (2.0 * c * mc * mc - 2.0 * c * c * mc) * Ts;
204  RankThreeTensor dDsurfdgradc = c * c * mc * mc * dTs;
205 
206  // Compute bulk properties
207  _Dbulk = _D0 * std::exp(-_Em / _kb / _T[_qp]);
208  const Real mult_bulk = 1.0;
209  const Real dmult_bulk = 0.0;
210 
211  // Compute diffusion tensor
212  _D[_qp] = _Dbulk * (_b_index * mult_bulk * I + _gb_index * Dgb + _s_index * Dsurf);
213  if (_dDdc)
214  (*_dDdc)[_qp] = _Dbulk * (_b_index * dmult_bulk * I + _s_index * dDsurfdc);
215  if (_dDdgradc)
216  (*_dDdgradc)[_qp] = _Dbulk * _s_index * dDsurfdgradc;
217  for (unsigned int i = 0; i < _op_num; ++i)
218  {
219  if (_dDdeta[i])
220  (*_dDdeta[i])[_qp] = _Dbulk * _gb_index * dDgbdeta[i];
221  if (_dDdgradeta[i])
222  (*_dDdgradeta[i])[_qp] = _Dbulk * _gb_index * dDgbdgradeta[i];
223  }
224  }
225 }
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
std::vector< MaterialProperty< RankThreeTensor > * > _dDdgradeta
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)
void mooseError(Args &&... args) const
registerMooseObject("PhaseFieldApp", PolycrystalDiffusivityTensorBase)
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