https://mooseframework.inl.gov
KKSPhaseConcentrationMultiPhaseDerivatives.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 concentration derivatives wrt global concentrations and order "
21  "parameters, which are used for the chain rule in the KKS kernels. This class is intended to "
22  "be used with KKSPhaseConcentrationMultiPhaseMaterial.");
23  params.addRequiredCoupledVar("global_cs", "The interpolated concentrations c, b, etc");
24  params.addRequiredCoupledVar("all_etas", "Order parameters.");
25  params.addRequiredParam<std::vector<MaterialPropertyName>>(
26  "ci_names",
27  "Phase concentrations. They must have the same order as Fj_names and global_cs, for "
28  "example, c1, c2, b1, b2.");
29  params.addRequiredParam<std::vector<MaterialName>>(
30  "Fj_names", "Free energy material objects in the same order as all_etas.");
31  params.addRequiredParam<std::vector<MaterialPropertyName>>(
32  "hj_names", "witching functions in the same order as all_etas.");
33  return params;
34 }
35 
37  const InputParameters & parameters)
39  _num_c(coupledComponents("global_cs")),
40  _c_names(coupledNames("global_cs")),
41  _eta_names(coupledNames("all_etas")),
42  _num_j(coupledComponents("all_etas")),
43  _prop_ci(_num_c * _num_j),
44  _ci_names(getParam<std::vector<MaterialPropertyName>>("ci_names")),
45  _dcidetaj(_num_c),
46  _dcidb(_num_c),
47  _Fj_names(getParam<std::vector<MaterialName>>("Fj_names")),
48  _d2Fidcidbi(_num_j),
49  _hj_names(getParam<std::vector<MaterialPropertyName>>("hj_names")),
50  _prop_hj(_num_j),
51  _dhjdetai(_num_j)
52 
53 {
54  for (const auto m : make_range(_num_c * _num_j))
55  _prop_ci[m] = &getMaterialPropertyByName<Real>(_ci_names[m]);
56 
57  for (const auto m : make_range(_num_c))
58  {
59  _dcidb[m].resize(_num_j);
60  _dcidetaj[m].resize(_num_j);
61 
62  for (const auto n : make_range(_num_j))
63  {
64  _dcidb[m][n].resize(_num_c);
65  _dcidetaj[m][n].resize(_num_j);
66 
67  // Derivative of phase concentration wrt global concentration. In _dcidb[m][n][l], m is the
68  // species index of ci, n is the phase index of ci, and l is the species index of b
69  for (const auto l : make_range(_num_c))
70  _dcidb[m][n][l] = &declarePropertyDerivative<Real>(_ci_names[n + m * _num_j], _c_names[l]);
71 
72  // Derivative of phase concentration wrt eta. In _dcidetaj[m][n][l], m is the species index
73  // of ci, n is the phase index of ci, and l is the phase of etaj
74  for (const auto l : make_range(_num_j))
75  _dcidetaj[m][n][l] =
76  &declarePropertyDerivative<Real>(_ci_names[n + m * _num_j], _eta_names[l]);
77  }
78  }
79 
80  // Second derivative of free energy wrt phase concentrations for use in this material. In
81  // _d2Fidcidbi[m][n][l], m is phase index of Fi, n is the species index of ci, l is the species
82  // index of bi.
83  for (const auto m : make_range(_num_j))
84  {
85  _d2Fidcidbi[m].resize(_num_c);
86 
87  for (const auto n : make_range(_num_c))
88  {
89  _d2Fidcidbi[m][n].resize(_num_c);
90 
91  for (const auto l : make_range(_num_c))
92  _d2Fidcidbi[m][n][l] = &getMaterialPropertyDerivative<Real>(
93  _Fj_names[m], _ci_names[m + n * _num_j], _ci_names[m + l * _num_j]);
94  }
95  }
96 
97  for (const auto m : make_range(_num_j))
98  {
99  _prop_hj[m] = &getMaterialPropertyByName<Real>(_hj_names[m]);
100 
101  _dhjdetai[m].resize(_num_j);
102 
103  for (const auto n : make_range(_num_j))
104  _dhjdetai[m][n] = &getMaterialPropertyDerivative<Real>(_hj_names[m], _eta_names[n]);
105  }
106 }
107 
108 void
110 {
111  // declare Jacobian matrix A
112  Eigen::MatrixXd A(_num_c * _num_j, _num_c * _num_j);
113 
114  // initialize all elements in A to be zero
115  A.setZero();
116 
117  // fill in the non-zero elements in A
118  for (const auto m : make_range(_num_c))
119  {
120  // equal chemical potential derivative equations
121  for (const auto n : make_range(_num_j - 1))
122  {
123  for (const auto l : make_range(_num_c))
124  {
125  A(m * _num_j + n, n + l * _num_j) = (*_d2Fidcidbi[n][m][l])[_qp];
126  A(m * _num_j + n, n + l * _num_j + 1) = -(*_d2Fidcidbi[n + 1][m][l])[_qp];
127  }
128  }
129 
130  // concentration conservation derivative equations
131  for (const auto n : make_range(_num_j))
132  A((m + 1) * _num_j - 1, m * _num_j + n) = (*_prop_hj[n])[_qp];
133  }
134 
135  A = A.inverse();
136 
137  // solve linear system of constraint derivatives wrt b for computing dcidb loop through
138  // derivatives wrt the ith component; they have the same A, but different k_c
139  for (const auto i : make_range(_num_c))
140  {
141  std::vector<Real> k_c(_num_j * _num_c);
142  std::vector<Real> x_c(_num_j * _num_c);
143 
144  // assign non-zero elements in k_c
145  k_c[i * _num_j + _num_j - 1] = 1;
146 
147  // compute x_c
148  for (const auto m : make_range(_num_j * _num_c))
149  {
150  for (const auto n : make_range(_num_j * _num_c))
151  x_c[m] += A(m, n) * k_c[n];
152  }
153 
154  // assign the values in x_c to _dcidb
155  for (const auto m : make_range(_num_c))
156  {
157  for (const auto n : make_range(_num_j))
158  (*_dcidb[m][n][i])[_qp] = x_c[m * _num_j + n];
159  }
160  }
161 
162  // solve linear system of constraint derivatives wrt eta for computing dcidetaj use the same
163  // linear matrix as computing dcidb
164  for (const auto i : make_range(_num_j))
165  {
166  std::vector<Real> k_eta(_num_j * _num_c);
167  std::vector<Real> x_eta(_num_j * _num_c);
168 
169  // assign non-zero elements in k_eta
170  for (const auto m : make_range(_num_c))
171  {
172  Real sum = 0.0;
173 
174  for (const auto n : make_range(_num_j))
175  sum += (*_dhjdetai[n][i])[_qp] * (*_prop_ci[m * _num_j + n])[_qp];
176 
177  k_eta[m * _num_j + _num_j - 1] = -sum;
178  }
179 
180  // compute x_eta
181  for (const auto m : make_range(_num_j * _num_c))
182  {
183  for (const auto n : make_range(_num_j * _num_c))
184  x_eta[m] += A(m, n) * k_eta[n];
185  }
186 
187  // assign the values in x_eta to _dcidetaj
188  for (const auto m : make_range(_num_c))
189  {
190  for (const auto n : make_range(_num_j))
191  (*_dcidetaj[m][n][i])[_qp] = x_eta[m * _num_j + n];
192  }
193  }
194 }
std::vector< MaterialName > _Fj_names
Free energy names.
std::vector< std::vector< std::vector< MaterialProperty< Real > * > > > _dcidb
Derivative of phase concentrations wrt global concentrations .
void addRequiredParam(const std::string &name, const std::string &doc_string)
std::vector< std::vector< std::vector< MaterialProperty< Real > * > > > _dcidetaj
Derivative of phase concentrations wrt etaj .
InputParameters validParams()
KKSPhaseConcentrationMultiPhaseDerivatives(const InputParameters &parameters)
std::vector< std::vector< const MaterialProperty< Real > * > > _dhjdetai
Derivatives of switching functions.
const unsigned int _num_c
Number of global concentrations.
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
std::vector< const MaterialProperty< Real > * > _prop_ci
Phase concentrations.
std::vector< std::vector< std::vector< const MaterialProperty< Real > * > > > _d2Fidcidbi
Second derivative of phase concentrations wrt two phase concentrations .
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< VariableName > _c_names
Names of global concentrations.
registerMooseObject("PhaseFieldApp", KKSPhaseConcentrationMultiPhaseDerivatives)
std::vector< const MaterialProperty< Real > * > _prop_hj
IntRange< T > make_range(T beg, T end)
void addClassDescription(const std::string &doc_string)
std::vector< MaterialPropertyName > _hj_names
Switching functions.
const unsigned int _num_j
Number of phase parameters.
const std::vector< VariableName > _eta_names
Phase parameters.