LCOV - code coverage report
Current view: top level - src/actions - GrandPotentialKernelAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #32971 (54bef8) with base c6cf66 Lines: 230 236 97.5 %
Date: 2026-05-29 20:38:39 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          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()

Generated by: LCOV version 1.14