1 /*! 2 * \file mfront/src/BehaviourDescription.cxx 3 * \brief 4 * \author Thomas Helfer 5 * \brief 07 mars 2014 6 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 7 * reserved. 8 * This project is publicly released under either the GNU GPL Licence 9 * or the CECILL-A licence. A copy of thoses licences are delivered 10 * with the sources of TFEL. CEA or EDF may also distribute this 11 * project under specific licensing conditions. 12 */ 13 14 #include <string> 15 #include <sstream> 16 #include <stdexcept> 17 #include <algorithm> 18 #include "TFEL/Raise.hxx" 19 #include "TFEL/Glossary/Glossary.hxx" 20 #include "TFEL/Glossary/GlossaryEntry.hxx" 21 #include "TFEL/Math/Evaluator.hxx" 22 #include "TFEL/Utilities/CxxTokenizer.hxx" 23 #include "MFront/PedanticMode.hxx" 24 #include "MFront/MFrontLogStream.hxx" 25 #include "MFront/LocalDataStructure.hxx" 26 #include "MFront/ModelDescription.hxx" 27 #include "MFront/MaterialPropertyDescription.hxx" 28 #include "MFront/BehaviourDescription.hxx" 29 30 namespace mfront { 31 buildMaterialPropertyDescription(const BehaviourDescription::ConstantMaterialProperty & mp,const BehaviourDescription & bd,const std::string & n)32 static MaterialPropertyDescription buildMaterialPropertyDescription( 33 const BehaviourDescription::ConstantMaterialProperty& mp, 34 const BehaviourDescription& bd, 35 const std::string& n) { 36 const auto prefix = 37 bd.isBehaviourNameDefined() ? bd.getBehaviourName() + "_" : ""; 38 auto mpd = MaterialPropertyDescription{}; 39 mpd.output = VariableDescription{"real", "res", 1u, 0u}; 40 std::ostringstream body; 41 body << "res = " << mp.value << ";\n"; 42 mpd.law = prefix + n; 43 mpd.className = prefix + n; 44 mpd.material = bd.getMaterialName(); 45 mpd.f.modified = true; 46 mpd.f.body = body.str(); 47 return mpd; 48 } // end of buildMaterialPropertyDescription 49 buildMaterialPropertyDescription(const BehaviourDescription::ExternalMFrontMaterialProperty & mp,const BehaviourDescription & bd,const std::string & n)50 static MaterialPropertyDescription buildMaterialPropertyDescription( 51 const BehaviourDescription::ExternalMFrontMaterialProperty& mp, 52 const BehaviourDescription& bd, 53 const std::string& n) { 54 const auto prefix = 55 bd.isBehaviourNameDefined() ? bd.getBehaviourName() + "_" : ""; 56 auto mpd = *(mp.mpd); 57 mpd.law = prefix + n; 58 mpd.className = prefix + n; 59 mpd.material = bd.getMaterialName(); 60 return mpd; 61 } // end of buildMaterialPropertyDescription 62 buildMaterialPropertyDescription(const BehaviourDescription::AnalyticMaterialProperty & mp,const BehaviourDescription & bd,const std::string & n)63 static MaterialPropertyDescription buildMaterialPropertyDescription( 64 const BehaviourDescription::AnalyticMaterialProperty& mp, 65 const BehaviourDescription& bd, 66 const std::string& n) { 67 const auto prefix = 68 bd.isBehaviourNameDefined() ? bd.getBehaviourName() + "_" : ""; 69 auto mpd = MaterialPropertyDescription{}; 70 mpd.output = VariableDescription{"real", "res", 1u, 0u}; 71 mpd.law = prefix + n; 72 mpd.className = prefix + n; 73 mpd.material = bd.getMaterialName(); 74 const auto h = *(bd.getDistinctModellingHypotheses().begin()); 75 const auto& d = bd.getBehaviourData(h); 76 for (const auto& i : bd.getMaterialPropertyInputs(mp.getVariablesNames())) { 77 if (i.category == 78 BehaviourDescription::MaterialPropertyInput::STATICVARIABLE) { 79 mpd.staticVars.push_back(d.getStaticVariables().get(i.name)); 80 } else { 81 const auto& v = d.getVariableDescriptionByExternalName(i.ename); 82 mpd.inputs.push_back(v); 83 } 84 } 85 mpd.f.modified = true; 86 tfel::math::Evaluator e(mp.f); 87 mpd.f.body = "res = " + e.getCxxFormula() + ";\n"; 88 return mpd; 89 } // end of buildMaterialPropertyDescription 90 buildMaterialPropertyDescription(const BehaviourDescription::MaterialProperty & mp,const BehaviourDescription & bd,const std::string & n)91 static MaterialPropertyDescription buildMaterialPropertyDescription( 92 const BehaviourDescription::MaterialProperty& mp, 93 const BehaviourDescription& bd, 94 const std::string& n) { 95 if (mp.is<BehaviourDescription::ConstantMaterialProperty>()) { 96 return buildMaterialPropertyDescription( 97 mp.get<BehaviourDescription::ConstantMaterialProperty>(), bd, n); 98 } else if (mp.is<BehaviourDescription::ExternalMFrontMaterialProperty>()) { 99 return buildMaterialPropertyDescription( 100 mp.get<BehaviourDescription::ExternalMFrontMaterialProperty>(), bd, 101 n); 102 } else if (mp.is<BehaviourDescription::AnalyticMaterialProperty>()) { 103 return buildMaterialPropertyDescription( 104 mp.get<BehaviourDescription::AnalyticMaterialProperty>(), bd, n); 105 } else { 106 tfel::raise( 107 "buildMaterialPropertyDescription: unsupported material property " 108 "type"); 109 } 110 } // end of buildMaterialPropertyDescription 111 112 std::vector<std::string> getVariablesNames() const113 BehaviourDescription::AnalyticMaterialProperty::getVariablesNames() const { 114 return tfel::math::Evaluator(this->f).getVariablesNames(); 115 } // end of AnalyticMaterialProperty::getVariablesNames 116 117 template <typename Arg1> callBehaviourData(const Hypothesis h,void (BehaviourData::* m)(const Arg1 &),const Arg1 & a,const bool b)118 void BehaviourDescription::callBehaviourData( 119 const Hypothesis h, 120 void (BehaviourData::*m)(const Arg1&), 121 const Arg1& a, 122 const bool b) { 123 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 124 (this->d.*m)(a); 125 if (b) { 126 for (auto md : this->sd) { 127 (md.second.get()->*m)(a); 128 } 129 } 130 } else { 131 (this->getBehaviourData2(h).*m)(a); 132 } 133 } // end of BehaviourDescription::callBehaviourData 134 135 template <typename Arg1> callBehaviourData(const Hypothesis h,void (BehaviourData::* m)(const Arg1),const Arg1 a,const bool b)136 void BehaviourDescription::callBehaviourData( 137 const Hypothesis h, 138 void (BehaviourData::*m)(const Arg1), 139 const Arg1 a, 140 const bool b) { 141 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 142 (this->d.*m)(a); 143 if (b) { 144 for (const auto& ptr : this->sd) { 145 auto& bdata = *(ptr.second); 146 (bdata.*m)(a); 147 } 148 } 149 } else { 150 (this->getBehaviourData2(h).*m)(a); 151 } 152 } // end of BehaviourDescription::callBehaviourData 153 154 template <typename Arg1, typename Arg2> callBehaviourData(const Hypothesis h,void (BehaviourData::* m)(const Arg1 &,const Arg2),const Arg1 & a1,const Arg2 a2,const bool b)155 void BehaviourDescription::callBehaviourData( 156 const Hypothesis h, 157 void (BehaviourData::*m)(const Arg1&, const Arg2), 158 const Arg1& a1, 159 const Arg2 a2, 160 const bool b) { 161 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 162 (this->d.*m)(a1, a2); 163 if (b) { 164 for (const auto& ptr : this->sd) { 165 auto& bdata = *(ptr.second); 166 (bdata.*m)(a1, a2); 167 } 168 } 169 } else { 170 (this->getBehaviourData2(h).*m)(a1, a2); 171 } 172 } // end of BehaviourDescription::callBehaviourData 173 174 template <typename Arg1, typename Arg2> callBehaviourData(const Hypothesis h,void (BehaviourData::* m)(const Arg1 &,const Arg2 &),const Arg1 & a1,const Arg2 & a2,const bool b)175 void BehaviourDescription::callBehaviourData( 176 const Hypothesis h, 177 void (BehaviourData::*m)(const Arg1&, const Arg2&), 178 const Arg1& a1, 179 const Arg2& a2, 180 const bool b) { 181 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 182 (this->d.*m)(a1, a2); 183 if (b) { 184 for (const auto& ptr : this->sd) { 185 auto& bdata = *(ptr.second); 186 (bdata.*m)(a1, a2); 187 } 188 } 189 } else { 190 (this->getBehaviourData2(h).*m)(a1, a2); 191 } 192 } // end of BehaviourDescription::callBehaviourData 193 194 template <typename Arg1, typename Arg2, typename Arg3> callBehaviourData(const Hypothesis h,void (BehaviourData::* m)(const Arg1 &,const Arg2 &,const Arg3 &),const Arg1 & a1,const Arg2 & a2,const Arg3 & a3,const bool b)195 void BehaviourDescription::callBehaviourData( 196 const Hypothesis h, 197 void (BehaviourData::*m)(const Arg1&, const Arg2&, const Arg3&), 198 const Arg1& a1, 199 const Arg2& a2, 200 const Arg3& a3, 201 const bool b) { 202 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 203 (this->d.*m)(a1, a2, a3); 204 if (b) { 205 for (const auto& ptr : this->sd) { 206 auto& bdata = *(ptr.second); 207 (bdata.*m)(a1, a2, a3); 208 } 209 } 210 } else { 211 (this->getBehaviourData2(h).*m)(a1, a2, a3); 212 } 213 } // end of BehaviourDescription::callBehaviourData 214 215 template <typename Res, typename Arg1> 216 Res BehaviourDescription::getData(const Hypothesis h, 217 Res (BehaviourData::*m)(const Arg1&) const, 218 const Arg1& a) const { 219 return (this->getBehaviourData(h).*m)(a); 220 } // end of BehaviourDescription::getData 221 declareParameter(BehaviourDescription & bd,BehaviourDescription::MaterialProperty & mp,const tfel::glossary::GlossaryEntry & e,const std::string & n)222 static void declareParameter(BehaviourDescription& bd, 223 BehaviourDescription::MaterialProperty& mp, 224 const tfel::glossary::GlossaryEntry& e, 225 const std::string& n) { 226 const auto h = tfel::material::ModellingHypothesis::UNDEFINEDHYPOTHESIS; 227 if (mp.is<BehaviourDescription::ConstantMaterialProperty>()) { 228 auto& cmp = mp.get<BehaviourDescription::ConstantMaterialProperty>(); 229 cmp.name = n; 230 // declare associated parameter 231 VariableDescription m("real", n, 1u, 0u); 232 bd.addParameter(h, m); 233 bd.setParameterDefaultValue(h, n, cmp.value); 234 bd.setGlossaryName(h, n, e.getKey()); 235 } 236 } // end of declareParameter 237 checkElasticMaterialProperty(BehaviourDescription & bd,BehaviourDescription::MaterialProperty & emp,const tfel::glossary::GlossaryEntry & e,const std::string & n2)238 static void checkElasticMaterialProperty( 239 BehaviourDescription& bd, 240 BehaviourDescription::MaterialProperty& emp, 241 const tfel::glossary::GlossaryEntry& e, 242 const std::string& n2) { 243 if (emp.is<BehaviourDescription::ExternalMFrontMaterialProperty>()) { 244 const auto& mpd = *( 245 emp.get<BehaviourDescription::ExternalMFrontMaterialProperty>().mpd); 246 const auto& ename = mpd.output.getExternalName(); 247 if (ename != e) { 248 getLogStream() 249 << "checkElasticMaterialProperty: inconsistent external name for " 250 << "material property '" + e.getKey() + 251 "': external name of mfront file " 252 << "output is '" << ename << "'\n"; 253 } 254 } 255 declareParameter(bd, emp, e, n2); 256 } 257 checkThermalExpansionCoefficientArgument(BehaviourDescription & bd,BehaviourDescription::MaterialProperty & a,const tfel::glossary::GlossaryEntry & e,const std::string & n)258 static void checkThermalExpansionCoefficientArgument( 259 BehaviourDescription& bd, 260 BehaviourDescription::MaterialProperty& a, 261 const tfel::glossary::GlossaryEntry& e, 262 const std::string& n) { 263 auto throw_if = [](const bool c, const std::string& m) { 264 tfel::raise_if(c, "checkThermalExpansionCoefficientArgument: " + m); 265 }; 266 declareParameter(bd, a, e, n); 267 if (a.is<BehaviourDescription::ConstantMaterialProperty>()) { 268 return; 269 } 270 if (a.is<BehaviourDescription::ExternalMFrontMaterialProperty>()) { 271 const auto& mpd = 272 *(a.get<BehaviourDescription::ExternalMFrontMaterialProperty>().mpd); 273 for (const auto& i : bd.getMaterialPropertyInputs(mpd, false)) { 274 const auto c = i.category; 275 throw_if( 276 (c != BehaviourDescription::MaterialPropertyInput::TEMPERATURE) && 277 (c != BehaviourDescription::MaterialPropertyInput:: 278 MATERIALPROPERTY) && 279 (c != BehaviourDescription::MaterialPropertyInput::PARAMETER) && 280 (c != 281 BehaviourDescription::MaterialPropertyInput::STATICVARIABLE), 282 "invalid input '" + i.ename + "' (" + i.name + 283 ") for thermal expansion"); 284 } 285 } else if (a.is<BehaviourDescription::AnalyticMaterialProperty>()) { 286 const auto& vn = a.get<BehaviourDescription::AnalyticMaterialProperty>() 287 .getVariablesNames(); 288 for (const auto& i : bd.getMaterialPropertyInputs(vn, false)) { 289 const auto c = i.category; 290 throw_if( 291 (c != BehaviourDescription::MaterialPropertyInput::TEMPERATURE) && 292 (c != BehaviourDescription::MaterialPropertyInput:: 293 MATERIALPROPERTY) && 294 (c != BehaviourDescription::MaterialPropertyInput::PARAMETER) && 295 (c != 296 BehaviourDescription::MaterialPropertyInput::STATICVARIABLE), 297 "invalid input '" + i.ename + "' (" + i.name + 298 ") for thermal expansion"); 299 } 300 } else { 301 throw_if(true, "unsupported material property type"); 302 } 303 } // end of checkThermalExpansionCoefficientArgument 304 305 static std::pair<VariableDescription, VariableDescription> decomposeAdditionalTangentOperatorBlock(const BehaviourDescription & bd,const std::string & bn)306 decomposeAdditionalTangentOperatorBlock(const BehaviourDescription& bd, 307 const std::string& bn) { 308 const auto h = [&bd] { 309 if (bd.areModellingHypothesesDefined()) { 310 const auto mhs = bd.getModellingHypotheses(); 311 if (mhs.size() == 1u) { 312 return *(mhs.begin()); 313 } 314 } 315 return BehaviourDescription::ModellingHypothesis::UNDEFINEDHYPOTHESIS; 316 }(); 317 auto a = VariableDescription{}; 318 auto b = VariableDescription{}; 319 auto found = false; 320 auto check = [&found, &bn] { 321 if (found) { 322 tfel::raise( 323 "decomposeAdditionalTangentOperatorBlock: " 324 "multiple match for block '" + 325 bn + "'"); 326 } 327 }; 328 auto assign_if = [&check, &a, &b, &found, &bn]( 329 const VariableDescription& v1, const VariableDescription& v2, 330 const bool no_inc) { 331 const auto block_name = [&v1, &v2, &no_inc] { 332 if (no_inc) { 333 return "d" + v1.name + "_d" + v2.name + "1"; 334 } 335 return "d" + v1.name + "_dd" + v2.name; 336 }(); 337 const auto symbolic_block_name = [&v1, &v2, &no_inc] { 338 const auto tmp = "\u2202" + displayName(v1) + "\u2215\u2202"; 339 if (no_inc) { 340 return tmp + displayName(v2) + "1"; 341 } 342 return tmp + "\u0394" + displayName(v2); 343 }(); 344 if ((bn == block_name) || (bn == symbolic_block_name)) { 345 check(); 346 a = v1; 347 b = v2; 348 found = true; 349 } 350 }; 351 const auto& d = bd.getBehaviourData(h); 352 for (const auto& mv : bd.getMainVariables()) { 353 for (const auto& mv2 : bd.getMainVariables()) { 354 assign_if(mv.second, mv2.first, !Gradient::isIncrementKnown(mv2.first)); 355 } 356 for (const auto& e : d.getExternalStateVariables()) { 357 assign_if(mv.second, e, false); 358 } 359 } 360 for (const auto& s : d.getPersistentVariables()) { 361 for (const auto& mv : bd.getMainVariables()) { 362 assign_if(s, mv.first, !Gradient::isIncrementKnown(mv.first)); 363 } 364 for (const auto& e : d.getExternalStateVariables()) { 365 assign_if(s, e, false); 366 } 367 } 368 if (!found) { 369 tfel::raise( 370 "decomposeAdditionalTangentOperatorBlock: " 371 "no match for '" + 372 bn + "'"); 373 } 374 return {a, b}; 375 } // end of decomposeTangentOperatorBlock 376 377 const char* const BehaviourDescription::requiresStiffnessTensor = 378 "requiresStiffnessTensor"; 379 380 const char* const BehaviourDescription::computesStiffnessTensor = 381 "computesStiffnessTensor"; 382 383 const char* const BehaviourDescription::requiresUnAlteredStiffnessTensor = 384 "requiresUnAlteredStiffnessTensor"; 385 386 const char* const 387 BehaviourDescription::requiresThermalExpansionCoefficientTensor = 388 "requiresThermalExpansionCoefficientTensor"; 389 390 BehaviourDescription::BehaviourDescription() = default; 391 392 BehaviourDescription::BehaviourDescription(const BehaviourDescription&) = 393 default; 394 allowsNewUserDefinedVariables() const395 bool BehaviourDescription::allowsNewUserDefinedVariables() const { 396 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 397 return this->getAttribute(h, BehaviourData::allowsNewUserDefinedVariables, 398 true); 399 } // end of BehaviourDescription::allowNewsUserDefinedVariables 400 disallowNewUserDefinedVariables()401 void BehaviourDescription::disallowNewUserDefinedVariables() { 402 const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 403 this->setAttribute(uh, BehaviourData::allowsNewUserDefinedVariables, false); 404 } // end of BehaviourDescription::disallowNewUserDefinedVariables 405 throwUndefinedAttribute(const std::string & n)406 void BehaviourDescription::throwUndefinedAttribute(const std::string& n) { 407 tfel::raise( 408 "BehaviourDescription::getAttribute: " 409 "no attribute named '" + 410 n + "'"); 411 } // end of BehaviourDescription::throwUndefinedAttribute 412 getBehaviourData(const Hypothesis h) const413 const BehaviourData& BehaviourDescription::getBehaviourData( 414 const Hypothesis h) const { 415 // check that the given hypothesis is supported 416 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 417 return this->d; 418 } 419 this->checkModellingHypothesis(h); 420 this->requestedHypotheses.insert(h); 421 // check if a specialised version of the behaviour 422 // description has been defined 423 const auto p = this->sd.find(h); 424 if (p != this->sd.end()) { 425 return *(p->second); 426 } 427 // return the default... 428 return this->d; 429 } // end of BehaviourDescription::getBehaviourData 430 specialize(const Hypothesis h)431 void BehaviourDescription::specialize(const Hypothesis h) { 432 if (this->areModellingHypothesesDefined()) { 433 this->checkModellingHypothesis(h); 434 } 435 auto p = this->sd.find(h); 436 if (p == this->sd.end()) { 437 // copy of the default description 438 this->sd.insert({h, std::make_shared<BehaviourData>(this->d)}).first; 439 } 440 } // end of BehaviourDescription::specialize 441 getBehaviourData2(const Hypothesis h)442 BehaviourData& BehaviourDescription::getBehaviourData2(const Hypothesis h) { 443 // check that the given hypothesis is supported 444 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 445 return this->d; 446 } 447 if (this->areModellingHypothesesDefined()) { 448 this->checkModellingHypothesis(h); 449 } 450 this->requestedHypotheses.insert(h); 451 auto p = this->sd.find(h); 452 if (p == this->sd.end()) { 453 // copy of the default description 454 p = this->sd.insert({h, std::make_shared<BehaviourData>(this->d)}).first; 455 } 456 return *(p->second); 457 } // end of BehaviourDescription::getBehaviourData2 458 isBehaviourNameDefined() const459 bool BehaviourDescription::isBehaviourNameDefined() const { 460 return !this->behaviour.empty(); 461 } // end of BehaviourDescription::isBehaviourNameDefined 462 setBehaviourName(const std::string & m)463 void BehaviourDescription::setBehaviourName(const std::string& m) { 464 tfel::raise_if(!this->behaviour.empty(), 465 "BehaviourDescription::setBehaviourName: " 466 "behaviour name already defined"); 467 this->behaviour = m; 468 this->updateClassName(); 469 } // end of BehaviourDescription::setBehaviourName 470 getBehaviourName() const471 const std::string& BehaviourDescription::getBehaviourName() const { 472 tfel::raise_if(this->behaviour.empty(), 473 "BehaviourDescription::getBehaviourName: " 474 "behaviour name not defined"); 475 return this->behaviour; 476 } // end of BehaviourDescription::getBehaviourName 477 setDSLName(const std::string & m)478 void BehaviourDescription::setDSLName(const std::string& m) { 479 tfel::raise_if(!this->dsl.empty(), 480 "BehaviourDescription::setDSLName: " 481 "dsl name already defined"); 482 this->dsl = m; 483 this->updateClassName(); 484 } // end of BehaviourDescription::setDSLName 485 getDSLName() const486 const std::string& BehaviourDescription::getDSLName() const { 487 tfel::raise_if(this->dsl.empty(), 488 "BehaviourDescription::getDSLName: " 489 "dsl name not defined"); 490 return this->dsl; 491 } // end of BehaviourDescription::getDSLName 492 493 BehaviourDescription::MaterialPropertyInput::Category getMaterialPropertyInputCategory(const Hypothesis h,const std::string & v) const494 BehaviourDescription::getMaterialPropertyInputCategory( 495 const Hypothesis h, const std::string& v) const { 496 auto throw_if = [](const bool c, const std::string& m) { 497 tfel::raise_if( 498 c, "BehaviourDescription::getMaterialPropertyInputCategory: " + m); 499 }; 500 if (this->isStateVariableName(h, v)) { 501 return MaterialPropertyInput::STATEVARIABLE; 502 } else if (this->isExternalStateVariableName(h, v)) { 503 return MaterialPropertyInput::EXTERNALSTATEVARIABLE; 504 } else if (this->isAuxiliaryStateVariableName(h, v)) { 505 const auto& bd = this->getBehaviourData(h); 506 const auto& av = bd.getAuxiliaryStateVariableDescription(v); 507 throw_if( 508 !av.getAttribute<bool>("ComputedByExternalModel", false), 509 "only auxiliary state variable computed by a model are allowed here"); 510 return MaterialPropertyInput::AUXILIARYSTATEVARIABLEFROMEXTERNALMODEL; 511 } else if (this->isMaterialPropertyName(h, v)) { 512 return MaterialPropertyInput::MATERIALPROPERTY; 513 } else if (this->isParameterName(h, v)) { 514 return MaterialPropertyInput::PARAMETER; 515 } else if (this->isStaticVariableName(h, v)) { 516 return MaterialPropertyInput::STATICVARIABLE; 517 } 518 throw_if(true, "unsupported variable: variable '" + v + 519 "' is " 520 "neither an external state variable, a material " 521 "property nor a parameter nor an auxiliary " 522 "state variable evaluated by an external model, " 523 "nor a static variable"); 524 } // end of BehaviourDescription::getMaterialPropertyInputCategory 525 526 std::vector<BehaviourDescription::MaterialPropertyInput> getMaterialPropertyInputs(const std::vector<std::string> & i,const bool b) const527 BehaviourDescription::getMaterialPropertyInputs( 528 const std::vector<std::string>& i, const bool b) const { 529 auto throw_if = [](const bool c, const std::string& m) { 530 tfel::raise_if(c, 531 "BehaviourDescription::getMaterialPropertyInputs: " + m); 532 }; 533 auto inputs = std::vector<MaterialPropertyInput>{}; 534 const auto hs = [this, b, 535 throw_if]() -> std::set<BehaviourDescription::Hypothesis> { 536 if (this->hypotheses.empty()) { 537 // modelling hypotheses are not set yet 538 throw_if(b, "modelling hypothesis must be defined"); 539 return {ModellingHypothesis::UNDEFINEDHYPOTHESIS}; 540 } 541 return this->getDistinctModellingHypotheses(); 542 }(); 543 for (const auto& v : i) { 544 if (v == "T") { 545 inputs.push_back({"T", tfel::glossary::Glossary::Temperature, 546 MaterialPropertyInput::TEMPERATURE}); 547 } else { 548 const auto rh = *(hs.begin()); 549 const auto t = this->getMaterialPropertyInputCategory(rh, v); 550 if (t == MaterialPropertyInput::STATICVARIABLE) { 551 for (const auto h : hs) { 552 throw_if(this->getMaterialPropertyInputCategory(h, v) != t, 553 "the variable '" + v + 554 "' belongs to two different " 555 "categories in two distinct modelling hypotheses. " 556 "This is not supported."); 557 } 558 inputs.push_back({v, v, t}); 559 } else { 560 const auto vd = this->getBehaviourData(rh).getVariableDescription(v); 561 const auto en = vd.getExternalName(); 562 for (const auto h : hs) { 563 const auto vd2 = 564 this->getBehaviourData(h).getVariableDescription(v); 565 throw_if(vd2.getExternalName() != en, 566 "the variable '" + v + 567 "' has two different " 568 "external names in two distinct modelling hypotheses." 569 "This is not supported."); 570 throw_if(this->getMaterialPropertyInputCategory(h, v) != t, 571 "the variable '" + v + 572 "' belongs to two different " 573 "categories in two distinct modelling hypotheses. " 574 "This is not supported."); 575 } 576 inputs.push_back({v, en, t}); 577 } 578 } 579 } 580 return inputs; 581 } // end of BehaviourDescription::getMaterialPropertyInputs 582 583 std::vector<BehaviourDescription::MaterialPropertyInput> getMaterialPropertyInputs(const MaterialPropertyDescription & mpd,const bool b) const584 BehaviourDescription::getMaterialPropertyInputs( 585 const MaterialPropertyDescription& mpd, const bool b) const { 586 auto throw_if = [](const bool c, const std::string& m) { 587 tfel::raise_if(c, 588 "BehaviourDescription::getMaterialPropertyInputs: " + m); 589 }; 590 auto inputs = std::vector<MaterialPropertyInput>{}; 591 const auto hs = [this, b, 592 throw_if]() -> std::set<BehaviourDescription::Hypothesis> { 593 if (this->hypotheses.empty()) { 594 // modelling hypotheses are not set yet 595 throw_if(b, "modelling hypothesis must be defined"); 596 return {ModellingHypothesis::UNDEFINEDHYPOTHESIS}; 597 } 598 return this->getDistinctModellingHypotheses(); 599 }(); 600 for (const auto& v : mpd.inputs) { 601 if ((getPedanticMode()) && 602 (!(v.hasGlossaryName()) && (!v.hasEntryName()))) { 603 getLogStream() << "BehaviourDescription::getMaterialPropertyInputs: " 604 "no glossary nor entry name declared for variable " 605 "'" + 606 v.name + "' used by the material property '" + 607 mpd.law + "'\n"; 608 } 609 const auto& vn = v.getExternalName(); 610 if (vn == tfel::glossary::Glossary::Temperature) { 611 inputs.push_back({"T", tfel::glossary::Glossary::Temperature, 612 MaterialPropertyInput::TEMPERATURE}); 613 } else { 614 const auto n = 615 this->getVariableDescriptionByExternalName(*(hs.begin()), vn).name; 616 const auto t = this->getMaterialPropertyInputCategory(*(hs.begin()), n); 617 for (const auto h : hs) { 618 throw_if(this->getVariableDescriptionByExternalName(h, vn).name != n, 619 "the external name '" + vn + 620 "' is associated with " 621 "two differents variables in two distinct " 622 "modelling hypotheses. This is not supported."); 623 throw_if(this->getMaterialPropertyInputCategory(h, n) != t, 624 "the external name '" + vn + 625 "' has two different " 626 "types in two distinct modelling hypotheses. " 627 "This is not supported."); 628 } 629 inputs.push_back({n, vn, t}); 630 } 631 } 632 return inputs; 633 } // end of BehaviourDescription::getMaterialPropertyInputs 634 setIntegrationScheme(const BehaviourDescription::IntegrationScheme s)635 void BehaviourDescription::setIntegrationScheme( 636 const BehaviourDescription::IntegrationScheme s) { 637 tfel::raise_if(this->ischeme != UNDEFINEDINTEGRATIONSCHEME, 638 "BehaviourDescription::setIntegrationScheme: " 639 "integration scheme already defined"); 640 this->ischeme = s; 641 } // end of BehaviourDescription::setIntegrationScheme 642 643 BehaviourDescription::IntegrationScheme getIntegrationScheme() const644 BehaviourDescription::getIntegrationScheme() const { 645 tfel::raise_if(this->ischeme == UNDEFINEDINTEGRATIONSCHEME, 646 "BehaviourDescription::getIntegrationScheme: " 647 "the integration scheme is undefined"); 648 return this->ischeme; 649 } // end of BehaviourDescription::getIntegrationScheme 650 setLibrary(const std::string & l)651 void BehaviourDescription::setLibrary(const std::string& l) { 652 tfel::raise_if(!this->library.empty(), 653 "BehaviourDescription::setLibrary: " 654 "library alreay defined"); 655 this->library = l; 656 } // end of BehaviourDescription::setLibrary 657 getLibrary() const658 const std::string& BehaviourDescription::getLibrary() const { 659 return this->library; 660 } // end of BehaviourDescription::getLibrary 661 setMaterialName(const std::string & m)662 void BehaviourDescription::setMaterialName(const std::string& m) { 663 tfel::raise_if(!this->material.empty(), 664 "BehaviourDescription::setMaterialName: " 665 "material name alreay defined"); 666 this->material = m; 667 this->updateClassName(); 668 } // end of BehaviourDescription::setMaterialName 669 getMaterialName() const670 const std::string& BehaviourDescription::getMaterialName() const { 671 return this->material; 672 } // end of BehaviourDescription::getMaterialName 673 setClassName(const std::string & n)674 void BehaviourDescription::setClassName(const std::string& n) { 675 tfel::raise_if(!this->className.empty(), 676 "BehaviourDescription::setClassName: " 677 "class name alreay defined"); 678 this->className = n; 679 } // end of BehaviourDescription::setClassName 680 getClassName() const681 const std::string& BehaviourDescription::getClassName() const { 682 tfel::raise_if(this->className.empty(), 683 "BehaviourDescription::getClassName: " 684 "class name not defined"); 685 return this->className; 686 } // end of BehaviourDescription::getClassName 687 appendToIncludes(const std::string & c)688 void BehaviourDescription::appendToIncludes(const std::string& c) { 689 this->includes += c; 690 if (!this->includes.empty()) { 691 if (*(this->includes.rbegin()) != '\n') { 692 this->includes += '\n'; 693 } 694 } 695 } // end of BehaviourDescription::appendToIncludes 696 getIncludes() const697 const std::string& BehaviourDescription::getIncludes() const { 698 return this->includes; 699 } // end of BehaviourDescription::getIncludes 700 appendToMembers(const Hypothesis h,const std::string & c,const bool b)701 void BehaviourDescription::appendToMembers(const Hypothesis h, 702 const std::string& c, 703 const bool b) { 704 this->callBehaviourData(h, &BehaviourData::appendToMembers, c, b); 705 } // end of BehaviourDescription::appendToMembers 706 getMembers(const Hypothesis h) const707 std::string BehaviourDescription::getMembers(const Hypothesis h) const { 708 return this->getBehaviourData(h).getMembers(); 709 } // end of BehaviourDescription::getMembers 710 appendToPrivateCode(const Hypothesis h,const std::string & c,const bool b)711 void BehaviourDescription::appendToPrivateCode(const Hypothesis h, 712 const std::string& c, 713 const bool b) { 714 this->callBehaviourData(h, &BehaviourData::appendToPrivateCode, c, b); 715 } // end of BehaviourDescription::appendToPrivateCode 716 getPrivateCode(const Hypothesis h) const717 std::string BehaviourDescription::getPrivateCode(const Hypothesis h) const { 718 return this->getBehaviourData(h).getPrivateCode(); 719 } // end of BehaviourDescription::getPrivateCode 720 appendToSources(const std::string & c)721 void BehaviourDescription::appendToSources(const std::string& c) { 722 this->sources += c; 723 if (!this->sources.empty()) { 724 if (*(this->sources.rbegin()) != '\n') { 725 this->sources += '\n'; 726 } 727 } 728 } // end of BehaviourDescription::appendToSources 729 getSources() const730 const std::string& BehaviourDescription::getSources() const { 731 return this->sources; 732 } // end of BehaviourDescription::getSources 733 getBehaviourType() const734 BehaviourDescription::BehaviourType BehaviourDescription::getBehaviourType() 735 const { 736 if (this->type.empty()) { 737 tfel::raise( 738 "BehaviourDescription::getBehaviourType: " 739 "undefined behaviour type"); 740 } 741 return this->type; 742 } // end of BehaviourDescription::getBehaviourType 743 getBehaviourTypeFlag() const744 std::string BehaviourDescription::getBehaviourTypeFlag() const { 745 std::string btype; 746 if (this->getBehaviourType() == 747 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) { 748 btype = "MechanicalBehaviourBase::STANDARDSTRAINBASEDBEHAVIOUR"; 749 } else if (this->getBehaviourType() == 750 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 751 btype = "MechanicalBehaviourBase::STANDARDFINITESTRAINBEHAVIOUR"; 752 } else if (this->getBehaviourType() == 753 BehaviourDescription::COHESIVEZONEMODEL) { 754 btype = "MechanicalBehaviourBase::COHESIVEZONEMODEL"; 755 } else if (this->getBehaviourType() == 756 BehaviourDescription::GENERALBEHAVIOUR) { 757 btype = "MechanicalBehaviourBase::GENERALBEHAVIOUR"; 758 } else { 759 tfel::raise( 760 "BehaviourDescription::getBehaviourTypeFlag: " 761 "unsupported behaviour type"); 762 } 763 return btype; 764 } // end of BehaviourDescription::getBehaviourTypeFlag 765 areElasticMaterialPropertiesDefined() const766 bool BehaviourDescription::areElasticMaterialPropertiesDefined() const { 767 return !this->elasticMaterialProperties.empty(); 768 } // end of BehaviourDescription::areElasticMaterialPropertiesDefined 769 isMaterialPropertyConstantDuringTheTimeStep(const MaterialProperty & mp) const770 bool BehaviourDescription::isMaterialPropertyConstantDuringTheTimeStep( 771 const MaterialProperty& mp) const { 772 if (mp.is<ExternalMFrontMaterialProperty>()) { 773 const auto& cmp = mp.get<ExternalMFrontMaterialProperty>(); 774 for (const auto& i : this->getMaterialPropertyInputs(*(cmp.mpd))) { 775 if (!((i.category == 776 BehaviourDescription::MaterialPropertyInput::MATERIALPROPERTY) || 777 (i.category == 778 BehaviourDescription::MaterialPropertyInput::PARAMETER))) { 779 return false; 780 } 781 } 782 return true; 783 } else if (mp.is<AnalyticMaterialProperty>()) { 784 const auto& amp = mp.get<AnalyticMaterialProperty>(); 785 for (const auto& i : 786 this->getMaterialPropertyInputs(amp.getVariablesNames())) { 787 if (!((i.category == 788 BehaviourDescription::MaterialPropertyInput::MATERIALPROPERTY) || 789 (i.category == 790 BehaviourDescription::MaterialPropertyInput::PARAMETER))) { 791 return false; 792 } 793 } 794 return true; 795 } 796 return true; 797 } // end of BehaviourDescription::isMaterialPropertyConstantDuringTheTimeStep 798 799 bool areElasticMaterialPropertiesConstantDuringTheTimeStep() const800 BehaviourDescription::areElasticMaterialPropertiesConstantDuringTheTimeStep() 801 const { 802 tfel::raise_if(!this->areElasticMaterialPropertiesDefined(), 803 "BehaviourDescription::" 804 "areElasticMaterialPropertiesConstantDuringTheTimeStep: " 805 "no elastic material property defined"); 806 return this->areMaterialPropertiesConstantDuringTheTimeStep( 807 this->elasticMaterialProperties); 808 } // end of 809 // BehaviourDescription::areElasticMaterialPropertiesConstantDuringTheTimeStep 810 areMaterialPropertiesConstantDuringTheTimeStep(const std::vector<MaterialProperty> & mps) const811 bool BehaviourDescription::areMaterialPropertiesConstantDuringTheTimeStep( 812 const std::vector<MaterialProperty>& mps) const { 813 for (const auto& mp : mps) { 814 if (!this->isMaterialPropertyConstantDuringTheTimeStep(mp)) { 815 return false; 816 } 817 } 818 return true; 819 } // end of 820 // BehaviourDescription::areMaterialPropertiesConstantDuringTheTimeStep 821 isMaterialPropertyDependantOnStateVariables(const MaterialProperty & mp) const822 bool BehaviourDescription::isMaterialPropertyDependantOnStateVariables( 823 const MaterialProperty& mp) const { 824 if (mp.is<ExternalMFrontMaterialProperty>()) { 825 const auto& cmp = mp.get<ExternalMFrontMaterialProperty>(); 826 for (const auto& i : this->getMaterialPropertyInputs(*(cmp.mpd))) { 827 if (i.category == 828 BehaviourDescription::MaterialPropertyInput::STATEVARIABLE) { 829 return true; 830 } 831 } 832 return false; 833 } 834 if (mp.is<AnalyticMaterialProperty>()) { 835 const auto& amp = mp.get<AnalyticMaterialProperty>(); 836 for (const auto& i : 837 this->getMaterialPropertyInputs(amp.getVariablesNames())) { 838 if (i.category == 839 BehaviourDescription::MaterialPropertyInput::STATEVARIABLE) { 840 return true; 841 } 842 } 843 return false; 844 } 845 tfel::raise_if( 846 !mp.is<ConstantMaterialProperty>(), 847 "BehaviourDescription::isMaterialPropertyDependantOnStateVariables: " 848 "unsupported material property"); 849 return false; 850 } // end of BehaviourDescription::isMaterialPropertyDependantOnStateVariables 851 852 bool areElasticMaterialPropertiesDependantOnStateVariables() const853 BehaviourDescription::areElasticMaterialPropertiesDependantOnStateVariables() 854 const { 855 tfel::raise_if(!this->areElasticMaterialPropertiesDefined(), 856 "BehaviourDescription::" 857 "areElasticMaterialPropertiesDependantOnStateVariables: " 858 "no elastic material property defined"); 859 return this->areMaterialPropertiesDependantOnStateVariables( 860 this->elasticMaterialProperties); 861 } // end of 862 // BehaviourDescription::areElasticMaterialPropertiesDependantOnStateVariables 863 areMaterialPropertiesDependantOnStateVariables(const std::vector<MaterialProperty> & mps) const864 bool BehaviourDescription::areMaterialPropertiesDependantOnStateVariables( 865 const std::vector<MaterialProperty>& mps) const { 866 for (const auto& mp : mps) { 867 if (this->isMaterialPropertyDependantOnStateVariables(mp)) { 868 return true; 869 } 870 } 871 return false; 872 } // end of 873 // BehaviourDescription::areMaterialPropertiesDependantOnStateVariables 874 875 const std::vector<BehaviourDescription::MaterialProperty>& getElasticMaterialProperties() const876 BehaviourDescription::getElasticMaterialProperties() const { 877 tfel::raise_if(!this->areElasticMaterialPropertiesDefined(), 878 "BehaviourDescription::getElasticMaterialProperties: " 879 "no elastic material property defined"); 880 return this->elasticMaterialProperties; 881 } 882 setElasticMaterialProperties(const std::vector<MaterialProperty> & emps)883 void BehaviourDescription::setElasticMaterialProperties( 884 const std::vector<MaterialProperty>& emps) { 885 auto throw_if = [](const bool b, const std::string& m) { 886 tfel::raise_if( 887 b, "BehaviourDescription::setElasticMaterialProperties: " + m); 888 }; 889 throw_if(!this->allowsNewUserDefinedVariables(), 890 "new variables are can't be defined after the first code block."); 891 throw_if((this->getBehaviourType() != 892 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) && 893 (this->getBehaviourType() != 894 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR), 895 "only finite and strain behaviour are supported"); 896 this->setAttribute(BehaviourDescription::requiresStiffnessTensor, false, 897 false); 898 throw_if(!this->elasticMaterialProperties.empty(), 899 "elastic material property already declared"); 900 auto lemps = 901 emps; // local copy, swap to data member if no exceptions is thrown 902 if (emps.size() == 2u) { 903 if (this->isElasticSymmetryTypeDefined()) { 904 throw_if(this->getElasticSymmetryType() != mfront::ISOTROPIC, 905 "inconsistent elastic symmetry type"); 906 } else { 907 this->setElasticSymmetryType(mfront::ISOTROPIC); 908 } 909 checkElasticMaterialProperty( 910 *this, lemps[0], tfel::glossary::Glossary::YoungModulus, "young"); 911 checkElasticMaterialProperty( 912 *this, lemps[1], tfel::glossary::Glossary::PoissonRatio, "nu"); 913 } else if (emps.size() == 9u) { 914 throw_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 915 "the behaviour is not orthotropic."); 916 if (this->isElasticSymmetryTypeDefined()) { 917 throw_if(this->getElasticSymmetryType() != mfront::ORTHOTROPIC, 918 "inconsistent elastic symmetry type"); 919 } else { 920 this->setElasticSymmetryType(mfront::ORTHOTROPIC); 921 } 922 checkElasticMaterialProperty( 923 *this, lemps[0], tfel::glossary::Glossary::YoungModulus1, "young1"); 924 checkElasticMaterialProperty( 925 *this, lemps[1], tfel::glossary::Glossary::YoungModulus2, "young2"); 926 checkElasticMaterialProperty( 927 *this, lemps[2], tfel::glossary::Glossary::YoungModulus3, "young3"); 928 checkElasticMaterialProperty( 929 *this, lemps[3], tfel::glossary::Glossary::PoissonRatio12, "nu12"); 930 checkElasticMaterialProperty( 931 *this, lemps[4], tfel::glossary::Glossary::PoissonRatio23, "nu23"); 932 checkElasticMaterialProperty( 933 *this, lemps[5], tfel::glossary::Glossary::PoissonRatio13, "nu13"); 934 checkElasticMaterialProperty( 935 *this, lemps[6], tfel::glossary::Glossary::ShearModulus12, "mu12"); 936 checkElasticMaterialProperty( 937 *this, lemps[7], tfel::glossary::Glossary::ShearModulus23, "mu23"); 938 checkElasticMaterialProperty( 939 *this, lemps[8], tfel::glossary::Glossary::ShearModulus13, "mu13"); 940 } else { 941 throw_if(true, "unsupported behaviour type"); 942 } 943 this->elasticMaterialProperties.swap(lemps); 944 } // end of BehaviourDescription::setElasticMaterialProperties 945 getElasticSymmetryType() const946 BehaviourSymmetryType BehaviourDescription::getElasticSymmetryType() const { 947 if (!this->estypeIsDefined) { 948 this->estype = this->getSymmetryType(); 949 this->estypeIsDefined = true; 950 } 951 return this->estype; 952 } // end of BehaviourDescription::getElasticSymmetryType 953 setElasticSymmetryType(const BehaviourSymmetryType t)954 void BehaviourDescription::setElasticSymmetryType( 955 const BehaviourSymmetryType t) { 956 tfel::raise_if(this->estypeIsDefined, 957 "BehaviourDescription::setElasticSymmetryType: " 958 "elastic symmetry type already declared"); 959 const auto s = this->getSymmetryType(); 960 tfel::raise_if((s == mfront::ISOTROPIC) && (t == mfront::ORTHOTROPIC), 961 "BehaviourDescription::setElasticSymmetryType: " 962 "can't define an orthotropic elastic symmetry for " 963 "an isotropic material"); 964 this->estype = t; 965 this->estypeIsDefined = true; 966 } // end of BehaviourDescription::setElasticSymmetryType 967 isElasticSymmetryTypeDefined() const968 bool BehaviourDescription::isElasticSymmetryTypeDefined() const { 969 return this->estypeIsDefined; 970 } // end of BehaviourDescription::isElasticSymmetryTypeDefined 971 getSymmetryType() const972 BehaviourSymmetryType BehaviourDescription::getSymmetryType() const { 973 if (!this->stypeIsDefined) { 974 this->stype = mfront::ISOTROPIC; 975 this->stypeIsDefined = true; 976 } 977 return this->stype; 978 } // end of BehaviourDescription::getSymmetryType 979 setSymmetryType(const BehaviourSymmetryType t)980 void BehaviourDescription::setSymmetryType(const BehaviourSymmetryType t) { 981 tfel::raise_if(this->stypeIsDefined, 982 "BehaviourDescription::setSymmetryType: " 983 "symmetry type already declared"); 984 this->stype = t; 985 this->stypeIsDefined = true; 986 } // end of BehaviourDescription::setSymmetryType 987 isSymmetryTypeDefined() const988 bool BehaviourDescription::isSymmetryTypeDefined() const { 989 return this->stypeIsDefined; 990 } // end of BehaviourDescription::setSymmetryType 991 setCrystalStructure(const CrystalStructure s)992 void BehaviourDescription::setCrystalStructure(const CrystalStructure s) { 993 tfel::raise_if(this->hasCrystalStructure(), 994 "BehaviourDescription::setCrystalStructure: " 995 "crystal structure already declared"); 996 this->gs = SlipSystemsDescription(s); 997 } // end of BehaviourDescription::setCrystalStructure 998 hasCrystalStructure() const999 bool BehaviourDescription::hasCrystalStructure() const { 1000 return !this->gs.empty(); 1001 } // end of BehaviourDescription::hasCrystalStructure 1002 1003 BehaviourDescription::CrystalStructure getCrystalStructure() const1004 BehaviourDescription::getCrystalStructure() const { 1005 tfel::raise_if(!this->hasCrystalStructure(), 1006 "BehaviourDescription::setCrystalStructure: " 1007 "no crystal structure declared"); 1008 return this->gs.get<SlipSystemsDescription>().getCrystalStructure(); 1009 } // end of BehaviourDescription::getCrystalStructure 1010 addHillTensor(const VariableDescription & v,const std::vector<MaterialProperty> & hcs)1011 void BehaviourDescription::addHillTensor( 1012 const VariableDescription& v, const std::vector<MaterialProperty>& hcs) { 1013 auto throw_if = [](const bool c, const std::string& m) { 1014 tfel::raise_if(c, "BehaviourDescription::addHillTensor: " + m); 1015 }; 1016 throw_if( 1017 (this->getBehaviourType() != 1018 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) && 1019 (this->getBehaviourType() != 1020 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR), 1021 "this method is only valid for small and finite strain behaviours"); 1022 throw_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 1023 "the behaviour is not orthotropic."); 1024 throw_if(hcs.size() != 6u, "invalid number of Hill coefficients"); 1025 throw_if(v.arraySize != 1u, "invalid array size"); 1026 throw_if(v.type != "tfel::math::st2tost2<N,stress>", "invalid type"); 1027 this->addLocalVariable(ModellingHypothesis::UNDEFINEDHYPOTHESIS, v); 1028 HillTensor h; 1029 h.name = v.name; 1030 h.symbolic_form = v.symbolic_form; 1031 std::copy(hcs.begin(), hcs.end(), std::back_inserter(h.c)); 1032 this->hillTensors.push_back(std::move(h)); 1033 } // end of BehaviourDescription::addHillTensor 1034 1035 const std::vector<BehaviourDescription::HillTensor>& getHillTensors() const1036 BehaviourDescription::getHillTensors() const { 1037 return this->hillTensors; 1038 } // end of BehaviourDescription::getHillTensors 1039 declareAsGenericBehaviour()1040 void BehaviourDescription::declareAsGenericBehaviour() { 1041 tfel::raise_if(!this->type.empty(), 1042 "BehaviourDescription::declareAsGenericBehaviour: " 1043 "behaviour type has already been defined"); 1044 this->type = GENERALBEHAVIOUR; 1045 } // end of BehaviourDescription::declareAsGenericBehaviour 1046 declareAsASmallStrainStandardBehaviour()1047 void BehaviourDescription::declareAsASmallStrainStandardBehaviour() { 1048 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1049 tfel::raise_if( 1050 !this->type.empty(), 1051 "BehaviourDescription::declareAsASmallStrainStandardBehaviour: " 1052 "behaviour type has already been defined"); 1053 tfel::raise_if( 1054 !this->mvariables.empty(), 1055 "BehaviourDescription::declareAsASmallStrainStandardBehaviour: " 1056 "some driving variables are already declared"); 1057 Gradient eto("StrainStensor", "\u03B5\u1D57\u1D52", "eto"); 1058 Gradient::setIsIncrementKnownAttribute(eto, true); 1059 eto.setGlossaryName("Strain"); 1060 ThermodynamicForce sig("StressStensor", "\u03C3", "sig"); 1061 sig.setGlossaryName("Stress"); 1062 this->mvariables.push_back({eto, sig}); 1063 this->type = BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR; 1064 this->registerMemberName(h, "eto"); 1065 this->registerMemberName(h, "deto"); 1066 this->registerMemberName(h, "sig"); 1067 this->registerGlossaryName(h, "eto", "Strain"); 1068 this->registerGlossaryName(h, "sig", "Stress"); 1069 } // end of BehaviourDescription::declareAsASmallStrainStandardBehaviour 1070 declareAsAFiniteStrainStandardBehaviour(const bool b)1071 void BehaviourDescription::declareAsAFiniteStrainStandardBehaviour( 1072 const bool b) { 1073 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1074 tfel::raise_if( 1075 !this->type.empty(), 1076 "BehaviourDescription::declareAsAFiniteStrainStandardBehaviour: " 1077 "behaviour type has already been defined"); 1078 tfel::raise_if( 1079 !this->mvariables.empty(), 1080 "BehaviourDescription::declareAsAFiniteStrainStandardBehaviour: " 1081 "some driving variables are already declared"); 1082 Gradient F("DeformationGradientTensor", "F"); 1083 F.setGlossaryName("DeformationGradient"); 1084 Gradient::setIsIncrementKnownAttribute(F, false); 1085 ThermodynamicForce sig("StressStensor", "\u03C3", "sig"); 1086 sig.setGlossaryName("Stress"); 1087 this->mvariables.push_back({F, sig}); 1088 this->type = BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR; 1089 if (b) { 1090 this->registerMemberName(h, "F"); 1091 this->registerMemberName(h, "dF"); 1092 } 1093 this->registerMemberName(h, "F0"); 1094 this->registerMemberName(h, "F1"); 1095 this->registerMemberName(h, "sig"); 1096 this->registerGlossaryName(h, "F1", "DeformationGradient"); 1097 this->registerGlossaryName(h, "sig", "Stress"); 1098 } 1099 declareAsACohesiveZoneModel()1100 void BehaviourDescription::declareAsACohesiveZoneModel() { 1101 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1102 tfel::raise_if(!this->type.empty(), 1103 "BehaviourDescription::declareAsACohesiveZoneModel: " 1104 "behaviour type has already been defined"); 1105 tfel::raise_if(!this->mvariables.empty(), 1106 "BehaviourDescription::declareAsACohesiveZoneModel: " 1107 "some driving variables are already declared"); 1108 Gradient u("DisplacementTVector", "u"); 1109 u.setGlossaryName("OpeningDisplacement"); 1110 Gradient::setIsIncrementKnownAttribute(u, true); 1111 ThermodynamicForce t("ForceTVector", "t"); 1112 t.setGlossaryName("CohesiveForce"); 1113 this->mvariables.push_back({u, t}); 1114 this->type = BehaviourDescription::COHESIVEZONEMODEL; 1115 this->registerMemberName(h, "u"); 1116 this->registerMemberName(h, "du"); 1117 this->registerMemberName(h, "t"); 1118 this->registerGlossaryName(h, "u", "OpeningDisplacement"); 1119 this->registerGlossaryName(h, "t", "CohesiveForce"); 1120 } 1121 addLocalDataStructure(const LocalDataStructure & lds,const BehaviourData::RegistrationStatus s)1122 void BehaviourDescription::addLocalDataStructure( 1123 const LocalDataStructure& lds, 1124 const BehaviourData::RegistrationStatus s) { 1125 auto structify = [](const std::vector<LocalDataStructure::Variable>& vars) { 1126 auto r = std::string("struct{\n"); 1127 for (const auto& v : vars) { 1128 if (v.asize == 1u) { 1129 r += v.type + ' ' + v.name + ";\n"; 1130 } else { 1131 r += v.type + ' ' + v.name + "[" + std::to_string(v.asize) + "];\n"; 1132 } 1133 } 1134 r += "}"; 1135 return r; 1136 }; 1137 tfel::raise_if( 1138 !tfel::utilities::CxxTokenizer::isValidIdentifier(lds.name, true), 1139 "BehaviourDSLCommon::addLocalDataStructure: " 1140 "invalid local structure name '" + 1141 lds.name + "'"); 1142 const auto mh = lds.getSpecialisedHypotheses(); 1143 for (const auto h : mh) { 1144 if (!lds.get(h).empty()) { // paranoiac checks, this can't occur 1145 this->addLocalVariable(h, {structify(lds.get(h)), lds.name, 1u, 0u}, s); 1146 } 1147 } 1148 const auto v = lds.get(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 1149 if (v.empty()) { 1150 return; 1151 } 1152 auto vd = VariableDescription{structify(v), lds.name, 1u, 0u}; 1153 if (!this->areAllMechanicalDataSpecialised()) { 1154 this->d.addLocalVariable(vd, s); 1155 } 1156 for (auto& ld : this->sd) { 1157 if (std::find(mh.begin(), mh.end(), ld.first) == mh.end()) { 1158 ld.second->addLocalVariable(vd, s); 1159 } 1160 } 1161 } 1162 addMainVariable(const Gradient & g,const ThermodynamicForce & f)1163 void BehaviourDescription::addMainVariable(const Gradient& g, 1164 const ThermodynamicForce& f) { 1165 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1166 tfel::raise_if( 1167 this->getBehaviourType() != BehaviourDescription::GENERALBEHAVIOUR, 1168 "BehaviourDescription::addMainVariables: " 1169 "one can not add a main variable if the behaviour " 1170 "don't have a general behaviour type"); 1171 tfel::raise_if( 1172 !this->allowsNewUserDefinedVariables(), 1173 "BehaviourDescription::addMainVariables: " 1174 "new variables are can't be defined after the first code block."); 1175 for (const auto& v : this->mvariables) { 1176 tfel::raise_if(g.name == v.first.name, 1177 "BehaviourDescription::addMainVariables: " 1178 "a driving variable '" + 1179 g.name + 1180 "' has " 1181 "already been declared"); 1182 tfel::raise_if(f.name == v.second.name, 1183 "BehaviourDescription::addMainVariables: " 1184 "a driving variable '" + 1185 f.name + 1186 "' has " 1187 "already been declared"); 1188 } 1189 if (Gradient::isIncrementKnown(g)) { 1190 this->registerMemberName(h, g.name); 1191 this->registerMemberName(h, "d" + g.name); 1192 } else { 1193 this->registerMemberName(h, g.name + "0"); 1194 this->registerMemberName(h, g.name + "1"); 1195 } 1196 if (g.hasGlossaryName()) { 1197 this->registerGlossaryName(h, g.name, g.getExternalName()); 1198 } 1199 if (g.hasEntryName()) { 1200 this->registerEntryName(h, g.name, g.getExternalName()); 1201 } 1202 this->registerMemberName(h, f.name); 1203 if (f.hasGlossaryName()) { 1204 this->registerGlossaryName(h, f.name, f.getExternalName()); 1205 } 1206 if (f.hasEntryName()) { 1207 this->registerEntryName(h, f.name, f.getExternalName()); 1208 } 1209 this->registerMemberName(h, this->getTangentOperatorBlockName({f, g})); 1210 this->mvariables.push_back({g, f}); 1211 } // end of BehaviourDescription::addMainVariables 1212 1213 const std::vector<std::pair<Gradient, ThermodynamicForce>>& getMainVariables() const1214 BehaviourDescription::getMainVariables() const { 1215 return this->mvariables; 1216 } // end of BehaviourDescription::getMainVariables 1217 getGradient(const std::string & n)1218 Gradient& BehaviourDescription::getGradient(const std::string& n) { 1219 using value_type = std::pair<Gradient, ThermodynamicForce>; 1220 const auto p = 1221 std::find_if(this->mvariables.begin(), this->mvariables.end(), 1222 [&n](const value_type& v) { return v.first.name == n; }); 1223 tfel::raise_if(p == this->mvariables.end(), 1224 "BehaviourDescription::getGradient: " 1225 "unknown driving variable '" + 1226 n + "'"); 1227 return p->first; 1228 } // end of BehaviourDescription::getGradient 1229 getGradient(const std::string & n) const1230 const Gradient& BehaviourDescription::getGradient( 1231 const std::string& n) const { 1232 using value_type = std::pair<Gradient, ThermodynamicForce>; 1233 const auto p = 1234 std::find_if(this->mvariables.begin(), this->mvariables.end(), 1235 [&n](const value_type& v) { return v.first.name == n; }); 1236 tfel::raise_if(p == this->mvariables.end(), 1237 "BehaviourDescription::getGradient: " 1238 "unknown driving variable '" + 1239 n + "'"); 1240 return p->first; 1241 } // end of BehaviourDescription::getGradient 1242 getThermodynamicForce(const std::string & n)1243 ThermodynamicForce& BehaviourDescription::getThermodynamicForce( 1244 const std::string& n) { 1245 using value_type = std::pair<Gradient, ThermodynamicForce>; 1246 const auto p = 1247 std::find_if(this->mvariables.begin(), this->mvariables.end(), 1248 [&n](const value_type& v) { return v.second.name == n; }); 1249 tfel::raise_if(p == this->mvariables.end(), 1250 "BehaviourDescription::getGradient: " 1251 "unknown driving variable '" + 1252 n + "'"); 1253 return p->second; 1254 } // end of BehaviourDescription::getThermodynamicForce 1255 getThermodynamicForce(const std::string & n) const1256 const ThermodynamicForce& BehaviourDescription::getThermodynamicForce( 1257 const std::string& n) const { 1258 using value_type = std::pair<Gradient, ThermodynamicForce>; 1259 const auto p = 1260 std::find_if(this->mvariables.begin(), this->mvariables.end(), 1261 [&n](const value_type& v) { return v.second.name == n; }); 1262 tfel::raise_if(p == this->mvariables.end(), 1263 "BehaviourDescription::getGradient: " 1264 "unknown driving variable '" + 1265 n + "'"); 1266 return p->second; 1267 } // end of BehaviourDescription::getThermodynamicForce 1268 isGradientName(const std::string & n) const1269 bool BehaviourDescription::isGradientName(const std::string& n) const { 1270 for (const auto& v : this->getMainVariables()) { 1271 if (v.first.name == n) { 1272 return true; 1273 } 1274 } 1275 return false; 1276 } // end of BehaviourDescription::isGradientName 1277 isGradientIncrementName(const std::string & n) const1278 bool BehaviourDescription::isGradientIncrementName( 1279 const std::string& n) const { 1280 for (const auto& v : this->getMainVariables()) { 1281 const auto& g = v.first; 1282 if ((Gradient::isIncrementKnown(g)) && ("d" + g.name == n)) { 1283 return true; 1284 } 1285 } 1286 return false; 1287 } // end of BehaviourDescription::isGradientIncrementName 1288 isThermodynamicForceName(const std::string & n) const1289 bool BehaviourDescription::isThermodynamicForceName( 1290 const std::string& n) const { 1291 for (const auto& v : this->getMainVariables()) { 1292 const auto& tf = v.second; 1293 if (tf.name == n) { 1294 return true; 1295 } 1296 } 1297 return false; 1298 } // end of BehaviourDescription::isThermodynamicForceName 1299 1300 std::pair<SupportedTypes::TypeSize, SupportedTypes::TypeSize> getMainVariablesSize() const1301 BehaviourDescription::getMainVariablesSize() const { 1302 auto ov = SupportedTypes::TypeSize{}; 1303 auto of = SupportedTypes::TypeSize{}; 1304 for (const auto& v : this->getMainVariables()) { 1305 ov += this->getTypeSize(v.first.type, 1u); 1306 of += this->getTypeSize(v.second.type, 1u); 1307 } 1308 return {ov, of}; 1309 } // end of BehaviourDescription::getMainVariablesSize 1310 getTangentOperatorBlockName(const std::pair<VariableDescription,VariableDescription> & block) const1311 std::string BehaviourDescription::getTangentOperatorBlockName( 1312 const std::pair<VariableDescription, VariableDescription>& block) const { 1313 const auto& a = block.first; 1314 const auto& b = block.second; 1315 if (this->isGradientName(b.name)) { 1316 if (Gradient::isIncrementKnown(b)) { 1317 return "d" + a.name + "_dd" + b.name; 1318 } else { 1319 return "d" + a.name + "_d" + b.name + "1"; 1320 } 1321 } 1322 return "d" + a.name + "_dd" + b.name; 1323 } // end of BehaviourDescription::getTangentOperatorBlockName 1324 getTangentOperatorBlockSymbolicName(const std::pair<VariableDescription,VariableDescription> & block) const1325 std::string BehaviourDescription::getTangentOperatorBlockSymbolicName( 1326 const std::pair<VariableDescription, VariableDescription>& block) const { 1327 const auto& a = block.first; 1328 const auto& b = block.second; 1329 const auto tmp = "\u2202" + displayName(a) + "\u2215\u2202"; 1330 if ((this->isGradientName(b.name)) && (!Gradient::isIncrementKnown(b))) { 1331 return tmp + displayName(b) + "1"; 1332 } 1333 return tmp + "\u0394" + displayName(b); 1334 } // end of BehaviourDescription::getTangentOperatorBlockSymbolicName 1335 addTangentOperatorBlock(const std::string & bn)1336 void BehaviourDescription::addTangentOperatorBlock(const std::string& bn) { 1337 tfel::raise_if( 1338 this->getBehaviourType() != BehaviourDescription::GENERALBEHAVIOUR, 1339 "BehaviourDescription::addTangentOperatorBlock: " 1340 "the behaviour must be generic " 1341 "to add a tangent operator block"); 1342 // check that the operator blocks exists 1343 const auto b = decomposeAdditionalTangentOperatorBlock(*this, bn); 1344 const auto block_name = this->getTangentOperatorBlockName(b); 1345 for (const auto& eb : this->getTangentOperatorBlocks()) { 1346 if (block_name == this->getTangentOperatorBlockName(eb)) { 1347 tfel::raise( 1348 "BehaviourDescription::addTangentOperatorBlock: " 1349 "tangent operator block '" + 1350 bn + "' already defined"); 1351 } 1352 } 1353 this->additionalTangentOperatorBlocks.push_back(b); 1354 } // end of addTangentOperatorBlock 1355 addTangentOperatorBlocks(const std::vector<std::string> & blocks)1356 void BehaviourDescription::addTangentOperatorBlocks( 1357 const std::vector<std::string>& blocks) { 1358 for (const auto& b : blocks) { 1359 this->addTangentOperatorBlock(b); 1360 } 1361 } // end of BehaviourDescription::addTangentOperatorBlocks 1362 setTangentOperatorBlocks(const std::vector<std::string> & blocks)1363 void BehaviourDescription::setTangentOperatorBlocks( 1364 const std::vector<std::string>& blocks) { 1365 if (!this->additionalTangentOperatorBlocks.empty()) { 1366 if (this->useDefaultTangentOperatorBlocks) { 1367 tfel::raise( 1368 "BehaviourDescription::setTangentOperatorBlocks: " 1369 "invalid call, must be called before adding tangent operator " 1370 "blocks"); 1371 } else { 1372 tfel::raise( 1373 "BehaviourDescription::setTangentOperatorBlocks: " 1374 "invalid call, this method has already been called"); 1375 } 1376 } 1377 if (blocks.empty()) { 1378 tfel::raise( 1379 "BehaviourDescription::setTangentOperatorBlocks: " 1380 "empty list of tangent operator blocks"); 1381 } 1382 this->useDefaultTangentOperatorBlocks = false; 1383 for (const auto& b : blocks) { 1384 this->addTangentOperatorBlock(b); 1385 } 1386 } // end of BehaviourDescription::setTangentOperatorBlocks 1387 1388 std::vector<std::pair<VariableDescription, VariableDescription>> getTangentOperatorBlocks() const1389 BehaviourDescription::getTangentOperatorBlocks() const { 1390 auto blocks = 1391 std::vector<std::pair<VariableDescription, VariableDescription>>{}; 1392 if (this->useDefaultTangentOperatorBlocks) { 1393 for (const auto& f : this->getMainVariables()) { 1394 for (const auto& g : this->getMainVariables()) { 1395 blocks.push_back({f.second, g.first}); 1396 } 1397 } 1398 } 1399 blocks.insert(blocks.end(), this->additionalTangentOperatorBlocks.begin(), 1400 this->additionalTangentOperatorBlocks.end()); 1401 return blocks; 1402 } // end of BehaviourDescription::getTangentOperatorBlocks 1403 setThermalExpansionCoefficient(MaterialProperty a)1404 void BehaviourDescription::setThermalExpansionCoefficient( 1405 MaterialProperty a) { 1406 using tfel::glossary::Glossary; 1407 auto throw_if = [](const bool c, const std::string& m) { 1408 tfel::raise_if( 1409 c, "BehaviourDescription::setThermalExpansionCoefficient: " + m); 1410 }; 1411 throw_if(!this->allowsNewUserDefinedVariables(), 1412 "new variables are can't be defined after the first code block."); 1413 tfel::raise_if(this->areThermalExpansionCoefficientsDefined(), 1414 "BehaviourDescription::setThermalExpansionCoefficient: " 1415 "thermal expansion coefficient already defined"); 1416 this->setAttribute( 1417 ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1418 BehaviourDescription::requiresThermalExpansionCoefficientTensor, false); 1419 checkThermalExpansionCoefficientArgument( 1420 *this, a, Glossary::ThermalExpansion, "alpha"); 1421 this->thermalExpansionCoefficients.push_back(a); 1422 } // end of BehaviourDescription::setThermalExpansionCoefficient 1423 setThermalExpansionCoefficients(MaterialProperty a1,MaterialProperty a2,MaterialProperty a3)1424 void BehaviourDescription::setThermalExpansionCoefficients( 1425 MaterialProperty a1, MaterialProperty a2, MaterialProperty a3) { 1426 using tfel::glossary::Glossary; 1427 auto throw_if = [](const bool c, const std::string& m) { 1428 tfel::raise_if( 1429 c, "BehaviourDescription::setThermalExpansionCoefficients: " + m); 1430 }; 1431 throw_if(!this->allowsNewUserDefinedVariables(), 1432 "new variables are can't be defined after the first code block."); 1433 throw_if(this->areThermalExpansionCoefficientsDefined(), 1434 "thermal expansion coefficient already defined"); 1435 throw_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 1436 "the behaviour is not orthotropic."); 1437 this->setAttribute( 1438 ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1439 BehaviourDescription::requiresThermalExpansionCoefficientTensor, false); 1440 checkThermalExpansionCoefficientArgument( 1441 *this, a1, Glossary::ThermalExpansion1, "alpha1"); 1442 checkThermalExpansionCoefficientArgument( 1443 *this, a2, Glossary::ThermalExpansion2, "alpha2"); 1444 checkThermalExpansionCoefficientArgument( 1445 *this, a3, Glossary::ThermalExpansion3, "alpha3"); 1446 this->thermalExpansionCoefficients.push_back(a1); 1447 this->thermalExpansionCoefficients.push_back(a2); 1448 this->thermalExpansionCoefficients.push_back(a3); 1449 } // end of BehaviourDescription::setThermalExpansionCoefficients 1450 addStressFreeExpansion(const Hypothesis h,const StressFreeExpansionDescription & sfed)1451 void BehaviourDescription::addStressFreeExpansion( 1452 const Hypothesis h, const StressFreeExpansionDescription& sfed) { 1453 auto throw_if = [](const bool c, const std::string& m) { 1454 tfel::raise_if(c, "BehaviourDescription::addStressFreeExpansion: " + m); 1455 }; 1456 throw_if(!this->allowsNewUserDefinedVariables(), 1457 "new variables are can't be defined after the first code block."); 1458 if ((sfed.is<BehaviourData::AxialGrowth>()) || 1459 (sfed.is<BehaviourData::OrthotropicStressFreeExpansion>()) || 1460 (sfed.is<BehaviourData::OrthotropicStressFreeExpansionII>())) { 1461 throw_if((this->getBehaviourType() != 1462 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 1463 (this->getBehaviourType() != 1464 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 1465 "AxialGrowth or OrthotropicStressFreeExpansion " 1466 "are only valid for small or " 1467 "finite strain behaviours"); 1468 throw_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 1469 "axial growth is only valid for orthotropic behaviour"); 1470 } else { 1471 throw_if((!sfed.is<BehaviourData::VolumeSwellingStressFreeExpansion>()) && 1472 (!sfed.is<BehaviourData::Relocation>()) && 1473 (!sfed.is<BehaviourData::IsotropicStressFreeExpansion>()), 1474 "internal error, unsupported stress free expansion type"); 1475 throw_if((this->getBehaviourType() != 1476 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 1477 (this->getBehaviourType() != 1478 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 1479 "Isotropic, Relocation or VolumeSwelling " 1480 "are only valid for small or " 1481 "finite strain behaviours"); 1482 } 1483 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 1484 this->d.addStressFreeExpansion(sfed); 1485 for (auto& md : this->sd) { 1486 md.second->addStressFreeExpansion(sfed); 1487 } 1488 } else { 1489 this->getBehaviourData2(h).addStressFreeExpansion(sfed); 1490 } 1491 } // end of BehaviourDescription::addStressFreeExpansion 1492 requiresStressFreeExpansionTreatment(const Hypothesis h) const1493 bool BehaviourDescription::requiresStressFreeExpansionTreatment( 1494 const Hypothesis h) const { 1495 return ((this->areThermalExpansionCoefficientsDefined()) || 1496 (!this->getBehaviourData(h) 1497 .getStressFreeExpansionDescriptions() 1498 .empty()) || 1499 (this->hasCode(h, BehaviourData::ComputeStressFreeExpansion))); 1500 } // end of BehaviourDescription::requiresStressFreeExpansionTreatment 1501 areThermalExpansionCoefficientsDefined() const1502 bool BehaviourDescription::areThermalExpansionCoefficientsDefined() const { 1503 return !this->thermalExpansionCoefficients.empty(); 1504 } // end of BehaviourDescription::areThermalExpansionCoefficientsDefined 1505 1506 const std::vector<BehaviourDescription::MaterialProperty>& getThermalExpansionCoefficients() const1507 BehaviourDescription::getThermalExpansionCoefficients() const { 1508 tfel::raise_if(!this->areThermalExpansionCoefficientsDefined(), 1509 "BehaviourDescription::getThermalExpansionCoefficients: " 1510 "no thermal expansion coefficients defined"); 1511 return this->thermalExpansionCoefficients; 1512 } 1513 setSlipSystems(const std::vector<SlipSystem> & ss)1514 void BehaviourDescription::setSlipSystems(const std::vector<SlipSystem>& ss) { 1515 auto throw_if = [](const bool c, const std::string& m) { 1516 tfel::raise_if(c, "BehaviourDescription::setSlipSystems: " + m); 1517 }; 1518 const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1519 throw_if(!this->allowsNewUserDefinedVariables(), 1520 "new variables are can't be defined after the first code block."); 1521 throw_if(ss.empty(), "empty number of slip systems specified"); 1522 throw_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 1523 "the behaviour is not orthotropic"); 1524 throw_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 1525 "the behaviour is not orthotropic"); 1526 throw_if(!this->hasCrystalStructure(), 1527 "crystal structure is not defined yet"); 1528 for (const auto& s : ss) { 1529 auto& ssd = this->gs.get<SlipSystemsDescription>(); 1530 const auto nb = ssd.getNumberOfSlipSystemsFamilies(); 1531 if (s.is<SlipSystemsDescription::system3d>()) { 1532 const auto& s3d = s.get<SlipSystemsDescription::system3d>(); 1533 ssd.addSlipSystemsFamily(s3d.burgers, s3d.plane); 1534 } else { 1535 throw_if(!s.is<SlipSystemsDescription::system4d>(), 1536 "internal error (unsupported slip system definition)"); 1537 const auto& s4d = s.get<SlipSystemsDescription::system4d>(); 1538 ssd.addSlipSystemsFamily(s4d.burgers, s4d.plane); 1539 } 1540 const auto css = ssd.getSlipSystems(nb); 1541 StaticVariableDescription v("int", "Nss" + std::to_string(nb), 0u, 1542 static_cast<int>(css.size())); 1543 this->addStaticVariable(uh, v, BehaviourData::UNREGISTRED); 1544 } 1545 const auto& ssd = this->gs.get<SlipSystemsDescription>(); 1546 auto n = int{}; 1547 for (SlipSystemsDescription::size_type i = 0; 1548 i != ssd.getNumberOfSlipSystemsFamilies(); ++i) { 1549 const auto css = ssd.getSlipSystems(i); 1550 n += static_cast<int>(css.size()); 1551 } 1552 StaticVariableDescription v("int", "Nss", 0u, n); 1553 this->addStaticVariable(uh, v, BehaviourData::UNREGISTRED); 1554 } 1555 areSlipSystemsDefined() const1556 bool BehaviourDescription::areSlipSystemsDefined() const { 1557 if (this->gs.empty()) { 1558 return false; 1559 } 1560 auto& ssd = this->gs.get<SlipSystemsDescription>(); 1561 return ssd.getNumberOfSlipSystemsFamilies() != 0; 1562 } // end of BehaviourDescription::areSlipSystemsDefined 1563 1564 const tfel::material::SlipSystemsDescription& getSlipSystems() const1565 BehaviourDescription::getSlipSystems() const { 1566 tfel::raise_if(!this->areSlipSystemsDefined(), 1567 "BehaviourDescription::getSlipSystems: " 1568 "no slip systems defined"); 1569 return this->gs; 1570 } // end of BehaviourDescription::getSlipSystems 1571 1572 BehaviourDescription::InteractionMatrixStructure getInteractionMatrixStructure() const1573 BehaviourDescription::getInteractionMatrixStructure() const { 1574 tfel::raise_if(!this->areSlipSystemsDefined(), 1575 "BehaviourDescription::getInteractionMatrixStructure: " 1576 "no slip system defined"); 1577 return this->gs.get<SlipSystemsDescription>() 1578 .getInteractionMatrixStructure(); 1579 } // end of BehaviourDescription::getInteractionMatrix 1580 hasInteractionMatrix() const1581 bool BehaviourDescription::hasInteractionMatrix() const { 1582 if (!this->gs.is<SlipSystemsDescription>()) { 1583 return false; 1584 } 1585 return this->gs.get<SlipSystemsDescription>().hasInteractionMatrix(); 1586 } // end of BehaviourDescription::hasInteractionMatrix 1587 setInteractionMatrix(const std::vector<long double> & m)1588 void BehaviourDescription::setInteractionMatrix( 1589 const std::vector<long double>& m) { 1590 auto throw_if = [](const bool c, const std::string& msg) { 1591 tfel::raise_if(c, "BehaviourDescription::setInteractionMatrix: " + msg); 1592 }; 1593 throw_if(!this->allowsNewUserDefinedVariables(), 1594 "new variables are can't be defined after the first code block."); 1595 throw_if(!this->areSlipSystemsDefined(), "no slip system defined"); 1596 this->gs.get<SlipSystemsDescription>().setInteractionMatrix(m); 1597 } // end of BehaviourDescription::setInteractionMatrix 1598 hasDislocationsMeanFreePathInteractionMatrix() const1599 bool BehaviourDescription::hasDislocationsMeanFreePathInteractionMatrix() 1600 const { 1601 if (!this->gs.is<SlipSystemsDescription>()) { 1602 return false; 1603 } 1604 return this->gs.get<SlipSystemsDescription>() 1605 .hasDislocationsMeanFreePathInteractionMatrix(); 1606 } // end of 1607 // BehaviourDescription::hasDislocationsMeanFreePathInteractionMatrix 1608 setDislocationsMeanFreePathInteractionMatrix(const std::vector<long double> & m)1609 void BehaviourDescription::setDislocationsMeanFreePathInteractionMatrix( 1610 const std::vector<long double>& m) { 1611 auto throw_if = [](const bool c, const std::string& msg) { 1612 tfel::raise_if(c, 1613 "BehaviourDescription::" 1614 "setDislocationsMeanFreePathInteractionMatrix: " + 1615 msg); 1616 }; 1617 throw_if(!this->allowsNewUserDefinedVariables(), 1618 "new variables are can't be defined after the first code block."); 1619 throw_if(!this->areSlipSystemsDefined(), "no slip system defined"); 1620 this->gs.get<SlipSystemsDescription>() 1621 .setDislocationsMeanFreePathInteractionMatrix(m); 1622 } // end of 1623 // BehaviourDescription::setDislocationsMeanFreePathInteractionMatrix 1624 setUseQt(const bool b)1625 void BehaviourDescription::setUseQt(const bool b) { 1626 tfel::raise_if(this->use_qt, 1627 "BehaviourDescription::setUseQt: " 1628 "setUseQt already called"); 1629 this->use_qt = b; 1630 } // end of BehaviourDescription::setUseQt 1631 useQt() const1632 bool BehaviourDescription::useQt() const { 1633 return this->use_qt; 1634 } // end of BehaviourDescription::useQt 1635 hasTangentOperator() const1636 bool BehaviourDescription::hasTangentOperator() const { 1637 const auto& mvs = this->getMainVariables(); 1638 return (!mvs.empty()) || (!this->additionalTangentOperatorBlocks.empty()); 1639 } // end of BehaviourDescription::hasTangentOperator 1640 hasTrivialTangentOperatorStructure() const1641 bool BehaviourDescription::hasTrivialTangentOperatorStructure() const { 1642 const auto& mvs = this->getMainVariables(); 1643 return (mvs.size() == 1) && (mvs.front().first.arraySize == 1u) && 1644 (mvs.front().second.arraySize == 1u) && 1645 (this->additionalTangentOperatorBlocks.empty()); 1646 } // end of BehaviourDescription::hasTrivialTangentOperatorStructure 1647 computeTangentOperatorSize() const1648 std::string BehaviourDescription::computeTangentOperatorSize() const { 1649 const auto& blocks = this->getTangentOperatorBlocks(); 1650 if (blocks.empty()) { 1651 return "0"; 1652 } 1653 std::ostringstream t; 1654 auto p = blocks.begin(); 1655 const auto pe = blocks.end(); 1656 t << "(" << p->first.getTypeSize() << ")" 1657 << "*(" << p->second.getTypeSize() << ")"; 1658 ++p; 1659 while (p != pe) { 1660 t << "+" 1661 << "(" << p->first.getTypeSize() << ")" 1662 << "*(" << p->second.getTypeSize() << ")"; 1663 ++p; 1664 } 1665 return t.str(); 1666 } // end of BehaviourDescription::computeTangentOperatorSize 1667 getTangentOperatorType() const1668 std::string BehaviourDescription::getTangentOperatorType() const { 1669 if (this->getBehaviourType() == GENERALBEHAVIOUR) { 1670 const auto& mvs = this->getMainVariables(); 1671 if (this->hasTrivialTangentOperatorStructure()) { 1672 const auto& mv = mvs.front(); 1673 const auto gflags = mv.first.getTypeFlag(); 1674 const auto fflags = mv.second.getTypeFlag(); 1675 auto throw_unmatch = [&mv] { 1676 tfel::raise( 1677 "BehaviourDescription::getTangentOperatorType: " 1678 "gradient '" + 1679 mv.first.name + "' is not conjugated with flux '" + 1680 mv.second.name + "'"); 1681 }; 1682 if (gflags == SupportedTypes::SCALAR) { 1683 if (fflags != SupportedTypes::SCALAR) { 1684 throw_unmatch(); 1685 } 1686 return "real"; 1687 } else if (gflags == SupportedTypes::TVECTOR) { 1688 if (fflags != SupportedTypes::TVECTOR) { 1689 throw_unmatch(); 1690 } 1691 return "tfel::math::tmatrix<N,N,real>"; 1692 } else if (gflags == SupportedTypes::STENSOR) { 1693 if (fflags != SupportedTypes::STENSOR) { 1694 throw_unmatch(); 1695 } 1696 return "tfel::math::st2tost2<N,real>"; 1697 } else if (gflags == SupportedTypes::TENSOR) { 1698 if (fflags == SupportedTypes::STENSOR) { 1699 return "tfel::math::t2tost2<N,real>"; 1700 } else if (fflags == SupportedTypes::TENSOR) { 1701 return "tfel::math::t2tot2<N,real>"; 1702 } else { 1703 throw_unmatch(); 1704 } 1705 } else { 1706 tfel::raise( 1707 "BehaviourDescription::getTangentOperatorType: " 1708 "unsupported type for gradient '" + 1709 mv.first.name + "'"); 1710 } 1711 } 1712 return "tfel::math::tvector<" + this->computeTangentOperatorSize() + 1713 ",real>"; 1714 } else if (this->getBehaviourType() == STANDARDSTRAINBASEDBEHAVIOUR) { 1715 return "StiffnessTensor"; 1716 } else if (this->getBehaviourType() == STANDARDFINITESTRAINBEHAVIOUR) { 1717 return "FiniteStrainBehaviourTangentOperator<N,stress>"; 1718 } else if (this->getBehaviourType() == COHESIVEZONEMODEL) { 1719 return "tfel::math::tmatrix<N,N,stress>"; 1720 } 1721 tfel::raise( 1722 "BehaviourDescription::getStiffnessOperatorType: " 1723 "internal error (unsupported behaviour type)"); 1724 } // end of BehaviourDescription::getStiffnessOperatorType 1725 1726 const std::vector<BehaviourData::StressFreeExpansionDescription>& getStressFreeExpansionDescriptions(const Hypothesis h) const1727 BehaviourDescription::getStressFreeExpansionDescriptions( 1728 const Hypothesis h) const { 1729 return this->getBehaviourData(h).getStressFreeExpansionDescriptions(); 1730 } // end of BehaviourDescription::getStressFreeExpansionDescriptions 1731 getStressFreeExpansionType() const1732 std::string BehaviourDescription::getStressFreeExpansionType() const { 1733 if ((this->getBehaviourType() == STANDARDSTRAINBASEDBEHAVIOUR) || 1734 (this->getBehaviourType() == STANDARDFINITESTRAINBEHAVIOUR)) { 1735 return "StrainStensor"; 1736 } 1737 tfel::raise( 1738 "BehaviourDescription::getStressFreeExpansionType: " 1739 "internal error (unsupported behaviour type)"); 1740 } // end of BehaviourDescription::getStressFreeExpansionType 1741 isStressFreeExansionAnisotropic(const Hypothesis h) const1742 bool BehaviourDescription::isStressFreeExansionAnisotropic( 1743 const Hypothesis h) const { 1744 return this->getBehaviourData(h).isStressFreeExansionAnisotropic(); 1745 } // end of BehaviourDescription::isStressFreeExansionAnisotropic 1746 checkModellingHypothesis(const Hypothesis h) const1747 void BehaviourDescription::checkModellingHypothesis( 1748 const Hypothesis h) const { 1749 if (this->getModellingHypotheses().find(h) == 1750 this->getModellingHypotheses().end()) { 1751 std::ostringstream msg; 1752 msg << "BehaviourDescription::checkModellingHypothesis: " 1753 << "modelling hypothesis '" << ModellingHypothesis::toString(h) 1754 << "' is not supported. Refer to the documentation of " 1755 << "the '@ModellingHypothesis' or " 1756 << "the '@ModellingHypotheses' keywords for details.\n"; 1757 msg << "Supported modelling hypotheses are :"; 1758 for (const auto& lh : this->hypotheses) { 1759 msg << "\n- '" << ModellingHypothesis::toString(lh) << "'"; 1760 } 1761 tfel::raise(msg.str()); 1762 } 1763 } // end of BehaviourDescription::checkModellingHypothesis 1764 areModellingHypothesesDefined() const1765 bool BehaviourDescription::areModellingHypothesesDefined() const { 1766 return !this->hypotheses.empty(); 1767 } // end of BehaviourDescription::areModellingHypothesesDefined 1768 1769 const std::set<BehaviourDescription::Hypothesis>& getModellingHypotheses() const1770 BehaviourDescription::getModellingHypotheses() const { 1771 tfel::raise_if(this->hypotheses.empty(), 1772 "BehaviourDescription::getModellingHypotheses: " 1773 "hypothesis undefined yet"); 1774 return this->hypotheses; 1775 } // end of BehaviourDescription::getModellingHypotheses 1776 1777 std::set<BehaviourDescription::Hypothesis> getDistinctModellingHypotheses() const1778 BehaviourDescription::getDistinctModellingHypotheses() const { 1779 const auto& mh = this->getModellingHypotheses(); 1780 if (mh.size() == 1u) { 1781 // if only one modelling hypothesis is supported, it is not 1782 // considered as specialised, so we return it. 1783 return mh; 1784 } 1785 std::set<Hypothesis> dh; 1786 if (!this->areAllMechanicalDataSpecialised()) { 1787 // We return UNDEFINEDHYPOTHESIS to take into account all the 1788 // modelling hypotheses that were not specialised 1789 dh.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 1790 } 1791 for (const auto& h : mh) { 1792 if (this->hasSpecialisedMechanicalData(h)) { 1793 dh.insert(h); 1794 } 1795 } 1796 return dh; 1797 } // end of BehaviourDescription::getDistinctModellingHypotheses 1798 isModellingHypothesisSupported(const Hypothesis h) const1799 bool BehaviourDescription::isModellingHypothesisSupported( 1800 const Hypothesis h) const { 1801 return this->getModellingHypotheses().count(h) != 0u; 1802 } 1803 setModellingHypotheses(const std::set<Hypothesis> & mh,const bool b)1804 void BehaviourDescription::setModellingHypotheses( 1805 const std::set<Hypothesis>& mh, const bool b) { 1806 constexpr const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1807 auto throw_if = [](const bool c, const std::string& m) { 1808 tfel::raise_if(c, "BehaviourDescription::setHypotheses: " + m); 1809 }; 1810 // never ever trust a user 1811 throw_if(mh.empty(), "empty set of modelling hypotheses specificied"); 1812 // never ever trust a user 1813 throw_if(mh.find(uh) != mh.end(), 1814 "undefined modelling hypothesis specified"); 1815 // check that the user did not already set the modelling hypotheses 1816 throw_if(!this->hypotheses.empty(), 1817 "supported modelling hypotheses have already been declared"); 1818 // check that if a specialised version of the behaviour 1819 // is defined, it is present in the set of hypotheses defined here 1820 for (const auto& ld : this->sd) { 1821 throw_if(mh.find(ld.first) == mh.end(), 1822 "partial specialisation of the behaviour exists for " 1823 "the hypothesis '" + 1824 ModellingHypothesis::toString(ld.first) + 1825 "' " 1826 "which is not in the set of hypotheses which have to be " 1827 "supported by the behaviour."); 1828 } 1829 for (const auto h : this->requestedHypotheses) { 1830 throw_if(mh.find(h) == mh.end(), 1831 "a description of the behaviour for " 1832 "the hypothesis '" + 1833 ModellingHypothesis::toString(h) + 1834 "' " 1835 "has been requested earlier, but this hypothesis is not " 1836 "in the set of hypotheses which will to be " 1837 "supported by the behaviour. This may lead to " 1838 "inconsistencies. " 1839 "Cowardly aborting."); 1840 } 1841 if (this->hypotheses.empty()) { 1842 if ((this->stypeIsDefined) && 1843 (this->getSymmetryType() == mfront::ORTHOTROPIC) && 1844 (this->oacIsDefined) && (this->getOrthotropicAxesConvention() == 1845 OrthotropicAxesConvention::PLATE)) { 1846 for (const auto h : mh) { 1847 throw_if((h != ModellingHypothesis::TRIDIMENSIONAL) && 1848 (h != ModellingHypothesis::PLANESTRESS) && 1849 (h != ModellingHypothesis::PLANESTRAIN) && 1850 (h != ModellingHypothesis::GENERALISEDPLANESTRAIN), 1851 "Modelling hypothesis '" + ModellingHypothesis::toString(h) + 1852 "' is not compatible " 1853 "with the `Plate` orthotropic axes convention"); 1854 } 1855 } 1856 this->hypotheses.insert(mh.begin(), mh.end()); 1857 } else { 1858 if (b) { 1859 // find the intersection of the given hypotheses and the 1860 // existing one 1861 std::set<Hypothesis> nh; 1862 for (const auto h : this->hypotheses) { 1863 if (mh.find(h) != mh.end()) { 1864 nh.insert(h); 1865 } 1866 } 1867 throw_if(nh.empty(), 1868 "intersection of previously modelling hypotheses " 1869 "with the new ones is empty"); 1870 // as this is the intersection with previously defined 1871 // hyppotheses, restrictions related to the orthotropic axes 1872 // conditions does not have to be checked. 1873 this->hypotheses.swap(nh); 1874 } else { 1875 throw_if(true, 1876 "supported modelling hypotheses have already been declared"); 1877 } 1878 } 1879 } // end of BehaviourDescription::setModellingHypotheses 1880 1881 const std::vector<ModelDescription>& getModelsDescriptions() const1882 BehaviourDescription::getModelsDescriptions() const { 1883 return this->models; 1884 } // end of BehaviourDescription::getModelsDescriptions 1885 addModelDescription(const ModelDescription & md)1886 void BehaviourDescription::addModelDescription(const ModelDescription& md) { 1887 constexpr const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 1888 for (auto ov : md.outputs) { 1889 VariableDescription dov{ov.type, "d" + ov.name, ov.arraySize, 1890 ov.lineNumber}; 1891 ov.setAttribute("ComputedByExternalModel", true, false); 1892 this->addAuxiliaryStateVariable(uh, ov, BehaviourData::UNREGISTRED); 1893 this->addLocalVariable(uh, dov, BehaviourData::UNREGISTRED); 1894 } 1895 this->models.push_back(md); 1896 } // end of BehaviourDescription::addModelDescription 1897 addMaterialProperties(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)1898 void BehaviourDescription::addMaterialProperties( 1899 const Hypothesis h, 1900 const VariableDescriptionContainer& v, 1901 const BehaviourData::RegistrationStatus s) { 1902 using mptr = void (mfront::BehaviourData::*)( 1903 const mfront::VariableDescription&, 1904 const BehaviourData::RegistrationStatus); 1905 mptr f = &BehaviourData::addMaterialProperty; 1906 this->addVariables(h, v, s, f); 1907 } // end of BehaviourDescription::addMaterialProperties 1908 addParameters(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)1909 void BehaviourDescription::addParameters( 1910 const Hypothesis h, 1911 const VariableDescriptionContainer& v, 1912 const BehaviourData::RegistrationStatus s) { 1913 using mptr = void (mfront::BehaviourData::*)( 1914 const mfront::VariableDescription&, 1915 const BehaviourData::RegistrationStatus); 1916 mptr f = &BehaviourData::addParameter; 1917 this->addVariables(h, v, s, f); 1918 } // end of BehaviourDescription::addParameters 1919 addMaterialProperty(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)1920 void BehaviourDescription::addMaterialProperty( 1921 const Hypothesis h, 1922 const VariableDescription& v, 1923 const BehaviourData::RegistrationStatus s) { 1924 using mptr = void (mfront::BehaviourData::*)( 1925 const mfront::VariableDescription&, 1926 const BehaviourData::RegistrationStatus); 1927 mptr f = &BehaviourData::addMaterialProperty; 1928 this->addVariable(h, v, s, f); 1929 } 1930 addIntegrationVariables(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)1931 void BehaviourDescription::addIntegrationVariables( 1932 const Hypothesis h, 1933 const VariableDescriptionContainer& v, 1934 const BehaviourData::RegistrationStatus s) { 1935 using mptr = void (mfront::BehaviourData::*)( 1936 const mfront::VariableDescription&, 1937 const BehaviourData::RegistrationStatus); 1938 mptr f = &BehaviourData::addIntegrationVariable; 1939 this->addVariables(h, v, s, f); 1940 } 1941 addStateVariables(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)1942 void BehaviourDescription::addStateVariables( 1943 const Hypothesis h, 1944 const VariableDescriptionContainer& v, 1945 const BehaviourData::RegistrationStatus s) { 1946 using mptr = void (mfront::BehaviourData::*)( 1947 const mfront::VariableDescription&, 1948 const BehaviourData::RegistrationStatus); 1949 mptr f = &BehaviourData::addStateVariable; 1950 this->addVariables(h, v, s, f); 1951 } 1952 addIntegrationVariable(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)1953 void BehaviourDescription::addIntegrationVariable( 1954 const Hypothesis h, 1955 const VariableDescription& v, 1956 const BehaviourData::RegistrationStatus s) { 1957 using mptr = void (mfront::BehaviourData::*)( 1958 const mfront::VariableDescription&, 1959 const BehaviourData::RegistrationStatus); 1960 mptr f = &BehaviourData::addIntegrationVariable; 1961 this->addVariable(h, v, s, f); 1962 } 1963 addStateVariable(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)1964 void BehaviourDescription::addStateVariable( 1965 const Hypothesis h, 1966 const VariableDescription& v, 1967 const BehaviourData::RegistrationStatus s) { 1968 using mptr = void (mfront::BehaviourData::*)( 1969 const mfront::VariableDescription&, 1970 const BehaviourData::RegistrationStatus); 1971 mptr f = &BehaviourData::addStateVariable; 1972 this->addVariable(h, v, s, f); 1973 } 1974 addAuxiliaryStateVariables(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)1975 void BehaviourDescription::addAuxiliaryStateVariables( 1976 const Hypothesis h, 1977 const VariableDescriptionContainer& v, 1978 const BehaviourData::RegistrationStatus s) { 1979 using mptr = void (mfront::BehaviourData::*)( 1980 const mfront::VariableDescription&, 1981 const BehaviourData::RegistrationStatus); 1982 mptr f = &BehaviourData::addAuxiliaryStateVariable; 1983 this->addVariables(h, v, s, f); 1984 } 1985 addAuxiliaryStateVariable(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)1986 void BehaviourDescription::addAuxiliaryStateVariable( 1987 const Hypothesis h, 1988 const VariableDescription& v, 1989 const BehaviourData::RegistrationStatus s) { 1990 using mptr = void (mfront::BehaviourData::*)( 1991 const mfront::VariableDescription&, 1992 const BehaviourData::RegistrationStatus); 1993 mptr f = &BehaviourData::addAuxiliaryStateVariable; 1994 this->addVariable(h, v, s, f); 1995 } 1996 addExternalStateVariables(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)1997 void BehaviourDescription::addExternalStateVariables( 1998 const Hypothesis h, 1999 const VariableDescriptionContainer& v, 2000 const BehaviourData::RegistrationStatus s) { 2001 using mptr = void (mfront::BehaviourData::*)( 2002 const mfront::VariableDescription&, 2003 const BehaviourData::RegistrationStatus); 2004 mptr f = &BehaviourData::addExternalStateVariable; 2005 this->addVariables(h, v, s, f); 2006 } 2007 addExternalStateVariable(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)2008 void BehaviourDescription::addExternalStateVariable( 2009 const Hypothesis h, 2010 const VariableDescription& v, 2011 const BehaviourData::RegistrationStatus s) { 2012 using mptr = void (mfront::BehaviourData::*)( 2013 const mfront::VariableDescription&, 2014 const BehaviourData::RegistrationStatus); 2015 mptr f = &BehaviourData::addExternalStateVariable; 2016 this->addVariable(h, v, s, f); 2017 } 2018 addLocalVariables(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s)2019 void BehaviourDescription::addLocalVariables( 2020 const Hypothesis h, 2021 const VariableDescriptionContainer& v, 2022 const BehaviourData::RegistrationStatus s) { 2023 using mptr = void (mfront::BehaviourData::*)( 2024 const mfront::VariableDescription&, 2025 const BehaviourData::RegistrationStatus); 2026 mptr f = &BehaviourData::addLocalVariable; 2027 this->addVariables(h, v, s, f); 2028 } 2029 addLocalVariable(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)2030 void BehaviourDescription::addLocalVariable( 2031 const Hypothesis h, 2032 const VariableDescription& v, 2033 const BehaviourData::RegistrationStatus s) { 2034 using mptr = void (mfront::BehaviourData::*)( 2035 const mfront::VariableDescription&, 2036 const BehaviourData::RegistrationStatus); 2037 mptr f = &BehaviourData::addLocalVariable; 2038 this->addVariable(h, v, s, f); 2039 } 2040 addParameter(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s)2041 void BehaviourDescription::addParameter( 2042 const Hypothesis h, 2043 const VariableDescription& v, 2044 const BehaviourData::RegistrationStatus s) { 2045 using mptr = void (mfront::BehaviourData::*)( 2046 const mfront::VariableDescription&, 2047 const BehaviourData::RegistrationStatus); 2048 mptr f = &BehaviourData::addParameter; 2049 this->addVariable(h, v, s, f); 2050 } 2051 setVariableAttribute(const Hypothesis h,const std::string & v,const std::string & n,const VariableAttribute & a,const bool b)2052 void BehaviourDescription::setVariableAttribute(const Hypothesis h, 2053 const std::string& v, 2054 const std::string& n, 2055 const VariableAttribute& a, 2056 const bool b) { 2057 auto set = [&v, &n, &a, b](BehaviourData& bd) { 2058 bd.setVariableAttribute(v, n, a, b); 2059 }; 2060 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2061 set(this->d); 2062 for (auto md : this->sd) { 2063 set(*(md.second)); 2064 } 2065 } else { 2066 set(this->getBehaviourData2(h)); 2067 } 2068 } // end of BehaviourDescription::setVariableAttribute 2069 hasGlossaryName(const Hypothesis h,const std::string & v) const2070 bool BehaviourDescription::hasGlossaryName(const Hypothesis h, 2071 const std::string& v) const { 2072 return this->getData(h, &BehaviourData::hasGlossaryName, v); 2073 } // end of BehaviourDescription::hasGlossaryName 2074 hasEntryName(const Hypothesis h,const std::string & v) const2075 bool BehaviourDescription::hasEntryName(const Hypothesis h, 2076 const std::string& v) const { 2077 return this->getData(h, &BehaviourData::hasEntryName, v); 2078 } // end of BehaviourDescription::hasEntryName 2079 hasParameter(const Hypothesis h,const std::string & v) const2080 bool BehaviourDescription::hasParameter(const Hypothesis h, 2081 const std::string& v) const { 2082 return this->getData(h, &BehaviourData::hasParameter, v); 2083 } // end of BehaviourDescription::hasParameter 2084 hasParameters(const Hypothesis h) const2085 bool BehaviourDescription::hasParameters(const Hypothesis h) const { 2086 return this->getBehaviourData(h).hasParameters(); 2087 } // end of BehaviourDescription::hasParameters 2088 hasParameters() const2089 bool BehaviourDescription::hasParameters() const { 2090 if (this->d.hasParameters()) { 2091 return true; 2092 } 2093 for (const auto& ld : this->sd) { 2094 if (ld.second->hasParameters()) { 2095 return true; 2096 } 2097 } 2098 return false; 2099 } // end of BehaviourDescription::hasParameters 2100 setParameterDefaultValue(const Hypothesis h,const std::string & n,const double v)2101 void BehaviourDescription::setParameterDefaultValue(const Hypothesis h, 2102 const std::string& n, 2103 const double v) { 2104 void (BehaviourData::*mptr)(const std::string&, const double); 2105 mptr = &BehaviourData::setParameterDefaultValue; 2106 this->callBehaviourData(h, mptr, n, v, true); 2107 } 2108 setParameterDefaultValue(const Hypothesis h,const std::string & n,const unsigned short i,const double v)2109 void BehaviourDescription::setParameterDefaultValue(const Hypothesis h, 2110 const std::string& n, 2111 const unsigned short i, 2112 const double v) { 2113 void (BehaviourData::*m)(const std::string&, const unsigned short, 2114 const double) = 2115 &BehaviourData::setParameterDefaultValue; 2116 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2117 (this->d.*m)(n, i, v); 2118 for (auto md : this->sd) { 2119 (md.second.get()->*m)(n, i, v); 2120 } 2121 } else { 2122 (this->getBehaviourData2(h).*m)(n, i, v); 2123 } 2124 } 2125 setParameterDefaultValue(const Hypothesis h,const std::string & n,const int v)2126 void BehaviourDescription::setParameterDefaultValue(const Hypothesis h, 2127 const std::string& n, 2128 const int v) { 2129 void (BehaviourData::*mptr)(const std::string&, const int v); 2130 mptr = &BehaviourData::setParameterDefaultValue; 2131 this->callBehaviourData(h, mptr, n, v, true); 2132 } 2133 setParameterDefaultValue(const Hypothesis h,const std::string & n,const unsigned short v)2134 void BehaviourDescription::setParameterDefaultValue(const Hypothesis h, 2135 const std::string& n, 2136 const unsigned short v) { 2137 void (BehaviourData::*mptr)(const std::string&, const unsigned short v); 2138 mptr = &BehaviourData::setParameterDefaultValue; 2139 this->callBehaviourData(h, mptr, n, v, true); 2140 } 2141 getUnsignedShortParameterDefaultValue(const Hypothesis h,const std::string & n) const2142 unsigned short BehaviourDescription::getUnsignedShortParameterDefaultValue( 2143 const Hypothesis h, const std::string& n) const { 2144 return this->getData( 2145 h, &BehaviourData::getUnsignedShortParameterDefaultValue, n); 2146 } // end of BehaviourDescription::getUnsignedShortParameterDefaultValue 2147 getIntegerParameterDefaultValue(const Hypothesis h,const std::string & n) const2148 int BehaviourDescription::getIntegerParameterDefaultValue( 2149 const Hypothesis h, const std::string& n) const { 2150 return this->getData(h, &BehaviourData::getIntegerParameterDefaultValue, n); 2151 } // end of BehaviourDescription::getIntegerParameterDefaultValue 2152 getFloattingPointParameterDefaultValue(const Hypothesis h,const std::string & n) const2153 double BehaviourDescription::getFloattingPointParameterDefaultValue( 2154 const Hypothesis h, const std::string& n) const { 2155 return this->getData( 2156 h, &BehaviourData::getFloattingPointParameterDefaultValue, n); 2157 } // end of BehaviourDescription::getFloattingPointParameterDefaultValue 2158 getFloattingPointParameterDefaultValue(const Hypothesis h,const std::string & n,const unsigned short i) const2159 double BehaviourDescription::getFloattingPointParameterDefaultValue( 2160 const Hypothesis h, const std::string& n, const unsigned short i) const { 2161 return this->getBehaviourData(h).getFloattingPointParameterDefaultValue(n, 2162 i); 2163 } // end of BehaviourDescription::getFloattingPointParameterDefaultValue 2164 addStaticVariable(const Hypothesis h,const StaticVariableDescription & v,const BehaviourData::RegistrationStatus s)2165 void BehaviourDescription::addStaticVariable( 2166 const Hypothesis h, 2167 const StaticVariableDescription& v, 2168 const BehaviourData::RegistrationStatus s) { 2169 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2170 this->d.addStaticVariable(v, s); 2171 for (const auto& md : this->sd) { 2172 md.second->addStaticVariable(v, s); 2173 } 2174 } else { 2175 this->getBehaviourData2(h).addStaticVariable(v, s); 2176 } 2177 } // end of BehaviourDescription::addStaticVariable 2178 getIntegerConstant(const Hypothesis h,const std::string & n) const2179 int BehaviourDescription::getIntegerConstant(const Hypothesis h, 2180 const std::string& n) const { 2181 return this->getData(h, &BehaviourData::getIntegerConstant, n); 2182 } // end of BehaviourDescription::getIntegerConstant 2183 addVariables(const Hypothesis h,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s,void (BehaviourData::* m)(const VariableDescription &,const BehaviourData::RegistrationStatus))2184 void BehaviourDescription::addVariables( 2185 const Hypothesis h, 2186 const VariableDescriptionContainer& v, 2187 const BehaviourData::RegistrationStatus s, 2188 void (BehaviourData::*m)(const VariableDescription&, 2189 const BehaviourData::RegistrationStatus)) { 2190 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2191 this->addVariables(this->d, v, s, m); 2192 for (auto& md : this->sd) { 2193 this->addVariables(*(md.second), v, s, m); 2194 } 2195 } else { 2196 this->addVariables(this->getBehaviourData2(h), v, s, m); 2197 } 2198 } // end of BehaviourDescription::addVariables 2199 addVariable(const Hypothesis h,const VariableDescription & v,const BehaviourData::RegistrationStatus s,void (BehaviourData::* m)(const VariableDescription &,const BehaviourData::RegistrationStatus))2200 void BehaviourDescription::addVariable( 2201 const Hypothesis h, 2202 const VariableDescription& v, 2203 const BehaviourData::RegistrationStatus s, 2204 void (BehaviourData::*m)(const VariableDescription&, 2205 const BehaviourData::RegistrationStatus)) { 2206 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2207 this->addVariable(this->d, v, s, m); 2208 for (auto& md : this->sd) { 2209 this->addVariable(*(md.second), v, s, m); 2210 } 2211 } else { 2212 this->addVariable(this->getBehaviourData2(h), v, s, m); 2213 } 2214 } // end of BehaviourDescription::addVariable 2215 addVariables(BehaviourData & b,const VariableDescriptionContainer & v,const BehaviourData::RegistrationStatus s,void (BehaviourData::* m)(const VariableDescription &,const BehaviourData::RegistrationStatus))2216 void BehaviourDescription::addVariables( 2217 BehaviourData& b, 2218 const VariableDescriptionContainer& v, 2219 const BehaviourData::RegistrationStatus s, 2220 void (BehaviourData::*m)(const VariableDescription&, 2221 const BehaviourData::RegistrationStatus)) { 2222 for (const auto& e : v) { 2223 this->addVariable(b, e, s, m); 2224 } 2225 } // end of BehaviourDescription::addVariables 2226 addVariable(BehaviourData & b,const VariableDescription & v,const BehaviourData::RegistrationStatus s,void (BehaviourData::* m)(const VariableDescription &,const BehaviourData::RegistrationStatus))2227 void BehaviourDescription::addVariable( 2228 BehaviourData& b, 2229 const VariableDescription& v, 2230 const BehaviourData::RegistrationStatus s, 2231 void (BehaviourData::*m)(const VariableDescription&, 2232 const BehaviourData::RegistrationStatus)) { 2233 (b.*m)(v, s); 2234 } 2235 areAllMechanicalDataSpecialised() const2236 bool BehaviourDescription::areAllMechanicalDataSpecialised() const { 2237 return this->getModellingHypotheses().size() == this->sd.size(); 2238 } // end of BehaviourDescription::areAllMechanicalDataSpecialised 2239 areAllMechanicalDataSpecialised(const std::set<Hypothesis> & h) const2240 bool BehaviourDescription::areAllMechanicalDataSpecialised( 2241 const std::set<Hypothesis>& h) const { 2242 for (const auto& mh : h) { 2243 if (!this->hasSpecialisedMechanicalData(mh)) { 2244 return false; 2245 } 2246 } 2247 return true; 2248 } // end of BehaviourDescription::areAllMechanicalDataSpecialised 2249 hasSpecialisedMechanicalData(const Hypothesis h) const2250 bool BehaviourDescription::hasSpecialisedMechanicalData( 2251 const Hypothesis h) const { 2252 tfel::raise_if(this->getModellingHypotheses().find(h) == 2253 this->getModellingHypotheses().end(), 2254 "BehaviourDescription::areAllMechanicalDataSpecialised: " 2255 "hypothesis '" + 2256 ModellingHypothesis::toString(h) + "' is not supported"); 2257 return this->sd.find(h) != this->sd.end(); 2258 } 2259 requiresTVectorOrVectorIncludes(bool & b1,bool & b2,const BehaviourData & bd) const2260 void BehaviourDescription::requiresTVectorOrVectorIncludes( 2261 bool& b1, bool& b2, const BehaviourData& bd) const { 2262 for (const auto& v : bd.getMaterialProperties()) { 2263 if (v.arraySize > 1) { 2264 if (this->useDynamicallyAllocatedVector(v.arraySize)) { 2265 b2 = true; 2266 } else { 2267 b1 = true; 2268 } 2269 } 2270 if (b1 && b2) { 2271 return; 2272 } 2273 } 2274 for (const auto& v : bd.getIntegrationVariables()) { 2275 if (v.arraySize > 1) { 2276 if (this->useDynamicallyAllocatedVector(v.arraySize)) { 2277 b2 = true; 2278 } else { 2279 b1 = true; 2280 } 2281 } 2282 if (b1 && b2) { 2283 return; 2284 } 2285 } 2286 for (const auto& v : bd.getStateVariables()) { 2287 if (v.arraySize > 1) { 2288 if (this->useDynamicallyAllocatedVector(v.arraySize)) { 2289 b2 = true; 2290 } else { 2291 b1 = true; 2292 } 2293 } 2294 if (b1 && b2) { 2295 return; 2296 } 2297 } 2298 for (const auto& v : bd.getAuxiliaryStateVariables()) { 2299 if (v.arraySize > 1) { 2300 if (this->useDynamicallyAllocatedVector(v.arraySize)) { 2301 b2 = true; 2302 } else { 2303 b1 = true; 2304 } 2305 } 2306 if (b1 && b2) { 2307 return; 2308 } 2309 } 2310 for (const auto& v : bd.getLocalVariables()) { 2311 if (v.arraySize > 1) { 2312 if (this->useDynamicallyAllocatedVector(v.arraySize)) { 2313 b2 = true; 2314 } else { 2315 b1 = true; 2316 } 2317 } 2318 if (b1 && b2) { 2319 return; 2320 } 2321 } 2322 for (const auto& v : bd.getExternalStateVariables()) { 2323 if (v.arraySize > 1) { 2324 if (this->useDynamicallyAllocatedVector(v.arraySize)) { 2325 b2 = true; 2326 } else { 2327 b1 = true; 2328 } 2329 } 2330 if (b1 && b2) { 2331 return; 2332 } 2333 } 2334 } // end of BehaviourData::requiresTVectorOrVectorIncludes 2335 requiresTVectorOrVectorIncludes(bool & b1,bool & b2) const2336 void BehaviourDescription::requiresTVectorOrVectorIncludes(bool& b1, 2337 bool& b2) const { 2338 b1 = b2 = false; 2339 tfel::raise_if(this->hypotheses.empty(), 2340 "BehaviourDescription::areAllMechanicalDataSpecialised: " 2341 "no hypothesis defined"); 2342 if (!this->areAllMechanicalDataSpecialised()) { 2343 this->requiresTVectorOrVectorIncludes(b1, b2, d); 2344 } 2345 for (const auto& md : this->sd) { 2346 this->requiresTVectorOrVectorIncludes(b1, b2, *(md.second)); 2347 } 2348 } // end of BehaviourDescription::requiresTVectorOrVectorIncludes 2349 2350 void BehaviourDescription:: declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution(const Hypothesis h,const std::string & n)2351 declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution( 2352 const Hypothesis h, const std::string& n) { 2353 void (BehaviourData::*m)(const std::string&) = 2354 &BehaviourData:: 2355 declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution; 2356 this->callBehaviourData(h, m, n, true); 2357 } // end of 2358 // BehaviourDescription::declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution 2359 setUsableInPurelyImplicitResolution(const Hypothesis h,const bool b)2360 void BehaviourDescription::setUsableInPurelyImplicitResolution( 2361 const Hypothesis h, const bool b) { 2362 void (BehaviourData::*m)(const bool) = 2363 &BehaviourData::setUsableInPurelyImplicitResolution; 2364 this->callBehaviourData(h, m, b, true); 2365 } // end of 2366 // BehaviourDescription::declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution 2367 isMemberUsedInCodeBlocks(const Hypothesis h,const std::string & v) const2368 bool BehaviourDescription::isMemberUsedInCodeBlocks( 2369 const Hypothesis h, const std::string& v) const { 2370 return this->getData(h, &BehaviourData::isMemberUsedInCodeBlocks, v); 2371 } // end of BehaviourDescription::isMaterialPropertyName 2372 isMaterialPropertyName(const Hypothesis h,const std::string & v) const2373 bool BehaviourDescription::isMaterialPropertyName( 2374 const Hypothesis h, const std::string& v) const { 2375 return this->getData(h, &BehaviourData::isMaterialPropertyName, v); 2376 } // end of BehaviourDescription::isMaterialPropertyName 2377 isLocalVariableName(const Hypothesis h,const std::string & n) const2378 bool BehaviourDescription::isLocalVariableName(const Hypothesis h, 2379 const std::string& n) const { 2380 return this->getData(h, &BehaviourData::isLocalVariableName, n); 2381 } // end of BehaviourDescription::isLocalVariableName 2382 isPersistentVariableName(const Hypothesis h,const std::string & n) const2383 bool BehaviourDescription::isPersistentVariableName( 2384 const Hypothesis h, const std::string& n) const { 2385 return this->getData(h, &BehaviourData::isPersistentVariableName, n); 2386 } // end of BehaviourDescription::isPersistentVariableName 2387 isIntegrationVariableName(const Hypothesis h,const std::string & n) const2388 bool BehaviourDescription::isIntegrationVariableName( 2389 const Hypothesis h, const std::string& n) const { 2390 return this->getData(h, &BehaviourData::isIntegrationVariableName, n); 2391 } // end of BehaviourDescription::isIntegrationVariableName 2392 isIntegrationVariableIncrementName(const Hypothesis h,const std::string & n) const2393 bool BehaviourDescription::isIntegrationVariableIncrementName( 2394 const Hypothesis h, const std::string& n) const { 2395 return this->getData(h, &BehaviourData::isIntegrationVariableIncrementName, 2396 n); 2397 } // end of BehaviourDescription::isIntegrationVariableIncrementName 2398 isStateVariableName(const Hypothesis h,const std::string & n) const2399 bool BehaviourDescription::isStateVariableName(const Hypothesis h, 2400 const std::string& n) const { 2401 return this->getData(h, &BehaviourData::isStateVariableName, n); 2402 } // end of BehaviourDescription::isStateVariableName 2403 isStateVariableIncrementName(const Hypothesis h,const std::string & n) const2404 bool BehaviourDescription::isStateVariableIncrementName( 2405 const Hypothesis h, const std::string& n) const { 2406 return this->getData(h, &BehaviourData::isStateVariableIncrementName, n); 2407 } // end of BehaviourDescription::isStateVariableIncrementName 2408 isAuxiliaryStateVariableName(const Hypothesis h,const std::string & n) const2409 bool BehaviourDescription::isAuxiliaryStateVariableName( 2410 const Hypothesis h, const std::string& n) const { 2411 return this->getData(h, &BehaviourData::isAuxiliaryStateVariableName, n); 2412 } // end of BehaviourDescription::isAuxiliaryStateVariableName 2413 isExternalStateVariableName(const Hypothesis h,const std::string & n) const2414 bool BehaviourDescription::isExternalStateVariableName( 2415 const Hypothesis h, const std::string& n) const { 2416 return this->getData(h, &BehaviourData::isExternalStateVariableName, n); 2417 } // end of BehaviourDescription::isExternalStateVariableName 2418 isExternalStateVariableIncrementName(const Hypothesis h,const std::string & n) const2419 bool BehaviourDescription::isExternalStateVariableIncrementName( 2420 const Hypothesis h, const std::string& n) const { 2421 return this->getData( 2422 h, &BehaviourData::isExternalStateVariableIncrementName, n); 2423 } // end of BehaviourDescription::isExternalStateVariableIncrementName 2424 isParameterName(const Hypothesis h,const std::string & v) const2425 bool BehaviourDescription::isParameterName(const Hypothesis h, 2426 const std::string& v) const { 2427 return this->getData(h, &BehaviourData::isParameterName, v); 2428 } // end of BehaviourDescription::isParameterName 2429 isStaticVariableName(const Hypothesis h,const std::string & n) const2430 bool BehaviourDescription::isStaticVariableName(const Hypothesis h, 2431 const std::string& n) const { 2432 return this->getData(h, &BehaviourData::isStaticVariableName, n); 2433 } // end of BehaviourDescription::isStaticVariableName 2434 updateClassName()2435 void BehaviourDescription::updateClassName() { 2436 if ((!this->behaviour.empty()) || (!this->material.empty())) { 2437 this->className = this->material + this->behaviour; 2438 } 2439 } // end of BehaviourDescription::updateClassName 2440 setCode(const Hypothesis h,const std::string & n,const CodeBlock & c,const Mode m,const Position p,const bool b)2441 void BehaviourDescription::setCode(const Hypothesis h, 2442 const std::string& n, 2443 const CodeBlock& c, 2444 const Mode m, 2445 const Position p, 2446 const bool b) { 2447 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2448 if (getVerboseMode() >= VERBOSE_DEBUG) { 2449 auto& log = getLogStream(); 2450 log << "BehaviourDescription::setCode : setting '" << n 2451 << "' on default hypothesis" << std::endl; 2452 } 2453 this->d.setCode(n, c, m, p, b); 2454 for (const auto& pd : sd) { 2455 if (getVerboseMode() >= VERBOSE_DEBUG) { 2456 auto& log = getLogStream(); 2457 log << "BehaviourDescription::setCode : setting '" << n 2458 << "' on hypothesis '" << ModellingHypothesis::toString(pd.first) 2459 << "'" << std::endl; 2460 } 2461 pd.second->setCode(n, c, m, p, b); 2462 } 2463 } else { 2464 if (getVerboseMode() >= VERBOSE_DEBUG) { 2465 auto& log = getLogStream(); 2466 log << "BehaviourDescription::setCode : setting '" << n 2467 << "' on hypothesis '" << ModellingHypothesis::toString(h) << "'" 2468 << std::endl; 2469 } 2470 this->getBehaviourData2(h).setCode(n, c, m, p, b); 2471 } 2472 } // end of BehaviourDescription::setCode 2473 getCodeBlock(const Hypothesis h,const std::string & n) const2474 const CodeBlock& BehaviourDescription::getCodeBlock( 2475 const Hypothesis h, const std::string& n) const { 2476 return this->getBehaviourData(h).getCodeBlock(n); 2477 } // end of BehaviourDescription::getCode 2478 getCode(const Hypothesis h,const std::string & n) const2479 std::string BehaviourDescription::getCode(const Hypothesis h, 2480 const std::string& n) const { 2481 const auto b = this->getAttribute(BehaviourData::profiling, false); 2482 return this->getBehaviourData(h).getCode(n, this->getClassName(), b); 2483 } // end of BehaviourDescription::getCode 2484 hasCode(const Hypothesis h,const std::string & n) const2485 bool BehaviourDescription::hasCode(const Hypothesis h, 2486 const std::string& n) const { 2487 return this->getBehaviourData(h).hasCode(n); 2488 } // end of BehaviourDescription::getCode 2489 setAttribute(const Hypothesis h,const std::string & n,const BehaviourAttribute & a,const bool b)2490 void BehaviourDescription::setAttribute(const Hypothesis h, 2491 const std::string& n, 2492 const BehaviourAttribute& a, 2493 const bool b) { 2494 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2495 this->d.setAttribute(n, a, b); 2496 for (const auto& md : this->sd) { 2497 BehaviourData& bdata = *(md.second); 2498 bdata.setAttribute(n, a, b); 2499 } 2500 } else { 2501 this->getBehaviourData2(h).setAttribute(n, a, b); 2502 } 2503 } // end of BehaviourDescription::setAttribute 2504 updateAttribute(const Hypothesis h,const std::string & n,const BehaviourAttribute & a)2505 void BehaviourDescription::updateAttribute(const Hypothesis h, 2506 const std::string& n, 2507 const BehaviourAttribute& a) { 2508 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2509 this->d.updateAttribute(n, a); 2510 for (const auto& md : this->sd) { 2511 md.second->updateAttribute(n, a); 2512 } 2513 } else { 2514 this->getBehaviourData2(h).updateAttribute(n, a); 2515 } 2516 } // end of BehaviourDescription::updateAttribute 2517 hasAttribute(const Hypothesis h,const std::string & n) const2518 bool BehaviourDescription::hasAttribute(const Hypothesis h, 2519 const std::string& n) const { 2520 return this->getBehaviourData(h).hasAttribute(n); 2521 } // end of BehaviourDescription::hasAttribute 2522 getCodeBlockNames(const Hypothesis h) const2523 std::vector<std::string> BehaviourDescription::getCodeBlockNames( 2524 const Hypothesis h) const { 2525 return this->getBehaviourData(h).getCodeBlockNames(); 2526 } 2527 getExternalNames(const Hypothesis h,const VarContainer & v) const2528 std::vector<std::string> BehaviourDescription::getExternalNames( 2529 const Hypothesis h, const VarContainer& v) const { 2530 return this->getBehaviourData(h).getExternalNames(v); 2531 } 2532 getExternalNames(std::vector<std::string> & n,const Hypothesis h,const VarContainer & v) const2533 void BehaviourDescription::getExternalNames(std::vector<std::string>& n, 2534 const Hypothesis h, 2535 const VarContainer& v) const { 2536 return this->getBehaviourData(h).getExternalNames(n, v); 2537 } // end of BehaviourDescription::getExternalNames 2538 appendExternalNames(std::vector<std::string> & n,const Hypothesis h,const VarContainer & v) const2539 void BehaviourDescription::appendExternalNames(std::vector<std::string>& n, 2540 const Hypothesis h, 2541 const VarContainer& v) const { 2542 return this->getBehaviourData(h).appendExternalNames(n, v); 2543 } // end of BehaviourDescription::appendExternalNames 2544 setGlossaryName(const std::string & n,const std::string & gn)2545 void BehaviourDescription::setGlossaryName(const std::string& n, 2546 const std::string& gn) { 2547 using tfel::glossary::Glossary; 2548 const auto& glossary = Glossary::getGlossary(); 2549 tfel::raise_if(!glossary.contains(gn), 2550 "BehaviourDescription::setGlossaryName: " 2551 "'" + 2552 gn + "' is not a glossary name"); 2553 for (auto& v : this->mvariables) { 2554 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 2555 if (v.first.name == n) { 2556 v.first.setGlossaryName(gn); 2557 this->registerGlossaryName(h, n, gn); 2558 } 2559 if (v.second.name == n) { 2560 v.second.setGlossaryName(gn); 2561 this->registerGlossaryName(h, n, gn); 2562 } 2563 } 2564 } // end of BehaviourDescription::setGlossaryName 2565 setEntryName(const std::string & n,const std::string & e)2566 void BehaviourDescription::setEntryName(const std::string& n, 2567 const std::string& e) { 2568 using tfel::glossary::Glossary; 2569 using MainVariable = std::pair<Gradient, ThermodynamicForce>; 2570 const auto& glossary = Glossary::getGlossary(); 2571 tfel::raise_if(glossary.contains(e), 2572 "BehaviourDescription::setEntryName: " 2573 "'" + 2574 e + "' is a glossary name"); 2575 std::for_each(this->mvariables.begin(), this->mvariables.end(), 2576 [this, &n, &e](MainVariable& v) { 2577 constexpr const auto h = 2578 ModellingHypothesis::UNDEFINEDHYPOTHESIS; 2579 if (v.first.name == n) { 2580 v.first.setEntryName(e); 2581 this->registerEntryName(h, n, e); 2582 } 2583 if (v.second.name == n) { 2584 v.second.setEntryName(e); 2585 this->registerEntryName(h, n, e); 2586 } 2587 }); 2588 } // end of BehaviourDescription::setEntryName 2589 setGlossaryName(const Hypothesis h,const std::string & n,const std::string & g)2590 void BehaviourDescription::setGlossaryName(const Hypothesis h, 2591 const std::string& n, 2592 const std::string& g) { 2593 this->callBehaviourData(h, &BehaviourData::setGlossaryName, n, g, true); 2594 } // end of BehaviourDescription::setGlossaryName 2595 isGlossaryNameUsed(const Hypothesis h,const std::string & n) const2596 bool BehaviourDescription::isGlossaryNameUsed(const Hypothesis h, 2597 const std::string& n) const { 2598 return this->getBehaviourData(h).isGlossaryNameUsed(n); 2599 } // end of BehaviourDescription::isGlossaryName 2600 setEntryName(const Hypothesis h,const std::string & n,const std::string & g)2601 void BehaviourDescription::setEntryName(const Hypothesis h, 2602 const std::string& n, 2603 const std::string& g) { 2604 this->callBehaviourData(h, &BehaviourData::setEntryName, n, g, true); 2605 } // end of BehaviourDescription::setEntryName 2606 isUsedAsEntryName(const Hypothesis h,const std::string & n) const2607 bool BehaviourDescription::isUsedAsEntryName(const Hypothesis h, 2608 const std::string& n) const { 2609 return this->getBehaviourData(h).isUsedAsEntryName(n); 2610 } // end of BehaviourDescription::isEntryName 2611 getExternalName(const Hypothesis h,const std::string & n) const2612 std::string BehaviourDescription::getExternalName( 2613 const Hypothesis h, const std::string& n) const { 2614 return this->getData(h, &BehaviourData::getExternalName, n); 2615 } // end of BehaviourDescription::getGlossaryName 2616 getVariableNameFromGlossaryNameOrEntryName(const Hypothesis h,const std::string & n) const2617 std::string BehaviourDescription::getVariableNameFromGlossaryNameOrEntryName( 2618 const Hypothesis h, const std::string& n) const { 2619 return this->getBehaviourData(h).getVariableNameFromGlossaryNameOrEntryName( 2620 n); 2621 } // end of 2622 // BehaviourDescription::getVariableNameFromGlossaryNameOrEntryName 2623 2624 const VariableDescription& getVariableDescriptionByExternalName(const Hypothesis h,const std::string & n) const2625 BehaviourDescription::getVariableDescriptionByExternalName( 2626 const Hypothesis h, const std::string& n) const { 2627 return this->getBehaviourData(h).getVariableDescriptionByExternalName(n); 2628 } // end of BehaviourDescription::getVariableDescriptionByExternalName 2629 setBounds(const Hypothesis h,const std::string & n,const VariableBoundsDescription & b)2630 void BehaviourDescription::setBounds(const Hypothesis h, 2631 const std::string& n, 2632 const VariableBoundsDescription& b) { 2633 auto throw_if = [](const bool c, const std::string& m) { 2634 tfel::raise_if(c, "BehaviourDescription::setBounds: " + m); 2635 }; 2636 if (this->isGradientName(n)) { 2637 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2638 "invalid modelling hypothesis"); 2639 this->getGradient(n).setBounds(b); 2640 } else if (this->isThermodynamicForceName(n)) { 2641 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2642 "invalid modelling hypothesis"); 2643 this->getThermodynamicForce(n).setBounds(b); 2644 } else { 2645 this->callBehaviourData(h, &BehaviourData::setBounds, n, b, true); 2646 } 2647 } // end of BehaviourDescription::setBounds 2648 setBounds(const Hypothesis h,const std::string & n,const unsigned short i,const VariableBoundsDescription & b)2649 void BehaviourDescription::setBounds(const Hypothesis h, 2650 const std::string& n, 2651 const unsigned short i, 2652 const VariableBoundsDescription& b) { 2653 auto throw_if = [](const bool c, const std::string& m) { 2654 tfel::raise_if(c, "BehaviourDescription::setBounds: " + m); 2655 }; 2656 if (this->isGradientName(n)) { 2657 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2658 "invalid modelling hypothesis"); 2659 this->getGradient(n).setBounds(b, i); 2660 } else if (this->isThermodynamicForceName(n)) { 2661 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2662 "invalid modelling hypothesis"); 2663 this->getThermodynamicForce(n).setBounds(b, i); 2664 } else { 2665 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2666 this->d.setBounds(n, i, b); 2667 for (auto md : this->sd) { 2668 md.second.get()->setBounds(n, i, b); 2669 } 2670 } else { 2671 this->getBehaviourData2(h).setBounds(n, i, b); 2672 } 2673 } 2674 } // end of BehaviourDescription::setBounds 2675 setPhysicalBounds(const Hypothesis h,const std::string & n,const VariableBoundsDescription & b)2676 void BehaviourDescription::setPhysicalBounds( 2677 const Hypothesis h, 2678 const std::string& n, 2679 const VariableBoundsDescription& b) { 2680 auto throw_if = [](const bool c, const std::string& m) { 2681 tfel::raise_if(c, "BehaviourDescription::setPhysicalBounds: " + m); 2682 }; 2683 if (this->isGradientName(n)) { 2684 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2685 "invalid modelling hypothesis"); 2686 this->getGradient(n).setBounds(b); 2687 } else if (this->isThermodynamicForceName(n)) { 2688 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2689 "invalid modelling hypothesis"); 2690 this->getThermodynamicForce(n).setBounds(b); 2691 } else { 2692 this->callBehaviourData(h, &BehaviourData::setPhysicalBounds, n, b, true); 2693 } 2694 } // end of BehaviourDescription::setPhysicalBounds 2695 setPhysicalBounds(const Hypothesis h,const std::string & n,const unsigned short i,const VariableBoundsDescription & b)2696 void BehaviourDescription::setPhysicalBounds( 2697 const Hypothesis h, 2698 const std::string& n, 2699 const unsigned short i, 2700 const VariableBoundsDescription& b) { 2701 auto throw_if = [](const bool c, const std::string& m) { 2702 tfel::raise_if(c, "BehaviourDescription::setPhysicalBounds: " + m); 2703 }; 2704 if (this->isGradientName(n)) { 2705 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2706 "invalid modelling hypothesis"); 2707 this->getGradient(n).setBounds(b, i); 2708 } else if (this->isThermodynamicForceName(n)) { 2709 throw_if(h != ModellingHypothesis::UNDEFINEDHYPOTHESIS, 2710 "invalid modelling hypothesis"); 2711 this->getThermodynamicForce(n).setBounds(b, i); 2712 } else { 2713 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2714 this->d.setPhysicalBounds(n, i, b); 2715 for (auto md : this->sd) { 2716 md.second.get()->setPhysicalBounds(n, i, b); 2717 } 2718 } else { 2719 this->getBehaviourData2(h).setPhysicalBounds(n, i, b); 2720 } 2721 } 2722 } // end of BehaviourDescription::setPhysicalBounds 2723 setAttribute(const std::string & n,const BehaviourAttribute & a,const bool b)2724 void BehaviourDescription::setAttribute(const std::string& n, 2725 const BehaviourAttribute& a, 2726 const bool b) { 2727 if (b) { 2728 auto p = this->attributes.find(n); 2729 if (p != this->attributes.end()) { 2730 tfel::raise_if(a.getTypeIndex() != p->second.getTypeIndex(), 2731 "BehaviourDescription::setAttribute: " 2732 "attribute already exists with a different type"); 2733 return; 2734 } 2735 } 2736 tfel::raise_if(!this->attributes.insert({n, a}).second, 2737 "BehaviourDescription::setAttribute: " 2738 "attribute '" + 2739 n + "' already declared"); 2740 } // end of BehaviourDescription::setAttribute 2741 hasAttribute(const std::string & n) const2742 bool BehaviourDescription::hasAttribute(const std::string& n) const { 2743 return this->attributes.count(n) != 0u; 2744 } // end of BehaviourDescription::hasAttribute 2745 2746 const std::map<std::string, BehaviourAttribute>& getAttributes() const2747 BehaviourDescription::getAttributes() const { 2748 return this->attributes; 2749 } // end of BehaviourDescription::getAttributes 2750 reserveName(const Hypothesis h,const std::string & n)2751 void BehaviourDescription::reserveName(const Hypothesis h, 2752 const std::string& n) { 2753 this->callBehaviourData(h, &BehaviourData::reserveName, n, true); 2754 } 2755 isNameReserved(const std::string & n) const2756 bool BehaviourDescription::isNameReserved(const std::string& n) const { 2757 if (this->d.isNameReserved(n)) { 2758 return true; 2759 } 2760 for (auto md : this->sd) { 2761 if (md.second->isNameReserved(n)) { 2762 return true; 2763 } 2764 } 2765 return false; 2766 } // end of BehaviourDescription::isNameReserved 2767 registerGlossaryName(const Hypothesis h,const std::string & n,const std::string & g)2768 void BehaviourDescription::registerGlossaryName(const Hypothesis h, 2769 const std::string& n, 2770 const std::string& g) { 2771 this->callBehaviourData(h, &BehaviourData::registerGlossaryName, n, g, 2772 true); 2773 } // end of BehaviourDescription::registerGlossaryName 2774 registerEntryName(const Hypothesis h,const std::string & n,const std::string & e)2775 void BehaviourDescription::registerEntryName(const Hypothesis h, 2776 const std::string& n, 2777 const std::string& e) { 2778 this->callBehaviourData(h, &BehaviourData::registerEntryName, n, e, true); 2779 } // end of BehaviourDescription::registerEntryName 2780 registerMemberName(const Hypothesis h,const std::string & n)2781 void BehaviourDescription::registerMemberName(const Hypothesis h, 2782 const std::string& n) { 2783 this->callBehaviourData(h, &BehaviourData::registerMemberName, n, true); 2784 } // end of BehaviourDescription::registerMemberName 2785 registerStaticMemberName(const Hypothesis h,const std::string & n)2786 void BehaviourDescription::registerStaticMemberName(const Hypothesis h, 2787 const std::string& n) { 2788 this->callBehaviourData(h, &BehaviourData::registerStaticMemberName, n, 2789 true); 2790 } // end of BehaviourDescription::registerMemberName 2791 addMaterialLaw(const std::string & m)2792 void BehaviourDescription::addMaterialLaw(const std::string& m) { 2793 if (std::find(this->materialLaws.begin(), this->materialLaws.end(), m) == 2794 this->materialLaws.end()) { 2795 this->materialLaws.push_back(m); 2796 } 2797 } // end of BehaviourDescription::getMaterialLaws 2798 getMaterialLaws() const2799 const std::vector<std::string>& BehaviourDescription::getMaterialLaws() 2800 const { 2801 return this->materialLaws; 2802 } 2803 checkVariableExistence(const std::string & v) const2804 std::pair<bool, bool> BehaviourDescription::checkVariableExistence( 2805 const std::string& v) const { 2806 const auto& mh = this->getDistinctModellingHypotheses(); 2807 std::pair<bool, bool> r{true, false}; 2808 for (const auto& h : mh) { 2809 const auto& bdata = this->getBehaviourData(h); 2810 const auto& vn = bdata.getVariablesNames(); 2811 const bool b = vn.find(v) != vn.end(); 2812 r.first = r.first && b; 2813 r.second = r.second || b; 2814 } 2815 if (!r.second) { 2816 r.first = false; 2817 } 2818 return r; 2819 } // end of checkVariableExistence 2820 checkVariableExistence(const std::string & n,const std::string & c,const bool b) const2821 std::pair<bool, bool> BehaviourDescription::checkVariableExistence( 2822 const std::string& n, const std::string& c, const bool b) const { 2823 const auto& mh = this->getDistinctModellingHypotheses(); 2824 std::pair<bool, bool> r = {true, false}; 2825 for (const auto h : mh) { 2826 const auto& bd = this->getBehaviourData(h); 2827 const auto f = bd.getVariables(c).contains(n); 2828 tfel::raise_if(!f && b, 2829 "BehaviourDescription::checkVariableExistence: " 2830 "no '" + 2831 c + "' named '" + n + 2832 "' found for at " 2833 "least one modelling hypothesis"); 2834 r.first = r.first && f; 2835 r.second = r.second || f; 2836 } 2837 if (!r.second) { 2838 r.first = false; 2839 } 2840 return r; 2841 } 2842 checkVariableGlossaryName(const std::string & n,const std::string & g) const2843 void BehaviourDescription::checkVariableGlossaryName( 2844 const std::string& n, const std::string& g) const { 2845 auto throw_if = [](const bool c, const std::string& m) { 2846 tfel::raise_if(c, 2847 "BehaviourDescription::" 2848 "checkVariableGlossaryName: " + 2849 m); 2850 }; 2851 for (const auto& h : this->getDistinctModellingHypotheses()) { 2852 const auto& bdata = this->getBehaviourData(h); 2853 throw_if(!bdata.hasGlossaryName(n), 2854 "no glossary name associated with variable '" + n + "'"); 2855 const auto& en = bdata.getExternalName(n); 2856 throw_if(en != g, 2857 "the glossary name associated with " 2858 "variable '" + 2859 n + "' is not '" + g + "', but '" + en + "'"); 2860 } 2861 } // end of BehaviourDescription::checkVariableGlossaryName 2862 checkVariableEntryName(const std::string & n,const std::string & e) const2863 void BehaviourDescription::checkVariableEntryName( 2864 const std::string& n, const std::string& e) const { 2865 auto throw_if = [](const bool c, const std::string& m) { 2866 tfel::raise_if(c, 2867 "BehaviourDescription::" 2868 "checkVariableEntryName: " + 2869 m); 2870 }; 2871 for (const auto& h : this->getDistinctModellingHypotheses()) { 2872 const auto& bdata = this->getBehaviourData(h); 2873 throw_if(!bdata.hasEntryName(n), 2874 "no entry name associated with variable '" + n + "'"); 2875 const auto& en = bdata.getExternalName(n); 2876 throw_if(en != e, 2877 "the entry name associated with " 2878 "variable '" + 2879 n + "' is not '" + e + "', but '" + en + "'"); 2880 } 2881 } // end of BehaviourDescription::checkVariableEntryName 2882 checkVariablePosition(const std::string & n,const std::string & c,const size_t p)2883 void BehaviourDescription::checkVariablePosition(const std::string& n, 2884 const std::string& c, 2885 const size_t p) { 2886 for (const auto& h : this->getDistinctModellingHypotheses()) { 2887 const auto& bdata = this->getBehaviourData(h); 2888 const auto& vc = bdata.getVariables(c); 2889 tfel::raise_if(p >= vc.size(), 2890 "BehaviourDescription::checkVariablePosition: " 2891 "position given is greater than the number " 2892 "of variables of category '" + 2893 c + "'"); 2894 const auto& v = vc[p]; 2895 tfel::raise_if(v.name != n, 2896 "BehaviourDescription::checkVariablePosition: " 2897 "variable at the given position is not named '" + 2898 n + "' but '" + v.name + "'"); 2899 } 2900 } // end of BehaviourDescription::checkVariablePosition 2901 setOrthotropicAxesConvention(const OrthotropicAxesConvention c)2902 void BehaviourDescription::setOrthotropicAxesConvention( 2903 const OrthotropicAxesConvention c) { 2904 tfel::raise_if(this->oacIsDefined, 2905 "BehaviourDescription::setOrthotropicAxesConvention: " 2906 "orthotropic axes convention already defined"); 2907 tfel::raise_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 2908 "BehaviourDescription::setOrthotropicAxesConvention: " 2909 "the behaviour is not orthotropic."); 2910 if (c == OrthotropicAxesConvention::PLATE) { 2911 if (this->areModellingHypothesesDefined()) { 2912 for (const auto h : this->getModellingHypotheses()) { 2913 tfel::raise_if((h != ModellingHypothesis::TRIDIMENSIONAL) && 2914 (h != ModellingHypothesis::PLANESTRESS) && 2915 (h != ModellingHypothesis::PLANESTRAIN) && 2916 (h != ModellingHypothesis::GENERALISEDPLANESTRAIN), 2917 "Modelling hypothesis '" + 2918 ModellingHypothesis::toString(h) + 2919 "' is not compatible " 2920 "with the `Plate` orthotropic axes convention"); 2921 } 2922 } 2923 } 2924 this->oacIsDefined = true; 2925 this->oac = c; 2926 } 2927 2928 tfel::material::OrthotropicAxesConvention getOrthotropicAxesConvention() const2929 BehaviourDescription::getOrthotropicAxesConvention() const { 2930 tfel::raise_if(this->getSymmetryType() != mfront::ORTHOTROPIC, 2931 "BehaviourDescription::getOrthotropicAxesConvention: " 2932 "the behaviour is not orthotropic."); 2933 if (!this->oacIsDefined) { 2934 this->oacIsDefined = true; 2935 } 2936 return this->oac; 2937 } 2938 useDynamicallyAllocatedVector(const unsigned short s) const2939 bool BehaviourDescription::useDynamicallyAllocatedVector( 2940 const unsigned short s) const { 2941 return (s >= SupportedTypes::ArraySizeLimit) && 2942 (this->areDynamicallyAllocatedVectorsAllowed()); 2943 } // end of SupportedTypes::useDynamicallyAllocatedVector 2944 areDynamicallyAllocatedVectorsAllowed() const2945 bool BehaviourDescription::areDynamicallyAllocatedVectorsAllowed() const { 2946 if (this->areDynamicallyAllocatedVectorsAllowed_.is<bool>()) { 2947 return this->areDynamicallyAllocatedVectorsAllowed_.get<bool>(); 2948 } 2949 return true; 2950 } // end of SupportedTypes::areDynamicallyAllocatedVectorsAllowed 2951 areDynamicallyAllocatedVectorsAllowed(const bool b)2952 void BehaviourDescription::areDynamicallyAllocatedVectorsAllowed( 2953 const bool b) { 2954 if (this->areDynamicallyAllocatedVectorsAllowed_.is<bool>()) { 2955 tfel::raise_if( 2956 this->areDynamicallyAllocatedVectorsAllowed_.get<bool>() != b, 2957 "BehaviourDescription::areDynamicallyAllocatedVectorsAllowed: " 2958 "inconsistent policy for dynamically allocated vectors"); 2959 return; 2960 } 2961 this->areDynamicallyAllocatedVectorsAllowed_ = b; 2962 } // end of SupportedTypes::areDynamicallyAllocatedVectorsAllowed 2963 setStrainMeasure(const StrainMeasure sm)2964 void BehaviourDescription::setStrainMeasure(const StrainMeasure sm) { 2965 tfel::raise_if(this->getBehaviourType() != 2966 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR, 2967 "BehaviourDescription::setStrainMeasure: " 2968 "invalid behaviour type"); 2969 tfel::raise_if(this->isStrainMeasureDefined(), 2970 "BehaviourDescription::setStrainMeasure: " 2971 "strain measure already defined"); 2972 this->strainMeasure = sm; 2973 } 2974 getStrainMeasure() const2975 BehaviourDescription::StrainMeasure BehaviourDescription::getStrainMeasure() 2976 const { 2977 tfel::raise_if(!this->isStrainMeasureDefined(), 2978 "BehaviourDescription::getStrainMeasure: " 2979 "no strain measure defined"); 2980 return this->strainMeasure.get<StrainMeasure>(); 2981 } // end of BehaviourDescription::setStrainMeasure() 2982 isStrainMeasureDefined() const2983 bool BehaviourDescription::isStrainMeasureDefined() const { 2984 return this->strainMeasure.is<StrainMeasure>(); 2985 } // end of BehaviourDescription::isStrainMeasureDefined() 2986 getSymbols(std::map<std::string,std::string> & symbols,const Hypothesis h) const2987 void BehaviourDescription::getSymbols( 2988 std::map<std::string, std::string>& symbols, const Hypothesis h) const { 2989 for (const auto& mv : this->mvariables) { 2990 getSymbol(symbols, mv.first); 2991 getSymbol(symbols, mv.second); 2992 } 2993 for (const auto& b : this->getTangentOperatorBlocks()) { 2994 if ((Gradient::isIncrementKnown(b.second)) || 2995 (this->isExternalStateVariableName(h, b.second.name))) { 2996 symbols.insert({"\u2202" + displayName(b.first) + "\u2215\u2202\u0394" + 2997 displayName(b.second), 2998 "d" + b.first.name + "_dd" + b.second.name}); 2999 } else { 3000 symbols.insert({"\u2202" + displayName(b.first) + "\u2215\u2202" + 3001 displayName(b.second) + "\u2081", 3002 "d" + b.first.name + "_d" + b.second.name + "1"}); 3003 } 3004 } 3005 this->getBehaviourData(h).getSymbols(symbols); 3006 } // end of BehaviourDescription::getSymbols 3007 3008 std::vector<MaterialPropertyDescription> getElasticMaterialPropertiesDescriptions() const3009 BehaviourDescription::getElasticMaterialPropertiesDescriptions() const { 3010 const auto& emps = this->getElasticMaterialProperties(); 3011 auto empds = std::vector<MaterialPropertyDescription>{emps.size()}; 3012 if (emps.size() == 2u) { 3013 empds[0] = 3014 buildMaterialPropertyDescription(emps[0], *this, "YoungModulus"); 3015 empds[1] = 3016 buildMaterialPropertyDescription(emps[1], *this, "PoissonRatio"); 3017 } else if (emps.size() == 9u) { 3018 empds[0] = 3019 buildMaterialPropertyDescription(emps[0], *this, "YoungModulus1"); 3020 empds[1] = 3021 buildMaterialPropertyDescription(emps[1], *this, "YoungModulus2"); 3022 empds[2] = 3023 buildMaterialPropertyDescription(emps[2], *this, "YoungModulus3"); 3024 empds[3] = 3025 buildMaterialPropertyDescription(emps[3], *this, "PoissonRatio12"); 3026 empds[4] = 3027 buildMaterialPropertyDescription(emps[4], *this, "PoissonRatio23"); 3028 empds[5] = 3029 buildMaterialPropertyDescription(emps[5], *this, "PoissonRatio13"); 3030 empds[6] = 3031 buildMaterialPropertyDescription(emps[6], *this, "ShearModulus12"); 3032 empds[7] = 3033 buildMaterialPropertyDescription(emps[7], *this, "ShearModulus23"); 3034 empds[8] = 3035 buildMaterialPropertyDescription(emps[8], *this, "ShearModulus13"); 3036 } else { 3037 tfel::raise( 3038 "BehaviourDescription::getElasticMaterialPropertiesDescriptions: " 3039 "invalid number of material properties"); 3040 } 3041 return empds; 3042 } // end of BehaviourDescription::getElasticMaterialPropertiesDescriptions 3043 overrideByAParameter(const std::string & n,const double v)3044 void BehaviourDescription::overrideByAParameter(const std::string& n, 3045 const double v) { 3046 this->d.overrideByAParameter(n, v); 3047 for (auto& md : this->sd) { 3048 md.second->overrideByAParameter(n, v); 3049 } 3050 } // end of BehaviourDescription::overrideByAParameter 3051 3052 BehaviourDescription::~BehaviourDescription() = default; 3053 setElasticSymmetryType(BehaviourDescription & bd,const BehaviourSymmetryType s)3054 void setElasticSymmetryType(BehaviourDescription& bd, 3055 const BehaviourSymmetryType s) { 3056 if (bd.isElasticSymmetryTypeDefined()) { 3057 tfel::raise_if(bd.getElasticSymmetryType() != s, 3058 "setElasticSymmetryType: " 3059 "the elastic symmetry type defined for " 3060 "the behaviour is inconsistent."); 3061 } else { 3062 bd.setElasticSymmetryType(s); 3063 } 3064 } // end of setElasticSymmetryType 3065 checkIsStrictlyPositive(const BehaviourDescription::MaterialProperty & mp)3066 void checkIsStrictlyPositive( 3067 const BehaviourDescription::MaterialProperty& mp) { 3068 if (mp.is<BehaviourDescription::ConstantMaterialProperty>()) { 3069 auto& cmp = mp.get<BehaviourDescription::ConstantMaterialProperty>(); 3070 if (!(cmp.value > 0)) { 3071 tfel::raise("checkIsStrictlyPositive: material property '" + cmp.name + 3072 "' is not strictly positive"); 3073 } 3074 } 3075 } // end of checkIsStrictlyPositive 3076 checkIsStrictlyNegative(const BehaviourDescription::MaterialProperty & mp)3077 void checkIsStrictlyNegative( 3078 const BehaviourDescription::MaterialProperty& mp) { 3079 if (mp.is<BehaviourDescription::ConstantMaterialProperty>()) { 3080 auto& cmp = mp.get<BehaviourDescription::ConstantMaterialProperty>(); 3081 if (!(cmp.value < 0)) { 3082 tfel::raise("checkIsStrictlyNegative: material property '" + cmp.name + 3083 "' is not strictly negative"); 3084 } 3085 } 3086 } // end of checkIsStrictlyNegative 3087 getParametersFileName(const BehaviourDescription & bd)3088 std::string getParametersFileName(const BehaviourDescription& bd){ 3089 return bd.getClassName() + "-parameters.txt"; 3090 } // end of getParametersFileName 3091 getParametersFileName(const BehaviourDescription & bd,const BehaviourDescription::Hypothesis h)3092 std::string getParametersFileName(const BehaviourDescription& bd, 3093 const BehaviourDescription::Hypothesis h) { 3094 const auto hn = BehaviourDescription::ModellingHypothesis::toString(h); 3095 return bd.getClassName() + hn + "-parameters.txt"; 3096 } // end of getParametersFileName 3097 3098 } // end of namespace mfront 3099