LCOV - code coverage report
Current view: top level - src/materials - NEMLStress.C (source / functions) Hit Total Coverage
Test: idaholab/blackbear: 75f23c Lines: 65 75 86.7 %
Date: 2025-07-17 04:05:57 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /****************************************************************/
       2             : /*               DO NOT MODIFY THIS HEADER                      */
       3             : /*                       BlackBear                              */
       4             : /*                                                              */
       5             : /*           (c) 2017 Battelle Energy Alliance, LLC             */
       6             : /*                   ALL RIGHTS RESERVED                        */
       7             : /*                                                              */
       8             : /*          Prepared by Battelle Energy Alliance, LLC           */
       9             : /*            Under Contract No. DE-AC07-05ID14517              */
      10             : /*            With the U. S. Department of Energy               */
      11             : /*                                                              */
      12             : /*            See COPYRIGHT for full restrictions               */
      13             : /****************************************************************/
      14             : 
      15             : #ifdef NEML_ENABLED
      16             : 
      17             : #include <fstream>
      18             : #include <streambuf>
      19             : #include <algorithm>
      20             : 
      21             : #include "NEMLStress.h"
      22             : #include "Conversion.h"
      23             : 
      24             : registerMooseObject("BlackBearApp", NEMLStress);
      25             : 
      26             : InputParameters
      27        1575 : NEMLStress::validParams()
      28             : {
      29        1575 :   InputParameters params = NEMLStressBase::validParams();
      30        1575 :   params.addClassDescription("Use a constitutive model in the NEML library to compute stress");
      31        3150 :   params.addRequiredParam<FileName>("database", "Path to NEML XML database.");
      32        3150 :   params.addRequiredParam<std::string>("model", "Model name in NEML database.");
      33        3150 :   params.addParam<std::vector<std::string>>(
      34             :       "neml_variable_iname", {}, "Names of NEML XML name/value pairs");
      35        3150 :   params.addParam<std::vector<Real>>(
      36             :       "neml_variable_value", {}, "Corresponding NEML XML variable values");
      37       14175 :   for (size_t i = 0; i < _nvars_max; ++i)
      38             :   {
      39             :     auto istr = Moose::stringify(i);
      40       37800 :     params.addDeprecatedParam<Real>(
      41       25200 :         "neml_variable_value" + istr,
      42       25200 :         "NEML XML variable value for neml_variable_iname[" + istr + "]",
      43             :         "Deprecated in favor of the 'neml_variable_value' vector of names parameter");
      44             :   }
      45        1575 :   return params;
      46           0 : }
      47             : 
      48        1206 : NEMLStress::NEMLStress(const InputParameters & parameters)
      49             :   : NEMLStressBase(parameters),
      50        1206 :     _neml_variable_iname(getParam<std::vector<std::string>>("neml_variable_iname")),
      51        3618 :     _neml_variable_value(getParam<std::vector<Real>>("neml_variable_value")),
      52        2412 :     _nvars(_neml_variable_iname.size())
      53             : {
      54             :   // fetch and check inames and values for {variable} replacement
      55             :   bool value_vector = false;
      56        1206 :   if (!_neml_variable_value.empty())
      57             :   {
      58         186 :     if (_nvars != _neml_variable_value.size())
      59           0 :       paramError("neml_variable_value",
      60             :                  "If any values are specified the number must match the number of entries in "
      61             :                  "neml_variable_iname");
      62             :     value_vector = true;
      63             :   }
      64        1020 :   else if (_nvars > _nvars_max)
      65           0 :     paramError("neml_variable_iname",
      66             :                "NEMLStressVariableInput can only have up to ",
      67             :                _nvars_max,
      68             :                " neml_variable_iname entries");
      69             : 
      70             :   // We permit the numbered parameters to override the values vector.
      71        1206 :   _neml_variable_value.resize(_nvars);
      72        1578 :   for (std::size_t i = 0; i < _nvars; ++i)
      73             :   {
      74         744 :     std::string iname = "neml_variable_value" + std::to_string(i);
      75         372 :     if (isParamValid(iname))
      76           0 :       _neml_variable_value[i] = getParam<Real>(iname);
      77         372 :     else if (!value_vector)
      78           0 :       mooseError("Expected parameter '", iname, "' but it was not provided.");
      79             :   }
      80             : 
      81             :   // check if the file exists and can be read
      82        1206 :   const auto fname = getParam<FileName>("database");
      83        1206 :   MooseUtils::checkFileReadable(fname);
      84             : 
      85             :   // load file into string
      86        1206 :   std::ifstream t(fname.c_str());
      87        1206 :   _xml.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
      88             : 
      89             :   // replace {variables} in the XML file (the _nvars > 0 is an ugly hack)
      90        1206 :   if (_nvars > 0)
      91             :   {
      92         186 :     findXMLVariables();
      93         186 :     errorCheckXMLVariables();
      94         186 :     replaceXMLVariables();
      95             :   }
      96             : 
      97             :   // build NEML model object
      98        2412 :   auto mname = getParam<std::string>("model");
      99        3618 :   _model = neml::parse_string_unique(_xml, mname);
     100        1206 :   if (_model->is_damage_model())
     101         117 :     _damage_index = &declareProperty<Real>(_base_name + "damage_index");
     102        2412 : }
     103             : 
     104             : std::vector<std::string>
     105         372 : NEMLStress::setDifference(const std::set<std::string> & set1,
     106             :                           const std::set<std::string> & set2) const
     107             : {
     108         372 :   std::vector<std::string> result(set1.size() + set2.size());
     109         372 :   auto it = std::set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), result.begin());
     110         744 :   return std::vector<std::string>(result.begin(), it);
     111         372 : }
     112             : 
     113             : void
     114         186 : NEMLStress::findXMLVariables()
     115             : {
     116         186 :   auto open = _xml.find("{");
     117         186 :   auto close = _xml.find("}", open);
     118         558 :   while (open != std::string::npos)
     119             :   {
     120         372 :     _xml_vars.insert(_xml.substr(open + 1, close - (open + 1)));
     121         372 :     open = _xml.find("{", open + 1);
     122         372 :     close = _xml.find("}", open);
     123             :   }
     124         186 : }
     125             : 
     126             : void
     127         186 : NEMLStress::errorCheckXMLVariables() const
     128             : {
     129         186 :   std::set<std::string> inames(_neml_variable_iname.begin(), _neml_variable_iname.end());
     130         186 :   if (inames.size() != _nvars)
     131           0 :     paramError("neml_variable_iname", "Duplicate variable names");
     132             : 
     133         186 :   auto d1 = setDifference(inames, _xml_vars);
     134         186 :   auto d2 = setDifference(_xml_vars, inames);
     135             : 
     136         186 :   if (!d1.empty())
     137           0 :     paramError("neml_variable_iname",
     138             :                "Input file variable names not found in NEML xml file: ",
     139           0 :                Moose::stringify(d1));
     140         186 :   if (!d2.empty())
     141           0 :     paramError("database",
     142             :                "NEML xml file variable names not found in BlackBear input file: ",
     143           0 :                Moose::stringify(d2));
     144         372 : }
     145             : 
     146             : void
     147         186 : NEMLStress::replaceXMLVariables()
     148             : {
     149         558 :   for (std::size_t i = 0; i < _nvars; ++i)
     150             :   {
     151         744 :     auto key = "{" + _neml_variable_iname[i] + "}";
     152             :     auto len = key.length();
     153         372 :     auto value = Moose::stringify(_neml_variable_value[i]);
     154             : 
     155             :     // substitute all occurrences
     156             :     while (true)
     157             :     {
     158         744 :       auto pos = _xml.find(key);
     159         744 :       if (pos == std::string::npos)
     160             :         break;
     161             :       _xml.replace(pos, len, value);
     162             :     }
     163             :   }
     164         186 : }
     165             : 
     166             : #endif // NEML_ENABLED

Generated by: LCOV version 1.14