https://mooseframework.inl.gov
GrandPotentialSinteringMaterial.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 "libmesh/quadrature.h"
12 #include "libmesh/utility.h"
13 
15 
18 {
20  params.addClassDescription(
21  "Includes switching and thermodynamic properties for the grand potential sintering model");
23  "etas", "var_name_base", "op_num", "Array of order parameters that describe solid phase");
24  params.addRequiredCoupledVar("chemical_potential", "The name of the chemical potential variable");
25  params.addRequiredCoupledVar("void_op", "The name of the void phase order parameter");
26  params.addRequiredCoupledVar("Temperature", "Name of the temperature variable with units of K");
27  params.addParam<MaterialPropertyName>(
28  "solid_energy_coefficient",
29  1.0,
30  "Parabolic solid energy coefficient (energy/volume). Only used for parabolic energy.");
31  params.addRequiredParam<MaterialPropertyName>(
32  "void_energy_coefficient", "Parabolic void energy coefficient (energy/volume)");
33  params.addParam<Real>("surface_energy", 19.7, "Surface energy in units of problem (energy/area)");
34  params.addParam<Real>(
35  "grainboundary_energy", 9.86, "Grain boundary energy in units of problem (energy/area)");
36  params.addParam<Real>("int_width", 1, "Interface width in units of problem (length)");
37  params.addParam<Real>("surface_switch_value",
38  0.3,
39  "Value between 0 and 1 that determines when the interface begins to switch "
40  "from surface to GB. Small values give less error while large values "
41  "converge better.");
42  params.addRequiredParam<MaterialPropertyName>(
43  "equilibrium_vacancy_concentration",
44  "Name of material that determines the equilibrium vacancy concentration in the solid phase");
45  params.addParam<Real>("atomic_volume", 0.04092, "Atomic volume of material");
46  MooseEnum solid_energy_model("PARABOLIC DILUTE IDEAL", "PARABOLIC");
47  params.addParam<MooseEnum>("solid_energy_model",
48  solid_energy_model,
49  "Type of energy function to use for the solid phase.");
50  params.addParam<bool>(
51  "mass_conservation", false, "imposing strict mass conservation formulation");
52  return params;
53 }
54 
57  _neta(coupledComponents("etas")),
58  _eta(_neta),
59  _eta_name(_neta),
60  _w(coupledValue("chemical_potential")),
61  _w_name(coupledName("chemical_potential", 0)),
62  _phi(coupledValue("void_op")),
63  _phi_name(coupledName("void_op", 0)),
64  _cs_eq_name(getParam<MaterialPropertyName>("equilibrium_vacancy_concentration")),
65  _cs_eq(getMaterialProperty<Real>(_cs_eq_name)),
66  _dcs_eq(_neta),
67  _d2cs_eq(_neta),
68  _T(coupledValue("Temperature")),
69  _kv(getMaterialProperty<Real>("void_energy_coefficient")),
70  _ks(getMaterialProperty<Real>("solid_energy_coefficient")),
71  _hv(declareProperty<Real>("hv")),
72  _dhv(declarePropertyDerivative<Real>("hv", _phi_name)),
73  _d2hv(declarePropertyDerivative<Real>("hv", _phi_name, _phi_name)),
74  _hs(declareProperty<Real>("hs")),
75  _dhs(declarePropertyDerivative<Real>("hs", _phi_name)),
76  _d2hs(declarePropertyDerivative<Real>("hs", _phi_name, _phi_name)),
77  _chi(declareProperty<Real>("chi")),
78  _dchidphi(declarePropertyDerivative<Real>("chi", _phi_name)),
79  _dchidw(declarePropertyDerivative<Real>("chi", _w_name)),
80  _d2chidphi2(declarePropertyDerivative<Real>("chi", _phi_name, _phi_name)),
81  _d2chidw2(declarePropertyDerivative<Real>("chi", _w_name, _w_name)),
82  _d2chidphidw(declarePropertyDerivative<Real>("chi", _phi_name, _w_name)),
83  _rhov(declareProperty<Real>("rhov")),
84  _drhovdw(declarePropertyDerivative<Real>("rhov", _w_name)),
85  _rhos(declareProperty<Real>("rhos")),
86  _drhosdw(declarePropertyDerivative<Real>("rhos", _w_name)),
87  _d2rhosdw2(declarePropertyDerivative<Real>("rhos", _w_name, _w_name)),
88  _drhos(_neta),
89  _d2rhosdwdeta(_neta),
90  _d2rhos(_neta),
91  _omegav(declareProperty<Real>("omegav")),
92  _domegavdw(declarePropertyDerivative<Real>("omegav", _w_name)),
93  _d2omegavdw2(declarePropertyDerivative<Real>("omegav", _w_name, _w_name)),
94  _omegas(declareProperty<Real>("omegas")),
95  _domegasdw(declarePropertyDerivative<Real>("omegas", _w_name)),
96  _d2omegasdw2(declarePropertyDerivative<Real>("omegas", _w_name, _w_name)),
97  _domegasdeta(_neta),
98  _d2omegasdwdeta(_neta),
99  _d2omegasdetadeta(_neta),
100  _mu(declareProperty<Real>("mu")),
101  _dmu(declarePropertyDerivative<Real>("mu", _phi_name)),
102  _d2mu(declarePropertyDerivative<Real>("mu", _phi_name, _phi_name)),
103  _kappa(declareProperty<Real>("kappa")),
104  _dkappa(declarePropertyDerivative<Real>("kappa", _phi_name)),
105  _d2kappa(declarePropertyDerivative<Real>("kappa", _phi_name, _phi_name)),
106  _gamma(declareProperty<Real>("gamma")),
107  _hv_c_min(declareProperty<Real>("hv_c_min")),
108  _dhv_c_mindphi(declarePropertyDerivative<Real>("hv_c_min", _phi_name)),
109  _d2hv_c_mindphi2(declarePropertyDerivative<Real>("hv_c_min", _phi_name, _phi_name)),
110  _hs_c_min(declareProperty<Real>("hs_c_min")),
111  _dhs_c_mindphi(declarePropertyDerivative<Real>("hs_c_min", _phi_name)),
112  _d2hs_c_mindphi2(declarePropertyDerivative<Real>("hs_c_min", _phi_name, _phi_name)),
113  _dhs_c_min(_neta),
114  _d2hs_c_min(_neta),
115  _hv_over_kVa(declareProperty<Real>("hv_over_kVa")),
116  _dhv_over_kVadphi(declarePropertyDerivative<Real>("hv_over_kVa", _phi_name)),
117  _d2hv_over_kVadphi2(declarePropertyDerivative<Real>("hv_over_kVa", _phi_name, _phi_name)),
118  _hs_over_kVa(declareProperty<Real>("hs_over_kVa")),
119  _dhs_over_kVadphi(declarePropertyDerivative<Real>("hs_over_kVa", _phi_name)),
120  _d2hs_over_kVadphi2(declarePropertyDerivative<Real>("hs_over_kVa", _phi_name, _phi_name)),
121 
122  _sigma_s(getParam<Real>("surface_energy")),
123  _sigma_gb(getParam<Real>("grainboundary_energy")),
124  _int_width(getParam<Real>("int_width")),
125  _switch(getParam<Real>("surface_switch_value")),
126  _Va(getParam<Real>("atomic_volume")),
127  _solid_energy(getParam<MooseEnum>("solid_energy_model")),
128  _mu_s(6.0 * _sigma_s / _int_width),
129  _mu_gb(6.0 * _sigma_gb / _int_width),
130  _kappa_s(0.75 * _sigma_s * _int_width),
131  _kappa_gb(0.75 * _sigma_gb * _int_width),
132  _kB(8.617343e-5), // eV/K
133  _mass_conservation(getParam<bool>("mass_conservation"))
134 {
135  if ((_switch > 1.0) || (_switch < 0.0))
136  mooseError("GrandPotentialSinteringMaterial: surface_switch_value should be between 0 and 1");
137 
139  mooseError("GrandPotentialSinteringMaterial: strict mass conservation is currently only "
140  "applicable to parabolic free energy");
141 
142  for (unsigned int i = 0; i < _neta; ++i)
143  {
144  _eta[i] = &coupledValue("etas", i);
145  _eta_name[i] = coupledName("etas", i);
146  _dcs_eq[i] = &getMaterialPropertyDerivativeByName<Real>(_cs_eq_name, _eta_name[i]);
147  _d2cs_eq[i].resize(_neta);
148  _drhos[i] = &declarePropertyDerivative<Real>("rhos", _eta_name[i]);
149  _d2rhos[i].resize(_neta);
150  _d2rhosdwdeta[i] = &declarePropertyDerivative<Real>("rhos", _w_name, _eta_name[i]);
151  _domegasdeta[i] = &declarePropertyDerivative<Real>("omegas", _eta_name[i]);
152  _d2omegasdwdeta[i] = &declarePropertyDerivative<Real>("omegas", _w_name, _eta_name[i]);
153  _d2omegasdetadeta[i].resize(_neta);
154  _dhs_c_min[i] = &declarePropertyDerivative<Real>("hs_c_min", _eta_name[i]);
155  _d2hs_c_min[i].resize(_neta);
156 
157  for (unsigned int j = 0; j <= i; ++j)
158  {
159  _d2cs_eq[j][i] =
160  &getMaterialPropertyDerivativeByName<Real>(_cs_eq_name, _eta_name[j], _eta_name[i]);
161  _d2rhos[j][i] = &declarePropertyDerivative<Real>("rhos", _eta_name[j], _eta_name[i]);
162  _d2omegasdetadeta[j][i] =
163  &declarePropertyDerivative<Real>("omegas", _eta_name[j], _eta_name[i]);
164  _d2hs_c_min[j][i] = &declarePropertyDerivative<Real>("hs_c_min", _eta_name[j], _eta_name[i]);
165  }
166  }
167 }
168 
169 void
171 {
172  // Calculate phase switching functions
173  _hv[_qp] = 0.0;
174  _dhv[_qp] = 0.0;
175  _d2hv[_qp] = 0.0;
176 
177  if (_phi[_qp] >= 1.0)
178  _hv[_qp] = 1.0;
179  else if (_phi[_qp] > 0.0)
180  {
181  _hv[_qp] = _phi[_qp] * _phi[_qp] * _phi[_qp] * (10.0 + _phi[_qp] * (-15.0 + _phi[_qp] * 6.0));
182  _dhv[_qp] = 30.0 * _phi[_qp] * _phi[_qp] * (_phi[_qp] - 1.0) * (_phi[_qp] - 1.0);
183  _d2hv[_qp] = 60.0 * _phi[_qp] * (2.0 * _phi[_qp] - 1.0) * (_phi[_qp] - 1.0);
184  }
185 
186  _hs[_qp] = 1.0 - _hv[_qp];
187  _dhs[_qp] = -_dhv[_qp];
188  _d2hs[_qp] = -_d2hv[_qp];
189 
190  // Calculate interface switching function
191  Real phi = _phi[_qp] / _switch;
192  Real f = 0.0;
193  Real df = 0.0;
194  Real d2f = 0.0;
195  if (phi >= 1.0)
196  f = 1.0;
197  else if (phi > 0.0)
198  {
199  f = phi * phi * phi * (10.0 + phi * (-15.0 + phi * 6.0));
200  df = 30.0 / _switch * phi * phi * (phi - 1.0) * (phi - 1.0);
201  d2f = 60.0 * phi / (_switch * _switch) * (2.0 * phi - 1.0) * (phi - 1.0);
202  }
203 
204  // Equilibrium vacancy concentration
205  Real cv_eq = 1.0;
206 
207  // Calculate the void phase density and potentials
208  _rhov[_qp] = _w[_qp] / (_Va * _Va * _kv[_qp]) + cv_eq / _Va;
209  _drhovdw[_qp] = 1.0 / (_Va * _Va * _kv[_qp]);
210 
211  _omegav[_qp] = -0.5 * _w[_qp] * _w[_qp] / (_Va * _Va * _kv[_qp]) - _w[_qp] * cv_eq / _Va;
212  _domegavdw[_qp] = -_rhov[_qp];
214 
215  // Calculate solid phase density and potential
216  Real d3rhosdw3 = 0;
217  switch (_solid_energy)
218  {
219  case 0: // PARABOLIC
220  {
221  _rhos[_qp] = _w[_qp] / (_Va * _Va * _ks[_qp]) + _cs_eq[_qp] / _Va;
222  _drhosdw[_qp] = 1.0 / (_Va * _Va * _ks[_qp]);
223  _d2rhosdw2[_qp] = 0.0;
224  d3rhosdw3 = 0.0;
225 
226  _omegas[_qp] =
227  -0.5 * _w[_qp] * _w[_qp] / (_Va * _Va * _ks[_qp]) - _w[_qp] * _cs_eq[_qp] / _Va;
228  _domegasdw[_qp] = -_rhos[_qp];
230 
231  // bodyforce and matreact coefficients for strict mass conservation case
232  _hv_c_min[_qp] = _hv[_qp] * 1.0;
233  _dhv_c_mindphi[_qp] = _dhv[_qp] * 1.0;
234  _d2hv_c_mindphi2[_qp] = _d2hv[_qp] * 1.0;
235  _hs_c_min[_qp] = _hs[_qp] * _cs_eq[_qp];
238  _hv_over_kVa[_qp] = _hv[_qp] / (_Va * _kv[_qp]);
239  _dhv_over_kVadphi[_qp] = _dhv[_qp] / (_Va * _kv[_qp]);
241  _hs_over_kVa[_qp] = _hs[_qp] / (_Va * _ks[_qp]);
242  _dhs_over_kVadphi[_qp] = _dhs[_qp] / (_Va * _ks[_qp]);
244 
245  for (unsigned int i = 0; i < _neta; ++i)
246  {
247  (*_drhos[i])[_qp] = (*_dcs_eq[i])[_qp] / _Va;
248  (*_d2rhosdwdeta[i])[_qp] = 0.0;
249  (*_domegasdeta[i])[_qp] = -_w[_qp] * (*_dcs_eq[i])[_qp] / _Va;
250  (*_d2omegasdwdeta[i])[_qp] = -(*_dcs_eq[i])[_qp] / _Va;
251  (*_dhs_c_min[i])[_qp] = _hs[_qp] * (*_dcs_eq[i])[_qp];
252  for (unsigned int j = i; j < _neta; ++j)
253  {
254  (*_d2rhos[i][j])[_qp] = (*_d2cs_eq[i][j])[_qp] / _Va;
255  (*_d2omegasdetadeta[i][j])[_qp] = -_w[_qp] * (*_d2cs_eq[i][j])[_qp] / _Va;
256  (*_d2hs_c_min[i][j])[_qp] = _hs[_qp] * (*_d2cs_eq[i][j])[_qp];
257  }
258  }
259  break;
260  } // case 0; // PARABOLIC
261  case 1: // DILUTE
262  {
263  Real rho_exp = std::exp(_w[_qp] / _kB / _T[_qp]);
264  _rhos[_qp] = _cs_eq[_qp] / _Va * rho_exp;
265  _drhosdw[_qp] = _rhos[_qp] / _kB / _T[_qp];
266  _d2rhosdw2[_qp] = _drhosdw[_qp] / _kB / _T[_qp];
267  d3rhosdw3 = _d2rhosdw2[_qp] / _kB / _T[_qp];
268 
269  _omegas[_qp] = _kB * _T[_qp] * (_cs_eq[_qp] / _Va - _rhos[_qp]);
270  _domegasdw[_qp] = -_rhos[_qp];
272  for (unsigned int i = 0; i < _neta; ++i)
273  {
274  (*_drhos[i])[_qp] = (*_dcs_eq[i])[_qp] * rho_exp / _Va;
275  (*_d2rhosdwdeta[i])[_qp] = 0.0;
276  (*_domegasdeta[i])[_qp] = _kB * _T[_qp] * (*_dcs_eq[i])[_qp] / _Va * (1.0 - rho_exp);
277  (*_d2omegasdwdeta[i])[_qp] = -1.0 / _Va * (*_dcs_eq[i])[_qp] * rho_exp;
278  for (unsigned int j = i; j < _neta; ++j)
279  {
280  (*_d2rhos[i][j])[_qp] = (*_d2cs_eq[i][j])[_qp] * rho_exp / _Va;
281  (*_d2omegasdetadeta[i][j])[_qp] =
282  _kB * _T[_qp] * (*_d2cs_eq[i][j])[_qp] / _Va * (1.0 - rho_exp);
283  }
284  }
285  break;
286  } // case 1: // DILUTE
287  case 2: // IDEAL
288  {
289  Real Ef = -_kB * _T[_qp] * std::log(_cs_eq[_qp] / (1.0 - _cs_eq[_qp]));
290  std::vector<Real> dEf;
291  std::vector<std::vector<Real>> d2Ef;
292  dEf.resize(_neta);
293  d2Ef.resize(_neta);
294 
295  Real x = std::exp((_w[_qp] - Ef) / (_kB * _T[_qp]));
296  Real x0 = std::exp(-Ef / (_kB * _T[_qp]));
297  _rhos[_qp] = x / ((1.0 + x) * _Va);
298  Real rhos0 = x0 / ((1.0 + x0) * _Va);
299  _drhosdw[_qp] = x / (Utility::pow<2>(1.0 + x) * _Va * _kB * _T[_qp]);
300  _d2rhosdw2[_qp] =
301  x * (1.0 - x) / (_Va * Utility::pow<2>(_kB * _T[_qp]) * Utility::pow<3>(1.0 + x));
302  d3rhosdw3 = x * (1 - 4.0 * x + x * x) /
303  (_Va * Utility::pow<3>(_kB * _T[_qp]) * Utility::pow<4>(1.0 + x));
304 
305  _omegas[_qp] = _kB * _T[_qp] / _Va * (std::log(1.0 + x0) - std::log(1.0 + x));
306  _domegasdw[_qp] = -_rhos[_qp];
308  for (unsigned int i = 0; i < _neta; ++i)
309  {
310  dEf[i] =
311  -_kB * _T[_qp] * (*_dcs_eq[i])[_qp] * (1.0 / _cs_eq[_qp] + 1.0 / (1.0 - _cs_eq[_qp]));
312  d2Ef[i].resize(_neta);
313 
314  (*_drhos[i])[_qp] = -dEf[i] * _drhosdw[_qp];
315  (*_d2rhosdwdeta[i])[_qp] = -dEf[i] * _d2rhosdw2[_qp];
316 
317  (*_domegasdeta[i])[_qp] = dEf[i] * (_rhos[_qp] - rhos0);
318  (*_d2omegasdwdeta[i])[_qp] = dEf[i] * _drhosdw[_qp];
319 
320  for (unsigned int j = i; j < _neta; ++j)
321  {
322  d2Ef[i][j] = -_kB * _T[_qp] *
323  ((*_d2cs_eq[i][j])[_qp] * (1.0 / _cs_eq[_qp] + 1.0 / (1.0 - _cs_eq[_qp])) +
324  (*_dcs_eq[i])[_qp] * (*_dcs_eq[j])[_qp] *
325  (1.0 / ((1.0 - _cs_eq[_qp]) * (1.0 - _cs_eq[_qp])) -
326  1.0 / (_cs_eq[_qp] * _cs_eq[_qp])));
327 
328  (*_d2rhos[i][j])[_qp] = -d2Ef[i][j] * _drhosdw[_qp] + dEf[i] * dEf[j] * _d2rhosdw2[_qp];
329  (*_d2omegasdetadeta[i][j])[_qp] =
330  d2Ef[i][j] * (_rhos[_qp] - rhos0) +
331  dEf[i] * dEf[j] / (_Va * _kB * _T[_qp]) *
332  (x / Utility::pow<2>(1.0 + x) - x0 / Utility::pow<2>(1.0 + x0));
333  }
334  }
335  break;
336  } // case 2: // IDEAL
337  } // switch (_solid_energy)
338 
339  // Calculate the susceptibility
340  _chi[_qp] = _hs[_qp] * _drhosdw[_qp] + _hv[_qp] * _drhovdw[_qp];
342  _dchidw[_qp] = _hs[_qp] * _d2rhosdw2[_qp];
344  _d2chidw2[_qp] = _hs[_qp] * d3rhosdw3;
346 
347  // thermodynamic parameters
348  _mu[_qp] = _mu_gb + (_mu_s - _mu_gb) * f;
349  _kappa[_qp] = _kappa_gb + (_kappa_s - _kappa_gb) * f;
350  _dmu[_qp] = (_mu_s - _mu_gb) * df;
351  _dkappa[_qp] = (_kappa_s - _kappa_gb) * df;
352  _d2mu[_qp] = (_mu_s - _mu_gb) * d2f;
353  _d2kappa[_qp] = (_kappa_s - _kappa_gb) * d2f;
354  _gamma[_qp] = 1.5;
355 } // void GrandPotentialSinteringMaterial::computeQpProperties()
const MaterialProperty< Real > & _kv
void energy coefficient
registerMooseObject("PhaseFieldApp", GrandPotentialSinteringMaterial)
std::vector< const MaterialProperty< Real > * > _dcs_eq
const Real _kappa_gb
kappa value on grain boundaries
VariableName coupledName(const std::string &var_name, unsigned int comp=0) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
MaterialProperty< Real > & _rhos
solid phase vacancy density
MaterialProperty< Real > & _kappa
gradient energy coefficient
MaterialProperty< Real > & _chi
susceptibility
MaterialProperty< Real > & _gamma
interface profile coefficient
std::vector< MaterialProperty< Real > * > _domegasdeta
MaterialProperty< Real > & _rhov
void phase vacancy density
MaterialProperty< Real > & _hv_over_kVa
MatReaction Force coefficient for mass conservation in conc and chempot coupling. ...
std::vector< std::vector< MaterialProperty< Real > * > > _d2rhos
void addRequiredParam(const std::string &name, const std::string &doc_string)
const VariableValue & _phi
void phase order parameter
MaterialProperty< Real > & _omegav
void phase potential density
std::vector< MaterialProperty< Real > * > _drhos
virtual const VariableValue & coupledValue(const std::string &var_name, unsigned int comp=0) const
MaterialProperty< Real > & _hs
solid phase switching function
const Real _switch
Parameter to determine accuracy of surface/GB phase switching function.
MaterialProperty< Real > & _mu
energy barrier coefficient
std::vector< MaterialProperty< Real > * > _d2omegasdwdeta
static InputParameters validParams()
GrandPotentialSinteringMaterial(const InputParameters &parameters)
const std::vector< double > x
Real f(Real x)
Test function for Brents method.
std::vector< const VariableValue * > _eta
solid phase order parameters
This material calculates necessary parameters for the grand potential sintering model.
const Real _Va
Atomic volume of species.
std::vector< std::vector< const MaterialProperty< Real > * > > _d2cs_eq
const Real _mu_gb
mu value on grain boundaries
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
const VariableValue & _w
chemical potential
const MaterialProperty< Real > & _ks
solid energy coefficient
std::vector< MaterialProperty< Real > * > _dhs_c_min
const VariableValue & _T
temperature
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::vector< MaterialProperty< Real > * > > _d2hs_c_min
const MaterialPropertyName _cs_eq_name
equilibrium vacancy concentration
void addRequiredCoupledVarWithAutoBuild(const std::string &name, const std::string &base_name, const std::string &num_name, const std::string &doc_string)
MaterialProperty< Real > & _omegas
solid phase potential density
const Real _kappa_s
kappa value on surfaces
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const MooseEnum _solid_energy
Type of energy function to use for the solid phase.
const bool _mass_conservation
strict mass conservation flag
MaterialProperty< Real > & _hv_c_min
Body Force coefficient for mass conservation in conc and chempot coupling.
MaterialProperty< Real > & _hv
void phase switching function
const MaterialProperty< Real > & _cs_eq
const unsigned int _neta
number of solid phase order paramters
std::vector< MaterialProperty< Real > * > _d2rhosdwdeta
std::vector< std::vector< MaterialProperty< Real > * > > _d2omegasdetadeta