https://mooseframework.inl.gov
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 {
19  params.addClassDescription(
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 
138 void
140 {
141  for (const auto m : make_range(_num_c * _num_j))
142  (*_prop_ci[m])[_qp] = _ci_IC[m];
143 }
144 
145 void
147 {
148  _Fj_mat.resize(_num_j);
149 
150  for (unsigned int m = 0; m < _num_j; ++m)
152  if (_damped_newton)
154 }
155 
156 void
158 {
159  // parameters for nested Newton iteration
160  NestedSolve::Value<> solution(_num_c * _num_j);
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 }
const std::size_t & getIterations()
NestedSolve _nested_solve
Instantiation of the NestedSolve class.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static InputParameters validParams()
const Real _abs_tol
Absolute and relative tolerance of nested Newton iteration.
std::vector< MaterialBase * > _Fj_mat
Free energy instantiation of the MaterialBase class.
const std::vector< MaterialName > _Fj_names
Free energies.
std::vector< MaterialPropertyName > _hj_names
Switching functions.
std::vector< std::vector< const MaterialProperty< Real > * > > _dFidci
Derivative of free energies wrt phase concentrations .
std::vector< MaterialPropertyName > _ci_names
Phase concentrations.
MaterialName _condition_name
Condition that must be violated for damping to occur.
void addRequiredParam(const std::string &name, const std::string &doc_string)
const bool _damped_newton
Check whether to use damping.
typename std::conditional< N==1, NSReal, typename std::conditional< N==0, NestedSolveTempl< false >::DynamicVector, Eigen::Matrix< NSReal, N, 1 > >::type >::type Value
std::vector< std::vector< const MaterialProperty< Real > * > > _d2F1dc1darg
std::vector< MaterialProperty< Real > * > _prop_ci
void nonlinear(V &guess, T &&compute)
std::vector< const MaterialProperty< Real > * > _ci_old
InputParameters validParams()
std::vector< const MaterialProperty< Real > * > _prop_hj
typename std::conditional< N==1, NSReal, typename std::conditional< N==0, NestedSolveTempl< false >::DynamicMatrix, Eigen::Matrix< NSReal, N, N > >::type >::type Jacobian
void setRelativeTolerance(Real rel)
std::vector< const MaterialProperty< Real > * > _prop_Fi
const std::vector< VariableName > _args_names
Coupled variables of free energies.
const unsigned int _num_c
Number of global concentrations.
MaterialBase & getMaterialByName(const std::string &name, bool no_warn=false, bool no_dep=false)
void addCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
KKSPhaseConcentrationMultiPhaseMaterial(const InputParameters &parameters)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void setAbsoluteTolerance(Real abs)
const unsigned int _n_args
Number of coupled variables of free energies.
IntRange< T > make_range(T beg, T end)
void addClassDescription(const std::string &doc_string)
MaterialProperty< Real > & _iter
Number of nested Newton iteration.
virtual void computePropertiesAtQp(unsigned int qp)
void nonlinearDamped(V &guess, T &&compute, C &&computeCondition)
std::vector< std::vector< const MaterialProperty< Real > * > > _dFidarg
Derivative of free energies wrt coupled variables .
const unsigned int _num_j
Number of phase parameters.
const std::vector< const VariableValue * > _prop_c
Global concentrations.
std::vector< std::vector< std::vector< const MaterialProperty< Real > * > > > _d2Fidcidbi
const State & getState() const
registerMooseObject("PhaseFieldApp", KKSPhaseConcentrationMultiPhaseMaterial)