1 /*! 2 * \file mfront/src/BehaviourData.cxx 3 * 4 * \brief 5 * \author Thomas Helfer 6 * \date 18 Jan 2007 7 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 8 * reserved. 9 * This project is publicly released under either the GNU GPL Licence 10 * or the CECILL-A licence. A copy of thoses licences are delivered 11 * with the sources of TFEL. CEA or EDF may also distribute this 12 * project under specific licensing conditions. 13 */ 14 15 #include <sstream> 16 #include <iterator> 17 #include <algorithm> 18 #include <stdexcept> 19 20 #include "TFEL/Raise.hxx" 21 #include "TFEL/Glossary/Glossary.hxx" 22 #include "TFEL/Glossary/GlossaryEntry.hxx" 23 #include "TFEL/Utilities/CxxTokenizer.hxx" 24 #include "MFront/MFrontUtilities.hxx" 25 #include "MFront/DSLUtilities.hxx" 26 #include "MFront/PerformanceProfiling.hxx" 27 #include "MFront/ModelDescription.hxx" 28 #include "MFront/BehaviourData.hxx" 29 #include "MFront/MFrontLogStream.hxx" 30 31 namespace mfront { 32 33 const char* const BehaviourData::FlowRule = "FlowRule"; 34 const char* const BehaviourData::BeforeInitializeLocalVariables = 35 "BeforeInitializeLocalVariables"; 36 const char* const BehaviourData::InitializeLocalVariables = 37 "InitializeLocalVariables"; 38 const char* const BehaviourData::AfterInitializeLocalVariables = 39 "AfterInitializeLocalVariables"; 40 const char* const BehaviourData::ComputePredictor = "ComputePredictor"; 41 const char* const BehaviourData::ComputeStressFreeExpansion = 42 "ComputeStressFreeExpansion"; 43 const char* const BehaviourData::ComputeThermodynamicForces = 44 "ComputeThermodynamicForces"; 45 const char* const BehaviourData::ComputeFinalThermodynamicForces = 46 "ComputeFinalThermodynamicForces"; 47 const char* const BehaviourData::ComputeFinalThermodynamicForcesCandidate = 48 "ComputeFinalThermodynamicForcesCandidate"; 49 const char* const BehaviourData::ComputeInternalEnergy = 50 "ComputeInternalEnergy"; 51 const char* const BehaviourData::ComputeDissipatedEnergy = 52 "ComputeDissipatedEnergy"; 53 const char* const BehaviourData::APrioriTimeStepScalingFactor = 54 "APrioriTimeStepScalingFactor"; 55 const char* const BehaviourData::Integrator = "Integrator"; 56 const char* const BehaviourData::APosterioriTimeStepScalingFactor = 57 "APosterioriTimeStepScalingFactor"; 58 const char* const BehaviourData::ComputeDerivative = "ComputeDerivative"; 59 const char* const BehaviourData::UpdateAuxiliaryStateVariables = 60 "UpdateAuxiliaryStateVariables"; 61 const char* const BehaviourData::ComputePredictionOperator = 62 "ComputePredictionOperator"; 63 const char* const BehaviourData::ComputeTangentOperator = 64 "ComputeTangentOperator"; 65 const char* const BehaviourData::InitializeJacobian = "InitializeJacobian"; 66 const char* const BehaviourData::InitializeJacobianInvert = 67 "InitializeJacobianInvert"; 68 const char* const BehaviourData::AdditionalConvergenceChecks = 69 "AdditionalConvergenceChecks"; 70 71 const char* const BehaviourData::profiling = "profiling"; 72 const char* const BehaviourData::hasAPrioriTimeStepScalingFactor = 73 "hasAPrioriTimeStepScalingFactor"; 74 const char* const BehaviourData::hasAPosterioriTimeStepScalingFactor = 75 "hasAPosterioriTimeStepScalingFactor"; 76 const char* const BehaviourData::hasConsistentTangentOperator = 77 "hasConsistentTangentOperator"; 78 const char* const BehaviourData::isConsistentTangentOperatorSymmetric = 79 "isConsistentTangentOperatorSymmetric"; 80 const char* const BehaviourData::hasPredictionOperator = 81 "hasPredictionOperator"; 82 const char* const BehaviourData::compareToNumericalJacobian = 83 "compareToNumericalJacobian"; 84 const char* const BehaviourData::numericallyComputedJacobianBlocks = 85 "numericallyComputedJacobianBlocks"; 86 const char* const BehaviourData::allowsNewUserDefinedVariables = 87 "allowsNewUserDefinedVariables"; 88 const char* const BehaviourData::algorithm = "algorithm"; 89 const char* const BehaviourData::numberOfEvaluations = "numberOfEvaluations"; 90 91 /*! 92 * check if the given name has already been used as value in the 93 * glossary map or in the entry map 94 * \param[in] gm : glossray names 95 * \param[in] em : entry names 96 * \param[in] n : glossary name 97 */ BehaviourDataCheckIfNameIsAnEntryNameOrAGlossaryName(const std::map<std::string,std::string> & gm,const std::map<std::string,std::string> & em,const std::string & n)98 static void BehaviourDataCheckIfNameIsAnEntryNameOrAGlossaryName( 99 const std::map<std::string, std::string>& gm, 100 const std::map<std::string, std::string>& em, 101 const std::string& n) { 102 auto check = [&n](const std::map<std::string, std::string>& m, 103 const char* const t) { 104 for (const auto& v : m) { 105 tfel::raise_if(v.second == n, 106 "BehaviourDataCheckIfNameIsAnEntryNameOrAGlossaryName: " 107 "name '" + 108 n + "' is already used as a " + std::string(t)); 109 } 110 }; 111 check(gm, "glossary name"); 112 check(em, "entry name"); 113 } // end of BehaviourDataCheckIfNameIsAnEntryNameOrAGlossaryName 114 115 /*! 116 * \brief associate a glossary name or an entry name to a variable 117 * \param[in] m : map to be updated 118 * \param[in] gn : glossary names 119 * \param[in] en : entry names 120 * \param[in] vn : variable name 121 * \param[in] n : variable name 122 * \param[in] g : glossray name or entry name 123 */ BehaviourDataAddToGlossaryOrEntryNames(std::map<std::string,std::string> & m,const std::map<std::string,std::string> & gn,const std::map<std::string,std::string> & en,const std::set<std::string> & vn,const std::string & n,const std::string & g)124 static void BehaviourDataAddToGlossaryOrEntryNames( 125 std::map<std::string, std::string>& m, 126 const std::map<std::string, std::string>& gn, 127 const std::map<std::string, std::string>& en, 128 const std::set<std::string>& vn, 129 const std::string& n, 130 const std::string& g) { 131 auto throw_if = [](const bool c, const std::string& msg) { 132 tfel::raise_if(c, "BehaviourDataAddToGlossaryOrEntryNames: " + msg); 133 }; 134 BehaviourDataCheckIfNameIsAnEntryNameOrAGlossaryName(gn, en, g); 135 throw_if(en.find(n) != en.end(), 136 "an entry name has already been specified for " 137 "variable '" + 138 n + "'"); 139 throw_if(gn.find(n) != gn.end(), 140 "a glossary name has already been specified for " 141 "variable '" + 142 n + "'"); 143 if (n != g) { 144 throw_if(vn.find(g) != vn.end(), "a member with the '" + g + 145 "' name has already " 146 "been declared"); 147 } 148 throw_if(!m.insert({n, g}).second, "glossary name for variable '" + n + 149 "' " 150 "already specified"); 151 } 152 throwUndefinedAttribute(const std::string & n)153 void BehaviourData::throwUndefinedAttribute(const std::string& n) { 154 tfel::raise( 155 "BehaviourData::getAttribute: " 156 "no attribute named '" + 157 n + "'"); 158 } // end of BehaviourData::throwUndefinedAttribute 159 160 BehaviourData::CodeBlocksAggregator::CodeBlocksAggregator() = default; 161 isMutable() const162 bool BehaviourData::CodeBlocksAggregator::isMutable() const { 163 return this->is_mutable; 164 } // end of BehaviourData::CodeBlocksAggregator::isMutable 165 update()166 void BehaviourData::CodeBlocksAggregator::update() { 167 // updating code 168 this->cblock.code = cblock_begin; 169 if (!this->cblock_body.empty()) { 170 if (!this->cblock.code.empty()) { 171 if (*(this->cblock.code.rbegin()) != '\n') { 172 this->cblock.code.push_back('\n'); 173 } 174 } 175 } 176 this->cblock.code += cblock_body; 177 if (!this->cblock_end.empty()) { 178 if (!this->cblock.code.empty()) { 179 if (*(this->cblock.code.rbegin()) != '\n') { 180 this->cblock.code.push_back('\n'); 181 } 182 } 183 } 184 this->cblock.code += cblock_end; 185 // updating description 186 this->cblock.description = cdoc_begin; 187 if (!this->cdoc_body.empty()) { 188 if (!this->cblock.description.empty()) { 189 if (*(this->cblock.description.rbegin()) != '\n') { 190 this->cblock.description.push_back('\n'); 191 } 192 } 193 } 194 this->cblock.description += cdoc_body; 195 if (!this->cdoc_end.empty()) { 196 if (!this->cblock.description.empty()) { 197 if (*(this->cblock.description.rbegin()) != '\n') { 198 this->cblock.description.push_back('\n'); 199 } 200 } 201 } 202 this->cblock.description += cdoc_end; 203 } // end of BehaviourData::update 204 set(const CodeBlock & c,const Position p,const bool b)205 void BehaviourData::CodeBlocksAggregator::set(const CodeBlock& c, 206 const Position p, 207 const bool b) { 208 auto raise = [](const std::string& m) { 209 tfel::raise("BehaviourData::CodeBlocksAggregator::set: " + m); 210 }; 211 this->check(); 212 this->cblock.staticMembers.insert(c.staticMembers.begin(), 213 c.staticMembers.end()); 214 this->cblock.members.insert(c.members.begin(), c.members.end()); 215 for (const auto& a : c.attributes) { 216 if (this->cblock.attributes.count(a.first) != 0) { 217 auto& ca = this->cblock.attributes[a.first]; 218 if (ca.is<bool>()) { 219 if (!a.second.is<bool>()) { 220 raise("unmatched type for attribute '" + a.first + "'"); 221 } 222 if (a.second.get<bool>() != ca.get<bool>()) { 223 raise("unmatched value for attribute '" + a.first + "'"); 224 } 225 } else if (ca.is<std::string>()) { 226 if (!a.second.is<std::string>()) { 227 raise("unmatched type for attribute '" + a.first + "'"); 228 } 229 if (a.second.get<std::string>() != ca.get<std::string>()) { 230 raise("unmatched value for attribute '" + a.first + "'"); 231 } 232 } else if (ca.is<std::vector<VariableDescription>>()) { 233 if (!a.second.is<std::vector<VariableDescription>>()) { 234 raise("unmatched type for attribute '" + a.first + "'"); 235 } 236 auto& cv = ca.get<std::vector<VariableDescription>>(); 237 for (const auto& v : 238 a.second.get<std::vector<VariableDescription>>()) { 239 const auto pv = std::find_if(cv.cbegin(), cv.cend(), 240 [&v](const VariableDescription& v2) { 241 return v.name == v2.name; 242 }); 243 if (pv == cv.cend()) { 244 cv.push_back(v); 245 } 246 } 247 } else { 248 raise("unsupported attribute type (internal error)"); 249 } 250 } else { 251 this->cblock.attributes.insert(a); 252 } 253 } 254 switch (p) { 255 case AT_BEGINNING: 256 if (!this->cblock_begin.empty()) { 257 this->cblock_begin += '\n'; 258 } 259 this->cblock_begin += c.code; 260 if (!c.description.empty()) { 261 if (!this->cdoc_begin.empty()) { 262 this->cdoc_begin += '\n'; 263 } 264 this->cdoc_begin += c.description; 265 } 266 break; 267 case BODY: 268 if (!this->cblock_body.empty()) { 269 this->cblock_body += '\n'; 270 } 271 this->cblock_body += c.code; 272 if (!c.description.empty()) { 273 if (!this->cdoc_body.empty()) { 274 this->cdoc_body += '\n'; 275 } 276 this->cdoc_body += c.description; 277 } 278 break; 279 case AT_END: 280 if (!this->cblock_end.empty()) { 281 this->cblock_end += '\n'; 282 } 283 this->cblock_end += c.code; 284 if (!c.description.empty()) { 285 if (!this->cdoc_end.empty()) { 286 this->cdoc_end += '\n'; 287 } 288 this->cdoc_end += c.description; 289 } 290 break; 291 } 292 this->update(); 293 this->is_mutable = b; 294 } // end of BehaviourData::CodeBlocksAggregator::set 295 replace(const CodeBlock & c,const Position p,const bool b)296 void BehaviourData::CodeBlocksAggregator::replace(const CodeBlock& c, 297 const Position p, 298 const bool b) { 299 this->check(); 300 this->cblock_begin.clear(); 301 this->cblock_body.clear(); 302 this->cblock_end.clear(); 303 this->cblock.code.clear(); 304 this->cblock.members.clear(); 305 this->cblock.staticMembers.clear(); 306 this->set(c, p, b); 307 } // end of BehaviourData::CodeBlocksAggregator::set 308 check() const309 void BehaviourData::CodeBlocksAggregator::check() const { 310 tfel::raise_if(!this->is_mutable, 311 "BehaviourData::CodeBlocksAggregator::set: " 312 "can't modifiy a code block"); 313 } // end of BehaviourData::CodeBlocksAggregator::check 314 get() const315 const CodeBlock& BehaviourData::CodeBlocksAggregator::get() const { 316 this->is_mutable = false; 317 return this->cblock; 318 } // end of BehaviourData::CodeBlocksAggregator::get 319 320 BehaviourData::CodeBlocksAggregator::~CodeBlocksAggregator() = default; 321 BehaviourData()322 BehaviourData::BehaviourData() { 323 this->registerMemberName("dt"); 324 this->reserveName("\u0394t"); // symbolic value 325 // treating the temperature 326 auto T = VariableDescription{"temperature", "T", 1u, 0u}; 327 T.setGlossaryName("Temperature"); 328 this->addExternalStateVariable(T, UNREGISTRED); 329 } // end of BehaviourData::BehaviourData() 330 331 BehaviourData::BehaviourData(const BehaviourData&) = default; 332 checkAlreadyRegistred(const std::set<std::string> & r,const std::string & n)333 static void checkAlreadyRegistred(const std::set<std::string>& r, 334 const std::string& n) { 335 if (r.find(n) == r.end()) { 336 tfel::raise( 337 "checkAlreadyRegistred: " 338 "variable '" + 339 n + "' was not registred"); 340 } 341 } 342 addStaticVariable(const StaticVariableDescription & v,const RegistrationStatus s)343 void BehaviourData::addStaticVariable(const StaticVariableDescription& v, 344 const RegistrationStatus s) { 345 if ((this->hasAttribute(BehaviourData::allowsNewUserDefinedVariables)) && 346 (!this->getAttribute<bool>( 347 BehaviourData::allowsNewUserDefinedVariables))) { 348 const auto cbn = this->getCodeBlockNames(); 349 tfel::raise_if(cbn.empty(), 350 "BehaviourData::addStaticVariable: " 351 "no more variable can be defined. This may mean that " 352 "the parser does not expect you to add variables"); 353 auto cbs = std::string{}; 354 for (const auto& n : cbn) { 355 cbs += "\n- " + n; 356 } 357 tfel::raise( 358 "BehaviourData::addStaticVariable: " 359 "no more variable can be defined. This may mean that " 360 "you already declared a block of code (or that the dsl " 361 "does not expect you to add variables for whatever reason). " 362 "This is the list of " 363 "code blocks defined :" + 364 cbs); 365 } 366 if (s == UNREGISTRED) { 367 this->registerStaticMemberName(v.name); 368 } else { 369 checkAlreadyRegistred(this->reservedNames, v.name); 370 } 371 this->staticVariables.push_back(v); 372 } // end of BehaviourData::addStaticVariable 373 getIntegerConstant(const std::string & n) const374 int BehaviourData::getIntegerConstant(const std::string& n) const { 375 for (const auto& v : this->staticVariables) { 376 if (v.name == n) { 377 tfel::raise_if(v.type != "int", 378 "MaterialPropertyDSL::getIntegerConstant: " 379 "invalid type for variable '" + 380 n + "'"); 381 return v.value; 382 } 383 } 384 tfel::raise( 385 "MaterialPropertyDSL::getIntegerConstant: " 386 "unknown variable '" + 387 n + "'"); 388 } // end of BehaviourData::getIntegerConstant 389 getStaticVariables() const390 const StaticVariableDescriptionContainer& BehaviourData::getStaticVariables() 391 const { 392 return this->staticVariables; 393 } // end of BehaviourData::getStaticVariables 394 getPersistentVariableDescription(const std::string & v) const395 const VariableDescription& BehaviourData::getPersistentVariableDescription( 396 const std::string& v) const { 397 return this->getPersistentVariables().getVariable(v); 398 } // end of BehaviourData::getPersistentVariableDescription 399 400 const VariableDescription& getPersistentVariableDescriptionByExternalName(const std::string & v) const401 BehaviourData::getPersistentVariableDescriptionByExternalName( 402 const std::string& v) const { 403 return this->getPersistentVariables().getVariableByExternalName(v); 404 } // end of BehaviourData::getPersistentVariableDescriptionByExternalName 405 getIntegrationVariableDescription(const std::string & v) const406 const VariableDescription& BehaviourData::getIntegrationVariableDescription( 407 const std::string& v) const { 408 return this->getIntegrationVariables().getVariable(v); 409 } // end of BehaviourData::getIntegrationVariableDescription 410 411 const VariableDescription& getIntegrationVariableDescriptionByExternalName(const std::string & v) const412 BehaviourData::getIntegrationVariableDescriptionByExternalName( 413 const std::string& v) const { 414 return this->getIntegrationVariables().getVariableByExternalName(v); 415 } // end of BehaviourData::getIntegrationVariableDescriptionByExternalName 416 getStateVariableDescription(const std::string & v) const417 const VariableDescription& BehaviourData::getStateVariableDescription( 418 const std::string& v) const { 419 return this->getStateVariables().getVariable(v); 420 } // end of BehaviourData::getStateVariableDescription 421 422 const VariableDescription& getStateVariableDescriptionByExternalName(const std::string & v) const423 BehaviourData::getStateVariableDescriptionByExternalName( 424 const std::string& v) const { 425 return this->getStateVariables().getVariableByExternalName(v); 426 } // end of BehaviourData::getStateVariableDescriptionByExternalName 427 getExternalStateVariableDescription(const std::string & v) const428 const VariableDescription& BehaviourData::getExternalStateVariableDescription( 429 const std::string& v) const { 430 return this->getExternalStateVariables().getVariable(v); 431 } // end of BehaviourData::getExternalStateVariableDescription 432 433 const VariableDescription& getExternalStateVariableDescriptionByExternalName(const std::string & v) const434 BehaviourData::getExternalStateVariableDescriptionByExternalName( 435 const std::string& v) const { 436 return this->getExternalStateVariables().getVariableByExternalName(v); 437 } // end of BehaviourData::getExternalStateVariableDescriptionByExternalName 438 439 const VariableDescription& getAuxiliaryStateVariableDescription(const std::string & v) const440 BehaviourData::getAuxiliaryStateVariableDescription( 441 const std::string& v) const { 442 return this->getAuxiliaryStateVariables().getVariable(v); 443 } // end of BehaviourData::getAuxiliaryStateVariableDescription 444 445 const VariableDescription& getAuxiliaryStateVariableDescriptionByExternalName(const std::string & v) const446 BehaviourData::getAuxiliaryStateVariableDescriptionByExternalName( 447 const std::string& v) const { 448 return this->getAuxiliaryStateVariables().getVariableByExternalName(v); 449 } // end of BehaviourData::getAuxiliaryStateVariableDescriptionByExternalName 450 getParameterDescription(const std::string & v) const451 const VariableDescription& BehaviourData::getParameterDescription( 452 const std::string& v) const { 453 return this->getParameters().getVariable(v); 454 } // end of BehaviourData::getParameterDescription 455 456 const VariableDescription& getParameterDescriptionByExternalName(const std::string & v) const457 BehaviourData::getParameterDescriptionByExternalName( 458 const std::string& v) const { 459 return this->getParameters().getVariableByExternalName(v); 460 } // end of BehaviourData::getParameterDescriptionByExternalName 461 addMaterialProperty(const VariableDescription & v,const RegistrationStatus s)462 void BehaviourData::addMaterialProperty(const VariableDescription& v, 463 const RegistrationStatus s) { 464 const auto op = this->overriding_parameters.find(v.name); 465 if (op != this->overriding_parameters.end()) { 466 if (v.arraySize != 1u) { 467 tfel::raise( 468 "BehaviourData::addMaterialProperty: " 469 "overriding arrays of material properties is not supported yet"); 470 } 471 this->addParameter(v, s); 472 this->setParameterDefaultValue(v.name, op->second); 473 } else { 474 this->addVariable(this->materialProperties, v, s, false); 475 } 476 } // end of BehaviourData::addMaterialProperty 477 addIntegrationVariable(const VariableDescription & v,const RegistrationStatus s)478 void BehaviourData::addIntegrationVariable(const VariableDescription& v, 479 const RegistrationStatus s) { 480 this->addVariable(this->integrationVariables, v, s, true); 481 } // end of BehaviourData::addIntegrationVariable 482 addStateVariable(const VariableDescription & v,const RegistrationStatus s)483 void BehaviourData::addStateVariable(const VariableDescription& v, 484 const RegistrationStatus s) { 485 this->addVariable(this->stateVariables, v, s, true); 486 if (s == FORCEREGISTRATION) { 487 this->addVariable(this->integrationVariables, v, ALREADYREGISTRED, true, 488 true); 489 } else { 490 this->addVariable(this->integrationVariables, v, ALREADYREGISTRED, true); 491 } 492 /*! 493 * for compatibility reasons with previous mfront versions 494 * (<2.0), auxiliary state variables shall be put after 495 * state variables. 496 */ 497 bool found = false; 498 auto p = this->persistentVariables.begin(); 499 while (p != this->persistentVariables.end()) { 500 if (this->isAuxiliaryStateVariableName(p->name)) { 501 this->persistentVariables.insert(p, v); 502 found = true; 503 break; 504 } else { 505 ++p; 506 } 507 } 508 if (!found) { 509 this->persistentVariables.push_back(v); 510 } 511 } // end of BehaviourData::addStateVariable 512 addAuxiliaryStateVariable(const VariableDescription & v,const RegistrationStatus s)513 void BehaviourData::addAuxiliaryStateVariable(const VariableDescription& v, 514 const RegistrationStatus s) { 515 this->addVariable(this->auxiliaryStateVariables, v, s, false); 516 if (s == FORCEREGISTRATION) { 517 this->addVariable(this->persistentVariables, v, ALREADYREGISTRED, true, 518 true); 519 } else { 520 this->addVariable(this->persistentVariables, v, ALREADYREGISTRED, true); 521 } 522 } // end of BehaviourData::addAuxiliaryStateVariable 523 addExternalStateVariable(const VariableDescription & v,const RegistrationStatus s)524 void BehaviourData::addExternalStateVariable(const VariableDescription& v, 525 const RegistrationStatus s) { 526 this->addVariable(this->externalStateVariables, v, s, true); 527 } // end of BehaviourData::addExternalStateVariable 528 addLocalVariable(const VariableDescription & v,const RegistrationStatus s)529 void BehaviourData::addLocalVariable(const VariableDescription& v, 530 const RegistrationStatus s) { 531 this->addVariable(this->localVariables, v, s, false, true); 532 } // end of BehaviourData::addLocalVariable 533 addParameter(const VariableDescription & v,const RegistrationStatus s)534 void BehaviourData::addParameter(const VariableDescription& v, 535 const RegistrationStatus s) { 536 const auto op = this->overriding_parameters.find(v.name); 537 if (op != this->overriding_parameters.end()) { 538 if (v.arraySize != 1u) { 539 tfel::raise( 540 "BehaviourData::addParameter: " 541 "overriding array of parameters is not supported yet"); 542 } 543 } 544 this->addVariable(this->parameters, v, s, false); 545 } // end of BehaviourData::addParameter 546 hasParameter(const std::string & n) const547 bool BehaviourData::hasParameter(const std::string& n) const { 548 return this->parameters.contains(n); 549 } 550 hasParameters() const551 bool BehaviourData::hasParameters() const { 552 return !this->parameters.empty(); 553 } 554 isMemberUsedInCodeBlocks(const std::string & v) const555 bool BehaviourData::isMemberUsedInCodeBlocks(const std::string& v) const { 556 for (const auto& c : this->cblocks) { 557 const auto& m = c.second.get().members; 558 if (m.find(v) != m.end()) { 559 return true; 560 } 561 } 562 return false; 563 } // end of BehaviourData::isMemberUsedInCodeBlocks 564 isMaterialPropertyName(const std::string & n) const565 bool BehaviourData::isMaterialPropertyName(const std::string& n) const { 566 return this->getMaterialProperties().contains(n); 567 } // end of BehaviourData::isMaterialPropertyName 568 isStaticVariableName(const std::string & n) const569 bool BehaviourData::isStaticVariableName(const std::string& n) const { 570 return this->getStaticVariables().contains(n); 571 } // end of BehaviourData::isStaticVariableName 572 isLocalVariableName(const std::string & n) const573 bool BehaviourData::isLocalVariableName(const std::string& n) const { 574 return this->getLocalVariables().contains(n); 575 } // end of BehaviourData::isLocalVariableName 576 isPersistentVariableName(const std::string & n) const577 bool BehaviourData::isPersistentVariableName(const std::string& n) const { 578 return this->getPersistentVariables().contains(n); 579 } // end of BehaviourData::isPersistentVariableName 580 isIntegrationVariableName(const std::string & n) const581 bool BehaviourData::isIntegrationVariableName(const std::string& n) const { 582 return this->getIntegrationVariables().contains(n); 583 } // end of BehaviourData::isIntegrationVariableName 584 isIntegrationVariableIncrementName(const std::string & n) const585 bool BehaviourData::isIntegrationVariableIncrementName( 586 const std::string& n) const { 587 if (n.size() < 2) { 588 return false; 589 } 590 if (n[0] != 'd') { 591 return false; 592 } 593 return this->getIntegrationVariables().contains(n.substr(1)); 594 } // end of BehaviourData::isIntegrationVariableName 595 isStateVariableName(const std::string & n) const596 bool BehaviourData::isStateVariableName(const std::string& n) const { 597 return this->getStateVariables().contains(n); 598 } // end of BehaviourData::isStateVariableName 599 isStateVariableIncrementName(const std::string & n) const600 bool BehaviourData::isStateVariableIncrementName(const std::string& n) const { 601 if (n.size() < 2) { 602 return false; 603 } 604 if (n[0] != 'd') { 605 return false; 606 } 607 return this->getStateVariables().contains(n.substr(1)); 608 } // end of BehaviourData::isStateVariableName 609 isAuxiliaryStateVariableName(const std::string & n) const610 bool BehaviourData::isAuxiliaryStateVariableName(const std::string& n) const { 611 return this->getAuxiliaryStateVariables().contains(n); 612 } // end of BehaviourData::isStateVariableName 613 isExternalStateVariableName(const std::string & n) const614 bool BehaviourData::isExternalStateVariableName(const std::string& n) const { 615 return this->getExternalStateVariables().contains(n); 616 } // end of BehaviourData::isExternalStateVariableName 617 isExternalStateVariableIncrementName(const std::string & n) const618 bool BehaviourData::isExternalStateVariableIncrementName( 619 const std::string& n) const { 620 if (n.size() < 2) { 621 return false; 622 } 623 if (n[0] != 'd') { 624 return false; 625 } 626 return this->getExternalStateVariables().contains(n.substr(1)); 627 } // end of BehaviourData::isExternalStateVariableName 628 isParameterName(const std::string & n) const629 bool BehaviourData::isParameterName(const std::string& n) const { 630 return this->getParameters().contains(n); 631 } // end of BehaviourData::isParameterName 632 getMaterialProperties() const633 const VariableDescriptionContainer& BehaviourData::getMaterialProperties() 634 const { 635 return this->materialProperties; 636 } // end of BehaviourData::getMaterialProperties 637 getPersistentVariables() const638 const VariableDescriptionContainer& BehaviourData::getPersistentVariables() 639 const { 640 return this->persistentVariables; 641 } // end of BehaviourData::getPersistentVariables 642 getVariablesNames() const643 std::set<std::string> BehaviourData::getVariablesNames() const { 644 auto getNames = [](std::set<std::string>& r, 645 const VariableDescriptionContainer& c) { 646 for (const auto& v : c) { 647 tfel::raise_if(!r.insert(v.name).second, 648 "BehaviourData::getVariablesNames: " 649 "internal error, variable name " 650 "'" + 651 v.name + "' multiply defined"); 652 } 653 }; 654 auto n = std::set<std::string>{}; 655 getNames(n, this->getMaterialProperties()); 656 getNames(n, this->getStateVariables()); 657 getNames(n, this->getAuxiliaryStateVariables()); 658 getNames(n, this->getExternalStateVariables()); 659 getNames(n, this->getParameters()); 660 return n; 661 } // end of BehaviourData::getVariablesNames 662 getVariables(const std::string & t) const663 const VariableDescriptionContainer& BehaviourData::getVariables( 664 const std::string& t) const { 665 const VariableDescriptionContainer& (BehaviourData::*m)() const; 666 if (t == "MaterialProperty") { 667 m = &BehaviourData::getMaterialProperties; 668 } else if (t == "PersistentVariable") { 669 m = &BehaviourData::getPersistentVariables; 670 } else if (t == "IntegrationVariable") { 671 m = &BehaviourData::getIntegrationVariables; 672 } else if (t == "StateVariable") { 673 m = &BehaviourData::getStateVariables; 674 } else if (t == "AuxiliaryStateVariable") { 675 m = &BehaviourData::getAuxiliaryStateVariables; 676 } else if (t == "ExternalStateVariable") { 677 m = &BehaviourData::getExternalStateVariables; 678 } else if (t == "Parameter") { 679 m = &BehaviourData::getParameters; 680 } else { 681 tfel::raise( 682 "BehaviourData::getVariables: " 683 "invalid variables type '" + 684 t + "'"); 685 } 686 return (this->*m)(); 687 } // end of BehaviourData::getIntegrationVariables 688 getIntegrationVariables() const689 const VariableDescriptionContainer& BehaviourData::getIntegrationVariables() 690 const { 691 return this->integrationVariables; 692 } // end of BehaviourData::getIntegrationVariables 693 getStateVariables() const694 const VariableDescriptionContainer& BehaviourData::getStateVariables() const { 695 return this->stateVariables; 696 } // end of BehaviourData::getStateVariables 697 698 const VariableDescriptionContainer& getAuxiliaryStateVariables() const699 BehaviourData::getAuxiliaryStateVariables() const { 700 return this->auxiliaryStateVariables; 701 } // end of BehaviourData::getAuxiliaryStateVariables 702 getExternalStateVariables() const703 const VariableDescriptionContainer& BehaviourData::getExternalStateVariables() 704 const { 705 return this->externalStateVariables; 706 } // end of BehaviourData::getExternalStateVariables 707 getLocalVariables() const708 const VariableDescriptionContainer& BehaviourData::getLocalVariables() const { 709 return this->localVariables; 710 } // end of BehaviourData::getLocalVariables 711 isUsableInPurelyImplicitResolution() const712 bool BehaviourData::isUsableInPurelyImplicitResolution() const { 713 return this->usableInPurelyImplicitResolution; 714 } // end of BehaviourData::isUsableInPurelyImplicitResolution 715 setBounds(const std::string & n,const VariableBoundsDescription & b)716 void BehaviourData::setBounds(const std::string& n, 717 const VariableBoundsDescription& b) { 718 bool treated = false; 719 auto set_bounds = [&n, &b, &treated](VariableDescriptionContainer& c) { 720 if (c.contains(n)) { 721 c.getVariable(n).setBounds(b); 722 treated = true; 723 } 724 }; 725 set_bounds(this->materialProperties); 726 set_bounds(this->localVariables); 727 set_bounds(this->stateVariables); 728 set_bounds(this->auxiliaryStateVariables); 729 set_bounds(this->integrationVariables); 730 set_bounds(this->persistentVariables); 731 set_bounds(this->externalStateVariables); 732 set_bounds(this->parameters); 733 tfel::raise_if(!treated, 734 "BehaviourData::setBounds: " 735 "no variable named '" + 736 n + "'"); 737 } // end of BehaviourData::getBounds 738 setBounds(const std::string & n,const unsigned short i,const VariableBoundsDescription & b)739 void BehaviourData::setBounds(const std::string& n, 740 const unsigned short i, 741 const VariableBoundsDescription& b) { 742 bool treated = false; 743 auto set_bounds = [&n, i, &b, &treated](VariableDescriptionContainer& c) { 744 if (c.contains(n)) { 745 c.getVariable(n).setBounds(b, i); 746 treated = true; 747 } 748 }; 749 set_bounds(this->materialProperties); 750 set_bounds(this->localVariables); 751 set_bounds(this->stateVariables); 752 set_bounds(this->auxiliaryStateVariables); 753 set_bounds(this->integrationVariables); 754 set_bounds(this->persistentVariables); 755 set_bounds(this->externalStateVariables); 756 set_bounds(this->parameters); 757 tfel::raise_if(!treated, 758 "BehaviourData::setBounds: " 759 "no variable named '" + 760 n + "'"); 761 } 762 763 const VariableDescription& getVariableDescriptionByExternalName(const std::string & n) const764 BehaviourData::getVariableDescriptionByExternalName( 765 const std::string& n) const { 766 auto contains = [&n](const VariableDescriptionContainer& vc) { 767 for (const auto& v : vc) { 768 if (v.getExternalName() == n) { 769 return true; 770 } 771 } 772 return false; 773 }; 774 if (contains(this->materialProperties)) { 775 return this->materialProperties.getVariableByExternalName(n); 776 } 777 if (contains(this->localVariables)) { 778 return this->localVariables.getVariableByExternalName(n); 779 } 780 if (contains(this->stateVariables)) { 781 return this->stateVariables.getVariableByExternalName(n); 782 } 783 if (contains(this->auxiliaryStateVariables)) { 784 return this->auxiliaryStateVariables.getVariableByExternalName(n); 785 } 786 if (contains(this->integrationVariables)) { 787 return this->integrationVariables.getVariableByExternalName(n); 788 } 789 if (contains(this->externalStateVariables)) { 790 return this->externalStateVariables.getVariableByExternalName(n); 791 } 792 if (contains(this->parameters)) { 793 return this->parameters.getVariableByExternalName(n); 794 } 795 tfel::raise( 796 "BehaviourData::getVariableDescriptionByExternalName: " 797 "no variable with external name '" + 798 n + 799 "' found. " 800 "Such variable is *not*:\n" 801 "- a material property\n" 802 "- a local variable\n" 803 "- a state variable\n" 804 "- an auxiliary state variable\n" 805 "- an integration variable\n" 806 "- an external state variable\n" 807 "- a parameter"); 808 } // end of BehaviourData::getVariableDescriptionByExternalName 809 getVariableDescription(const std::string & n) const810 const VariableDescription& BehaviourData::getVariableDescription( 811 const std::string& n) const { 812 if (this->materialProperties.contains(n)) { 813 return this->materialProperties.getVariable(n); 814 } 815 if (this->localVariables.contains(n)) { 816 return this->localVariables.getVariable(n); 817 } 818 if (this->stateVariables.contains(n)) { 819 return this->stateVariables.getVariable(n); 820 } 821 if (this->auxiliaryStateVariables.contains(n)) { 822 return this->auxiliaryStateVariables.getVariable(n); 823 } 824 if (this->integrationVariables.contains(n)) { 825 return this->integrationVariables.getVariable(n); 826 } 827 if (this->externalStateVariables.contains(n)) { 828 return this->externalStateVariables.getVariable(n); 829 } 830 if (this->parameters.contains(n)) { 831 return this->parameters.getVariable(n); 832 } 833 tfel::raise( 834 "BehaviourData::getVariableDescription: " 835 "no variable named '" + 836 n + 837 "' found. " 838 "This variable is *not*:\n" 839 "- a material property\n" 840 "- a local variable\n" 841 "- a state variable\n" 842 "- an auxiliary state variable\n" 843 "- an integration variable\n" 844 "- an external state variable\n" 845 "- a parameter"); 846 } // end of BehaviourData::getVariableDescription 847 setVariableAttribute(const std::string & v,const std::string & n,const VariableAttribute & a,const bool b)848 void BehaviourData::setVariableAttribute(const std::string& v, 849 const std::string& n, 850 const VariableAttribute& a, 851 const bool b) { 852 bool treated = false; 853 auto set_if = [&v, &n, &a, b, &treated](VariableDescriptionContainer& vc) { 854 if (vc.contains(v)) { 855 vc.getVariable(v).setAttribute(n, a, b); 856 treated = true; 857 } 858 }; 859 set_if(this->materialProperties); 860 set_if(this->localVariables); 861 set_if(this->integrationVariables); 862 set_if(this->stateVariables); 863 set_if(this->auxiliaryStateVariables); 864 set_if(this->persistentVariables); 865 set_if(this->externalStateVariables); 866 set_if(this->parameters); 867 tfel::raise_if(!treated, 868 "BehaviourData::setVariableAttribute: " 869 "no variable named '" + 870 n + 871 "' found." 872 "This variable is *not*:\n" 873 "- a material property\n" 874 "- a local variable\n" 875 "- a state variable\n" 876 "- an auxiliary state variable\n" 877 "- an integration variable\n" 878 "- a persistent variable\n" 879 "- an external state variable\n" 880 "- a parameter"); 881 } // end of BehaviourData::setVariableAttribute 882 getVariableDescription(const std::string & n)883 VariableDescription& BehaviourData::getVariableDescription( 884 const std::string& n) { 885 if (this->materialProperties.contains(n)) { 886 return this->materialProperties.getVariable(n); 887 } 888 if (this->localVariables.contains(n)) { 889 return this->localVariables.getVariable(n); 890 } 891 if (this->stateVariables.contains(n)) { 892 return this->stateVariables.getVariable(n); 893 } 894 if (this->auxiliaryStateVariables.contains(n)) { 895 return this->auxiliaryStateVariables.getVariable(n); 896 } 897 if (this->integrationVariables.contains(n)) { 898 return this->integrationVariables.getVariable(n); 899 } 900 if (this->externalStateVariables.contains(n)) { 901 return this->externalStateVariables.getVariable(n); 902 } 903 if (this->parameters.contains(n)) { 904 return this->parameters.getVariable(n); 905 } 906 tfel::raise( 907 "BehaviourData::getVariableDescription: " 908 "no variable named '" + 909 n + 910 "' found." 911 "This variable is *not*:\n" 912 "- a material property\n" 913 "- a local variable\n" 914 "- a state variable\n" 915 "- an auxiliary state variable\n" 916 "- an integration variable\n" 917 "- an external state variable\n" 918 "- a parameter"); 919 } // end of BehaviourData::getVariableDescription 920 setPhysicalBounds(const std::string & n,const VariableBoundsDescription & b)921 void BehaviourData::setPhysicalBounds(const std::string& n, 922 const VariableBoundsDescription& b) { 923 bool treated = false; 924 auto set_bounds = [&n, &b, &treated](VariableDescriptionContainer& c) { 925 if (c.contains(n)) { 926 c.getVariable(n).setPhysicalBounds(b); 927 treated = true; 928 } 929 }; 930 set_bounds(this->materialProperties); 931 set_bounds(this->localVariables); 932 set_bounds(this->stateVariables); 933 set_bounds(this->auxiliaryStateVariables); 934 set_bounds(this->integrationVariables); 935 set_bounds(this->persistentVariables); 936 set_bounds(this->externalStateVariables); 937 set_bounds(this->parameters); 938 tfel::raise_if(!treated, 939 "BehaviourData::setPhysicalBounds: " 940 "no variable named '" + 941 n + "'"); 942 } // end of BehaviourData::setPhysicalBounds 943 setPhysicalBounds(const std::string & n,const unsigned short i,const VariableBoundsDescription & b)944 void BehaviourData::setPhysicalBounds(const std::string& n, 945 const unsigned short i, 946 const VariableBoundsDescription& b) { 947 bool treated = false; 948 auto set_bounds = [&n, &i, &b, &treated](VariableDescriptionContainer& c) { 949 if (c.contains(n)) { 950 c.getVariable(n).setPhysicalBounds(b, i); 951 treated = true; 952 } 953 }; 954 set_bounds(this->materialProperties); 955 set_bounds(this->localVariables); 956 set_bounds(this->stateVariables); 957 set_bounds(this->auxiliaryStateVariables); 958 set_bounds(this->integrationVariables); 959 set_bounds(this->persistentVariables); 960 set_bounds(this->externalStateVariables); 961 set_bounds(this->parameters); 962 tfel::raise_if(!treated, 963 "BehaviourData::setPhysicalBounds: " 964 "no variable named '" + 965 n + "'"); 966 } // end of BehaviourData::setPhysicalBounds 967 setUsableInPurelyImplicitResolution(const bool b)968 void BehaviourData::setUsableInPurelyImplicitResolution(const bool b) { 969 this->usableInPurelyImplicitResolution = b; 970 } // end of BehaviourData::setUsableInPurelyImplicitResolution 971 972 void BehaviourData:: declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution(const std::string & n)973 declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution( 974 const std::string& n) { 975 this->pupirv.insert(n); 976 } // end of 977 // BehaviourData::declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution 978 979 const std::set<std::string>& BehaviourData:: getExternalStateVariablesDeclaredProbablyUnusableInPurelyImplicitResolution() const980 getExternalStateVariablesDeclaredProbablyUnusableInPurelyImplicitResolution() 981 const { 982 return this->pupirv; 983 } // end of 984 // BehaviourData::getExternalStateVariablesDeclaredProbablyUnusableInPurelyImplicitResolution 985 addVariable(VariableDescriptionContainer & c,const VariableDescription & v,const RegistrationStatus s,const bool bi,const bool b)986 void BehaviourData::addVariable(VariableDescriptionContainer& c, 987 const VariableDescription& v, 988 const RegistrationStatus s, 989 const bool bi, 990 const bool b) { 991 if ((!b) && (s != FORCEREGISTRATION)) { 992 if ((this->hasAttribute(BehaviourData::allowsNewUserDefinedVariables)) && 993 (!this->getAttribute<bool>( 994 BehaviourData::allowsNewUserDefinedVariables))) { 995 const auto cbn = this->getCodeBlockNames(); 996 tfel::raise_if( 997 cbn.empty(), 998 "BehaviourData::addVariable: can't add variable '" + v.name + 999 "', " 1000 "no more variable can be defined. This may mean that " 1001 "the parser does not expect you to add variables"); 1002 auto cbs = std::string{}; 1003 for (const auto& n : cbn) { 1004 cbs += "\n- " + n; 1005 } 1006 tfel::raise( 1007 "BehaviourData::addVariable: can't add variable '" + v.name + 1008 "', " 1009 "no more variable can be defined. This may mean that " 1010 "you already declared a block of code (or that the dsl " 1011 "does not expect you to add variables for whatever reason). " 1012 "This is the list of " 1013 "code blocks defined :" + 1014 cbs); 1015 } 1016 } 1017 if (s == ALREADYREGISTRED) { 1018 checkAlreadyRegistred(this->reservedNames, v.name); 1019 if (!v.symbolic_form.empty()) { 1020 checkAlreadyRegistred(this->reservedNames, v.symbolic_form); 1021 } 1022 } else { 1023 this->registerMemberName(v.name); 1024 if (!v.symbolic_form.empty()) { 1025 this->reserveName(v.symbolic_form); 1026 } 1027 if (bi) { 1028 this->registerMemberName("d" + v.name); 1029 if (!v.symbolic_form.empty()) { 1030 this->reserveName("\u0394" + v.symbolic_form); 1031 } else { 1032 this->reserveName("\u0394" + v.name); 1033 } 1034 } 1035 } 1036 if (v.hasGlossaryName()) { 1037 this->glossaryNames.insert({v.name, v.getExternalName()}); 1038 } 1039 if (v.hasEntryName()) { 1040 this->entryNames.insert({v.name, v.getExternalName()}); 1041 } 1042 c.push_back(v); 1043 } // end of BehaviourData::addVariable 1044 reserveName(const std::string & n)1045 void BehaviourData::reserveName(const std::string& n) { 1046 tfel::raise_if(!this->reservedNames.insert(n).second, 1047 "BehaviourData::reserveName: " 1048 "name '" + 1049 n + "' already registred"); 1050 } // end of BehaviourData::reserveName 1051 isNameReserved(const std::string & n) const1052 bool BehaviourData::isNameReserved(const std::string& n) const { 1053 return this->reservedNames.count(n) != 0; 1054 } 1055 registerGlossaryName(const std::string & n,const std::string & g)1056 void BehaviourData::registerGlossaryName(const std::string& n, 1057 const std::string& g) { 1058 using namespace tfel::glossary; 1059 const auto& glossary = Glossary::getGlossary(); 1060 if (glossary.contains(n)) { 1061 std::ostringstream msg; 1062 msg << "BehaviourData::registerEntryName: " 1063 << "the name '" << n << "' is a registred as a glossary name.\n"; 1064 displayGlossaryEntryCompleteDescription(msg, 1065 glossary.getGlossaryEntry(n)); 1066 tfel::raise(msg.str()); 1067 } 1068 if (!glossary.contains(g)) { 1069 tfel::raise( 1070 "BehaviourData::registerGlossaryName: " 1071 "the name '" + 1072 g + "' is a not known as a glossary name"); 1073 } 1074 if (!this->isNameReserved(n)) { 1075 tfel::raise( 1076 "BehaviourData::registerGlossaryName: " 1077 "the variable name '" + 1078 n + "' not is registred"); 1079 } 1080 /* 1081 * Special exceptions for glossary name which are also supported type name: 1082 * those names are already registred and no clash ispossible. 1083 */ 1084 const auto& flags = SupportedTypes::getTypeFlags(); 1085 if (flags.find(g) == flags.end()) { 1086 this->reserveName(g); 1087 } 1088 tfel::raise_if(!this->glossaryNames.insert({n, g}).second, 1089 "BehaviourData::registerGlossaryName: " 1090 "a variable named '" + 1091 n + "' has already been registred"); 1092 } // end of BehaviourData::registerGlossaryName 1093 registerEntryName(const std::string & n,const std::string & e)1094 void BehaviourData::registerEntryName(const std::string& n, 1095 const std::string& e) { 1096 using namespace tfel::glossary; 1097 const auto& glossary = Glossary::getGlossary(); 1098 if (glossary.contains(e)) { 1099 std::ostringstream msg; 1100 msg << "BehaviourData::registerEntryName: " 1101 << "the name '" << e << "' is a registred as a glossary name.\n"; 1102 displayGlossaryEntryCompleteDescription(msg, 1103 glossary.getGlossaryEntry(e)); 1104 tfel::raise(msg.str()); 1105 } 1106 if (!this->isNameReserved(n)) { 1107 tfel::raise( 1108 "BehaviourData::registerGlossaryName: " 1109 "the variable name '" + 1110 n + "' is registred"); 1111 } 1112 /* 1113 * Special exceptions for glossary name which are also supported type name: 1114 * those names are already registred and no clash ispossible. 1115 */ 1116 const auto& flags = SupportedTypes::getTypeFlags(); 1117 if (flags.find(e) == flags.end()) { 1118 this->reserveName(e); 1119 } 1120 tfel::raise_if(!this->entryNames.insert({n, e}).second, 1121 "BehaviourData::registerEntryName: " 1122 "a variable named '" + 1123 n + "' has already been registred"); 1124 } // end of BehaviourData::registerEntryName 1125 registerMemberName(const std::string & n)1126 void BehaviourData::registerMemberName(const std::string& n) { 1127 using namespace tfel::glossary; 1128 const auto& glossary = Glossary::getGlossary(); 1129 for (auto& e : this->entryNames) { 1130 tfel::raise_if(e.second == n, 1131 "BehaviourData::registerMemberName: " 1132 "the name '" + 1133 n + 1134 "' is already been used " 1135 "for an entry name"); 1136 } 1137 if (glossary.contains(n)) { 1138 std::ostringstream msg; 1139 msg << "BehaviourData::registerMemberName: " 1140 << "the name '" << n << "' is a registred as a glossary name.\n"; 1141 displayGlossaryEntryCompleteDescription(msg, 1142 glossary.getGlossaryEntry(n)); 1143 tfel::raise(msg.str()); 1144 } 1145 this->reserveName(n); 1146 tfel::raise_if(!this->membersNames.insert(n).second, 1147 "BehaviourData::registerMemberName: " 1148 "a variable named '" + 1149 n + "' has already been registred"); 1150 } // end of BehaviourData::registerMemberName 1151 registerStaticMemberName(const std::string & n)1152 void BehaviourData::registerStaticMemberName(const std::string& n) { 1153 const auto& g = tfel::glossary::Glossary::getGlossary(); 1154 for (auto& e : this->entryNames) { 1155 tfel::raise_if(e.second == n, 1156 "BehaviourData::registerStaticMemberName: " 1157 "the name '" + 1158 n + 1159 "' is already been used " 1160 "for an entry name"); 1161 } 1162 if (g.contains(n)) { 1163 std::ostringstream msg; 1164 msg << "BehaviourData::registerStaticMemberName: " 1165 << "the name '" << n << "' is a registred as a glossary name.\n"; 1166 displayGlossaryEntryCompleteDescription(msg, g.getGlossaryEntry(n)); 1167 tfel::raise(msg.str()); 1168 } 1169 this->reserveName(n); 1170 tfel::raise_if(!this->staticMembersNames.insert(n).second, 1171 "BehaviourData::registerStaticMemberName: " 1172 "a variable named '" + 1173 n + "' has already been registred"); 1174 } // end of BehaviourData::registerStaticMemberName 1175 getRegistredMembersNames() const1176 const std::set<std::string>& BehaviourData::getRegistredMembersNames() const { 1177 return this->membersNames; 1178 } // end of BehaviourData::getRegistredMemberNames 1179 getRegistredStaticMembersNames() const1180 const std::set<std::string>& BehaviourData::getRegistredStaticMembersNames() 1181 const { 1182 return this->staticMembersNames; 1183 } // end of BehaviourData::getRegistredStaticMemberNames 1184 checkVariableName(const std::string & n) const1185 void BehaviourData::checkVariableName(const std::string& n) const { 1186 if ((this->materialProperties.contains(n)) || 1187 (this->persistentVariables.contains(n)) || 1188 (this->integrationVariables.contains(n)) || 1189 (this->stateVariables.contains(n)) || 1190 (this->auxiliaryStateVariables.contains(n)) || 1191 (this->externalStateVariables.contains(n)) || 1192 (this->localVariables.contains(n)) || (this->parameters.contains(n)) || 1193 (this->staticVariables.contains(n))) { 1194 return; 1195 } 1196 tfel::raise( 1197 "BehaviourData::checkVariableName: " 1198 "no variable named '" + 1199 n + "'"); 1200 } // end of BehaviourData::checkVariableName 1201 setCode(const std::string & n,const CodeBlock & c,const Mode m,const Position p,const bool b)1202 void BehaviourData::setCode(const std::string& n, 1203 const CodeBlock& c, 1204 const Mode m, 1205 const Position p, 1206 const bool b) { 1207 auto pc = this->cblocks.find(n); 1208 if (pc == this->cblocks.end()) { 1209 pc = this->cblocks.insert({n, CodeBlocksAggregator{}}).first; 1210 } else { 1211 if (m == CREATE) { 1212 tfel::raise( 1213 "BehaviourData::setCode: " 1214 "a code block named '" + 1215 n + 1216 "' already exists.\n" 1217 "If you wanted to append this new code to the " 1218 "existing one, you shall use the 'Append' option.\n" 1219 "You can also replace it with 'Replace' option " 1220 "(assuming you know what you are doing).\n"); 1221 } else if (m == CREATEORREPLACE) { 1222 tfel::raise_if(!pc->second.isMutable(), 1223 "BehaviourData::setCode: " 1224 "the code block named '" + 1225 n + 1226 "' " 1227 "is not modifiable"); 1228 this->cblocks.erase(pc); 1229 pc = this->cblocks.insert({n, CodeBlocksAggregator{}}).first; 1230 } else if (m == CREATEBUTDONTREPLACE) { 1231 return; 1232 } 1233 } 1234 pc->second.set(c, p, b); 1235 } // end of BehaviourData::setCode 1236 getCodeBlock(const std::string & n) const1237 const CodeBlock& BehaviourData::getCodeBlock(const std::string& n) const { 1238 auto p = this->cblocks.find(n); 1239 tfel::raise_if(p == this->cblocks.end(), 1240 "BehaviourData::getCode: " 1241 "no code block associated with '" + 1242 n + "'"); 1243 return p->second.get(); 1244 } // end of BehaviourData::getCodeBlock 1245 getCode(const std::string & n,const std::string & cn,const bool b) const1246 std::string BehaviourData::getCode(const std::string& n, 1247 const std::string& cn, 1248 const bool b) const { 1249 if (!b) { 1250 return this->getCodeBlock(n).code; 1251 } 1252 std::ostringstream out; 1253 writeStandardPerformanceProfilingBegin(out, cn, n); 1254 out << this->getCodeBlock(n).code; 1255 writeStandardPerformanceProfilingEnd(out); 1256 return out.str(); 1257 } // end of BehaviourData::getCode 1258 hasCode(const std::string & n) const1259 bool BehaviourData::hasCode(const std::string& n) const { 1260 return this->cblocks.find(n) != this->cblocks.end(); 1261 } 1262 setParameterDefaultValue(const std::string & n,const double v)1263 void BehaviourData::setParameterDefaultValue(const std::string& n, 1264 const double v) { 1265 auto throw_if = [](const bool b, const std::string& m) { 1266 tfel::raise_if(b, "BehaviourData::setParameterDefaultValue: " + m); 1267 }; 1268 throw_if(!this->parameters.contains(n), "no parameter '" + n + "' defined"); 1269 const auto& p = this->parameters.getVariable(n); 1270 const auto f = SupportedTypes::getTypeFlag(p.type); 1271 throw_if(f != SupportedTypes::SCALAR, 1272 "parameter '" + n + "' is not a scalar"); 1273 const auto op = this->overriding_parameters.find(n); 1274 if (op == this->overriding_parameters.end()) { 1275 throw_if(!this->parametersDefaultValues.insert({n, v}).second, 1276 "default value for parameter '" + n + "' already defined"); 1277 } else { 1278 throw_if(!this->parametersDefaultValues.insert({n, op->second}).second, 1279 "default value for parameter '" + n + "' already defined"); 1280 } 1281 } // end of BehaviourData::setParameterDefaultValue 1282 setParameterDefaultValue(const std::string & n,const unsigned short i,const double v)1283 void BehaviourData::setParameterDefaultValue(const std::string& n, 1284 const unsigned short i, 1285 const double v) { 1286 auto throw_if = [](const bool b, const std::string& m) { 1287 tfel::raise_if(b, "BehaviourData::setParameterDefaultValue: " + m); 1288 }; 1289 throw_if(!this->parameters.contains(n), "no parameter '" + n + "' defined"); 1290 const auto& p = this->parameters.getVariable(n); 1291 const auto f = SupportedTypes::getTypeFlag(p.type); 1292 throw_if(f != SupportedTypes::SCALAR, 1293 "parameter '" + n + "' is not a floatting point"); 1294 throw_if(p.arraySize == 1, 1295 "parameter '" + n + "' has not been declared as an array"); 1296 const auto idx = std::to_string(i); 1297 throw_if(i >= p.arraySize, "index " + idx + " is greater than parameter '" + 1298 n + "' array size"); 1299 const auto n2 = n + '[' + idx + ']'; 1300 // const auto op = this->overriding_parameters.find(n2); 1301 // if (op != this->overriding_parameters.end()) { 1302 // } 1303 throw_if(!this->parametersDefaultValues.insert({n2, v}).second, 1304 "default value for parameter '" + n2 + "' already defined"); 1305 } 1306 setParameterDefaultValue(const std::string & n,const int v)1307 void BehaviourData::setParameterDefaultValue(const std::string& n, 1308 const int v) { 1309 auto throw_if = [](const bool b, const std::string& m) { 1310 tfel::raise_if(b, "BehaviourData::setParameterDefaultValue: " + m); 1311 }; 1312 throw_if(!this->parameters.contains(n), "no parameter '" + n + "' defined"); 1313 const auto& p = this->parameters.getVariable(n); 1314 throw_if(p.type != "int", "parameter '" + n + "' is not a floatting point"); 1315 throw_if(!this->iParametersDefaultValues.insert({n, v}).second, 1316 "default value for parameter '" + n + "' already defined"); 1317 } 1318 setParameterDefaultValue(const std::string & n,const unsigned short v)1319 void BehaviourData::setParameterDefaultValue(const std::string& n, 1320 const unsigned short v) { 1321 auto throw_if = [](const bool b, const std::string& m) { 1322 tfel::raise_if(b, "BehaviourData::setParameterDefaultValue: " + m); 1323 }; 1324 throw_if(!this->parameters.contains(n), "no parameter '" + n + "' defined"); 1325 const auto& p = this->parameters.getVariable(n); 1326 throw_if(p.type != "ushort", 1327 "parameter '" + n + "' is not a floatting point"); 1328 throw_if(!this->uParametersDefaultValues.insert({n, v}).second, 1329 "default value for parameter '" + n + "' already defined"); 1330 } 1331 getFloattingPointParameterDefaultValue(const std::string & n) const1332 double BehaviourData::getFloattingPointParameterDefaultValue( 1333 const std::string& n) const { 1334 auto throw_if = [](const bool b, const std::string& m) { 1335 tfel::raise_if( 1336 b, "BehaviourData::getFloattingPointParameterDefaultValue: " + m); 1337 }; 1338 throw_if(!this->parameters.contains(n), "no parameter '" + n + "' defined"); 1339 const auto p = this->parametersDefaultValues.find(n); 1340 throw_if(p == this->parametersDefaultValues.end(), 1341 "no default value defined for parameter '" + n + "'"); 1342 return p->second; 1343 } // end of BehaviourData::getFloattingPointParameterDefaultValue 1344 getFloattingPointParameterDefaultValue(const std::string & n,const unsigned short i) const1345 double BehaviourData::getFloattingPointParameterDefaultValue( 1346 const std::string& n, const unsigned short i) const { 1347 auto throw_if = [](const bool b, const std::string& m) { 1348 tfel::raise_if( 1349 b, "BehaviourData::getFloattingPointParameterDefaultValue: " + m); 1350 }; 1351 throw_if(!this->parameters.contains(n), "no parameter '" + n + "' defined"); 1352 const auto& v = this->parameters.getVariable(n); 1353 throw_if(v.arraySize == 1u, "parameter '" + n + "' is not an array"); 1354 throw_if(i >= v.arraySize, "invalid index for parameter '" + n + "'"); 1355 const auto n2 = n + '[' + std::to_string(i) + ']'; 1356 const auto p = this->parametersDefaultValues.find(n2); 1357 throw_if(p == this->parametersDefaultValues.end(), 1358 "no default value defined for parameter '" + n2 + "'"); 1359 return p->second; 1360 } // end of BehaviourData::getFloattingPointParameterDefaultValue 1361 getIntegerParameterDefaultValue(const std::string & n) const1362 int BehaviourData::getIntegerParameterDefaultValue( 1363 const std::string& n) const { 1364 tfel::raise_if(!this->parameters.contains(n), 1365 "BehaviourData::getIntegerParameterDefaultValue: " 1366 "no parameter '" + 1367 n + "' defined"); 1368 auto p = this->iParametersDefaultValues.find(n); 1369 tfel::raise_if(p == this->iParametersDefaultValues.end(), 1370 "BehaviourData::getIntegerParameterDefaultValue: " 1371 "no default value defined for parameter '" + 1372 n + "'"); 1373 return p->second; 1374 } // end of BehaviourData::getIntegerParameterDefaultValue 1375 getUnsignedShortParameterDefaultValue(const std::string & n) const1376 unsigned short BehaviourData::getUnsignedShortParameterDefaultValue( 1377 const std::string& n) const { 1378 tfel::raise_if(!this->parameters.contains(n), 1379 "BehaviourData::getUnsignedShortParameterDefaultValue: " 1380 "no parameter '" + 1381 n + "' defined"); 1382 auto p = this->uParametersDefaultValues.find(n); 1383 tfel::raise_if(p == this->uParametersDefaultValues.end(), 1384 "BehaviourData::getUnsignedShortParameterDefaultValue: " 1385 "no default value defined for parameter '" + 1386 n + "'"); 1387 return p->second; 1388 } // end of BehaviourData::getUnsignedShortParameterDefaultValue 1389 setAttribute(const std::string & n,const BehaviourAttribute & a,const bool b)1390 void BehaviourData::setAttribute(const std::string& n, 1391 const BehaviourAttribute& a, 1392 const bool b) { 1393 auto throw_if = [](const bool c, const std::string& m) { 1394 tfel::raise_if(c, "BehaviourData::setAttribute: " + m); 1395 }; 1396 auto p = this->attributes.find(n); 1397 if (p != this->attributes.end()) { 1398 throw_if(a.getTypeIndex() != p->second.getTypeIndex(), 1399 "attribute already exists with a different type"); 1400 } 1401 if (!this->attributes.insert({n, a}).second) { 1402 throw_if(!b, "attribute '" + n + "' already declared"); 1403 } 1404 } // end of BehaviourData::setAttribute 1405 updateAttribute(const std::string & n,const BehaviourAttribute & a)1406 void BehaviourData::updateAttribute(const std::string& n, 1407 const BehaviourAttribute& a) { 1408 auto throw_if = [](const bool c, const std::string& m) { 1409 tfel::raise_if(c, "BehaviourData::updateAttribute: " + m); 1410 }; 1411 auto p = this->attributes.find(n); 1412 throw_if(p == this->attributes.end(), "unknown attribute '" + n + "'"); 1413 throw_if(a.getTypeIndex() != p->second.getTypeIndex(), 1414 "attribute already exists with a different type"); 1415 p->second = a; 1416 } // end of BehaviourData::setAttribute 1417 hasAttribute(const std::string & n) const1418 bool BehaviourData::hasAttribute(const std::string& n) const { 1419 return this->attributes.count(n) != 0u; 1420 } // end of BehaviourData::hasAttribute 1421 1422 const std::map<std::string, BehaviourAttribute>& getAttributes() const1423 BehaviourData::getAttributes() const { 1424 return this->attributes; 1425 } // end of BehaviourData::getAttributes 1426 getCodeBlockNames() const1427 std::vector<std::string> BehaviourData::getCodeBlockNames() const { 1428 auto names = std::vector<std::string>{}; 1429 for (const auto& c : this->cblocks) { 1430 names.push_back(c.first); 1431 } 1432 return names; 1433 } // end of BehaviourData::getCodeBlockNames 1434 hasGlossaryName(const std::string & n) const1435 bool BehaviourData::hasGlossaryName(const std::string& n) const { 1436 this->checkVariableName(n); 1437 return this->glossaryNames.find(n) != this->glossaryNames.end(); 1438 } // end of BehaviourData::hasGlossaryName 1439 hasEntryName(const std::string & n) const1440 bool BehaviourData::hasEntryName(const std::string& n) const { 1441 this->checkVariableName(n); 1442 return this->entryNames.find(n) != this->entryNames.end(); 1443 } // end of BehaviourData::hasEntryName 1444 getExternalName(const std::string & n) const1445 std::string BehaviourData::getExternalName(const std::string& n) const { 1446 this->checkVariableName(n); 1447 auto p = this->glossaryNames.find(n); 1448 if (p != this->glossaryNames.end()) { 1449 return p->second; 1450 } 1451 p = this->entryNames.find(n); 1452 if (p != this->entryNames.end()) { 1453 return p->second; 1454 } 1455 return n; 1456 } // end of BehaviourData::getExternalName 1457 getExternalNames(const VarContainer & v) const1458 std::vector<std::string> BehaviourData::getExternalNames( 1459 const VarContainer& v) const { 1460 return v.getExternalNames(); 1461 } // end of BehaviourData::getExternalNames 1462 getExternalNames(std::vector<std::string> & names,const VarContainer & v) const1463 void BehaviourData::getExternalNames(std::vector<std::string>& names, 1464 const VarContainer& v) const { 1465 v.getExternalNames(names); 1466 } // end of BehaviourData::getExternalNames 1467 appendExternalNames(std::vector<std::string> & names,const VarContainer & v) const1468 void BehaviourData::appendExternalNames(std::vector<std::string>& names, 1469 const VarContainer& v) const { 1470 v.appendExternalNames(names); 1471 } // end of BehaviourData::appendExternalNames 1472 setGlossaryName(const std::string & n,const std::string & g)1473 void BehaviourData::setGlossaryName(const std::string& n, 1474 const std::string& g) { 1475 using tfel::glossary::Glossary; 1476 const auto& glossary = Glossary::getGlossary(); 1477 tfel::raise_if(!glossary.contains(g), 1478 "BehaviourData::setGlossaryName: " 1479 "'" + 1480 g + "' is not a glossary name"); 1481 bool treated = false; 1482 auto set_glossary_name = [&n, &g, 1483 &treated](VariableDescriptionContainer& c) { 1484 if (c.contains(n)) { 1485 c.getVariable(n).setGlossaryName(g); 1486 treated = true; 1487 } 1488 }; 1489 this->checkVariableName(n); 1490 BehaviourDataAddToGlossaryOrEntryNames( 1491 this->glossaryNames, this->glossaryNames, this->entryNames, 1492 this->reservedNames, n, glossary.getGlossaryEntry(g).getKey()); 1493 set_glossary_name(this->materialProperties); 1494 set_glossary_name(this->localVariables); 1495 set_glossary_name(this->stateVariables); 1496 set_glossary_name(this->auxiliaryStateVariables); 1497 set_glossary_name(this->integrationVariables); 1498 set_glossary_name(this->persistentVariables); 1499 set_glossary_name(this->externalStateVariables); 1500 set_glossary_name(this->parameters); 1501 tfel::raise_if(!treated, 1502 "BehaviourData::setGlossaryName: " 1503 "no variable named '" + 1504 n + "'"); 1505 } // end of BehaviourData::addGlossaryName 1506 isGlossaryNameUsed(const std::string & n) const1507 bool BehaviourData::isGlossaryNameUsed(const std::string& n) const { 1508 using namespace tfel::glossary; 1509 const auto& g = Glossary::getGlossary(); 1510 tfel::raise_if(!g.contains(n), 1511 "BehaviourData::isGlossaryNameUsed: " 1512 "'" + 1513 n + "' is not a glossary name"); 1514 for (const auto& gn : this->glossaryNames) { 1515 if (gn.second == n) { 1516 return true; 1517 } 1518 } 1519 return false; 1520 } // end of BehaviourData::isGlossaryName 1521 setEntryName(const std::string & n,const std::string & e)1522 void BehaviourData::setEntryName(const std::string& n, const std::string& e) { 1523 using namespace tfel::glossary; 1524 const auto& glossary = Glossary::getGlossary(); 1525 bool treated = false; 1526 auto set_entry_name = [&n, &e, &treated](VariableDescriptionContainer& c) { 1527 if (c.contains(n)) { 1528 c.getVariable(n).setEntryName(e); 1529 treated = true; 1530 } 1531 }; 1532 if (glossary.contains(e)) { 1533 std::ostringstream msg; 1534 msg << "BehaviourData::setEntryName: " 1535 << "'" << e << "' is a glossary name. " << std::endl 1536 << "Please use 'setGlossaryName' method instead or choose another " 1537 "entry name."; 1538 displayGlossaryEntryCompleteDescription(msg, 1539 glossary.getGlossaryEntry(e)); 1540 tfel::raise(msg.str()); 1541 } 1542 tfel::raise_if(!tfel::utilities::CxxTokenizer::isValidIdentifier(e, false), 1543 "BehaviourData::setEntryName: " 1544 "'" + 1545 e + "' is a not a valid entry name"); 1546 this->checkVariableName(n); 1547 BehaviourDataAddToGlossaryOrEntryNames( 1548 this->entryNames, this->glossaryNames, this->entryNames, 1549 this->reservedNames, n, e); 1550 set_entry_name(this->materialProperties); 1551 set_entry_name(this->localVariables); 1552 set_entry_name(this->stateVariables); 1553 set_entry_name(this->auxiliaryStateVariables); 1554 set_entry_name(this->integrationVariables); 1555 set_entry_name(this->persistentVariables); 1556 set_entry_name(this->externalStateVariables); 1557 set_entry_name(this->parameters); 1558 tfel::raise_if(!treated, 1559 "BehaviourData::setEntryName: " 1560 "no variable named '" + 1561 n + "'"); 1562 } // end of BehaviourData::addEntryName 1563 isUsedAsEntryName(const std::string & n) const1564 bool BehaviourData::isUsedAsEntryName(const std::string& n) const { 1565 for (const auto& en : this->entryNames) { 1566 if (en.second == n) { 1567 return true; 1568 } 1569 } 1570 return false; 1571 } // end of BehaviourData::isEntryName 1572 getVariableNameFromGlossaryNameOrEntryName(const std::string & n) const1573 std::string BehaviourData::getVariableNameFromGlossaryNameOrEntryName( 1574 const std::string& n) const { 1575 for (const auto& e : this->glossaryNames) { 1576 if (e.second == n) { 1577 return e.first; 1578 } 1579 } 1580 for (const auto& e : this->entryNames) { 1581 if (e.second == n) { 1582 return e.first; 1583 } 1584 } 1585 tfel::raise( 1586 "BehaviourData::getVariableNameFromGlossaryNameOrEntryName: " 1587 "no variable with glossary or entry name '" + 1588 n + "'"); 1589 } // end of BehaviourData::getVariableNameFromGlossaryNameOrEntryName 1590 getParameters() const1591 const VariableDescriptionContainer& BehaviourData::getParameters() const { 1592 return this->parameters; 1593 } // end of BehaviourData::getParameters 1594 appendToMembers(const std::string & c)1595 void BehaviourData::appendToMembers(const std::string& c) { 1596 this->members += c; 1597 if (!this->members.empty()) { 1598 if (*(this->members.rbegin()) != '\n') { 1599 this->members += '\n'; 1600 } 1601 } 1602 } // end of BehaviourData::appendToMembers 1603 getMembers() const1604 std::string BehaviourData::getMembers() const { 1605 return this->members; 1606 } // end of BehaviourData::getMembers 1607 appendToPrivateCode(const std::string & c)1608 void BehaviourData::appendToPrivateCode(const std::string& c) { 1609 this->privateCode += c; 1610 if (!this->privateCode.empty()) { 1611 if (*(this->privateCode.rbegin()) != '\n') { 1612 this->privateCode += '\n'; 1613 } 1614 } 1615 } // end of BehaviourData::appendToPrivateCode 1616 getPrivateCode() const1617 std::string BehaviourData::getPrivateCode() const { 1618 return this->privateCode; 1619 } // end of BehaviourData::getPrivateCode 1620 addStressFreeExpansion(const StressFreeExpansionDescription & sfed)1621 void BehaviourData::addStressFreeExpansion( 1622 const StressFreeExpansionDescription& sfed) { 1623 auto throw_if = [](const bool c, const std::string& m) { 1624 tfel::raise_if(c, "BehaviourData::addStressFreeExpansion: " + m); 1625 }; 1626 auto check_esv = [this, &throw_if](const SFED_ESV& h) { 1627 throw_if(!this->isExternalStateVariableName(h.vname), 1628 "'" + h.vname + "' is not an external state variable name"); 1629 const auto& ev = this->getExternalStateVariables().getVariable(h.vname); 1630 throw_if(ev.arraySize != 1u, 1631 "invalid arrary size of variable '" + h.vname + "'"); 1632 }; 1633 auto check_esv2 = [this, &throw_if](const SFED_ESV& h) { 1634 throw_if(!this->isExternalStateVariableName(h.vname), 1635 "'" + h.vname + "' is not an external state variable name"); 1636 const auto& ev = this->getExternalStateVariables().getVariable(h.vname); 1637 throw_if(ev.arraySize != 3u, 1638 "invalid arrary size of variable '" + h.vname + "'"); 1639 }; 1640 auto treat = [&check_esv, &throw_if, 1641 this](const StressFreeExpansionHandler& h) { 1642 if (h.is<SFED_ESV>()) { 1643 check_esv(h.get<SFED_ESV>()); 1644 } else if (h.is<std::shared_ptr<ModelDescription>>()) { 1645 const auto& md = *(h.get<std::shared_ptr<ModelDescription>>()); 1646 throw_if(!md.constantMaterialProperties.empty(), 1647 "constant material properties are not supported yet"); 1648 throw_if(md.functions.size() != 1u, 1649 "invalid number of functions in model '" + md.className + "'"); 1650 throw_if(md.functions[0].name.empty(), "invalid function name"); 1651 throw_if(md.functions[0].modifiedVariables.size() != 1u, 1652 "invalid number of modified variables in function '" + 1653 md.functions[0].name + "' in model '" + md.className + 1654 "'"); 1655 // checking output 1656 throw_if(md.outputs.size() != 1u, 1657 "external model must have one and only output"); 1658 // checking inputs 1659 for (const auto& i : md.inputs) { 1660 throw_if(i.arraySize != 1u, 1661 "invalid array size for model variable '" + i.name + "'"); 1662 // external name 1663 const auto& n = i.getExternalName(); 1664 // check that an external state variable with the same 1665 // external state variable exists 1666 const auto& evnames = 1667 this->getExternalNames(this->getExternalStateVariables()); 1668 if (n == tfel::glossary::Glossary::Temperature) { 1669 continue; 1670 } 1671 if ((std::find(std::begin(evnames), std::end(evnames), n) == 1672 std::end(evnames))) { 1673 // adding a new state variable with given external name 1674 auto v = i; 1675 v.name = md.className + "_" + v.name; 1676 this->addExternalStateVariable(v, UNREGISTRED); 1677 } 1678 } 1679 // declaring the output has an auxiliary state variable 1680 auto o = md.outputs[0]; 1681 o.name = md.className + "_" + o.name; 1682 this->addAuxiliaryStateVariable(o, UNREGISTRED); 1683 } else if (h.is<NullExpansion>()) { 1684 // do nothing 1685 } else { 1686 throw_if(true, "unsupported stress free expansion handler"); 1687 } 1688 }; 1689 if (sfed.is<VolumeSwellingStressFreeExpansion>()) { 1690 const auto& s = sfed.get<VolumeSwellingStressFreeExpansion>(); 1691 throw_if(s.sfe.is<NullExpansion>(), "null swelling is not allowed"); 1692 treat(s.sfe); 1693 } else if (sfed.is<IsotropicStressFreeExpansion>()) { 1694 const auto& s = sfed.get<IsotropicStressFreeExpansion>(); 1695 throw_if(s.sfe.is<NullExpansion>(), "null swelling is not allowed"); 1696 treat(s.sfe); 1697 } else if (sfed.is<AxialGrowth>()) { 1698 const auto& s = sfed.get<AxialGrowth>(); 1699 throw_if(s.sfe.is<NullExpansion>(), "null swelling is not allowed"); 1700 treat(s.sfe); 1701 } else if (sfed.is<Relocation>()) { 1702 const auto& s = sfed.get<Relocation>(); 1703 throw_if(s.sfe.is<NullExpansion>(), "null swelling is not allowed"); 1704 treat(s.sfe); 1705 } else if (sfed.is<OrthotropicStressFreeExpansion>()) { 1706 const auto& s = sfed.get<OrthotropicStressFreeExpansion>(); 1707 throw_if(s.sfe0.is<NullExpansion>() && s.sfe1.is<NullExpansion>() && 1708 s.sfe2.is<NullExpansion>(), 1709 "null swelling is not allowed"); 1710 treat(s.sfe0); 1711 treat(s.sfe1); 1712 treat(s.sfe2); 1713 } else if (sfed.is<OrthotropicStressFreeExpansionII>()) { 1714 const auto& s = sfed.get<OrthotropicStressFreeExpansionII>(); 1715 check_esv2(s.esv); 1716 } else { 1717 throw_if(true, "internal error, unsupported stress free expansion type"); 1718 } 1719 this->sfeds.push_back(sfed); 1720 } // end of BehaviourData::addStressFreeExpansion 1721 1722 const std::vector<BehaviourData::StressFreeExpansionDescription>& getStressFreeExpansionDescriptions() const1723 BehaviourData::getStressFreeExpansionDescriptions() const { 1724 return this->sfeds; 1725 } // end of BehaviourData::getStressFreeExpansionDescriptions 1726 isStressFreeExansionAnisotropic() const1727 bool BehaviourData::isStressFreeExansionAnisotropic() const { 1728 for (const auto& sfed : this->sfeds) { 1729 if ((sfed.is<BehaviourData::AxialGrowth>()) || 1730 (sfed.is<BehaviourData::Relocation>()) || 1731 (sfed.is<BehaviourData::OrthotropicStressFreeExpansion>()) || 1732 (sfed.is<BehaviourData::OrthotropicStressFreeExpansionII>())) { 1733 return true; 1734 } else { 1735 tfel::raise_if( 1736 (!sfed.is<BehaviourData::IsotropicStressFreeExpansion>()) && 1737 (!sfed.is<BehaviourData::VolumeSwellingStressFreeExpansion>()), 1738 "BehaviourData::isStressFreeExansionAnisotropic: " 1739 "internal error, unsupported stress " 1740 "free expansion type"); 1741 } 1742 } 1743 return false; 1744 } // end of BehaviourData::isStressFreeExansionAnisotropic 1745 getSymbols(std::map<std::string,std::string> & symbols) const1746 void BehaviourData::getSymbols( 1747 std::map<std::string, std::string>& symbols) const { 1748 mfront::getSymbols(symbols, this->materialProperties); 1749 mfront::getSymbols(symbols, this->persistentVariables); 1750 mfront::getSymbols(symbols, this->integrationVariables); 1751 mfront::getSymbols(symbols, this->stateVariables); 1752 mfront::getSymbols(symbols, this->auxiliaryStateVariables); 1753 mfront::getSymbols(symbols, this->externalStateVariables); 1754 mfront::getSymbols(symbols, this->localVariables); 1755 mfront::getSymbols(symbols, this->parameters); 1756 } // end of BehaviourData::getSymbols 1757 overrideByAParameter(const std::string & n,const double v)1758 void BehaviourData::overrideByAParameter(const std::string& n, 1759 const double v) { 1760 if (this->overriding_parameters.count(n) != 0) { 1761 tfel::raise( 1762 "BehaviourData::overrideByAParameter: " 1763 "an override for variable '" + 1764 n + "' has already been specified"); 1765 } 1766 this->overriding_parameters[n] = v; 1767 } // end of BehaviourData::overrideByAParameter 1768 1769 BehaviourData::~BehaviourData() = default; 1770 1771 } // end of namespace mfront 1772