https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KKSPhaseConcentrationMultiPhaseMaterial.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{
20 "Computes the KKS phase concentrations by using a nested Newton iteration "
21 "to solve the equal chemical potential and concentration conservation equations for "
22 "multiphase systems. This class is intented to be used with "
23 "KKSPhaseConcentrationMultiPhaseDerivatives.");
24 params.addRequiredCoupledVar("global_cs", "The interpolated concentrations c, b, etc.");
25 params.addRequiredCoupledVar("all_etas", "Order parameters.");
26 params.addRequiredParam<std::vector<MaterialPropertyName>>(
27 "hj_names", "Switching functions in the same order as all_etas.");
28 params.addRequiredParam<std::vector<MaterialName>>(
29 "Fj_names", "Free energy material objects in the same order as all_etas.");
30 params.addRequiredParam<std::vector<MaterialPropertyName>>(
31 "ci_names",
32 "Phase concentrations. They must have the same order as Fj_names and global_cs, for "
33 "example, c1, c2, b1, b2.");
34 params.addRequiredParam<std::vector<Real>>("ci_IC",
35 "Initial values of ci in the same order of ci_names");
36 params.addParam<MaterialPropertyName>(
37 "nested_iterations",
38 "The output number of nested Newton iterations at each quadrature point.");
39 params.addCoupledVar("args", "The coupled variables of free energies.");
40 params.addParam<bool>(
41 "damped_Newton", false, "Whether or not to use the damped Newton's method.");
42 params.addParam<MaterialName>("conditions",
43 "C",
44 "Material property that checks bounds and conditions on the "
45 "material properties being solved for.");
46 params += NestedSolve::validParams();
47 return params;
48}
49
51 const InputParameters & parameters)
53 _prop_c(coupledValues("global_cs")),
54 _num_c(coupledComponents("global_cs")),
55 _num_j(coupledComponents("all_etas")),
56 _hj_names(getParam<std::vector<MaterialPropertyName>>("hj_names")),
57 _prop_hj(_num_j),
58 _Fj_names(getParam<std::vector<MaterialName>>("Fj_names")),
59 _prop_Fi(_num_j),
60 _ci_names(getParam<std::vector<MaterialPropertyName>>("ci_names")),
61 _prop_ci(_num_c * _num_j),
62 _ci_old(_num_c * _num_j),
63 _ci_IC(getParam<std::vector<Real>>("ci_IC")),
64 _dFidci(_num_j),
65 _d2Fidcidbi(_num_j),
66 _args_names(coupledNames("args")),
67 _n_args(coupledComponents("args")),
68 _dFidarg(_num_j),
69 _d2F1dc1darg(_num_c),
70 _iter(declareProperty<Real>("nested_iterations")),
71 _abs_tol(getParam<Real>("absolute_tolerance")),
72 _rel_tol(getParam<Real>("relative_tolerance")),
73 _damped_newton(getParam<bool>("damped_Newton")),
74 _condition_name(getParam<MaterialName>("conditions")),
75 _nested_solve(NestedSolve(parameters))
76
77{
78 // phase concentrations
79 for (const auto m : make_range(_num_c * _num_j))
80 {
81 _ci_old[m] = &getMaterialPropertyOld<Real>(_ci_names[m]);
82 _prop_ci[m] = &declareProperty<Real>(_ci_names[m]);
83 }
84
85 // free energies
86 for (const auto m : make_range(_num_j))
87 _prop_Fi[m] = &getMaterialPropertyByName<Real>(_Fj_names[m]);
88
89 // free energy derivatives w.r.t. phase concentrations
90 for (const auto m : make_range(_num_j))
91 {
92 _prop_hj[m] = &getMaterialPropertyByName<Real>(_hj_names[m]);
93
94 _dFidci[m].resize(_num_c);
95 _d2Fidcidbi[m].resize(_num_c);
96
97 for (const auto n : make_range(_num_c))
98 {
99 _dFidci[m][n] = &getMaterialPropertyDerivative<Real>(_Fj_names[m], _ci_names[m + n * _num_j]);
100
101 _d2Fidcidbi[m][n].resize(_num_c);
102
103 for (unsigned int l = 0; l < _num_c; ++l)
104 {
105 _d2Fidcidbi[m][n][l] = &getMaterialPropertyDerivative<Real>(
106 _Fj_names[m], _ci_names[m + n * _num_j], _ci_names[m + l * _num_j]);
107 }
108 }
109 }
110
111 // derivative of free energies wrt coupled variables
112 for (const auto m : make_range(_num_j))
113 {
114 _dFidarg[m].resize(_n_args);
115
116 for (const auto n : make_range(_n_args))
117 _dFidarg[m][n] = &getMaterialPropertyDerivative<Real>(_Fj_names[m], _args_names[n]);
118 }
119
120 // second derivatives of F1 wrt c1 and other coupled variables
121 for (const auto m : make_range(_num_c))
122 {
123 _d2F1dc1darg[m].resize(_n_args);
124
125 for (const auto n : make_range(_n_args))
126 {
127 _d2F1dc1darg[m][n] =
128 &getMaterialPropertyDerivative<Real>(_Fj_names[0], _ci_names[m * _num_j], _args_names[n]);
129 }
130 }
131
132 if (_damped_newton)
133 _C = &getMaterialPropertyByName<Real>(_condition_name);
134 else
135 _C = nullptr;
136}
137
138void
140{
141 for (const auto m : make_range(_num_c * _num_j))
142 (*_prop_ci[m])[_qp] = _ci_IC[m];
143}
144
145void
147{
149
150 for (unsigned int m = 0; m < _num_j; ++m)
151 _Fj_mat[m] = &getMaterialByName(_Fj_names[m]);
152 if (_damped_newton)
153 _condition = &getMaterialByName(_condition_name);
154}
155
156void
158{
159 // parameters for nested Newton iteration
161
162 // initialize first guess using the solution from previous step
163 for (const auto m : make_range(_num_c * _num_j))
164 solution(m) = (*_ci_old[m])[_qp];
165
168
169 auto compute = [&](const NestedSolve::Value<> & guess,
170 NestedSolve::Value<> & residual,
171 NestedSolve::Jacobian<> & jacobian)
172 {
173 for (const auto m : make_range(_num_c * _num_j))
174 (*_prop_ci[m])[_qp] = guess(m);
175
176 for (const auto m : make_range(_num_j))
177 _Fj_mat[m]->computePropertiesAtQp(_qp);
178
179 // assign residual functions
180 for (const auto m : make_range(_num_c))
181 {
182 for (const auto n : make_range(_num_j - 1))
183 residual(m * _num_j + n) = (*_dFidci[n][m])[_qp] - (*_dFidci[n + 1][m])[_qp];
184
185 residual((m + 1) * _num_j - 1) = -(*_prop_c[m])[_qp];
186
187 for (const auto l : make_range(_num_j))
188 residual((m + 1) * _num_j - 1) += (*_prop_hj[l])[_qp] * (*_prop_ci[m * _num_j + l])[_qp];
189 }
190
191 jacobian.setZero();
192
193 // fill in the non-zero terms in jacobian
194 for (const auto m : make_range(_num_c))
195 {
196 // equal chemical potential derivative equations
197 for (const auto n : make_range(_num_j - 1))
198 {
199 for (const auto l : make_range(_num_c))
200 {
201 jacobian(m * _num_j + n, n + l * _num_j) = (*_d2Fidcidbi[n][m][l])[_qp];
202 jacobian(m * _num_j + n, n + l * _num_j + 1) = -(*_d2Fidcidbi[n + 1][m][l])[_qp];
203 }
204 }
205
206 // concentration conservation derivative equations
207 for (const auto n : make_range(_num_j))
208 jacobian((m + 1) * _num_j - 1, m * _num_j + n) = (*_prop_hj[n])[_qp];
209 }
210 };
211
212 auto computeCondition = [&](const NestedSolve::Value<> & guess) -> Real
213 {
214 for (const auto m : make_range(_num_c * _num_j))
215 (*_prop_ci[m])[_qp] = guess(m);
217 return ((*_C)[_qp]);
218 };
219
220 // choose between Newton or damped Newton's method
221 if (!_damped_newton)
222 _nested_solve.nonlinear(solution, compute);
223 else
224 _nested_solve.nonlinearDamped(solution, compute, computeCondition);
225
227
228 if (_nested_solve.getState() == NestedSolve::State::NOT_CONVERGED)
229 mooseException("Nested Newton iteration did not converge.");
230
231 // assign solution to ci
232 for (const auto m : make_range(_num_c * _num_j))
233 (*_prop_ci[m])[_qp] = solution[m];
234}
registerMooseObject("PhaseFieldApp", KKSPhaseConcentrationMultiPhaseMaterial)
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)
const unsigned int _num_c
Number of global concentrations.
const unsigned int _n_args
Number of coupled variables of free energies.
std::vector< std::vector< const MaterialProperty< Real > * > > _dFidci
Derivative of free energies wrt phase concentrations .
std::vector< const MaterialProperty< Real > * > _prop_hj
MaterialProperty< Real > & _iter
Number of nested Newton iteration.
const unsigned int _num_j
Number of phase parameters.
std::vector< std::vector< const MaterialProperty< Real > * > > _dFidarg
Derivative of free energies wrt coupled variables .
std::vector< std::vector< std::vector< const MaterialProperty< Real > * > > > _d2Fidcidbi
KKSPhaseConcentrationMultiPhaseMaterial(const InputParameters &parameters)
const std::vector< const VariableValue * > _prop_c
Global concentrations.
std::vector< std::vector< const MaterialProperty< Real > * > > _d2F1dc1darg
const Real _abs_tol
Absolute and relative tolerance of nested Newton iteration.
std::vector< const MaterialProperty< Real > * > _ci_old
std::vector< MaterialPropertyName > _hj_names
Switching functions.
const std::vector< VariableName > _args_names
Coupled variables of free energies.
MaterialName _condition_name
Condition that must be violated for damping to occur.
std::vector< MaterialBase * > _Fj_mat
Free energy instantiation of the MaterialBase class.
const std::vector< MaterialName > _Fj_names
Free energies.
NestedSolve _nested_solve
Instantiation of the NestedSolve class.
std::vector< MaterialPropertyName > _ci_names
Phase concentrations.
std::vector< const MaterialProperty< Real > * > _prop_Fi
virtual void computePropertiesAtQp(unsigned int qp)
virtual void resize(const std::size_t size) override final
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()