https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
187void
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 {
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()
Real f(Real x)
Test function for Brents method.
registerMooseObject("PhaseFieldApp", ElectrochemicalSinteringMaterial)
void mooseError(Args &&... args)
void ErrorVector unsigned int
This material calculates necessary parameters for the grand potential sintering model with multiple d...
const unsigned int _ndefects
number of defect species
std::vector< std::vector< MaterialProperty< Real > * > > _d2omegasdetadeta
const VariableValue & _v
electric potential
std::vector< const MaterialProperty< Real > * > _ns_min
ElectrochemicalSinteringMaterial(const InputParameters &parameters)
std::vector< MaterialProperty< Real > * > _domegavdw
MaterialProperty< Real > & _omegas
solid phase grand potential density
std::vector< std::vector< const MaterialProperty< Real > * > > _dns_min
MaterialProperty< Real > & _mu
energy barrier coefficient
const VariableValue & _phi
void phase order parameter
std::vector< MaterialPropertyName > _ks_names
Names of solid energy coefficient for each defect.
const Real _eps_r
Solid phase relative permittivity.
std::vector< const VariableValue * > _w
chemical potentials for defects
std::vector< MaterialProperty< Real > * > _domegasdeta
MaterialProperty< Real > & _hv
void phase switching function
MaterialProperty< Real > & _kappa
gradient energy coefficient
std::vector< MaterialPropertyName > _ns_min_names
minima in energy wrt vacancy concentration in solid
std::vector< MaterialProperty< Real > * > _d2omegavdw2
MaterialProperty< Real > & _gamma
interface profile coefficient
const std::vector< int > _z
Defects species charges in units of e.
std::vector< MaterialProperty< Real > * > _domegasdw
const VariableGradient & _grad_V
Gradient of electric potential.
MaterialProperty< Real > & _hs
solid phase switching function
std::vector< std::vector< std::vector< const MaterialProperty< Real > * > > > _d2ns_min
const MooseEnum _solid_energy
Type of energy function to use for the solid phase.
std::vector< std::vector< MaterialProperty< Real > * > > _d2omegasdwdeta
const unsigned int _neta
number of solid phase order paramters
const Real _switch
Parameter to determine accuracy of surface/GB phase switching function.
std::vector< const MaterialProperty< Real > * > _ks
solid energy coefficient for each defect
MaterialProperty< Real > & _omegav
void phase grand potential density
std::vector< MaterialPropertyName > _kv_names
Names of void energy coefficient for each defect.
const Real _mu_gb
mu value on grain boundaries
std::vector< const MaterialProperty< Real > * > _kv
void energy coefficients for each defect
std::vector< const VariableValue * > _eta
solid phase order parameters
const Real _kappa_gb
kappa value on grain boundaries
const std::vector< Real > _nv_min
minima in energy wrt vacancy concentration in void
std::vector< MaterialProperty< Real > * > _d2omegasdw2
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 addRequiredCoupledVarWithAutoBuild(const std::string &name, const std::string &base_name, const std::string &num_name, const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
static InputParameters validParams()