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