Line data Source code
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 :
10 : #include "GrandPotentialKernelAction.h"
11 : #include "Factory.h"
12 : #include "Parser.h"
13 : #include "Conversion.h"
14 : #include "FEProblem.h"
15 :
16 : registerMooseAction("PhaseFieldApp", GrandPotentialKernelAction, "add_kernel");
17 :
18 : InputParameters
19 21 : GrandPotentialKernelAction::validParams()
20 : {
21 21 : InputParameters parameters = Action::validParams();
22 21 : parameters.addClassDescription(
23 : "Automatically generate most or all of the kernels for the grand potential model");
24 42 : parameters.addRequiredParam<std::vector<NonlinearVariableName>>(
25 : "chemical_potentials", "List of chemical potential variables");
26 42 : parameters.addRequiredParam<std::vector<MaterialPropertyName>>(
27 : "susceptibilities", "List of susceptibilities that correspond to chemical_potentials");
28 42 : parameters.addRequiredParam<std::vector<MaterialPropertyName>>(
29 : "free_energies_gr",
30 : "List of free energies for each phase. Place in same order as switching_function_names.");
31 42 : parameters.addRequiredParam<std::vector<MaterialPropertyName>>(
32 : "free_energies_w",
33 : "List of functions for each phase. Length should be length of chemical_potentials * length "
34 : "of switching_function_names.");
35 42 : parameters.addRequiredParam<std::vector<MaterialPropertyName>>(
36 : "switching_function_names",
37 : "Switching function materials that provide switching function for free_energies_*.");
38 42 : parameters.addRequiredParam<std::vector<MaterialPropertyName>>(
39 : "mobilities", "Vector of mobilities that must match chemical_potentials");
40 42 : parameters.addRequiredParam<unsigned int>("op_num", "specifies the number of grains to create");
41 42 : parameters.addRequiredParam<std::string>("var_name_base",
42 : "specifies the base name of the grain variables");
43 42 : parameters.addParam<std::vector<NonlinearVariableName>>(
44 : "additional_ops", "List of any additional order parameters which are not grains");
45 42 : parameters.addParam<std::vector<MaterialPropertyName>>("free_energies_op",
46 : "List of free energies used by additional "
47 : "order parameters. Places in same order "
48 : "as switching_function_names.");
49 42 : parameters.addParam<MaterialPropertyName>("kappa_gr", "kappa", "The kappa used with the grains");
50 42 : parameters.addParam<MaterialPropertyName>(
51 : "kappa_op", "kappa", "The kappa used with additional_ops");
52 42 : parameters.addParam<MaterialPropertyName>(
53 : "gamma_gr", "gamma", "Name of the gamma used with grains");
54 42 : parameters.addParam<MaterialPropertyName>(
55 : "gamma_op", "gamma", "Name of the gamma used with additional order parameters");
56 42 : parameters.addParam<MaterialPropertyName>(
57 : "gamma_grxop",
58 : "gamma",
59 : "Name of the gamma used when grains interact with other order parameters");
60 42 : parameters.addParam<MaterialPropertyName>(
61 : "mobility_name_gr", "L", "Name of mobility to be used with grains");
62 42 : parameters.addParam<MaterialPropertyName>(
63 : "mobility_name_op", "L", "Name of mobility to be used with additional_ops");
64 42 : parameters.addParam<bool>("implicit", true, "Whether kernels are implicit or not");
65 42 : parameters.addParam<bool>(
66 42 : "use_displaced_mesh", false, "Whether to use displaced mesh in the kernels");
67 21 : MultiMooseEnum anisotropy("true=1 false=0", "false");
68 42 : parameters.addParam<bool>(
69 42 : "mass_conservation", false, "Whether strict mass conservation formulation is used or not");
70 42 : parameters.addRequiredParam<MultiMooseEnum>(
71 : "anisotropic", anisotropy, "Whether or not each mobility is anisotropic");
72 42 : parameters.addParam<std::vector<NonlinearVariableName>>(
73 : "concentrations", "List of concentration variables for strict mass conservation");
74 42 : parameters.addParam<std::vector<MaterialPropertyName>>(
75 : "hj_c_min",
76 : {},
77 : "List of body forces coefficients for strict mass conservation formulation that indicates "
78 : "the minima in concentration free energy."
79 : "Place in same order as switching_function_names.");
80 42 : parameters.addParam<std::vector<MaterialPropertyName>>(
81 : "hj_over_kVa",
82 : {},
83 : "List of MatReaction coefficients for strict mass conservation formulation that relates "
84 : "chemical potential with switching functionj between phases"
85 : "Place in same order as switching_function_names.");
86 21 : return parameters;
87 21 : }
88 :
89 21 : GrandPotentialKernelAction::GrandPotentialKernelAction(const InputParameters & parameters)
90 21 : : Action(parameters)
91 : {
92 21 : }
93 :
94 : void
95 21 : GrandPotentialKernelAction::act()
96 : {
97 : // Get Variables from parameters
98 42 : const auto w_names = getParam<std::vector<NonlinearVariableName>>("chemical_potentials");
99 42 : const auto chis = getParam<std::vector<MaterialPropertyName>>("susceptibilities");
100 42 : const auto Fj_gr = getParam<std::vector<MaterialPropertyName>>("free_energies_gr");
101 42 : const auto Fj_w = getParam<std::vector<MaterialPropertyName>>("free_energies_w");
102 42 : const auto hj = getParam<std::vector<MaterialPropertyName>>("switching_function_names");
103 42 : const auto M = getParam<std::vector<MaterialPropertyName>>("mobilities");
104 42 : auto n_grs = getParam<unsigned int>("op_num");
105 42 : const auto var_name_base = getParam<std::string>("var_name_base");
106 42 : const auto Fj_op = getParam<std::vector<MaterialPropertyName>>("free_energies_op");
107 21 : const auto kappa_gr = getParam<MaterialPropertyName>("kappa_gr");
108 21 : const auto kappa_op = getParam<MaterialPropertyName>("kappa_op");
109 21 : const auto gamma_gr = getParam<MaterialPropertyName>("gamma_gr");
110 21 : const auto gamma_op = getParam<MaterialPropertyName>("gamma_op");
111 21 : const auto gamma_xx = getParam<MaterialPropertyName>("gamma_grxop");
112 21 : const auto gr_mob = getParam<MaterialPropertyName>("mobility_name_gr");
113 21 : const auto op_mob = getParam<MaterialPropertyName>("mobility_name_op");
114 42 : auto implicity = getParam<bool>("implicit");
115 42 : auto displaced_mesh = getParam<bool>("use_displaced_mesh");
116 42 : auto aniso = getParam<MultiMooseEnum>("anisotropic");
117 42 : const auto hj_over_kVa = getParam<std::vector<MaterialPropertyName>>("hj_over_kVa");
118 42 : const auto hj_c_min = getParam<std::vector<MaterialPropertyName>>("hj_c_min");
119 42 : auto mass_conservation = getParam<bool>("mass_conservation");
120 :
121 : // Size definitions and checks
122 21 : unsigned int n_w = w_names.size();
123 21 : unsigned int n_hj = hj.size();
124 : std::vector<NonlinearVariableName> etas;
125 : std::vector<NonlinearVariableName> c_names;
126 : unsigned int n_etas = 0;
127 : std::string kernel_name;
128 42 : if (isParamValid("additional_ops"))
129 : {
130 63 : etas = getParam<std::vector<NonlinearVariableName>>("additional_ops");
131 21 : n_etas = etas.size();
132 : }
133 :
134 21 : if (chis.size() != n_w)
135 0 : mooseError("susceptibilities and chemical_potentials should be vectors of the same length.");
136 21 : if (Fj_w.size() != n_w * n_hj)
137 0 : mooseError("free_energies_w should be length of chemcial_potentials * length of "
138 : "switching_function_names");
139 21 : if (M.size() != n_w)
140 0 : mooseError("M and chemical_potentials should be vectors of the same length.");
141 21 : if (aniso.size() != n_w)
142 0 : paramError("anisotropic", "Provide as many values as entries in 'chemical_potentials'.");
143 :
144 : // Define additional vectors
145 : std::vector<std::string> grs; // vector of all grain variable names
146 21 : grs.resize(n_grs);
147 56 : for (unsigned int i = 0; i < n_grs; ++i)
148 70 : grs[i] = var_name_base + Moose::stringify(i);
149 :
150 : std::vector<NonlinearVariableName> all_etas; // vector of all grain variables and order parameters
151 21 : all_etas.reserve(n_etas + n_grs);
152 21 : all_etas.insert(all_etas.end(), etas.begin(), etas.end());
153 21 : all_etas.insert(all_etas.end(), grs.begin(), grs.end());
154 :
155 : std::vector<std::string> all_vars; // vector of all variables
156 21 : all_vars.reserve(n_etas + n_grs + n_w);
157 21 : all_vars.insert(all_vars.end(), all_etas.begin(), all_etas.end());
158 21 : all_vars.insert(all_vars.end(), w_names.begin(), w_names.end());
159 :
160 : std::vector<MaterialPropertyName> fj_temp;
161 21 : fj_temp.resize(n_hj);
162 : std::vector<VariableName> notarealvector;
163 21 : notarealvector.resize(1);
164 : std::vector<VariableName> v0;
165 21 : v0.resize(n_etas + n_grs + n_w);
166 105 : for (unsigned int i = 0; i < n_etas + n_grs + n_w; ++i)
167 168 : v0[i] = all_vars[i];
168 : std::vector<VariableName> v1;
169 21 : v1.resize(n_etas + n_grs);
170 77 : for (unsigned int i = 0; i < n_etas + n_grs; ++i)
171 112 : v1[i] = all_etas[i];
172 : std::vector<VariableName> v2;
173 21 : v2.resize(n_etas + n_grs - 1);
174 :
175 : std::vector<VariableName> v_etas;
176 21 : v_etas.resize(n_etas);
177 42 : for (unsigned int i = 0; i < n_etas; ++i)
178 42 : v_etas[i] = all_etas[i];
179 :
180 : // Grains and order parameters
181 : NonlinearVariableName var_name;
182 : MaterialPropertyName kappa;
183 : MaterialPropertyName mob_name;
184 : std::vector<MaterialPropertyName> Fj_names;
185 :
186 77 : for (unsigned int i = 0; i < n_etas + n_grs; ++i)
187 : {
188 56 : var_name = all_etas[i];
189 : // Distinguish between grains and the additional order parameters
190 56 : if (i < n_etas) // First part of list is grain variables
191 : {
192 : kappa = kappa_op;
193 : mob_name = op_mob;
194 21 : Fj_names.resize(Fj_op.size());
195 21 : Fj_names = Fj_op;
196 : }
197 : else // Second part of list is additional order parameters
198 : {
199 : kappa = kappa_gr;
200 : mob_name = gr_mob;
201 35 : Fj_names.resize(Fj_gr.size());
202 35 : Fj_names = Fj_gr;
203 : }
204 :
205 : // Remove var_name from coupled variables
206 : std::vector<MaterialPropertyName> gam;
207 56 : gam.resize(n_etas + n_grs - 1);
208 : unsigned int op = 0;
209 210 : for (unsigned int j = 0; j < n_etas + n_grs; ++j)
210 : {
211 154 : if (i != j)
212 : {
213 98 : v2[op] = all_etas[j];
214 98 : if (j < n_etas)
215 : gam[op] = gamma_op;
216 : else
217 : gam[op] = gamma_gr;
218 98 : if (i < n_etas && j < n_etas)
219 : gam[op] = gamma_op;
220 98 : else if (i >= n_etas && j >= n_etas)
221 : gam[op] = gamma_gr;
222 : else
223 : gam[op] = gamma_xx;
224 98 : ++op;
225 : }
226 : }
227 :
228 : // TimeDerivative Kernel
229 56 : InputParameters params = _factory.getValidParams("TimeDerivative");
230 56 : params.set<NonlinearVariableName>("variable") = var_name;
231 56 : params.set<bool>("implicit") = implicity;
232 56 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
233 56 : kernel_name = "DT_" + var_name;
234 56 : _problem->addKernel("TimeDerivative", kernel_name, params);
235 :
236 : // ACInterface Kernel
237 56 : params = _factory.getValidParams("ACInterface");
238 56 : params.set<NonlinearVariableName>("variable") = var_name;
239 56 : params.set<bool>("implicit") = implicity;
240 56 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
241 56 : params.set<MaterialPropertyName>("kappa_name") = kappa;
242 56 : params.set<MaterialPropertyName>("mob_name") = mob_name;
243 56 : params.set<std::vector<VariableName>>("coupled_variables") = v2;
244 56 : kernel_name = "ACInt_" + var_name;
245 56 : _problem->addKernel("ACInterface", kernel_name, params);
246 :
247 : // ACSwitching Kernel
248 56 : params = _factory.getValidParams("ACSwitching");
249 56 : params.set<NonlinearVariableName>("variable") = var_name;
250 56 : params.set<bool>("implicit") = implicity;
251 56 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
252 56 : params.set<std::vector<MaterialPropertyName>>("Fj_names") = Fj_names;
253 56 : params.set<std::vector<MaterialPropertyName>>("hj_names") = hj;
254 56 : params.set<MaterialPropertyName>("mob_name") = mob_name;
255 56 : params.set<std::vector<VariableName>>("coupled_variables") = v0;
256 56 : kernel_name = "ACSwitch_" + var_name;
257 56 : _problem->addKernel("ACSwitching", kernel_name, params);
258 :
259 : // ACGrGrMulti Kernel
260 56 : params = _factory.getValidParams("ACGrGrMulti");
261 56 : params.set<NonlinearVariableName>("variable") = var_name;
262 56 : params.set<bool>("implicit") = implicity;
263 56 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
264 56 : params.set<MaterialPropertyName>("mob_name") = mob_name;
265 56 : params.set<std::vector<VariableName>>("v") = v2;
266 56 : params.set<std::vector<MaterialPropertyName>>("gamma_names") = gam;
267 56 : kernel_name = "AcGrGr_" + var_name;
268 56 : _problem->addKernel("ACGrGrMulti", kernel_name, params);
269 56 : } // for (unsigned int i = 0; i < n_etas + n_grs; ++i)
270 :
271 21 : if (mass_conservation) // mass conservation kernels with conc and chempot coupling
272 : {
273 21 : c_names = getParam<std::vector<NonlinearVariableName>>("concentrations");
274 : std::vector<VariableName> v3;
275 7 : v3.resize(n_w);
276 14 : for (unsigned int i = 0; i < n_w; ++i)
277 14 : v3[i] = w_names[i];
278 :
279 : std::vector<VariableName> v4;
280 7 : unsigned int n_c = c_names.size();
281 7 : v4.resize(n_c);
282 14 : for (unsigned int i = 0; i < n_c; ++i)
283 14 : v4[i] = c_names[i];
284 :
285 14 : for (unsigned int i = 0; i < n_c; ++i)
286 : {
287 : // TimeDerivative concentration Kernel
288 7 : InputParameters params = _factory.getValidParams("TimeDerivative");
289 7 : params.set<NonlinearVariableName>("variable") = c_names[i];
290 7 : params.set<bool>("implicit") = implicity;
291 7 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
292 7 : kernel_name = "DT_" + c_names[i];
293 7 : _problem->addKernel("TimeDerivative", kernel_name, params);
294 :
295 : // MatDiffusion concentration (coupled with chempot)
296 14 : params = _factory.getValidParams("PolycrystalMatDiffusion");
297 7 : params.set<NonlinearVariableName>("variable") = c_names[i];
298 7 : params.set<std::vector<VariableName>>("v") = v3;
299 7 : params.set<bool>("implicit") = implicity;
300 7 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
301 14 : params.set<MaterialPropertyName>("diffusivity") = M[i];
302 7 : kernel_name = "MatDif_" + w_names[i];
303 7 : if (aniso.get(i))
304 : {
305 7 : params.set<std::vector<VariableName>>("args") = v1;
306 7 : params.set<std::vector<VariableName>>("surface_op_var") = v_etas;
307 14 : _problem->addKernel("PolycrystalMatAnisoDiffusion", kernel_name, params);
308 : }
309 : else
310 : {
311 0 : params.set<std::vector<VariableName>>("args") = v0;
312 0 : _problem->addKernel("PolycrystalMatDiffusion", kernel_name, params);
313 : }
314 7 : }
315 :
316 : // Chemical Potentials
317 14 : for (unsigned int i = 0; i < n_w; ++i)
318 : {
319 : // coupling of c and w
320 7 : InputParameters params = _factory.getValidParams("MatReaction");
321 7 : params.set<NonlinearVariableName>("variable") = w_names[i];
322 14 : params.set<std::vector<VariableName>>("v") = v4;
323 14 : params.set<MaterialPropertyName>("reaction_rate") = "-1";
324 7 : kernel_name = "MR_c" + w_names[i];
325 7 : _problem->addKernel("MatReaction", kernel_name, params);
326 :
327 : // contribution between chempot and each grains to concentration
328 : // Summations of MatReaction and MaskedBodyForce
329 :
330 21 : for (unsigned int j = 0; j < n_hj; ++j)
331 : {
332 : // MatReaction
333 28 : params = _factory.getValidParams("MatReaction");
334 14 : params.set<NonlinearVariableName>("variable") = w_names[i];
335 14 : params.set<std::vector<VariableName>>("args") = v1;
336 14 : params.set<MaterialPropertyName>("reaction_rate") = hj_over_kVa[j];
337 14 : params.set<bool>("implicit") = implicity;
338 14 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
339 28 : kernel_name = "MR_" + w_names[i] + "_" + all_etas[j];
340 14 : _problem->addKernel("MatReaction", kernel_name, params);
341 :
342 : // MaskedBodyForce
343 28 : InputParameters params = _factory.getValidParams("MaskedBodyForce");
344 14 : params.set<NonlinearVariableName>("variable") = w_names[i];
345 28 : params.set<std::vector<VariableName>>("coupled_variables") = v1;
346 14 : params.set<MaterialPropertyName>("mask") = hj_c_min[j];
347 14 : params.set<bool>("implicit") = implicity;
348 14 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
349 28 : kernel_name = "MBD_" + w_names[i] + "_" + all_etas[j];
350 14 : _problem->addKernel("MaskedBodyForce", kernel_name, params);
351 14 : }
352 7 : }
353 7 : }
354 : else
355 : {
356 : // Chemical Potentials
357 35 : for (unsigned int i = 0; i < n_w; ++i)
358 : {
359 : // SusceptibilityTimeDerivative
360 21 : InputParameters params = _factory.getValidParams("SusceptibilityTimeDerivative");
361 42 : params.set<NonlinearVariableName>("variable") = w_names[i];
362 21 : params.set<MaterialPropertyName>("f_name") = chis[i];
363 21 : params.set<std::vector<VariableName>>("coupled_variables") = v0;
364 21 : params.set<bool>("implicit") = implicity;
365 21 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
366 21 : kernel_name = "ChiDt_" + w_names[i];
367 21 : _problem->addKernel("SusceptibilityTimeDerivative", kernel_name, params);
368 :
369 : // MatDiffusion
370 42 : params = _factory.getValidParams("PolycrystalMatDiffusion");
371 21 : params.set<NonlinearVariableName>("variable") = w_names[i];
372 21 : params.set<bool>("implicit") = implicity;
373 21 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
374 42 : params.set<MaterialPropertyName>("diffusivity") = M[i];
375 21 : kernel_name = "MatDif_" + w_names[i];
376 21 : params.set<std::vector<VariableName>>("args") = v0;
377 21 : if (aniso.get(i))
378 : {
379 14 : params.set<std::vector<VariableName>>("surface_op_var") = v_etas;
380 28 : _problem->addKernel("PolycrystalMatAnisoDiffusion", kernel_name, params);
381 : }
382 : else
383 : {
384 7 : params.set<std::vector<VariableName>>("args") = v0;
385 14 : _problem->addKernel("PolycrystalMatDiffusion", kernel_name, params);
386 : }
387 :
388 : // CoupledSwitchingTimeDerivative
389 63 : for (unsigned int j = 0; j < n_hj; ++j)
390 42 : fj_temp[j] = Fj_w[i * n_hj + j];
391 77 : for (unsigned int j = 0; j < n_etas + n_grs; ++j)
392 : {
393 56 : notarealvector[0] = all_etas[j];
394 112 : params = _factory.getValidParams("CoupledSwitchingTimeDerivative");
395 56 : params.set<NonlinearVariableName>("variable") = w_names[i];
396 56 : params.set<std::vector<VariableName>>("v") = notarealvector;
397 56 : params.set<std::vector<VariableName>>("coupled_variables") = v0;
398 56 : params.set<std::vector<MaterialPropertyName>>("Fj_names") = fj_temp;
399 56 : params.set<std::vector<MaterialPropertyName>>("hj_names") = hj;
400 56 : params.set<bool>("implicit") = implicity;
401 56 : params.set<bool>("use_displaced_mesh") = displaced_mesh;
402 112 : kernel_name = "Coupled_" + w_names[i] + "_" + all_etas[j];
403 112 : _problem->addKernel("CoupledSwitchingTimeDerivative", kernel_name, params);
404 : }
405 21 : }
406 : }
407 105 : } // GrandPotentialKernelAction::act()
|