LCOV - code coverage report
Current view: top level - src/kernels - KKSCHBulk.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 43 45 95.6 %
Date: 2025-09-04 07:55:36 Functions: 4 4 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 "KKSCHBulk.h"
      11             : 
      12             : registerMooseObject("PhaseFieldApp", KKSCHBulk);
      13             : 
      14             : InputParameters
      15          11 : KKSCHBulk::validParams()
      16             : {
      17          11 :   InputParameters params = CHBulk<Real>::validParams();
      18          11 :   params.addClassDescription("KKS model kernel for the Bulk Cahn-Hilliard term. This operates on "
      19             :                              "the concentration 'c' as the non-linear variable");
      20          22 :   params.addRequiredParam<MaterialPropertyName>("fa_name",
      21             :                                                 "Base name of the free energy function "
      22             :                                                 "F (f_name in the corresponding "
      23             :                                                 "derivative function material)");
      24          22 :   params.addRequiredParam<MaterialPropertyName>("fb_name",
      25             :                                                 "Base name of the free energy function "
      26             :                                                 "F (f_name in the corresponding "
      27             :                                                 "derivative function material)");
      28          22 :   params.addRequiredCoupledVar(
      29             :       "ca", "phase concentration corresponding to the non-linear variable of this kernel");
      30          22 :   params.addRequiredCoupledVar(
      31             :       "cb", "phase concentration corresponding to the non-linear variable of this kernel");
      32          22 :   params.addCoupledVar("args_a", "Vector of additional arguments to Fa");
      33          22 :   params.addParam<MaterialPropertyName>(
      34             :       "h_name", "h", "Base name for the switching function h(eta)"); // TODO: everywhere else this
      35             :                                                                      // is called just "h"
      36          11 :   return params;
      37           0 : }
      38             : 
      39           6 : KKSCHBulk::KKSCHBulk(const InputParameters & parameters)
      40             :   : CHBulk<Real>(parameters),
      41           6 :     _ca_var(coupled("ca")),
      42           6 :     _ca_name(coupledName("ca", 0)),
      43           6 :     _cb_var(coupled("cb")),
      44          12 :     _cb_name(coupledName("cb", 0)),
      45          12 :     _prop_h(getMaterialProperty<Real>("h_name")),
      46           6 :     _second_derivative_Fa(getMaterialPropertyDerivative<Real>("fa_name", _ca_name, _ca_name)),
      47          12 :     _second_derivative_Fb(getMaterialPropertyDerivative<Real>("fb_name", _cb_name, _cb_name))
      48             : {
      49             :   // reserve space for derivatives
      50           6 :   _second_derivatives.resize(_n_args);
      51           6 :   _third_derivatives.resize(_n_args);
      52           6 :   _third_derivatives_ca.resize(_n_args);
      53           6 :   _grad_args.resize(_n_args);
      54             : 
      55             :   // Iterate over all coupled variables
      56          18 :   for (unsigned int i = 0; i < _n_args; ++i)
      57             :   {
      58             : 
      59             :     // get the second derivative material property (TODO:warn)
      60          12 :     _second_derivatives[i] = &getMaterialPropertyDerivative<Real>("fa_name", _ca_name, i);
      61             : 
      62             :     // get the third derivative material properties
      63          12 :     _third_derivatives[i].resize(_n_args);
      64          36 :     for (unsigned int j = 0; j < _n_args; ++j)
      65          24 :       _third_derivatives[i][j] = &getMaterialPropertyDerivative<Real>("fa_name", _ca_name, i, j);
      66             : 
      67          12 :     MooseVariable * cvar = _coupled_standard_moose_vars[i];
      68             : 
      69             :     // third derivative for the on-diagonal jacobian
      70          12 :     _third_derivatives_ca[i] =
      71          12 :         &getMaterialPropertyDerivative<Real>("fa_name", _ca_name, _ca_name, cvar->name());
      72             : 
      73             :     // get the gradient
      74          12 :     _grad_args[i] = &(cvar->gradSln());
      75             :   }
      76           6 : }
      77             : 
      78             : /**
      79             :  * Note that per product and chain rules:
      80             :  * \f$ \frac{d}{du_j}\left(F(u)\nabla u\right) = \nabla u \frac {dF(u)}{du}\frac{du}{du_j} +
      81             :  * F(u)\frac{d\nabla u}{du_j} \f$
      82             :  * which is:
      83             :  * \f$ \nabla u \frac {dF(u)}{du} \phi_j + F(u) \nabla \phi_j \f$
      84             :  */
      85             : RealGradient
      86      185200 : KKSCHBulk::computeGradDFDCons(PFFunctionType type)
      87             : {
      88             :   RealGradient res = 0.0;
      89             : 
      90      185200 :   switch (type)
      91             :   {
      92             :     case Residual:
      93      363600 :       for (unsigned int i = 0; i < _n_args; ++i)
      94      242400 :         res += (*_second_derivatives[i])[_qp] * (*_grad_args[i])[_qp];
      95             : 
      96      121200 :       return res;
      97             : 
      98             :     case Jacobian:
      99             :       // the nonlinear variable is c, but the free energy only contains the
     100             :       // phase concentrations. Equation (23) in the KKS paper gives the chain-
     101             :       // rule derivative dca/dc
     102             :       /* Real dcadc = _second_derivative_Fb[_qp]
     103             :                   / (  (1.0 - _prop_h[_qp]) * _second_derivative_Fb[_qp]
     104             :                      + _prop_h[_qp]         * _second_derivative_Fa[_qp]); */
     105             :       // The (1-h)*X_b, h*X_a pairing is opposite to what the KKSPhaseConcentration kernel does!
     106             : 
     107             :       res = _second_derivative_Fa[_qp] * _grad_phi[_j][_qp];
     108             : 
     109      192000 :       for (unsigned int i = 0; i < _n_args; ++i)
     110             :         res += (*_third_derivatives_ca[i])[_qp] * (*_grad_args[i])[_qp] * _phi[_j][_qp];
     111             : 
     112             :       // convergence improves if we return 0.0 here
     113             :       return 0.0; // res * dcadc;
     114             :   }
     115             : 
     116           0 :   mooseError("Invalid type passed in");
     117             : }
     118             : 
     119             : Real
     120     2048000 : KKSCHBulk::computeQpOffDiagJacobian(unsigned int jvar)
     121             : {
     122             :   // get the coupled variable jvar is referring to
     123             :   const unsigned int cvar = mapJvarToCvar(jvar);
     124             : 
     125     2048000 :   RealGradient res = (*_second_derivatives[cvar])[_qp] * _grad_phi[_j][_qp];
     126             : 
     127     6144000 :   for (unsigned int i = 0; i < _n_args; ++i)
     128     4096000 :     res += (*_third_derivatives[i][cvar])[_qp] * (*_grad_args[i])[_qp] * _phi[_j][_qp];
     129             : 
     130             :   // keeping this term seems to improve the solution.
     131     2048000 :   return res * _grad_test[_i][_qp];
     132             : }

Generated by: LCOV version 1.14