LCOV - code coverage report
Current view: top level - src/materials - LAROMANCEPartitionStressUpdateBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 97 110 88.2 %
Date: 2025-07-25 05:00:39 Functions: 7 14 50.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 "LAROMANCEPartitionStressUpdateBase.h"
      11             : 
      12             : #include <libmesh/dense_matrix.h> // libMesh::cholesky_solve
      13             : 
      14             : registerMooseObjectAliased("SolidMechanicsApp",
      15             :                            LAROMANCEPartitionStressUpdateBase,
      16             :                            "LAROMANCEPartitionStressUpdate");
      17             : registerMooseObjectAliased("SolidMechanicsApp",
      18             :                            ADLAROMANCEPartitionStressUpdateBase,
      19             :                            "ADLAROMANCEPartitionStressUpdate");
      20             : 
      21             : template <bool is_ad>
      22             : InputParameters
      23         144 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::validParams()
      24             : {
      25         144 :   InputParameters params = LAROMANCEStressUpdateBaseTempl<is_ad>::validParams();
      26         144 :   params.addClassDescription("LAROMANCE base class for partitioned reduced order models");
      27         432 :   params.addRangeCheckedParam<Real>(
      28             :       "finite_difference_width",
      29         288 :       1.0e-2,
      30             :       "finite_difference_width > 0",
      31             :       "Factor multiplied against the input stress to compute the finite "
      32             :       "difference derivative of the parition weights.");
      33             : 
      34         144 :   return params;
      35           0 : }
      36             : 
      37             : template <bool is_ad>
      38         108 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::LAROMANCEPartitionStressUpdateBaseTempl(
      39             :     const InputParameters & parameters)
      40             :   : LAROMANCEStressUpdateBaseTempl<is_ad>(parameters),
      41         216 :     _finite_difference_width(this->template getParam<Real>("finite_difference_width"))
      42             : {
      43         108 : }
      44             : 
      45             : template <bool is_ad>
      46             : void
      47         108 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::initialSetup()
      48             : {
      49         108 :   LAROMANCEStressUpdateBaseTempl<is_ad>::initialSetup();
      50         108 :   _partition_Mmean = getClassificationMmean();
      51         108 :   _partition_Mscale = getClassificationMscale();
      52         108 :   _partition_Xu = getClassificationXu();
      53         108 :   _partition_Ell = getClassificationEll();
      54         108 :   _partition_Eta = getClassificationEta();
      55         108 :   _partition_Luu = getClassificationLuu();
      56         108 :   _partition_Vind = getClassificationVind();
      57         108 :   _partition_difference.resize(_partition_Xu[0].size(),
      58         108 :                                std::vector<GenericReal<is_ad>>(_partition_Xu.size()));
      59         108 :   _partition_distance.resize(_partition_difference.size());
      60         108 :   _partition_covariance.resize(_partition_distance.size());
      61         108 :   _partition_b.resize(_partition_covariance.size());
      62         108 :   _partition_A.resize(_partition_Luu[0].size(), _partition_Luu.size());
      63         108 : }
      64             : 
      65             : template <bool is_ad>
      66             : void
      67          18 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::exportJSON()
      68             : {
      69          18 :   LAROMANCEStressUpdateBaseTempl<is_ad>::exportJSON();
      70             : 
      71          18 :   this->_json["m_mean"] = getClassificationMmean();
      72          18 :   this->_json["m_scale"] = getClassificationMscale();
      73          36 :   this->_json["xu"] = getClassificationXu();
      74          36 :   this->_json["ell"] = getClassificationEll();
      75          36 :   this->_json["eta"] = getClassificationEta();
      76          36 :   this->_json["luu"] = getClassificationLuu();
      77          18 :   this->_json["vind"] = getClassificationVind().get_values();
      78          18 : }
      79             : 
      80             : template <bool is_ad>
      81             : void
      82       13616 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::computePartitionWeights(
      83             :     std::vector<GenericReal<is_ad>> & weights, std::vector<GenericReal<is_ad>> & dweights_dstress)
      84             : {
      85       13616 :   std::vector<bool> in_partition(_num_partitions, false);
      86       13616 :   unsigned int num_partitions_active = 0;
      87       40848 :   for (unsigned int p = 0; p < _num_partitions; ++p)
      88             :   {
      89      122544 :     for (unsigned int t = 0; t < this->_num_tiles[p]; ++t)
      90       95312 :       if (!in_partition[p] && this->checkInTile(p, t))
      91             :         in_partition[p] = true;
      92             : 
      93       27232 :     num_partitions_active += in_partition[p];
      94             :   }
      95             :   mooseAssert(num_partitions_active <= _num_partitions,
      96             :               "Number of paritions active must be less than total number of paritions");
      97       13616 :   if (!num_partitions_active)
      98           0 :     mooseException("Number of active partitions (",
      99             :                    num_partitions_active,
     100             :                    ") out of total number of partitions (",
     101             :                    _num_partitions,
     102             :                    ") is zero. This may be because you are trying to sample outside the total "
     103             :                    "applicability of the model");
     104             : 
     105       13616 :   if (_num_partitions == 1) // If only one parition present, all weights are one
     106             :   {
     107           0 :     weights[0] = 1.0;
     108           0 :     dweights_dstress[0] = 0.0;
     109             :   }
     110       13616 :   else if (_num_partitions == 2)
     111             :   {
     112       13616 :     if (num_partitions_active == 1) // If only present in one partition, math is easy
     113             :     {
     114           0 :       std::fill(dweights_dstress.begin(), dweights_dstress.end(), 0.0);
     115             : 
     116           0 :       if (in_partition[0])
     117           0 :         weights[1] = 0.0;
     118           0 :       else if (in_partition[1])
     119           0 :         weights[1] = 1.0;
     120             :       else
     121           0 :         mooseError("Internal error: Parition weight calculation incorrect when only one "
     122             :                    "partition is applicable");
     123             :     }
     124       13616 :     else if (num_partitions_active == 2) // If present in two partitions, compute weights
     125             :     {
     126       13616 :       weights[1] = computeSecondPartitionWeight();
     127       13616 :       computeDSecondPartitionWeightDStress(dweights_dstress[1]);
     128       13616 :       dweights_dstress[0] = -dweights_dstress[1];
     129             :     }
     130       13616 :     weights[0] = 1.0 - weights[1];
     131             :   }
     132             :   else
     133           0 :     mooseError("Internal error: number of partitions can only be 1 or 2");
     134             : 
     135       13616 :   if (_num_partitions == 2)
     136       13616 :     _second_partition_weight[_qp] = this->_partition_weights[1];
     137             :   else
     138           0 :     _second_partition_weight[_qp] = 0.0;
     139             : 
     140             :   // Given the weight, compute the sigmoid transformed value to smoothly transition
     141       40848 :   for (unsigned int p = 0; p < _num_partitions; ++p)
     142             :   {
     143       27232 :     weights[p] = (1.0 - sigmoid(0.0, 1.0, weights[p]));
     144       27232 :     dweights_dstress[p] *= -sigmoid(0.0, 1.0, weights[p], true);
     145             :   }
     146       13616 : }
     147             : 
     148             : template <bool is_ad>
     149             : GenericReal<is_ad>
     150       27232 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::computeSecondPartitionWeight()
     151             : {
     152             :   // extract and scale only the relevant inputs on which the GPR was trained (ignore
     153             :   // _old_strain_input_index)
     154       27232 :   std::vector<GenericReal<is_ad>> scaled_input_values(_num_inputs - 1);
     155             :   unsigned int inc = 0;
     156      163392 :   for (const auto i : index_range(_input_values))
     157             :   {
     158      136160 :     if (i != _old_strain_input_index)
     159             :     {
     160      108928 :       scaled_input_values[inc] =
     161      108928 :           (_input_values[i] - _partition_Mmean[inc]) / _partition_Mscale[inc];
     162      108928 :       inc++;
     163             :     }
     164             :   }
     165             : 
     166             :   // compute the distance of the new point to ALL training points and sum the distance over all
     167             :   // input variables first compute difference between points.
     168             :   // for-loop to compute difference
     169      136160 :   for (const auto i : index_range(_partition_Xu))
     170     5555328 :     for (const auto j : index_range(_partition_Xu[0]))
     171     5446400 :       _partition_difference[j][i] =
     172     5446400 :           Utility::pow<2>((_partition_Xu[i][j] - scaled_input_values[i]) / _partition_Ell);
     173             : 
     174             :   // sum difference over input dimension and take square root
     175           0 :   std::fill(_partition_distance.begin(), _partition_distance.end(), 0.0);
     176     1388832 :   for (const auto i : index_range(_partition_difference))
     177             :   {
     178     6808000 :     for (const auto j : index_range(_partition_difference[0]))
     179     5446400 :       _partition_distance[i] += _partition_difference[i][j];
     180     1361600 :     _partition_distance[i] = std::sqrt(_partition_distance[i]);
     181             :   }
     182             : 
     183             :   // compute the covariance wrt ALL training points: the larger the distance, the smaller the
     184             :   // covariance
     185     1388832 :   for (const auto i : index_range(_partition_covariance))
     186     1361600 :     _partition_covariance[i] =
     187     1361600 :         Utility::pow<2>(_partition_Eta) * std::exp(-0.5 * _partition_distance[i]);
     188             : 
     189             :   // solve the system of equations: convert covariance to libMesh::DenseVector
     190     1388832 :   for (const auto i : index_range(_partition_covariance))
     191     1361600 :     _partition_b(i) = _partition_covariance[i];
     192             : 
     193             :   // convert Luu to libMesh::DenseMatrix, first fill values of A with Luu-values
     194     1388832 :   for (const auto i : index_range(_partition_Luu[0]))
     195    69441600 :     for (const auto j : index_range(_partition_Luu))
     196    68080000 :       _partition_A(i, j) = _partition_Luu[j][i];
     197             : 
     198             :   // solve the linear system of equations (lu_solve)
     199       27232 :   DenseVector<GenericReal<is_ad>> ma(_partition_b.size());
     200       27232 :   _partition_A.lu_solve(_partition_b, ma);
     201             : 
     202             :   // induce full array through sparse grid and summarize into mu
     203       27232 :   GenericReal<is_ad> partition_weight = 0.0;
     204     1388832 :   for (const auto i : index_range(ma))
     205     1361600 :     partition_weight += ma(i) * _partition_Vind(i);
     206             : 
     207             :   // scale mu between 0 and 1: the weight of partition 2
     208       27232 :   partition_weight = -partition_weight + 1.0;
     209       27232 :   partition_weight = std::min(partition_weight, 1.0);
     210       28008 :   partition_weight = std::max(partition_weight, 0.0);
     211       27232 :   return partition_weight;
     212             : }
     213             : 
     214             : template <bool is_ad>
     215             : void
     216       13616 : LAROMANCEPartitionStressUpdateBaseTempl<is_ad>::computeDSecondPartitionWeightDStress(
     217             :     GenericReal<is_ad> & dsecond_partition_weight_dstress)
     218             : {
     219       13616 :   const auto fd_tol =
     220       13616 :       _input_values[_stress_input_index] * _finite_difference_width; // Finite difference width
     221       13616 :   _input_values[_stress_input_index] += fd_tol;
     222       13616 :   dsecond_partition_weight_dstress =
     223       13616 :       (computeSecondPartitionWeight() - _second_partition_weight[_qp]) / fd_tol;
     224       13616 :   _input_values[_stress_input_index] -= fd_tol;
     225       13616 : }
     226             : 
     227             : template class LAROMANCEPartitionStressUpdateBaseTempl<false>;
     228             : template class LAROMANCEPartitionStressUpdateBaseTempl<true>;

Generated by: LCOV version 1.14