LCOV - code coverage report
Current view: top level - src/materials - KKSPhaseConcentrationDerivatives.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 77 78 98.7 %
Date: 2025-09-04 07:55:36 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 "KKSPhaseConcentrationDerivatives.h"
      11             : #include "MatrixTools.h"
      12             : 
      13             : registerMooseObject("PhaseFieldApp", KKSPhaseConcentrationDerivatives);
      14             : 
      15             : InputParameters
      16          94 : KKSPhaseConcentrationDerivatives::validParams()
      17             : {
      18          94 :   InputParameters params = DerivativeMaterialInterface<Material>::validParams();
      19          94 :   params.addClassDescription(
      20             :       "Computes the KKS phase concentration derivatives wrt global concentrations and order "
      21             :       "parameters, which are used in the chain rules in the KKS kernels. This class is intended to "
      22             :       "be used with KKSPhaseConcentrationMaterial.");
      23         188 :   params.addRequiredCoupledVar("global_cs", "The interpolated concentrations c, b, etc");
      24         188 :   params.addRequiredCoupledVar("eta", "Order parameter.");
      25         188 :   params.addRequiredParam<std::vector<MaterialPropertyName>>(
      26             :       "ci_names",
      27             :       "Phase concentrations. The order must match Fa, Fb, and global_cs, for example, c1, "
      28             :       "c2, b1, b2, etc");
      29         188 :   params.addRequiredParam<MaterialName>("fa_name", "Fa material object.");
      30         188 :   params.addRequiredParam<MaterialName>("fb_name", "Fb material object.");
      31         188 :   params.addParam<MaterialPropertyName>("h_name", "h", "Switching function h(eta).");
      32          94 :   return params;
      33           0 : }
      34             : 
      35          72 : KKSPhaseConcentrationDerivatives::KKSPhaseConcentrationDerivatives(
      36          72 :     const InputParameters & parameters)
      37             :   : DerivativeMaterialInterface<Material>(parameters),
      38          72 :     _num_c(coupledComponents("global_cs")),
      39          72 :     _c_names(coupledNames("global_cs")),
      40          72 :     _eta_name(getVar("eta", 0)->name()),
      41         144 :     _ci_names(getParam<std::vector<MaterialPropertyName>>("ci_names")),
      42          72 :     _prop_ci(_num_c * 2),
      43          72 :     _dcidb(_num_c),
      44          72 :     _dcideta(_num_c),
      45          72 :     _Fa_name(getParam<MaterialName>("fa_name")),
      46          72 :     _Fb_name(getParam<MaterialName>("fb_name")),
      47          72 :     _d2Fidcidbi(2),
      48         144 :     _prop_h(getMaterialProperty<Real>("h_name")),
      49         144 :     _prop_dh(getMaterialPropertyDerivative<Real>("h_name", _eta_name))
      50             : {
      51         216 :   for (const auto m : make_range(_num_c * 2))
      52         144 :     _prop_ci[m] = &getMaterialPropertyByName<Real>(_ci_names[m]);
      53             : 
      54         144 :   for (const auto m : make_range(_num_c))
      55             :   {
      56          72 :     _dcideta[m].resize(2);
      57          72 :     _dcidb[m].resize(2);
      58         216 :     for (const auto n : make_range(2))
      59             :     {
      60             :       // Derivative of phase concentration wrt eta. In _dcideta[m][n], m is the species index of
      61             :       // ci, n is the phase index of ci
      62         144 :       _dcideta[m][n] = &declarePropertyDerivative<Real>(_ci_names[m * 2 + n], _eta_name);
      63         144 :       _dcidb[m][n].resize(_num_c);
      64             : 
      65             :       // Derivative of phase concentration wrt global concentration. In _dcidb[m][n][l], m is the
      66             :       //  species index of ci, n is the phase index of ci, l is the species index of b
      67         288 :       for (const auto l : make_range(_num_c))
      68         144 :         _dcidb[m][n][l] = &declarePropertyDerivative<Real>(_ci_names[m * 2 + n], _c_names[l]);
      69             :     }
      70             :   }
      71             : 
      72             :   /** Second derivative of free energy wrt phase concentrations for use in this material. In
      73             :       _d2Fidcidbi[m][n][l], m is phase index of Fi, n is the species index of ci, l is the species
      74             :       index of bi.
      75             :   */
      76         216 :   for (const auto m : make_range(2))
      77             :   {
      78         144 :     _d2Fidcidbi[m].resize(_num_c);
      79         288 :     for (const auto n : make_range(_num_c))
      80             :     {
      81         144 :       _d2Fidcidbi[m][n].resize(_num_c);
      82         288 :       for (const auto l : make_range(_num_c))
      83             :       {
      84         144 :         if (m == 0)
      85          72 :           _d2Fidcidbi[0][n][l] =
      86         144 :               &getMaterialPropertyDerivative<Real>(_Fa_name, _ci_names[n * 2], _ci_names[l * 2]);
      87             : 
      88             :         else
      89          72 :           _d2Fidcidbi[1][n][l] = &getMaterialPropertyDerivative<Real>(
      90          72 :               _Fb_name, _ci_names[n * 2 + 1], _ci_names[l * 2 + 1]);
      91             :       }
      92             :     }
      93             :   }
      94          72 : }
      95             : 
      96             : void
      97     1884600 : KKSPhaseConcentrationDerivatives::computeQpProperties()
      98             : {
      99             :   // declare Jacobian matrix A
     100     1884600 :   Eigen::MatrixXd A(_num_c * 2, _num_c * 2);
     101             : 
     102             :   A.setZero();
     103             : 
     104             :   // fill in the non-zero elements in A
     105     3769200 :   for (const auto m : make_range(_num_c))
     106             :   {
     107     3769200 :     for (const auto n : make_range(_num_c))
     108             :     {
     109             :       // equal chemical potential derivative equations
     110     1884600 :       A(m * 2, n * 2) = (*_d2Fidcidbi[0][m][n])[_qp];
     111     1884600 :       A(m * 2, n * 2 + 1) = -(*_d2Fidcidbi[1][m][n])[_qp];
     112             :     }
     113             : 
     114             :     // concentration conservation derivative equations
     115     1884600 :     A(m * 2 + 1, m * 2) = 1 - _prop_h[_qp];
     116     1884600 :     A(m * 2 + 1, m * 2 + 1) = _prop_h[_qp];
     117             :   }
     118             : 
     119     1884600 :   A = A.inverse();
     120             : 
     121             :   // solve linear system of constraint derivatives wrt b for computing dcidb loop through
     122             :   // derivatives wrt the ith component; they have the same A, but different k_c
     123     3769200 :   for (const auto i : make_range(_num_c))
     124             :   {
     125     1884600 :     std::vector<Real> k_c(_num_c * 2);
     126     1884600 :     std::vector<Real> x_c(_num_c * 2);
     127             : 
     128             :     // assign the non-zero elements in k_c
     129     1884600 :     k_c[i * 2 + 1] = 1;
     130             : 
     131             :     // compute x_c
     132     5653800 :     for (const auto m : make_range(_num_c * 2))
     133             :     {
     134    11307600 :       for (const auto n : make_range(_num_c * 2))
     135     7538400 :         x_c[m] += A(m, n) * k_c[n];
     136             :     }
     137             : 
     138             :     // assign the values in x_c to _dcidb
     139     3769200 :     for (const auto m : make_range(_num_c))
     140             :     {
     141     5653800 :       for (const auto n : make_range(2))
     142     3769200 :         (*_dcidb[m][n][i])[_qp] = x_c[m * 2 + n];
     143             :     }
     144     1884600 :   }
     145             : 
     146             :   // solve linear system of constraint derivatives wrt eta for computing dcideta use the same
     147             :   // linear matrix as computing dcidb
     148     1884600 :   std::vector<Real> k_eta(_num_c * 2);
     149     1884600 :   std::vector<Real> x_eta(_num_c * 2);
     150             : 
     151             :   // fill in k_eta
     152     3769200 :   for (const auto m : make_range(_num_c))
     153             :   {
     154     1884600 :     k_eta[m * 2] = 0;
     155     1884600 :     k_eta[m * 2 + 1] = _prop_dh[_qp] * ((*_prop_ci[m * 2])[_qp] - (*_prop_ci[m * 2 + 1])[_qp]);
     156             :   }
     157             : 
     158             :   // compute x_eta
     159     5653800 :   for (const auto m : make_range(_num_c * 2))
     160             :   {
     161    11307600 :     for (const auto n : make_range(_num_c * 2))
     162     7538400 :       x_eta[m] += A(m, n) * k_eta[n];
     163             :   }
     164             : 
     165             :   // assign the values in x_eta to _dcideta
     166     3769200 :   for (const auto m : make_range(_num_c))
     167             :   {
     168     5653800 :     for (const auto n : make_range(2))
     169     3769200 :       (*_dcideta[m][n])[_qp] = x_eta[m * 2 + n];
     170             :   }
     171     1884600 : }

Generated by: LCOV version 1.14