LCOV - code coverage report
Current view: top level - src/functions - ParameterMeshFunction.C (source / functions) Hit Total Coverage
Test: idaholab/moose optimization: #31730 (e8b711) with base e0c998 Lines: 77 90 85.6 %
Date: 2025-10-29 16:52:42 Functions: 7 8 87.5 %
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 "ParameterMeshFunction.h"
      11             : 
      12             : #include "AddVariableAction.h"
      13             : 
      14             : registerMooseObject("OptimizationApp", ParameterMeshFunction);
      15             : 
      16             : InputParameters
      17         680 : ParameterMeshFunction::validParams()
      18             : {
      19         680 :   InputParameters params = OptimizationFunction::validParams();
      20         680 :   params.addClassDescription("Optimization function with parameters represented by a mesh and "
      21             :                              "finite-element shape functions.");
      22             : 
      23        1360 :   params.addRequiredParam<FileName>("exodus_mesh", "File containing parameter mesh.");
      24        1360 :   params.addParam<MooseEnum>("family",
      25        1360 :                              AddVariableAction::getNonlinearVariableFamilies(),
      26             :                              "Family of FE shape functions for parameter.");
      27        1360 :   params.addParam<MooseEnum>("order",
      28        1360 :                              AddVariableAction::getNonlinearVariableOrders(),
      29             :                              "Order of FE shape functions for parameter.");
      30             : 
      31        1360 :   params.addRequiredParam<ReporterName>(
      32             :       "parameter_name", "Reporter or VectorPostprocessor vector containing parameter values.");
      33        1360 :   params.addParam<ReporterName>("time_name",
      34             :                                 "Name of vector-postprocessor or reporter vector containing time, "
      35             :                                 "default assumes time independence.");
      36        1360 :   params.addParam<bool>(
      37        1360 :       "project_points", false, "Whether to find the closest point on parameter mesh.");
      38        1360 :   params.addParam<unsigned int>(
      39             :       "kdtree_candidates",
      40        1360 :       5,
      41             :       "Number of nearest node candidates to consider when projecting points to parameter mesh.");
      42             : 
      43         680 :   return params;
      44           0 : }
      45             : 
      46         356 : ParameterMeshFunction::ParameterMeshFunction(const InputParameters & parameters)
      47             :   : OptimizationFunction(parameters),
      48             :     ReporterInterface(this),
      49         356 :     _parameter_mesh(AddVariableAction::feType(parameters),
      50         354 :                     getParam<FileName>("exodus_mesh"),
      51        1066 :                     getParam<bool>("project_points"),
      52         710 :                     getParam<unsigned int>("kdtree_candidates")),
      53         354 :     _values(getReporterValue<std::vector<Real>>("parameter_name")),
      54         730 :     _coordt(isParamValid("time_name") ? getReporterValue<std::vector<Real>>("time_name")
      55         356 :                                       : _empty_vec)
      56             : {
      57         354 : }
      58             : 
      59             : Real
      60    11405013 : ParameterMeshFunction::value(Real t, const Point & p) const
      61             : {
      62    11405013 :   checkSize();
      63             : 
      64    11405011 :   const auto ti = interpolateTime(t);
      65    11405011 :   const dof_id_type offset0 = ti[0].first * _parameter_mesh.size();
      66    11405011 :   const dof_id_type offset1 = ti[1].first * _parameter_mesh.size();
      67             : 
      68             :   std::vector<dof_id_type> dof_indices;
      69             :   std::vector<Real> weights;
      70             : 
      71    11405011 :   _parameter_mesh.getIndexAndWeight(p, dof_indices, weights);
      72             : 
      73             :   Real val = 0;
      74    57560360 :   for (const auto & i : index_range(dof_indices))
      75    46155349 :     val += (_values[dof_indices[i] + offset0] * ti[0].second +
      76    46155349 :             _values[dof_indices[i] + offset1] * ti[1].second) *
      77             :            weights[i];
      78    11405011 :   return val;
      79    11405011 : }
      80             : 
      81             : RealGradient
      82       16200 : ParameterMeshFunction::gradient(Real t, const Point & p) const
      83             : {
      84       16200 :   checkSize();
      85             : 
      86       16200 :   const auto ti = interpolateTime(t);
      87       16200 :   const dof_id_type offset0 = ti[0].first * _parameter_mesh.size();
      88       16200 :   const dof_id_type offset1 = ti[1].first * _parameter_mesh.size();
      89             : 
      90             :   std::vector<dof_id_type> dof_indices;
      91             :   std::vector<RealGradient> weights;
      92       16200 :   _parameter_mesh.getIndexAndWeight(p, dof_indices, weights);
      93             : 
      94             :   RealGradient val(0, 0, 0);
      95       84600 :   for (const auto & i : index_range(dof_indices))
      96       68400 :     val += (_values[dof_indices[i] + offset0] * ti[0].second +
      97       68400 :             _values[dof_indices[i] + offset1] * ti[1].second) *
      98             :            weights[i];
      99       16200 :   return val;
     100       16200 : }
     101             : 
     102             : Real
     103           0 : ParameterMeshFunction::timeDerivative(Real t, const Point & p) const
     104             : {
     105           0 :   checkSize();
     106             : 
     107           0 :   const auto ti = interpolateTime(t, true);
     108           0 :   if (ti[0].first == ti[1].first)
     109             :     return 0.0;
     110           0 :   const dof_id_type offset0 = ti[0].first * _parameter_mesh.size();
     111           0 :   const dof_id_type offset1 = ti[1].first * _parameter_mesh.size();
     112             : 
     113             :   std::vector<dof_id_type> dof_indices;
     114             :   std::vector<Real> weights;
     115           0 :   _parameter_mesh.getIndexAndWeight(p, dof_indices, weights);
     116             : 
     117             :   Real val = 0;
     118           0 :   for (const auto & i : index_range(dof_indices))
     119           0 :     val += (_values[dof_indices[i] + offset0] * ti[0].second +
     120           0 :             _values[dof_indices[i] + offset1] * ti[1].second) *
     121             :            weights[i];
     122             :   return val;
     123           0 : }
     124             : 
     125             : std::vector<Real>
     126     1569401 : ParameterMeshFunction::parameterGradient(Real t, const Point & p) const
     127             : {
     128     1569401 :   const auto ti = interpolateTime(t);
     129     1569401 :   const dof_id_type offset0 = ti[0].first * _parameter_mesh.size();
     130     1569401 :   const dof_id_type offset1 = ti[1].first * _parameter_mesh.size();
     131             : 
     132             :   std::vector<dof_id_type> dof_indices;
     133             :   std::vector<Real> weights;
     134     1569401 :   _parameter_mesh.getIndexAndWeight(p, dof_indices, weights);
     135             : 
     136             :   dof_id_type sz = _parameter_mesh.size();
     137     1569401 :   if (!_coordt.empty())
     138        6534 :     sz *= _coordt.size();
     139     1569401 :   std::vector<Real> pg(sz, 0.0);
     140     7908383 :   for (const auto & i : index_range(dof_indices))
     141             :   {
     142     6338982 :     pg[dof_indices[i] + offset0] += weights[i] * ti[0].second;
     143     6338982 :     pg[dof_indices[i] + offset1] += weights[i] * ti[1].second;
     144             :   }
     145     1569401 :   return pg;
     146     1569401 : }
     147             : 
     148             : std::array<std::pair<std::size_t, Real>, 2>
     149    12990612 : ParameterMeshFunction::interpolateTime(Real t, bool derivative) const
     150             : {
     151    12990612 :   std::array<std::pair<std::size_t, Real>, 2> ti;
     152    12990612 :   if (_coordt.size() <= 1 || MooseUtils::absoluteFuzzyLessEqual(t, _coordt[0]))
     153             :   {
     154             :     ti[0] = {0, 0.5};
     155             :     ti[1] = {0, 0.5};
     156             :   }
     157       18945 :   else if (MooseUtils::absoluteFuzzyGreaterEqual(t, _coordt.back()))
     158             :   {
     159        3789 :     ti[0] = {_coordt.size() - 1, 0.5};
     160             :     ti[1] = {_coordt.size() - 1, 0.5};
     161             :   }
     162             :   else
     163       22734 :     for (std::size_t i = 1; i < _coordt.size(); ++i)
     164       22734 :       if (MooseUtils::absoluteFuzzyGreaterEqual(_coordt[i], t))
     165             :       {
     166       15156 :         const Real dt = _coordt[i] - _coordt[i - 1];
     167       15156 :         if (derivative)
     168             :         {
     169           0 :           ti[0] = {i - 1, -1.0 / dt};
     170             :           ti[1] = {i, 1.0 / dt};
     171             :         }
     172             :         else
     173             :         {
     174       15156 :           ti[0] = {i - 1, (_coordt[i] - t) / dt};
     175       15156 :           ti[1] = {i, (t - _coordt[i - 1]) / dt};
     176             :         }
     177             :         break;
     178             :       }
     179             : 
     180    12990612 :   return ti;
     181             : }
     182             : 
     183             : void
     184    11421213 : ParameterMeshFunction::checkSize() const
     185             : {
     186             :   dof_id_type sz = _parameter_mesh.size();
     187    11421213 :   if (!_coordt.empty())
     188       16200 :     sz *= _coordt.size();
     189    11421213 :   if (sz != _values.size())
     190           2 :     paramError("parameter_name",
     191             :                "Size of parameter vector (",
     192             :                _values.size(),
     193             :                ") does not match number of degrees of freedom in mesh (",
     194             :                sz,
     195             :                ").");
     196    11421211 : }

Generated by: LCOV version 1.14