https://mooseframework.inl.gov
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 
16 registerMooseAction("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 
90  : Action(parameters)
91 {
92 }
93 
94 void
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>("mob_name") = "-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>("mob_name") = 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  if (aniso.get(i))
377  {
378  params.set<std::vector<VariableName>>("surface_op_var") = v_etas;
379  _problem->addKernel("PolycrystalMatAnisoDiffusion", kernel_name, params);
380  }
381  else
382  {
383  params.set<std::vector<VariableName>>("args") = v0;
384  _problem->addKernel("PolycrystalMatDiffusion", kernel_name, params);
385  }
386 
387  // CoupledSwitchingTimeDerivative
388  for (unsigned int j = 0; j < n_hj; ++j)
389  fj_temp[j] = Fj_w[i * n_hj + j];
390  for (unsigned int j = 0; j < n_etas + n_grs; ++j)
391  {
392  notarealvector[0] = all_etas[j];
393  params = _factory.getValidParams("CoupledSwitchingTimeDerivative");
394  params.set<NonlinearVariableName>("variable") = w_names[i];
395  params.set<std::vector<VariableName>>("v") = notarealvector;
396  params.set<std::vector<VariableName>>("coupled_variables") = v0;
397  params.set<std::vector<MaterialPropertyName>>("Fj_names") = fj_temp;
398  params.set<std::vector<MaterialPropertyName>>("hj_names") = hj;
399  params.set<bool>("implicit") = implicity;
400  params.set<bool>("use_displaced_mesh") = displaced_mesh;
401  kernel_name = "Coupled_" + w_names[i] + "_" + all_etas[j];
402  _problem->addKernel("CoupledSwitchingTimeDerivative", kernel_name, params);
403  }
404  }
405  }
406 } // GrandPotentialKernelAction::act()
GrandPotentialKernelAction(const InputParameters &parameters)
registerMooseAction("PhaseFieldApp", GrandPotentialKernelAction, "add_kernel")
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
Factory & _factory
const InputParameters & parameters() const
T & set(const std::string &name, bool quiet_mode=false)
Generates the necessary kernels for the Grand Potential Function for any number of order parameters a...
InputParameters getValidParams(const std::string &name) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
static InputParameters validParams()
static InputParameters validParams()
std::string stringify(const T &t)
static const std::string kappa
Definition: NS.h:116
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::shared_ptr< FEProblemBase > & _problem
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
bool isParamValid(const std::string &name) const