https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KKSPhaseConcentrationMaterial.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 "MatrixTools.h"
12
14
17{
19 params.addClassDescription("Computes the KKS phase concentrations by using nested Newton "
20 "iteration to solve the equal chemical "
21 "potential and concentration conservation equations. This class is "
22 "intended to be used with KKSPhaseConcentrationDerivatives.");
23 params.addRequiredCoupledVar("global_cs", "The interpolated concentrations c, b, etc.");
24 params.addRequiredParam<MaterialPropertyName>("h_name", "Switching function h(eta).");
25 params.addRequiredParam<std::vector<MaterialPropertyName>>(
26 "ci_names",
27 "Phase concentrations. The order must match Fa, Fb, and global_cs, for example, c1, c2, b1, "
28 "b2, etc.");
29 params.addRequiredParam<std::vector<Real>>("ci_IC",
30 "Initial values of ci in the same order as ci_names.");
31 params.addRequiredParam<MaterialName>("fa_name", "Fa material object.");
32 params.addRequiredParam<MaterialName>("fb_name", "Fb material object.");
33 params.addParam<MaterialPropertyName>(
34 "nested_iterations",
35 "The output number of nested Newton iterations at each quadrature point.");
36 params.addCoupledVar("args", "The coupled variables of Fa and Fb.");
37 params.addParam<bool>(
38 "damped_Newton", false, "Whether or not to use the damped Newton's method.");
39 params.addParam<MaterialName>("conditions",
40 "C",
41 "Material property that checks bounds and conditions on the "
42 "material properties being solved for.");
43 params += NestedSolve::validParams();
44 return params;
45}
46
49 _prop_c(coupledValues("global_cs")),
50 _num_c(coupledComponents("global_cs")),
51 _prop_h(getMaterialProperty<Real>("h_name")),
52 _ci_names(getParam<std::vector<MaterialPropertyName>>("ci_names")),
53 _prop_ci(_num_c * 2),
54 _ci_old(_num_c * 2),
55 _ci_IC(getParam<std::vector<Real>>("ci_IC")),
56 _Fa_name(getParam<MaterialName>("fa_name")),
57 _Fb_name(getParam<MaterialName>("fb_name")),
58 _prop_Fi(2),
59 _Fi_copy(2),
60 _dFidci(_num_c * 2),
61 _dFidci_copy(_num_c * 2),
62 _d2Fidcidbi(2),
63 _d2Fadc1db1_copy(_num_c),
64 _args_names(coupledNames("args")),
65 _n_args(coupledComponents("args")),
66 _dFadarg(_n_args),
67 _dFadarg_copy(_n_args),
68 _dFbdarg(_n_args),
69 _dFbdarg_copy(_n_args),
70 _d2Fadcadarg(_n_args),
71 _d2Fadcadarg_copy(_n_args),
72 _iter(declareProperty<Real>("nested_iterations")),
73 _abs_tol(getParam<Real>("absolute_tolerance")),
74 _rel_tol(getParam<Real>("relative_tolerance")),
75 _damped_newton(getParam<bool>("damped_Newton")),
76 _condition_name(getParam<MaterialName>("conditions")),
77 _nested_solve(NestedSolve(parameters))
78
79{
80 // phase concentrations
81 for (const auto m : make_range(_num_c * 2))
82 {
83 _prop_ci[m] = &declareProperty<Real>(_ci_names[m]);
84 _ci_old[m] = &getMaterialPropertyOld<Real>(_ci_names[m]);
85 }
86
87 // free energies
88 _prop_Fi[0] = &getMaterialPropertyByName<Real>(_Fa_name);
89 _prop_Fi[1] = &getMaterialPropertyByName<Real>(_Fb_name);
90
91 // declare _fi_copy to be passed to the kernels
92 _Fi_copy[0] = &declareProperty<Real>("cp" + _Fa_name);
93 _Fi_copy[1] = &declareProperty<Real>("cp" + _Fb_name);
94
95 // derivative of free energy wrt phase concentrations
96 for (const auto m : make_range(_num_c))
97 {
98 _dFidci[m * 2] = &getMaterialPropertyDerivative<Real>(_Fa_name, _ci_names[m * 2]);
99 _dFidci[m * 2 + 1] = &getMaterialPropertyDerivative<Real>(_Fb_name, _ci_names[m * 2 + 1]);
100
101 // declare _dFidci_copy to be passed to the kernels
102 _dFidci_copy[m * 2] = &declarePropertyDerivative<Real>("cp" + _Fa_name, _ci_names[m * 2]);
103 _dFidci_copy[m * 2 + 1] =
104 &declarePropertyDerivative<Real>("cp" + _Fb_name, _ci_names[m * 2 + 1]);
105 }
106
107 // Second derivative of free energy wrt phase concentrations for use in this material. In
108 // _d2Fidcidbi[m][n][l], m is phase index of Fi, n is the species index of ci, l is the species
109 // index of bi.
110 for (const auto m : make_range(2))
111 {
112 _d2Fidcidbi[m].resize(_num_c);
113 for (const auto n : make_range(_num_c))
114 {
115 _d2Fidcidbi[m][n].resize(_num_c);
116 for (const auto l : make_range(_num_c))
117 {
118 if (m == 0)
119 _d2Fidcidbi[0][n][l] =
120 &getMaterialPropertyDerivative<Real>(_Fa_name, _ci_names[n * 2], _ci_names[l * 2]);
121
122 else
123 _d2Fidcidbi[1][n][l] = &getMaterialPropertyDerivative<Real>(
124 _Fb_name, _ci_names[n * 2 + 1], _ci_names[l * 2 + 1]);
125 }
126 }
127 }
128
129 // _d2Fadc1db1_copy (2D symmetric matrix), to be passed to kernels
130 for (const auto m : make_range(_num_c))
131 {
132 _d2Fadc1db1_copy[m].resize(_num_c);
133 for (const auto n : make_range(_num_c))
134 _d2Fadc1db1_copy[m][n] =
135 &declarePropertyDerivative<Real>("cp" + _Fa_name, _ci_names[m * 2], _ci_names[n * 2]);
136 }
137
138 // partial derivative of Fa and Fb wrt coupled variables, to be passed to kernels
139 for (const auto m : make_range(_n_args))
140 {
141 _dFadarg[m] = &getMaterialPropertyDerivative<Real>(_Fa_name, _args_names[m]);
142 _dFadarg_copy[m] = &declarePropertyDerivative<Real>("cp" + _Fa_name, _args_names[m]);
143 _dFbdarg[m] = &getMaterialPropertyDerivative<Real>(_Fb_name, _args_names[m]);
144 _dFbdarg_copy[m] = &declarePropertyDerivative<Real>("cp" + _Fb_name, _args_names[m]);
145 }
146
147 // second partial derivatives of Fa wrt ca and another coupled variable, to be passed to
148 // kernels
149 for (const auto m : make_range(_n_args))
150 {
151 _d2Fadcadarg[m].resize(_num_c);
152 _d2Fadcadarg_copy[m].resize(_num_c);
153 for (const auto n : make_range(_num_c))
154 {
155 _d2Fadcadarg[m][n] =
156 &getMaterialPropertyDerivative<Real>(_Fa_name, _ci_names[n * 2], _args_names[m]);
157 _d2Fadcadarg_copy[m][n] =
158 &declarePropertyDerivative<Real>("cp" + _Fa_name, _ci_names[n * 2], _args_names[m]);
159 }
160 }
161
162 if (_damped_newton)
163 _C = &getMaterialPropertyByName<Real>(_condition_name);
164 else
165 _C = nullptr;
166}
167
168void
170{
171 for (const auto m : make_range(_num_c * 2))
172 (*_prop_ci[m])[_qp] = _ci_IC[m];
173}
174
175void
177{
178 _Fa = &getMaterial("fa_name");
179 _Fb = &getMaterial("fb_name");
180 if (_damped_newton)
181 _condition = &getMaterialByName(_condition_name);
182}
183
184void
186{
187 // parameters for nested Newton iteration
188 NestedSolve::Value<> solution(_num_c * 2);
189
190 for (unsigned int m = 0; m < _num_c * 2; ++m)
191 solution(m) = (*_ci_old[m])[_qp];
192
195
196 auto compute = [&](const NestedSolve::Value<> & guess,
197 NestedSolve::Value<> & residual,
198 NestedSolve::Jacobian<> & jacobian)
199 {
200 for (const auto m : make_range(_num_c * 2))
201 (*_prop_ci[m])[_qp] = guess(m);
202
205
206 // assign residual functions
207 for (const auto m : make_range(_num_c))
208 {
209 residual(m * 2) = (*_dFidci[m * 2])[_qp] - (*_dFidci[m * 2 + 1])[_qp];
210 residual(m * 2 + 1) = (1 - _prop_h[_qp]) * (*_prop_ci[m * 2])[_qp] +
211 _prop_h[_qp] * (*_prop_ci[m * 2 + 1])[_qp] - (*_prop_c[m])[_qp];
212 }
213
214 jacobian.setZero();
215
216 // fill in the non-zero elements in jacobian
217 for (const auto m : make_range(_num_c))
218 {
219 for (const auto n : make_range(_num_c))
220 {
221 // equal chemical potential derivative equations
222 jacobian(m * 2, n * 2) = (*_d2Fidcidbi[0][m][n])[_qp];
223 jacobian(m * 2, n * 2 + 1) = -(*_d2Fidcidbi[1][m][n])[_qp];
224 }
225 // concentration conservation derivative equations
226 jacobian(m * 2 + 1, m * 2) = 1 - _prop_h[_qp];
227 jacobian(m * 2 + 1, m * 2 + 1) = _prop_h[_qp];
228 }
229 };
230 auto computeCondition = [&](const NestedSolve::Value<> & guess) -> Real
231 {
232 for (const auto m : make_range(_num_c * 2))
233 (*_prop_ci[m])[_qp] = guess(m);
235 return ((*_C)[_qp]);
236 };
237 // choose between Newton or damped Newton's method
238 if (!_damped_newton)
239 _nested_solve.nonlinear(solution, compute);
240 else
241 _nested_solve.nonlinearDamped(solution, compute, computeCondition);
243
244 if (_nested_solve.getState() == NestedSolve::State::NOT_CONVERGED)
245 mooseException("Nested Newton iteration did not converge.");
246
247 // assign solution to ci
248 for (const auto m : make_range(_num_c * 2))
249 (*_prop_ci[m])[_qp] = solution[m];
250
251 // assign to the copied parameters to be used in kernels
252 for (const auto m : make_range(2))
253 (*_Fi_copy[m])[_qp] = (*_prop_Fi[m])[_qp];
254
255 for (const auto m : make_range(_num_c * 2))
256 (*_dFidci_copy[m])[_qp] = (*_dFidci[m])[_qp];
257
258 for (const auto m : make_range(_num_c))
259 {
260 for (const auto n : make_range(_num_c))
261 (*_d2Fadc1db1_copy[m][n])[_qp] = (*_d2Fidcidbi[0][m][n])[_qp];
262 }
263
264 for (const auto m : make_range(_n_args))
265 {
266 (*_dFadarg_copy[m])[_qp] = (*_dFadarg[m])[_qp];
267 (*_dFbdarg_copy[m])[_qp] = (*_dFbdarg[m])[_qp];
268 }
269
270 for (const auto m : make_range(_n_args))
271 {
272 for (const auto n : make_range(_num_c))
273 (*_d2Fadcadarg_copy[m][n])[_qp] = (*_d2Fadcadarg[m][n])[_qp];
274 }
275}
registerMooseObject("PhaseFieldApp", KKSPhaseConcentrationMaterial)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addCoupledVar(const std::string &name, const std::string &doc_string)
std::vector< MaterialProperty< Real > * > _prop_ci
MaterialBase * _Fa
Free energy instantiation of the MaterialBase class.
const std::vector< const VariableValue * > _prop_c
Global concentrations.
std::vector< std::vector< std::vector< const MaterialProperty< Real > * > > > _d2Fidcidbi
const MaterialProperty< Real > * _C
std::vector< const MaterialProperty< Real > * > _prop_Fi
std::vector< const MaterialProperty< Real > * > _ci_old
std::vector< std::vector< MaterialProperty< Real > * > > _d2Fadc1db1_copy
std::vector< const MaterialProperty< Real > * > _dFadarg
Derivative of free energies wrt coupled variables .
MaterialProperty< Real > & _iter
Number of nested Newton iteration.
const unsigned int _n_args
Number of coupled variables of free energies.
std::vector< const MaterialProperty< Real > * > _dFbdarg
Derivative of free energies wrt coupled variables .
const bool _damped_newton
Add damping functionality to nested Newton solve.
std::vector< MaterialProperty< Real > * > _dFadarg_copy
const unsigned int _num_c
Number of global concentrations.
const MaterialName _Fa_name
Free energies.
std::vector< MaterialProperty< Real > * > _dFidci_copy
const Real _abs_tol
Absolute and relative tolerance of nested Newton iteration.
std::vector< std::vector< const MaterialProperty< Real > * > > _d2Fadcadarg
const std::vector< MaterialPropertyName > _ci_names
Phase concentrations.
std::vector< std::vector< MaterialProperty< Real > * > > _d2Fadcadarg_copy
std::vector< MaterialProperty< Real > * > _dFbdarg_copy
KKSPhaseConcentrationMaterial(const InputParameters &parameters)
NestedSolve _nested_solve
Instantiation of the NestedSolve class.
std::vector< MaterialProperty< Real > * > _Fi_copy
const MaterialProperty< Real > & _prop_h
Switching functions.
const std::vector< VariableName > _args_names
Coupled variables of free energies.
MaterialName _condition_name
Material property that defines the confidence bounds for the newton solve.
std::vector< const MaterialProperty< Real > * > _dFidci
Derivative of free energies wrt phase concentrations .
virtual void computePropertiesAtQp(unsigned int qp)
void nonlinearDamped(V &guess, T &&compute, C &&computeCondition)
typename std::conditional< N==1, NSReal, typename std::conditional< N==0, NestedSolveTempl< is_ad >::DynamicVector, Eigen::Matrix< NSReal, N, 1 > >::type >::type Value
const State & getState() const
void nonlinear(V &guess, T &&compute)
typename std::conditional< N==1, NSReal, typename std::conditional< N==0, NestedSolveTempl< is_ad >::DynamicMatrix, Eigen::Matrix< NSReal, N, N > >::type >::type Jacobian
static InputParameters validParams()
void setRelativeTolerance(Real rel)
void setAbsoluteTolerance(Real abs)
const std::size_t & getIterations()