LCOV - code coverage report
Current view: top level - src/materials - KKSPhaseConcentrationMultiPhaseDerivatives.C (source / functions) Hit Total Coverage
Test: idaholab/moose phase_field: #31405 (292dce) with base fef103 Lines: 86 87 98.9 %
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 "KKSPhaseConcentrationMultiPhaseDerivatives.h"
      11             : #include "MatrixTools.h"
      12             : 
      13             : registerMooseObject("PhaseFieldApp", KKSPhaseConcentrationMultiPhaseDerivatives);
      14             : 
      15             : InputParameters
      16          94 : KKSPhaseConcentrationMultiPhaseDerivatives::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 for the chain rule in the KKS kernels. This class is intended to "
      22             :       "be used with KKSPhaseConcentrationMultiPhaseMaterial.");
      23         188 :   params.addRequiredCoupledVar("global_cs", "The interpolated concentrations c, b, etc");
      24         188 :   params.addRequiredCoupledVar("all_etas", "Order parameters.");
      25         188 :   params.addRequiredParam<std::vector<MaterialPropertyName>>(
      26             :       "ci_names",
      27             :       "Phase concentrations. They must have the same order as Fj_names and global_cs, for "
      28             :       "example, c1, c2, b1, b2.");
      29         188 :   params.addRequiredParam<std::vector<MaterialName>>(
      30             :       "Fj_names", "Free energy material objects in the same order as all_etas.");
      31         188 :   params.addRequiredParam<std::vector<MaterialPropertyName>>(
      32             :       "hj_names", "witching functions in the same order as all_etas.");
      33          94 :   return params;
      34           0 : }
      35             : 
      36          72 : KKSPhaseConcentrationMultiPhaseDerivatives::KKSPhaseConcentrationMultiPhaseDerivatives(
      37          72 :     const InputParameters & parameters)
      38             :   : DerivativeMaterialInterface<Material>(parameters),
      39          72 :     _num_c(coupledComponents("global_cs")),
      40          72 :     _c_names(coupledNames("global_cs")),
      41          72 :     _eta_names(coupledNames("all_etas")),
      42          72 :     _num_j(coupledComponents("all_etas")),
      43          72 :     _prop_ci(_num_c * _num_j),
      44         144 :     _ci_names(getParam<std::vector<MaterialPropertyName>>("ci_names")),
      45          72 :     _dcidetaj(_num_c),
      46          72 :     _dcidb(_num_c),
      47         144 :     _Fj_names(getParam<std::vector<MaterialName>>("Fj_names")),
      48          72 :     _d2Fidcidbi(_num_j),
      49         144 :     _hj_names(getParam<std::vector<MaterialPropertyName>>("hj_names")),
      50          72 :     _prop_hj(_num_j),
      51         144 :     _dhjdetai(_num_j)
      52             : 
      53             : {
      54         288 :   for (const auto m : make_range(_num_c * _num_j))
      55         216 :     _prop_ci[m] = &getMaterialPropertyByName<Real>(_ci_names[m]);
      56             : 
      57         144 :   for (const auto m : make_range(_num_c))
      58             :   {
      59          72 :     _dcidb[m].resize(_num_j);
      60          72 :     _dcidetaj[m].resize(_num_j);
      61             : 
      62         288 :     for (const auto n : make_range(_num_j))
      63             :     {
      64         216 :       _dcidb[m][n].resize(_num_c);
      65         216 :       _dcidetaj[m][n].resize(_num_j);
      66             : 
      67             :       // Derivative of phase concentration wrt global concentration. In _dcidb[m][n][l], m is the
      68             :       // species index of ci, n is the phase index of ci, and l is the species index of b
      69         432 :       for (const auto l : make_range(_num_c))
      70         216 :         _dcidb[m][n][l] = &declarePropertyDerivative<Real>(_ci_names[n + m * _num_j], _c_names[l]);
      71             : 
      72             :       // Derivative of phase concentration wrt eta. In _dcidetaj[m][n][l], m is the species index
      73             :       // of ci, n is the phase index of ci, and l is the phase of etaj
      74         864 :       for (const auto l : make_range(_num_j))
      75         648 :         _dcidetaj[m][n][l] =
      76        1296 :             &declarePropertyDerivative<Real>(_ci_names[n + m * _num_j], _eta_names[l]);
      77             :     }
      78             :   }
      79             : 
      80             :   // Second derivative of free energy wrt phase concentrations for use in this material. In
      81             :   // _d2Fidcidbi[m][n][l], m is phase index of Fi, n is the species index of ci, l is the species
      82             :   // index of bi.
      83         288 :   for (const auto m : make_range(_num_j))
      84             :   {
      85         216 :     _d2Fidcidbi[m].resize(_num_c);
      86             : 
      87         432 :     for (const auto n : make_range(_num_c))
      88             :     {
      89         216 :       _d2Fidcidbi[m][n].resize(_num_c);
      90             : 
      91         432 :       for (const auto l : make_range(_num_c))
      92         216 :         _d2Fidcidbi[m][n][l] = &getMaterialPropertyDerivative<Real>(
      93         216 :             _Fj_names[m], _ci_names[m + n * _num_j], _ci_names[m + l * _num_j]);
      94             :     }
      95             :   }
      96             : 
      97         288 :   for (const auto m : make_range(_num_j))
      98             :   {
      99         216 :     _prop_hj[m] = &getMaterialPropertyByName<Real>(_hj_names[m]);
     100             : 
     101         216 :     _dhjdetai[m].resize(_num_j);
     102             : 
     103         864 :     for (const auto n : make_range(_num_j))
     104         648 :       _dhjdetai[m][n] = &getMaterialPropertyDerivative<Real>(_hj_names[m], _eta_names[n]);
     105             :   }
     106          72 : }
     107             : 
     108             : void
     109     2454400 : KKSPhaseConcentrationMultiPhaseDerivatives::computeQpProperties()
     110             : {
     111             :   // declare Jacobian matrix A
     112     2454400 :   Eigen::MatrixXd A(_num_c * _num_j, _num_c * _num_j);
     113             : 
     114             :   // initialize all elements in A to be zero
     115             :   A.setZero();
     116             : 
     117             :   // fill in the non-zero elements in A
     118     4908800 :   for (const auto m : make_range(_num_c))
     119             :   {
     120             :     // equal chemical potential derivative equations
     121     7363200 :     for (const auto n : make_range(_num_j - 1))
     122             :     {
     123     9817600 :       for (const auto l : make_range(_num_c))
     124             :       {
     125     4908800 :         A(m * _num_j + n, n + l * _num_j) = (*_d2Fidcidbi[n][m][l])[_qp];
     126     4908800 :         A(m * _num_j + n, n + l * _num_j + 1) = -(*_d2Fidcidbi[n + 1][m][l])[_qp];
     127             :       }
     128             :     }
     129             : 
     130             :     // concentration conservation derivative equations
     131     9817600 :     for (const auto n : make_range(_num_j))
     132     7363200 :       A((m + 1) * _num_j - 1, m * _num_j + n) = (*_prop_hj[n])[_qp];
     133             :   }
     134             : 
     135     2454400 :   A = A.inverse();
     136             : 
     137             :   // solve linear system of constraint derivatives wrt b for computing dcidb loop through
     138             :   // derivatives wrt the ith component; they have the same A, but different k_c
     139     4908800 :   for (const auto i : make_range(_num_c))
     140             :   {
     141     2454400 :     std::vector<Real> k_c(_num_j * _num_c);
     142     2454400 :     std::vector<Real> x_c(_num_j * _num_c);
     143             : 
     144             :     // assign non-zero elements in k_c
     145     2454400 :     k_c[i * _num_j + _num_j - 1] = 1;
     146             : 
     147             :     // compute x_c
     148     9817600 :     for (const auto m : make_range(_num_j * _num_c))
     149             :     {
     150    29452800 :       for (const auto n : make_range(_num_j * _num_c))
     151    22089600 :         x_c[m] += A(m, n) * k_c[n];
     152             :     }
     153             : 
     154             :     // assign the values in x_c to _dcidb
     155     4908800 :     for (const auto m : make_range(_num_c))
     156             :     {
     157     9817600 :       for (const auto n : make_range(_num_j))
     158     7363200 :         (*_dcidb[m][n][i])[_qp] = x_c[m * _num_j + n];
     159             :     }
     160     2454400 :   }
     161             : 
     162             :   // solve linear system of constraint derivatives wrt eta for computing dcidetaj use the same
     163             :   // linear matrix as computing dcidb
     164     9817600 :   for (const auto i : make_range(_num_j))
     165             :   {
     166     7363200 :     std::vector<Real> k_eta(_num_j * _num_c);
     167     7363200 :     std::vector<Real> x_eta(_num_j * _num_c);
     168             : 
     169             :     // assign non-zero elements in k_eta
     170    14726400 :     for (const auto m : make_range(_num_c))
     171             :     {
     172             :       Real sum = 0.0;
     173             : 
     174    29452800 :       for (const auto n : make_range(_num_j))
     175    22089600 :         sum += (*_dhjdetai[n][i])[_qp] * (*_prop_ci[m * _num_j + n])[_qp];
     176             : 
     177     7363200 :       k_eta[m * _num_j + _num_j - 1] = -sum;
     178             :     }
     179             : 
     180             :     // compute x_eta
     181    29452800 :     for (const auto m : make_range(_num_j * _num_c))
     182             :     {
     183    88358400 :       for (const auto n : make_range(_num_j * _num_c))
     184    66268800 :         x_eta[m] += A(m, n) * k_eta[n];
     185             :     }
     186             : 
     187             :     // assign the values in x_eta to _dcidetaj
     188    14726400 :     for (const auto m : make_range(_num_c))
     189             :     {
     190    29452800 :       for (const auto n : make_range(_num_j))
     191    22089600 :         (*_dcidetaj[m][n][i])[_qp] = x_eta[m * _num_j + n];
     192             :     }
     193     7363200 :   }
     194     2454400 : }

Generated by: LCOV version 1.14