https://mooseframework.inl.gov
ElectrochemicalSinteringMaterial.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("Includes switching and thermodynamic properties for the grand "
21  "potential sintering model coupled with electrochemistry");
23  "etas", "var_name_base", "op_num", "Array of order parameters that describe solid phase");
24  params.addRequiredCoupledVar("chemical_potentials",
25  "The name of the chemical potential variables for defects");
26  params.addRequiredCoupledVar("void_op", "The name of the void phase order parameter");
27  params.addRequiredCoupledVar("Temperature", "Name of the temperature variable with units of K");
28  params.addRequiredCoupledVar("electric_potential",
29  "Name of the electric potential variable with units of V");
30  params.addParam<std::vector<MaterialPropertyName>>(
31  "solid_energy_coefficients",
32  "Vector of parabolic solid energy coefficients (energy*volume) for "
33  "each defect species. Only used for parabolic energy. Place in same order as "
34  "chemical_potentials!");
35  params.addRequiredParam<std::vector<MaterialPropertyName>>(
36  "void_energy_coefficients",
37  "Vector of parabolic void energy coefficients (energy*volume) for each defect species. Place "
38  "in same order as chemical_potentials!");
39  params.addParam<Real>("surface_energy", 19.7, "Surface energy in units of problem (energy/area)");
40  params.addParam<Real>(
41  "grainboundary_energy", 9.86, "Grain boundary energy in units of problem (energy/area)");
42  params.addParam<Real>("int_width", 1, "Interface width in units of problem (length)");
43  params.addRangeCheckedParam<Real>(
44  "surface_switch_value",
45  0.3,
46  "surface_switch_value >= 0 & surface_switch_value <= 1.0",
47  "Value between 0 and 1 that determines when the interface begins to switch "
48  "from surface to GB. Small values give less error while large values "
49  "converge better.");
50  params.addRequiredParam<std::vector<MaterialPropertyName>>(
51  "min_vacancy_concentrations_solid",
52  "Vector of names of materials that determine the minimum in energy wrt defect concentrations "
53  "in the solid phase. Place in same order as chemical_potentials!");
54  params.addRequiredParam<std::vector<Real>>("min_vacancy_concentrations_void",
55  "Vector of minima in energy wrt defect concentrations "
56  "in the void phase. Place in same order as "
57  "chemical_potentials!");
58  MooseEnum solid_energy_model("PARABOLIC DILUTE IDEAL", "PARABOLIC");
59  params.addParam<MooseEnum>("solid_energy_model",
60  solid_energy_model,
61  "Type of energy function to use for the solid phase.");
62  params.addRequiredParam<std::vector<int>>(
63  "defect_charges",
64  "Vector of charges of defect species. Place in same order as chemical_potentials!");
65  params.addRequiredParam<Real>("solid_relative_permittivity",
66  "Solid phase relative permittivity (dimensionless)");
67  params.addParam<Real>("voltage_scale", 1, "Voltage scale (default is for voltage in V)");
68  return params;
69 }
70 
72  const InputParameters & parameters)
74  _neta(coupledComponents("etas")),
75  _eta(_neta),
76  _eta_name(_neta),
77  _ndefects(coupledComponents("chemical_potentials")),
78  _w(coupledValues("chemical_potentials")),
79  _w_name(_ndefects),
80  _phi(coupledValue("void_op")),
81  _phi_name(coupledName("void_op", 0)),
82  _ns_min_names(getParam<std::vector<MaterialPropertyName>>("min_vacancy_concentrations_solid")),
83  _ns_min(_ndefects),
84  _dns_min(_ndefects),
85  _d2ns_min(_ndefects),
86  _temp(coupledValue("Temperature")),
87  _v(coupledValue("electric_potential")),
88  _grad_V(coupledGradient("electric_potential")),
89  _kv_names(getParam<std::vector<MaterialPropertyName>>("void_energy_coefficients")),
90  _kv(_ndefects),
91  _ks_names(getParam<std::vector<MaterialPropertyName>>("solid_energy_coefficients")),
92  _ks(_ndefects),
93  _hv(declareProperty<Real>("hv")),
94  _dhv(declarePropertyDerivative<Real>("hv", _phi_name)),
95  _d2hv(declarePropertyDerivative<Real>("hv", _phi_name, _phi_name)),
96  _hs(declareProperty<Real>("hs")),
97  _dhs(declarePropertyDerivative<Real>("hs", _phi_name)),
98  _d2hs(declarePropertyDerivative<Real>("hs", _phi_name, _phi_name)),
99  _omegav(declareProperty<Real>("omegav")),
100  _domegavdw(_ndefects),
101  _d2omegavdw2(_ndefects),
102  _omegas(declareProperty<Real>("omegas")),
103  _domegasdw(_ndefects),
104  _d2omegasdw2(_ndefects),
105  _domegasdeta(_neta),
106  _d2omegasdwdeta(_ndefects),
107  _d2omegasdetadeta(_neta),
108  _mu(declareProperty<Real>("mu")),
109  _dmu(declarePropertyDerivative<Real>("mu", _phi_name)),
110  _d2mu(declarePropertyDerivative<Real>("mu", _phi_name, _phi_name)),
111  _kappa(declareProperty<Real>("kappa")),
112  _dkappa(declarePropertyDerivative<Real>("kappa", _phi_name)),
113  _d2kappa(declarePropertyDerivative<Real>("kappa", _phi_name, _phi_name)),
114  _gamma(declareProperty<Real>("gamma")),
115  _sigma_s(getParam<Real>("surface_energy")),
116  _sigma_gb(getParam<Real>("grainboundary_energy")),
117  _int_width(getParam<Real>("int_width")),
118  _switch(getParam<Real>("surface_switch_value")),
119  _solid_energy(getParam<MooseEnum>("solid_energy_model")),
120  _mu_s(6.0 * _sigma_s / _int_width),
121  _mu_gb(6.0 * _sigma_gb / _int_width),
122  _kappa_s(0.75 * _sigma_s * _int_width),
123  _kappa_gb(0.75 * _sigma_gb * _int_width),
124  _kB(8.617343e-5), // eV/K
125  _e(1.0), // to put energy units in eV
126  _z(getParam<std::vector<int>>("defect_charges")),
127  _v_scale(getParam<Real>("voltage_scale")),
128  _eps_r(getParam<Real>("solid_relative_permittivity")),
129  _nv_min(getParam<std::vector<Real>>("min_vacancy_concentrations_void"))
130 {
131  if (_ndefects != _z.size())
132  paramError("defect_charges", "Need to pass in as many defect_charges as chemical_potentials");
133  if (_ndefects != _ns_min_names.size())
134  paramError("min_vacancy_concentrations_solid",
135  "Need to pass in as many min_vacancy_concentrations_solid as chemical_potentials");
136  if (_ndefects != _nv_min.size())
137  paramError("min_vacancy_concentrations_void",
138  "Need to pass in as many min_vacancy_concentrations_void as chemical_potentials");
139  if (_ndefects != _kv_names.size())
140  paramError("void_energy_coefficients",
141  "Need to pass in as many void_energy_coefficients as chemical_potentials");
142  if (_ndefects != _ks_names.size())
143  paramError("solid_energy_coefficients",
144  "Need to pass in as many solid_energy_coefficients as chemical_potentials");
145 
146  for (unsigned int i = 0; i < _ndefects; ++i)
147  {
148  _w_name[i] = coupledName("chemical_potentials", i);
149  _ns_min[i] = &getMaterialPropertyByName<Real>(_ns_min_names[i]);
150  _dns_min[i].resize(_neta);
151  _d2ns_min[i].resize(_neta);
152  _d2omegasdwdeta[i].resize(_neta);
153  _kv[i] = &getMaterialPropertyByName<Real>(_kv_names[i]);
154  _ks[i] = &getMaterialPropertyByName<Real>(_ks_names[i]);
155  _domegavdw[i] = &declarePropertyDerivative<Real>("omegav", _w_name[i]);
156  _d2omegavdw2[i] = &declarePropertyDerivative<Real>("omegav", _w_name[i], _w_name[i]);
157  _domegasdw[i] = &declarePropertyDerivative<Real>("omegas", _w_name[i]);
158  _d2omegasdw2[i] = &declarePropertyDerivative<Real>("omegas", _w_name[i], _w_name[i]);
159  for (unsigned int j = 0; j < _neta; ++j)
160  {
161  _dns_min[i][j] = &getMaterialPropertyDerivativeByName<Real>(_ns_min_names[i], _eta_name[j]);
162  _d2ns_min[i][j].resize(_neta);
163 
164  for (unsigned int k = 0; k < _neta; ++k)
165  _d2ns_min[i][j][k] = &getMaterialPropertyDerivativeByName<Real>(
167  }
168  }
169 
170  for (unsigned int i = 0; i < _neta; ++i)
171  {
172  _eta[i] = &coupledValue("etas", i);
173  _eta_name[i] = coupledName("etas", i);
174  _domegasdeta[i] = &declarePropertyDerivative<Real>("omegas", _eta_name[i]);
175  _d2omegasdetadeta[i].resize(_neta);
176 
177  for (unsigned int j = 0; j <= i; ++j)
179  &declarePropertyDerivative<Real>("omegas", _eta_name[j], _eta_name[i]);
180  }
181 
182  for (unsigned int i = 0; i < _ndefects; ++i)
183  for (unsigned int j = 0; j < _neta; ++j)
184  _d2omegasdwdeta[i][j] = &declarePropertyDerivative<Real>("omegas", _w_name[i], _eta_name[j]);
185 }
186 
187 void
189 {
190  // Calculate phase switching functions
191  _hv[_qp] = 0.0;
192  _dhv[_qp] = 0.0;
193  _d2hv[_qp] = 0.0;
194 
195  if (_phi[_qp] >= 1.0)
196  _hv[_qp] = 1.0;
197  else if (_phi[_qp] > 0.0)
198  {
199  _hv[_qp] = _phi[_qp] * _phi[_qp] * _phi[_qp] * (10.0 + _phi[_qp] * (-15.0 + _phi[_qp] * 6.0));
200  _dhv[_qp] = 30.0 * _phi[_qp] * _phi[_qp] * (_phi[_qp] - 1.0) * (_phi[_qp] - 1.0);
201  _d2hv[_qp] = 60.0 * _phi[_qp] * (2.0 * _phi[_qp] - 1.0) * (_phi[_qp] - 1.0);
202  }
203 
204  _hs[_qp] = 1.0 - _hv[_qp];
205  _dhs[_qp] = -_dhv[_qp];
206  _d2hs[_qp] = -_d2hv[_qp];
207 
208  // Calculate interface switching function
209  Real phi = _phi[_qp] / _switch;
210  Real f = 0.0;
211  Real df = 0.0;
212  Real d2f = 0.0;
213  if (phi >= 1.0)
214  f = 1.0;
215  else if (phi > 0.0)
216  {
217  f = phi * phi * phi * (10.0 + phi * (-15.0 + phi * 6.0));
218  df = 30.0 / _switch * phi * phi * (phi - 1.0) * (phi - 1.0);
219  d2f = 60.0 * phi / (_switch * _switch) * (2.0 * phi - 1.0) * (phi - 1.0);
220  }
221 
222  // Permittivity in the void phase (permittivity of free space)
223  Real eps_0 = 5.52e-2 * _v_scale * _v_scale; // units eV/V^2/nm, change with V_scale if needed
224 
225  // Calculate grand potential of void phase
226  Real sum_omega_v = 0.0;
227  for (unsigned int i = 0; i < _ndefects; ++i)
228  sum_omega_v += -0.5 / (*_kv[i])[_qp] * ((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) *
229  ((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) -
230  _nv_min[i] * ((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale);
231 
232  _omegav[_qp] = sum_omega_v - 0.5 * eps_0 * _grad_V[_qp] * _grad_V[_qp];
233 
234  // Calculate derivatives of grand potential wrt chemical potential
235  for (unsigned int i = 0; i < _ndefects; ++i)
236  {
237  (*_domegavdw[i])[_qp] =
238  -((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) / (*_kv[i])[_qp] - _nv_min[i];
239  (*_d2omegavdw2[i])[_qp] = -1.0 / (*_kv[i])[_qp];
240  }
241 
242  // Calculate solid phase density and potential
243  switch (_solid_energy)
244  {
245  case 0: // PARABOLIC
246  {
247  // Calculate grand potential of solid phase and derivatives wrt chemical potentials
248  Real sum_omega_s = 0.0;
249  for (unsigned int i = 0; i < _ndefects; ++i)
250  {
251  sum_omega_s += -0.5 / (*_ks[i])[_qp] * ((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) *
252  ((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) -
253  (*_ns_min[i])[_qp] * ((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale);
254  (*_domegasdw[i])[_qp] =
255  -((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) / (*_ks[i])[_qp] -
256  (*_ns_min[i])[_qp];
257  (*_d2omegasdw2[i])[_qp] = -1.0 / (*_ks[i])[_qp];
258  }
259 
260  _omegas[_qp] = sum_omega_s - 0.5 * _eps_r * eps_0 * _grad_V[_qp] * _grad_V[_qp];
261 
262  // Calculate derivatives of grand potential wrt order parameters and mixed derivatives
263  for (unsigned int i = 0; i < _neta; ++i)
264  {
265  Real sum_domegasdeta = 0.0;
266  for (unsigned int j = 0; j < _ndefects; ++j)
267  {
268  sum_domegasdeta +=
269  -(*_dns_min[j][i])[_qp] * ((*_w[j])[_qp] - _z[j] * _e * _v[_qp] * _v_scale);
270  (*_d2omegasdwdeta[j][i])[_qp] = -(*_dns_min[j][i])[_qp];
271  }
272  (*_domegasdeta[i])[_qp] = sum_domegasdeta;
273 
274  for (unsigned int j = i; j < _neta; ++j)
275  {
276  Real sum_d2omegadeta2 = 0.0;
277  for (unsigned int k = 0; k < _ndefects; ++k)
278  sum_d2omegadeta2 +=
279  -(*_d2ns_min[k][i][j])[_qp] * ((*_w[k])[_qp] - _z[k] * _e * _v[_qp] * _v_scale);
280 
281  (*_d2omegasdetadeta[i][j])[_qp] = (*_d2omegasdetadeta[j][i])[_qp] = sum_d2omegadeta2;
282  }
283  }
284  break;
285  } // case 0; // PARABOLIC
286  case 1: // DILUTE
287  {
288  // Calculate grand potential of solid phase and derivatives wrt chemical potentials
289  Real sum_omega_s = 0.0;
290  for (unsigned int i = 0; i < _ndefects; ++i)
291  {
292  Real n_exp = std::exp(((*_w[i])[_qp] - _z[i] * _e * _v[_qp] * _v_scale) / _kB / _temp[_qp]);
293  sum_omega_s += -_kB * _temp[_qp] * (*_ns_min[i])[_qp] * n_exp;
294  (*_domegasdw[i])[_qp] = -(*_ns_min[i])[_qp] * n_exp;
295  (*_d2omegasdw2[i])[_qp] = -(*_ns_min[i])[_qp] * n_exp / _kB / _temp[_qp];
296  }
297 
298  _omegas[_qp] = sum_omega_s - 0.5 * _eps_r * eps_0 * _grad_V[_qp] * _grad_V[_qp];
299 
300  // Calculate derivatives of grand potential wrt order parameters and mixed derivatives
301  for (unsigned int i = 0; i < _neta; ++i)
302  {
303  Real sum_domegasdeta = 0.0;
304  for (unsigned int j = 0; j < _ndefects; ++j)
305  {
306  Real n_exp =
307  std::exp(((*_w[j])[_qp] - _z[j] * _e * _v[_qp] * _v_scale) / _kB / _temp[_qp]);
308  sum_domegasdeta += -_kB / _temp[_qp] * (*_dns_min[j][i])[_qp] * n_exp;
309  (*_d2omegasdwdeta[j][i])[_qp] = -(*_dns_min[j][i])[_qp] * n_exp;
310  }
311  (*_domegasdeta[i])[_qp] = sum_domegasdeta;
312 
313  for (unsigned int j = i; j < _neta; ++j)
314  {
315  Real sum_d2omegadeta2 = 0.0;
316  for (unsigned int k = 0; k < _ndefects; ++k)
317  {
318  Real n_exp =
319  std::exp(((*_w[k])[_qp] - _z[k] * _e * _v[_qp] * _v_scale) / _kB / _temp[_qp]);
320  sum_d2omegadeta2 += -_kB / _temp[_qp] * (*_d2ns_min[k][i][j])[_qp] * n_exp;
321  }
322 
323  (*_d2omegasdetadeta[i][j])[_qp] = (*_d2omegasdetadeta[j][i])[_qp] = sum_d2omegadeta2;
324  }
325  }
326 
327  break;
328  } // case 1: // DILUTE
329  case 2: // IDEAL
330  {
331  mooseError(
332  "Ideal solution in solid is not yet supported in ElectrochemicalSinteringMaterial");
333  break;
334  } // case 2: // IDEAL
335  } // switch (_solid_energy)
336 
337  // thermodynamic parameters
338  _mu[_qp] = _mu_gb + (_mu_s - _mu_gb) * f;
339  _kappa[_qp] = _kappa_gb + (_kappa_s - _kappa_gb) * f;
340  _dmu[_qp] = (_mu_s - _mu_gb) * df;
341  _dkappa[_qp] = (_kappa_s - _kappa_gb) * df;
342  _d2mu[_qp] = (_mu_s - _mu_gb) * d2f;
343  _d2kappa[_qp] = (_kappa_s - _kappa_gb) * d2f;
344  _gamma[_qp] = 1.5;
345 } // void ElectrochemicalSinteringMaterial::computeQpProperties()
This material calculates necessary parameters for the grand potential sintering model with multiple d...
const std::vector< int > _z
Defects species charges in units of e.
MaterialProperty< Real > & _mu
energy barrier coefficient
ElectrochemicalSinteringMaterial(const InputParameters &parameters)
MaterialProperty< Real > & _hs
solid phase switching function
VariableName coupledName(const std::string &var_name, unsigned int comp=0) const
const VariableValue & _v
electric potential
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const unsigned int _ndefects
number of defect species
const VariableValue & _phi
void phase order parameter
std::vector< MaterialPropertyName > _ns_min_names
minima in energy wrt vacancy concentration in solid
MaterialProperty< Real > & _hv
void phase switching function
const Real _kappa_gb
kappa value on grain boundaries
std::vector< std::vector< MaterialProperty< Real > * > > _d2omegasdwdeta
const Real _kappa_s
kappa value on surfaces
const VariableValue & _temp
temperature
void addRequiredParam(const std::string &name, const std::string &doc_string)
const std::vector< Real > _nv_min
minima in energy wrt vacancy concentration in void
virtual const VariableValue & coupledValue(const std::string &var_name, unsigned int comp=0) const
MaterialProperty< Real > & _omegas
solid phase grand potential density
static InputParameters validParams()
std::vector< const MaterialProperty< Real > * > _kv
void energy coefficients for each defect
Real f(Real x)
Test function for Brents method.
std::vector< MaterialProperty< Real > * > _d2omegasdw2
registerMooseObject("PhaseFieldApp", ElectrochemicalSinteringMaterial)
MaterialProperty< Real > & _kappa
gradient energy coefficient
void paramError(const std::string &param, Args... args) const
std::vector< const VariableValue * > _w
chemical potentials for defects
std::vector< MaterialProperty< Real > * > _d2omegavdw2
MaterialProperty< Real > & _omegav
void phase grand potential density
const VariableGradient & _grad_V
Gradient of electric potential.
std::vector< const MaterialProperty< Real > * > _ks
solid energy coefficient for each defect
std::vector< MaterialProperty< Real > * > _domegasdeta
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
static const Real eps_0
Electric permittivity of free space in SI units (F/m)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< MaterialPropertyName > _ks_names
Names of solid energy coefficient for each defect.
std::vector< MaterialProperty< Real > * > _domegasdw
void addRequiredCoupledVarWithAutoBuild(const std::string &name, const std::string &base_name, const std::string &num_name, const std::string &doc_string)
const Real _mu_gb
mu value on grain boundaries
const Real _switch
Parameter to determine accuracy of surface/GB phase switching function.
std::vector< MaterialProperty< Real > * > _domegavdw
MaterialProperty< Real > & _gamma
interface profile coefficient
const unsigned int _neta
number of solid phase order paramters
std::vector< MaterialPropertyName > _kv_names
Names of void energy coefficient for each defect.
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")
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
std::vector< std::vector< const MaterialProperty< Real > * > > _dns_min
std::vector< const MaterialProperty< Real > * > _ns_min
const Real _eps_r
Solid phase relative permittivity.
const MooseEnum _solid_energy
Type of energy function to use for the solid phase.
std::vector< const VariableValue * > _eta
solid phase order parameters
static const std::string k
Definition: NS.h:130
void ErrorVector unsigned int
std::vector< std::vector< std::vector< const MaterialProperty< Real > * > > > _d2ns_min
std::vector< std::vector< MaterialProperty< Real > * > > _d2omegasdetadeta