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