https://mooseframework.inl.gov
SLKKSMultiACBulkC.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 
10 #include "SLKKSMultiACBulkC.h"
11 
12 registerMooseObject("PhaseFieldApp", SLKKSMultiACBulkC);
13 
16 {
17  auto params = SLKKSMultiPhaseBase::validParams();
18  params.addClassDescription("Multi-phase SLKKS model kernel for the bulk Allen-Cahn. "
19  "This includes all terms dependent on chemical potential.");
20  params.addRequiredParam<MaterialPropertyName>(
21  "F", "Phase free energy function that is a function of 'c'");
22  params.addRequiredCoupledVar("c", "Concentration variable F depends on");
23  params.addCoupledVar("eta_i",
24  "Order parameter that derivatives are taken with respect to (kernel "
25  "variable is used if this is not specified)");
26  params.addParam<MaterialPropertyName>("mob_name", "L", "The mobility used with the kernel");
27  return params;
28 }
29 
31  : SLKKSMultiPhaseBase(parameters),
32  _c_name(coupledName("c", 0)),
33  _lagrange(isCoupled("eta_i")),
34  _etai_name(_lagrange ? coupledName("eta_i", 0) : _var.name()),
35  _etai_var(_lagrange ? coupled("eta_i") : _var.number()),
36  _cs_names(_ncs),
37  _prop_dFdc(getMaterialPropertyDerivative<Real>("F", _c_name)),
38  _prop_d2Fdcdcs(_ncs),
39  _prop_dhdni(_nh),
40  _prop_d2hdnidn(_nh),
41  _l_cs(-1),
42  _l_etai(-1),
43  _mob(getMaterialProperty<Real>("mob_name"))
44 {
45  // Determine position of the selected concentration variable
46  for (std::size_t i = 0; i < _ncs; ++i)
47  {
48  _cs_names[i] = coupledName("cs", i);
49  if (coupled("cs", i) == _c_var)
50  _l_cs = i;
51  }
52 
53  // Check to make sure the nonlinear variable is in the cs list
54  if (_l_cs < 0)
55  paramError("cs", "One of the listed variables must be the 'c' variable");
56 
57  // Determine position of the selected concentration variable
58  for (std::size_t i = 0; i < _neta; ++i)
59  if (coupled("eta", i) == _etai_var)
60  _l_etai = i;
61 
62  // Check to make sure the nonlinear variable or eta_i (if supplied) is in the eta list
63  if (_l_etai < 0)
64  paramError("eta_i",
65  "Either eta_i or the kernel variable must be one of the listed 'eta' variables");
66 
67  // Iterate over all sublattice concentrations
68  for (std::size_t i = 0; i < _ncs; ++i)
69  // get second partial derivatives w.r.t. c and cs (only if c and cs are in the same phase)
70  _prop_d2Fdcdcs[i] = (_phase[i] == _phase[_l_cs])
71  ? &getMaterialPropertyDerivative<Real>("F", _c_name, _cs_names[i])
72  : nullptr;
73 
74  // fetch all switching function derivatives
75  for (std::size_t i = 0; i < _nh; ++i)
76  {
77  _prop_dhdni[i] = &getMaterialPropertyDerivativeByName<Real>(_h_names[i], _etai_name);
78 
79  _prop_d2hdnidn[i].resize(_neta);
80  for (std::size_t j = 0; j < _neta; ++j)
81  _prop_d2hdnidn[i][j] =
82  &getMaterialPropertyDerivativeByName<Real>(_h_names[i], _etai_name, _eta_names[j]);
83  }
84 }
85 
86 Real
88 { // sum over phases
89  std::size_t k = 0;
90  Real sum = 0.0;
91  for (std::size_t i = 0; i < _nh; ++i)
92  {
93  // sum sublattice concentrations
94  Real csum = 0.0;
95  for (unsigned int j = 0; j < _ns[i]; ++j)
96  {
97  csum += (*_cs[k])[_qp] * _a_cs[k];
98  k++;
99  }
100  sum += (*_prop_dhdni[i])[_qp] * csum;
101  }
102 
103  return -_mob[_qp] * _prop_dFdc[_qp] / _a_cs[_l_cs] * sum;
104 }
105 
106 Real
108 {
109  // For when this kernel is used in the Lagrange multiplier equation
110  if (_lagrange)
111  return 0.0;
112 
113  // For when eta_i is the nonlinear variable
114  std::size_t k = 0;
115  Real sum = 0.0;
116  for (std::size_t i = 0; i < _nh; ++i)
117  {
118  // sum sublattice concentrations
119  Real csum = 0.0;
120  for (unsigned int j = 0; j < _ns[i]; ++j)
121  {
122  csum += (*_cs[k])[_qp] * _a_cs[k];
123  k++;
124  }
125  sum += (*_prop_d2hdnidn[i][_l_etai])[_qp] * csum;
126  }
127 
128  return -_mob[_qp] * _phi[_j][_qp] * _prop_dFdc[_qp] / _a_cs[_l_cs] * sum;
129 }
130 
131 Real
133 {
134  // concentration variables
135  auto csvar = mapJvarToCvar(jvar, _cs_map);
136  if (csvar >= 0)
137  {
138  // does F depend on the csvar? if so we need to apply the product rule
139  if (_phase[csvar] == _phase[_l_cs])
140  {
141  // sum over phases
142  std::size_t k = 0;
143  Real sum = 0.0;
144  for (std::size_t i = 0; i < _nh; ++i)
145  {
146  // sum sublattice concentrations
147  Real csum = 0.0;
148  for (unsigned int j = 0; j < _ns[i]; ++j)
149  {
150  csum += (*_cs[k])[_qp] * _a_cs[k];
151  k++;
152  }
153  sum += (*_prop_dhdni[i])[_qp] * csum;
154  }
155 
156  return -_mob[_qp] *
157  ((*_prop_d2Fdcdcs[csvar])[_qp] * sum +
158  _prop_dFdc[_qp] * (*_prop_dhdni[_phase[csvar]])[_qp] * _a_cs[csvar]) /
159  _a_cs[_l_cs] * _phi[_j][_qp] * _test[_i][_qp];
160  }
161 
162  return -_mob[_qp] * _prop_dFdc[_qp] / _a_cs[_l_cs] * (*_prop_dhdni[_phase[csvar]])[_qp] *
163  _a_cs[csvar] * _phi[_j][_qp] * _test[_i][_qp];
164  }
165 
166  // order parameters
167  auto etavar = mapJvarToCvar(jvar, _eta_map);
168  if (etavar >= 0)
169  {
170  // sum over phases
171  std::size_t k = 0;
172  Real sum = 0.0;
173  for (std::size_t i = 0; i < _nh; ++i)
174  {
175  // sum sublattice concentrations
176  Real csum = 0.0;
177  for (unsigned int j = 0; j < _ns[i]; ++j)
178  {
179  csum += (*_cs[k])[_qp] * _a_cs[k];
180  k++;
181  }
182  sum += (*_prop_d2hdnidn[i][etavar])[_qp] * csum;
183  }
184 
185  return -_mob[_qp] * _prop_dFdc[_qp] / _a_cs[_l_cs] * sum * _phi[_j][_qp] * _test[_i][_qp];
186  }
187 
188  return 0.0;
189 }
const std::size_t _neta
Order parameters for each phase .
const MaterialProperty< Real > & _mob
Mobility.
int _l_cs
Position of the c variable in the cs list.
const JvarMap & _cs_map
int _l_etai
Position of the eta_i variable in the eta list.
virtual Real computeQpOffDiagJacobian(unsigned int jvar)
const VariableName _c_name
name of the coupled concentration variable c
const std::size_t _ncs
Sublattice concentrations.
const unsigned int _c_var
virtual Real precomputeQpJacobian()
std::vector< const MaterialProperty< Real > * > _prop_dhdni
first derivatives of all h w.r.t. to etai
static InputParameters validParams()
virtual Real precomputeQpResidual()
std::vector< VariableName > _eta_names
std::vector< const VariableValue * > _cs
VariableName _etai_name
name of order parameter that derivatives are taken w.r.t.
unsigned int _etai_var
index of order parameter that derivatives are taken w.r.t.
SLKKSMultiPhaseBase child class for the phase concentration term in the the Allen-Cahn bulk residual...
std::vector< Real > _a_cs
Sublattice site numbers.
const std::string name
Definition: Setup.h:20
const JvarMap & _eta_map
std::vector< VariableName > _cs_names
names of all sublattice concentrations
registerMooseObject("PhaseFieldApp", SLKKSMultiACBulkC)
std::vector< std::vector< const MaterialProperty< Real > * > > _prop_d2hdnidn
first derivatives of all h w.r.t. to the kernel variable and other etas
std::vector< const MaterialProperty< Real > * > _prop_d2Fdcdcs
Second derivatives of F w.r.t. c and all cs.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::size_t _nh
std::vector< unsigned int > _phase
phase index of each cs entry
Enforce sum of phase sublattice concentrations to be the real concentration.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< MaterialPropertyName > _h_names
Switching function names.
static InputParameters validParams()
std::vector< unsigned int > _ns
Number of sublattices per phase.
const bool _lagrange
is eta_i supplied (then we assume the kernel operates on the Lagrange var)
static const std::string k
Definition: NS.h:130
const MaterialProperty< Real > & _prop_dFdc
Derivative of the free energy function w.r.t. c.
SLKKSMultiACBulkC(const InputParameters &parameters)