1 /*! 2 * \file mfront/src/BehaviourDSLCommon.cxx 3 * \brief 4 * 5 * \author Thomas Helfer 6 * \date 05/05/2008 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 <algorithm> 16 #include <stdexcept> 17 #include <iterator> 18 #include <sstream> 19 #include <utility> 20 #include <vector> 21 #include <limits> 22 #include <cctype> 23 #include <cmath> 24 25 #include "TFEL/Raise.hxx" 26 #include "TFEL/System/System.hxx" 27 #include "TFEL/UnicodeSupport/UnicodeSupport.hxx" 28 #include "TFEL/Glossary/Glossary.hxx" 29 #include "TFEL/Glossary/GlossaryEntry.hxx" 30 #include "TFEL/Math/General/IEEE754.hxx" 31 #include "TFEL/Material/FiniteStrainBehaviourTangentOperator.hxx" 32 #include "TFEL/Utilities/Data.hxx" 33 #include "TFEL/Utilities/StringAlgorithms.hxx" 34 #include "TFEL/Math/Evaluator.hxx" 35 36 #include "MFront/MFront.hxx" 37 #include "MFront/MFrontHeader.hxx" 38 #include "MFront/DSLUtilities.hxx" 39 #include "MFront/MFrontUtilities.hxx" 40 #include "MFront/MFrontDebugMode.hxx" 41 #include "MFront/PedanticMode.hxx" 42 #include "MFront/MFrontLogStream.hxx" 43 #include "MFront/SearchPathsHandler.hxx" 44 #include "MFront/AbstractBehaviourInterface.hxx" 45 #include "MFront/MFrontMaterialPropertyInterface.hxx" 46 #include "MFront/PerformanceProfiling.hxx" 47 #include "MFront/BehaviourInterfaceFactory.hxx" 48 #include "MFront/FiniteStrainBehaviourTangentOperatorConversionPath.hxx" 49 #include "MFront/AbstractBehaviourBrick.hxx" 50 #include "MFront/BehaviourBrickFactory.hxx" 51 #include "MFront/TargetsDescription.hxx" 52 #include "MFront/MaterialPropertyDescription.hxx" 53 #include "MFront/ModelDSL.hxx" 54 #include "MFront/MFrontModelInterface.hxx" 55 #include "MFront/BehaviourDSLCommon.hxx" 56 #include "MFront/BehaviourBrick/Requirement.hxx" 57 #include "MFront/BehaviourBrick/RequirementManager.hxx" 58 59 // fixing a bug on current glibc++ cygwin versions (19/08/2015) 60 #if defined __CYGWIN__ && (!defined _GLIBCXX_USE_C99) 61 #include <sstream> 62 namespace std { 63 template <typename T> to_string(const T & v)64 std::string to_string(const T& v) { 65 std::ostringstream s; 66 s << v; 67 return s.str(); 68 } 69 } 70 #endif /* defined __CYGWIN__ && (!defined _GLIBCXX_USE_C99) */ 71 72 #ifndef _MSC_VER 73 static const char* const constexpr_c = "constexpr"; 74 #else 75 static const char* const constexpr_c = "const"; 76 #endif 77 78 namespace mfront { 79 StandardVariableModifier(const Hypothesis h,const FunctionType f)80 BehaviourDSLCommon::StandardVariableModifier::StandardVariableModifier( 81 const Hypothesis h, const FunctionType f) 82 : hypothesis(h), 83 fct(f) {} // end of StandardVariableModifier::StandardVariableModifier 84 exe(const std::string & v,const bool b)85 std::string BehaviourDSLCommon::StandardVariableModifier::exe( 86 const std::string& v, const bool b) { 87 return (this->fct)(this->hypothesis, v, b); 88 } // end of StandardVariableModifier::exe 89 90 BehaviourDSLCommon::StandardVariableModifier::~StandardVariableModifier() = 91 default; 92 StandardWordAnalyser(const Hypothesis h,const FunctionType f)93 BehaviourDSLCommon::StandardWordAnalyser::StandardWordAnalyser( 94 const Hypothesis h, const FunctionType f) 95 : hypothesis(h), 96 fct(f) {} // end of StandardWordAnalyser::StandardWordAnalyser 97 exe(CodeBlock & c,const std::string & v)98 void BehaviourDSLCommon::StandardWordAnalyser::exe(CodeBlock& c, 99 const std::string& v) { 100 this->fct(c, this->hypothesis, v); 101 } // end of StandardWordAnalyser::exe 102 103 BehaviourDSLCommon::StandardWordAnalyser::~StandardWordAnalyser() = default; 104 isValidBehaviourName(const std::string & n)105 bool isValidBehaviourName(const std::string& n) { 106 return tfel::utilities::CxxTokenizer::isValidIdentifier(n, false); 107 } 108 BehaviourDSLCommon()109 BehaviourDSLCommon::BehaviourDSLCommon() 110 : useStateVarTimeDerivative(false), explicitlyDeclaredUsableInPurelyImplicitResolution(false) { 111 using MemberFunc = void (BehaviourDSLCommon::*)(); 112 // By default disable use of quantities 113 this->mb.setUseQt(false); 114 // By default, a behaviour can be used in a purely implicit resolution 115 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 116 this->mb.setUsableInPurelyImplicitResolution(h, true); 117 // reserve names 118 for (const auto& v : DSLBase::getDefaultReservedNames()) { 119 this->mb.reserveName(h, v); 120 } 121 // register behaviours specific names 122 this->registerDefaultVarNames(); 123 this->reserveName("minimal_time_step_scaling_factor"); 124 this->reserveName("maximal_time_step_scaling_factor"); 125 this->reserveName("current_time_step_scaling_factor"); 126 // default call backs 127 auto add = [this](const std::string& k, const MemberFunc f) { 128 this->callBacks.insert({k, [this, f] { (this->*f)(); }}); 129 this->registredKeyWords.insert(k); 130 }; 131 add(";", &BehaviourDSLCommon::treatLonelySeparator); 132 add("@DSL", &BehaviourDSLCommon::treatParser); 133 add("@Parser", &BehaviourDSLCommon::treatParser); 134 add("@Model", &BehaviourDSLCommon::treatModel); 135 add("@Brick", &BehaviourDSLCommon::treatBrick); 136 add("@ModellingHypothesis", &BehaviourDSLCommon::treatModellingHypothesis); 137 add("@ModellingHypotheses", &BehaviourDSLCommon::treatModellingHypotheses); 138 add("@Import", &BehaviourDSLCommon::treatImport); 139 add("@Material", &BehaviourDSLCommon::treatMaterial); 140 add("@Library", &BehaviourDSLCommon::treatLibrary); 141 add("@Profiling", &BehaviourDSLCommon::treatProfiling); 142 add("@Behaviour", &BehaviourDSLCommon::treatBehaviour); 143 add("@StrainMeasure", &BehaviourDSLCommon::treatStrainMeasure); 144 add("@Author", &BehaviourDSLCommon::treatAuthor); 145 add("@Date", &BehaviourDSLCommon::treatDate); 146 add("@MFront", &BehaviourDSLCommon::treatMFront); 147 add("@Link", &BehaviourDSLCommon::treatLink); 148 add("@Includes", &BehaviourDSLCommon::treatIncludes); 149 add("@Members", &BehaviourDSLCommon::treatMembers); 150 add("@Coef", &BehaviourDSLCommon::treatCoef); 151 add("@MaterialProperty", &BehaviourDSLCommon::treatCoef); 152 add("@LocalVar", &BehaviourDSLCommon::treatLocalVar); 153 add("@LocalVariable", &BehaviourDSLCommon::treatLocalVar); 154 add("@Parameter", &BehaviourDSLCommon::treatParameter); 155 add("@StateVar", &BehaviourDSLCommon::treatStateVariable); 156 add("@StateVariable", &BehaviourDSLCommon::treatStateVariable); 157 add("@AuxiliaryStateVar", &BehaviourDSLCommon::treatAuxiliaryStateVariable); 158 add("@AuxiliaryStateVariable", 159 &BehaviourDSLCommon::treatAuxiliaryStateVariable); 160 add("@ExternalStateVar", &BehaviourDSLCommon::treatExternalStateVariable); 161 add("@ExternalStateVariable", 162 &BehaviourDSLCommon::treatExternalStateVariable); 163 add("@InitLocalVars", &BehaviourDSLCommon::treatInitLocalVariables); 164 add("@InitLocalVariables", &BehaviourDSLCommon::treatInitLocalVariables); 165 add("@InitializeLocalVariables", 166 &BehaviourDSLCommon::treatInitLocalVariables); 167 add("@MinimalTimeStepScalingFactor", 168 &BehaviourDSLCommon::treatMinimalTimeStepScalingFactor); 169 add("@MaximalTimeStepScalingFactor", 170 &BehaviourDSLCommon::treatMaximalTimeStepScalingFactor); 171 add("@APrioriTimeStepScalingFactor", 172 &BehaviourDSLCommon::treatAPrioriTimeStepScalingFactor); 173 add("@Integrator", &BehaviourDSLCommon::treatIntegrator); 174 add("@APosterioriTimeStepScalingFactor", 175 &BehaviourDSLCommon::treatAPosterioriTimeStepScalingFactor); 176 add("@Interface", &BehaviourDSLCommon::treatInterface); 177 add("@StaticVar", &BehaviourDSLCommon::treatStaticVar); 178 add("@StaticVariable", &BehaviourDSLCommon::treatStaticVar); 179 add("@IntegerConstant", &BehaviourDSLCommon::treatIntegerConstant); 180 add("@UseQt", &BehaviourDSLCommon::treatUseQt); 181 add("@Description", &BehaviourDSLCommon::treatDescription); 182 add("@Bounds", &BehaviourDSLCommon::treatBounds); 183 add("@PhysicalBounds", &BehaviourDSLCommon::treatPhysicalBounds); 184 add("@RequireStiffnessOperator", 185 &BehaviourDSLCommon::treatRequireStiffnessOperator); 186 add("@RequireStiffnessTensor", 187 &BehaviourDSLCommon::treatRequireStiffnessTensor); 188 add("@RequireThermalExpansionCoefficientTensor", 189 &BehaviourDSLCommon::treatRequireThermalExpansionCoefficientTensor); 190 add("@OrthotropicBehaviour", 191 &BehaviourDSLCommon::treatOrthotropicBehaviour); 192 add("@IsotropicElasticBehaviour", 193 &BehaviourDSLCommon::treatIsotropicElasticBehaviour); 194 add("@IsotropicBehaviour", &BehaviourDSLCommon::treatIsotropicBehaviour); 195 add("@PredictionOperator", &BehaviourDSLCommon::treatPredictionOperator); 196 add("@Private", &BehaviourDSLCommon::treatPrivate); 197 add("@Sources", &BehaviourDSLCommon::treatSources); 198 add("@UpdateAuxiliaryStateVars", 199 &BehaviourDSLCommon::treatUpdateAuxiliaryStateVariables); 200 add("@UpdateAuxiliaryStateVariables", 201 &BehaviourDSLCommon::treatUpdateAuxiliaryStateVariables); 202 add("@ComputeThermalExpansion", 203 &BehaviourDSLCommon::treatComputeThermalExpansion); 204 add("@ComputeStressFreeExpansion", 205 &BehaviourDSLCommon::treatComputeStressFreeExpansion); 206 add("@Swelling", &BehaviourDSLCommon::treatSwelling); 207 add("@AxialGrowth", &BehaviourDSLCommon::treatAxialGrowth); 208 add("@Relocation", &BehaviourDSLCommon::treatRelocation); 209 add("@InternalEnergy", &BehaviourDSLCommon::treatInternalEnergy); 210 add("@DissipatedEnergy", &BehaviourDSLCommon::treatDissipatedEnergy); 211 add("@CrystalStructure", &BehaviourDSLCommon::treatCrystalStructure); 212 add("@SlipSystem", &BehaviourDSLCommon::treatSlipSystem); 213 add("@GlidingSystem", &BehaviourDSLCommon::treatSlipSystem); 214 add("@SlidingSystem", &BehaviourDSLCommon::treatSlipSystem); 215 add("@SlipSystems", &BehaviourDSLCommon::treatSlipSystems); 216 add("@GlidingSystems", &BehaviourDSLCommon::treatSlipSystems); 217 add("@SlidingSystems", &BehaviourDSLCommon::treatSlipSystems); 218 add("@InteractionMatrix", &BehaviourDSLCommon::treatInteractionMatrix); 219 add("@DislocationsMeanFreePathInteractionMatrix", 220 &BehaviourDSLCommon::treatDislocationsMeanFreePathInteractionMatrix); 221 } // end of BehaviourDSLCommon::BehaviourDSLCommon 222 getMaterialKnowledgeIdentifier() const223 std::string BehaviourDSLCommon::getMaterialKnowledgeIdentifier() const { 224 if (this->mb.isBehaviourNameDefined()) { 225 return this->mb.getBehaviourName(); 226 } 227 return {}; 228 } // end of BehaviourDSLCommon::getMaterialKnowledgeIdentifier 229 getMaterialName() const230 std::string BehaviourDSLCommon::getMaterialName() const { 231 return this->mb.getMaterialName(); 232 } // end of BehaviourDSLCommon::getMaterialName( 233 analyse()234 void BehaviourDSLCommon::analyse() { 235 const auto& mh = ModellingHypothesis::getModellingHypotheses(); 236 std::vector<std::string> hn(mh.size()); 237 std::vector<Hypothesis>::const_iterator pmh; 238 std::vector<std::string>::iterator phn; 239 for (pmh = mh.begin(), phn = hn.begin(); pmh != mh.end(); ++pmh, ++phn) { 240 *phn = ModellingHypothesis::toString(*pmh); 241 } 242 // strip comments from file 243 this->stripComments(); 244 // begin treatement 245 this->current = this->tokens.begin(); 246 while (this->current != this->tokens.end()) { 247 if (find(hn.begin(), hn.end(), this->current->value) != hn.end()) { 248 const auto h = ModellingHypothesis::fromString(this->current->value); 249 ++(this->current); 250 this->checkNotEndOfFile("BehaviourDSLCommon::analyse"); 251 this->readSpecifiedToken("BehaviourDSLCommon::analyse", "::"); 252 const auto v = tfel::unicode::getMangledString(this->current->value); 253 if (!this->isCallableVariable(h, v)) { 254 this->throwRuntimeError("BehaviourDSLCommon::analyse", 255 "no variable named '" + v + 256 "' for hypothesis '" + 257 ModellingHypothesis::toString(h) + "'"); 258 } 259 if (this->mb.isParameterName(h, v)) { 260 this->treatParameterMethod(h); 261 } else { 262 this->treatVariableMethod(h); 263 } 264 } else { 265 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 266 const auto v = tfel::unicode::getMangledString(this->current->value); 267 if (this->isCallableVariable(h, v)) { 268 const auto isGradient = [this, &v] { 269 for (const auto& g : this->gradients) { 270 if (g.name == v) { 271 return true; 272 } 273 } 274 return this->mb.isGradientName(v); 275 }(); 276 const auto isThermodynamicForce = [this, &v] { 277 for (const auto& f : this->thermodynamic_forces) { 278 if (f.name == v) { 279 return true; 280 } 281 } 282 return this->mb.isThermodynamicForceName(v); 283 }(); 284 if (isGradient) { 285 this->treatGradientMethod(); 286 } else if (isThermodynamicForce) { 287 this->treatThermodynamicForceMethod(); 288 } else if (this->mb.isParameterName(h, v)) { 289 this->treatParameterMethod(h); 290 } else { 291 this->treatVariableMethod(h); 292 } 293 } else { 294 const auto k = this->current->value; 295 const auto l = this->current->line; 296 CallBack handler; 297 auto p = this->callBacks.find(k); 298 if (p == this->callBacks.end()) { 299 if (getVerboseMode() >= VERBOSE_DEBUG) { 300 auto& log = getLogStream(); 301 log << "treating unknown keyword\n"; 302 } 303 handler = [this] { this->treatUnknownKeyword(); }; 304 } else { 305 if (getVerboseMode() >= VERBOSE_DEBUG) { 306 auto& log = getLogStream(); 307 log << "treating keyword : " << this->current->value << '\n'; 308 } 309 handler = p->second; 310 } 311 this->currentComment = this->current->comment; 312 ++(this->current); 313 try { 314 handler(); 315 const auto ph = this->hooks.find(k); 316 if (ph != this->hooks.end()) { 317 for (auto& hook : ph->second) { 318 hook(); 319 } 320 } 321 } catch (std::exception& e) { 322 std::ostringstream msg; 323 msg << "BehaviourDSLCommon::analyse: " 324 << "error while treating keyword '" << k << "' at line '" << l 325 << "' of file '" << this->fd.fileName << "'.\n" 326 << e.what(); 327 tfel::raise(msg.str()); 328 } catch (...) { 329 this->currentComment.clear(); 330 throw; 331 } 332 this->currentComment.clear(); 333 } 334 } 335 } 336 } // end of BehaviourDSLCommon::analyse 337 importFile(const std::string & fn,const std::vector<std::string> & ecmds,const std::map<std::string,std::string> & s)338 void BehaviourDSLCommon::importFile( 339 const std::string& fn, 340 const std::vector<std::string>& ecmds, 341 const std::map<std::string, std::string>& s) { 342 this->fd.fileName = fn; 343 this->openFile(this->fd.fileName, ecmds, s); 344 this->analyse(); 345 } // end of BehaviourDSLCommon::importFile 346 analyseString(const std::string & s)347 void BehaviourDSLCommon::analyseString(const std::string& s) { 348 this->fd.fileName = "user defined string"; 349 this->parseString(s); 350 this->analyse(); 351 } // end of BehaviourDSLCommon::analyseString 352 getKeywordsList(std::vector<std::string> & k) const353 void BehaviourDSLCommon::getKeywordsList( 354 std::vector<std::string>& k) const { 355 for (const auto& c : this->callBacks) { 356 k.push_back(c.first); 357 } 358 } // end of BehaviourDSLCommon::getKeywordsList 359 addCallBack(const std::string & k,const CallBack c)360 void BehaviourDSLCommon::addCallBack(const std::string& k, const CallBack c) { 361 this->callBacks.insert({k, c}); 362 this->registredKeyWords.insert(k); 363 } // end of BehaviourDSLCommon::addCallBack 364 addHook(const std::string & k,const Hook h)365 void BehaviourDSLCommon::addHook(const std::string& k, const Hook h) { 366 if (this->callBacks.find(k) == this->callBacks.end()) { 367 this->throwRuntimeError("BehaviourDSLCommon::addHook", 368 "no callback called '" + k + "'"); 369 } 370 this->hooks[k].push_back(h); 371 } // end of BehaviourDSLCommon::addHook 372 setMaterial(const std::string & m)373 void BehaviourDSLCommon::setMaterial(const std::string& m) { 374 if (!isValidMaterialName(m)) { 375 this->throwRuntimeError("BehaviourDSLCommon::setMaterial", 376 "invalid material name '" + m + "'"); 377 } 378 this->mb.setMaterialName(m); 379 if (!isValidIdentifier(this->mb.getClassName())) { 380 this->throwRuntimeError("BehaviourDSLCommon::setMaterial", 381 "resulting class name is not valid (read '" + 382 this->mb.getClassName() + "')"); 383 } 384 } // end of BehaviourDSLCommon::setMaterial 385 386 treatDisabledCallBack()387 void BehaviourDSLCommon::treatDisabledCallBack() { 388 --(this->current); 389 tfel::raise("The keyword: '" + this->current->value + 390 "' has been disabled"); 391 } // end of treatDisabledCallBack 392 disableCallBack(const std::string & k)393 void BehaviourDSLCommon::disableCallBack(const std::string& k) { 394 auto c = [this] { this->treatDisabledCallBack(); }; 395 auto p = this->callBacks.find(k); 396 if (p == this->callBacks.end()) { 397 this->callBacks.insert({k, c}); 398 this->registredKeyWords.insert(k); 399 return; 400 } 401 p->second = c; 402 } // end of disableCallBack 403 readCodeBlock(const std::string & n,std::function<std::string (const Hypothesis,const std::string &,const bool)> m,const bool b,const bool s)404 BehaviourDSLCommon::CodeBlockOptions BehaviourDSLCommon::readCodeBlock( 405 const std::string& n, 406 std::function< 407 std::string(const Hypothesis, const std::string&, const bool)> m, 408 const bool b, 409 const bool s) { 410 CodeBlockOptions o; 411 this->readCodeBlockOptions(o, s); 412 this->treatUnsupportedCodeBlockOptions(o); 413 this->readCodeBlock(o, n, m, b); 414 return o; 415 } 416 readCodeBlock(const std::string & n,std::function<std::string (const Hypothesis,const std::string &,const bool)> m,std::function<void (CodeBlock &,const Hypothesis,const std::string &)> a,const bool b,const bool s)417 BehaviourDSLCommon::CodeBlockOptions BehaviourDSLCommon::readCodeBlock( 418 const std::string& n, 419 std::function< 420 std::string(const Hypothesis, const std::string&, const bool)> m, 421 std::function<void(CodeBlock&, const Hypothesis, const std::string&)> a, 422 const bool b, 423 const bool s) { 424 CodeBlockOptions o; 425 this->readCodeBlockOptions(o, s); 426 this->treatUnsupportedCodeBlockOptions(o); 427 this->readCodeBlock(o, n, m, a, b); 428 return o; 429 } // end of BehaviourDSLCommon::readCodeBlock 430 readCodeBlock(const BehaviourDSLCommon::CodeBlockOptions & o,const std::string & n,std::function<std::string (const Hypothesis,const std::string &,const bool)> m,std::function<void (CodeBlock &,const Hypothesis,const std::string &)> a,const bool b)431 void BehaviourDSLCommon::readCodeBlock( 432 const BehaviourDSLCommon::CodeBlockOptions& o, 433 const std::string& n, 434 std::function< 435 std::string(const Hypothesis, const std::string&, const bool)> m, 436 std::function<void(CodeBlock&, const Hypothesis, const std::string&)> a, 437 const bool b) { 438 const auto beg = this->current; 439 this->disableVariableDeclaration(); 440 for (const auto h : o.hypotheses) { 441 this->current = beg; 442 const auto& md = this->mb.getBehaviourData(h); 443 auto vm = std::make_shared<StandardVariableModifier>(h, m); 444 auto wa = std::make_shared<StandardWordAnalyser>(h, a); 445 CodeBlockParserOptions option; 446 option.qualifyStaticVariables = b; 447 option.qualifyMemberVariables = b; 448 option.modifier = vm; 449 option.analyser = wa; 450 option.mn = md.getRegistredMembersNames(); 451 option.smn = md.getRegistredStaticMembersNames(); 452 this->getSymbols(option.symbols, h, n); 453 const auto& c = this->readNextBlock(option); 454 this->mb.setCode(h, n, c, o.m, o.p); 455 } 456 } // end of BehaviourDSLCommon::readCodeBlock 457 readCodeBlock(const BehaviourDSLCommon::CodeBlockOptions & o,const std::string & n,std::function<std::string (const Hypothesis,const std::string &,const bool)> m,const bool b)458 void BehaviourDSLCommon::readCodeBlock( 459 const BehaviourDSLCommon::CodeBlockOptions& o, 460 const std::string& n, 461 std::function< 462 std::string(const Hypothesis, const std::string&, const bool)> m, 463 const bool b) { 464 const auto beg = this->current; 465 this->disableVariableDeclaration(); 466 for (const auto h : o.hypotheses) { 467 const auto& md = this->mb.getBehaviourData(h); 468 this->current = beg; 469 auto vm = std::make_shared<StandardVariableModifier>(h, m); 470 CodeBlockParserOptions option; 471 option.qualifyStaticVariables = b; 472 option.qualifyMemberVariables = b; 473 option.modifier = vm; 474 option.mn = md.getRegistredMembersNames(); 475 option.smn = md.getRegistredStaticMembersNames(); 476 this->getSymbols(option.symbols, h, n); 477 const auto& c = this->readNextBlock(option); 478 this->mb.setCode(h, n, c, o.m, o.p); 479 } 480 } // end of BehaviourDSLCommon::readCodeBlock 481 readCodeBlock(const std::string & n1,const std::string & n2,std::function<std::string (const Hypothesis,const std::string &,const bool)> m1,std::function<std::string (const Hypothesis,const std::string &,const bool)> m2,const bool b,const bool s)482 BehaviourDSLCommon::CodeBlockOptions BehaviourDSLCommon::readCodeBlock( 483 const std::string& n1, 484 const std::string& n2, 485 std::function< 486 std::string(const Hypothesis, const std::string&, const bool)> m1, 487 std::function< 488 std::string(const Hypothesis, const std::string&, const bool)> m2, 489 const bool b, 490 const bool s) { 491 using std::shared_ptr; 492 CodeBlockOptions o; 493 this->readCodeBlockOptions(o, s); 494 this->treatUnsupportedCodeBlockOptions(o); 495 this->readCodeBlock(o, n1, n2, m1, m2, b); 496 return o; 497 } // end of BehaviourDSLCommon::readCodeBlock 498 readCodeBlock(const BehaviourDSLCommon::CodeBlockOptions & o,const std::string & n1,const std::string & n2,std::function<std::string (const Hypothesis,const std::string &,const bool)> m1,std::function<std::string (const Hypothesis,const std::string &,const bool)> m2,const bool b)499 void BehaviourDSLCommon::readCodeBlock( 500 const BehaviourDSLCommon::CodeBlockOptions& o, 501 const std::string& n1, 502 const std::string& n2, 503 std::function< 504 std::string(const Hypothesis, const std::string&, const bool)> m1, 505 std::function< 506 std::string(const Hypothesis, const std::string&, const bool)> m2, 507 const bool b) { 508 const auto beg = this->current; 509 this->disableVariableDeclaration(); 510 for (const auto& h : o.hypotheses) { 511 const auto& md = this->mb.getBehaviourData(h); 512 this->current = beg; 513 CodeBlock c1; 514 CodeBlock c2; 515 CodeBlockParserOptions o1; 516 o1.qualifyStaticVariables = b; 517 o1.qualifyMemberVariables = b; 518 o1.modifier = std::make_shared<StandardVariableModifier>(h, m1); 519 o1.mn = md.getRegistredMembersNames(); 520 o1.smn = md.getRegistredStaticMembersNames(); 521 this->getSymbols(o1.symbols, h, n1); 522 CodeBlockParserOptions o2; 523 o2.qualifyStaticVariables = b; 524 o2.qualifyMemberVariables = b; 525 o2.modifier = std::make_shared<StandardVariableModifier>(h, m2); 526 o2.mn = md.getRegistredMembersNames(); 527 o2.smn = md.getRegistredStaticMembersNames(); 528 this->getSymbols(o2.symbols, h, n1); 529 this->readNextBlock(c1, c2, o1, o2); 530 this->mb.setCode(h, n1, c1, o.m, o.p); 531 this->mb.setCode(h, n2, c2, o.m, o.p); 532 } 533 } // end of BehaviourDSLCommon::readCodeBlock 534 addMaterialProperties(const VariableDescriptionContainer & mps)535 void BehaviourDSLCommon::addMaterialProperties( 536 const VariableDescriptionContainer& mps) { 537 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 538 const auto d = this->getBehaviourDSLDescription(); 539 tfel::raise_if(!d.allowUserDefinedMaterialProperties, 540 "BehaviourDSLCommon::addMaterialProperties: " 541 "adding material properties is not allowed"); 542 this->mb.addMaterialProperties(h, mps); 543 } // end of BehaviourDSLCommon::addMaterialProperties 544 addParameters(const VariableDescriptionContainer & params)545 void BehaviourDSLCommon::addParameters( 546 const VariableDescriptionContainer& params) { 547 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 548 const auto d = this->getBehaviourDSLDescription(); 549 tfel::raise_if(!d.allowUserDefinedParameters, 550 "BehaviourDSLCommon::addParameters: " 551 "adding parameters is not allowed"); 552 this->mb.addParameters(h, params); 553 } // end of BehaviourDSLCommon::addParameters 554 addStateVariables(const VariableDescriptionContainer & isvs)555 void BehaviourDSLCommon::addStateVariables( 556 const VariableDescriptionContainer& isvs) { 557 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 558 const auto d = this->getBehaviourDSLDescription(); 559 tfel::raise_if(!d.allowUserDefinedStateVariables, 560 "BehaviourDSLCommon::addStateVariables: " 561 "adding state variables is not allowed"); 562 this->mb.addStateVariables(h, isvs); 563 } // end of BehaviourDSLCommon::addStateVariables 564 addAuxiliaryStateVariables(const VariableDescriptionContainer & isvs)565 void BehaviourDSLCommon::addAuxiliaryStateVariables( 566 const VariableDescriptionContainer& isvs) { 567 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 568 const auto d = this->getBehaviourDSLDescription(); 569 tfel::raise_if(!d.allowUserDefinedAuxiliaryStateVariables, 570 "BehaviourDSLCommon::addAuxiliaryStateVariables: " 571 "adding auxiliary state variables is not allowed"); 572 this->mb.addAuxiliaryStateVariables(h, isvs); 573 } // end of BehaviourDSLCommon::addAuxiliaryStateVariables 574 addExternalStateVariables(const VariableDescriptionContainer & esvs)575 void BehaviourDSLCommon::addExternalStateVariables( 576 const VariableDescriptionContainer& esvs) { 577 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 578 const auto d = this->getBehaviourDSLDescription(); 579 tfel::raise_if(!d.allowUserDefinedExternalStateVariables, 580 "BehaviourDSLCommon::addExternalStateVariables: " 581 "adding external state variables is not allowed"); 582 this->mb.addExternalStateVariables(h, esvs); 583 } // end of BehaviourDSLCommon::addExternalStateVariables 584 addLocalVariables(const VariableDescriptionContainer & lvs)585 void BehaviourDSLCommon::addLocalVariables( 586 const VariableDescriptionContainer& lvs) { 587 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 588 const auto d = this->getBehaviourDSLDescription(); 589 tfel::raise_if(!d.allowUserDefinedLocalVariables, 590 "BehaviourDSLCommon::addLocalVariables: " 591 "adding local variables is not allowed"); 592 this->mb.addLocalVariables(h, lvs); 593 } // end of BehaviourDSLCommon::addLocalVariables 594 addIntegrationVariables(const VariableDescriptionContainer & ivs)595 void BehaviourDSLCommon::addIntegrationVariables( 596 const VariableDescriptionContainer& ivs) { 597 constexpr const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 598 const auto d = this->getBehaviourDSLDescription(); 599 tfel::raise_if(!d.allowUserDefinedIntegrationVariables, 600 "BehaviourDSLCommon::addIntegrationVariables: " 601 "adding integration variables is not allowed"); 602 this->mb.addIntegrationVariables(h, ivs); 603 } // end of BehaviourDSLCommon::addIntegrationVariables 604 writeModelCall(std::ostream & out,std::vector<std::string> & tmpnames,const Hypothesis h,const ModelDescription & md,const std::string & vo,const std::string & vs,const std::string & bn) const605 void BehaviourDSLCommon::writeModelCall(std::ostream& out, 606 std::vector<std::string>& tmpnames, 607 const Hypothesis h, 608 const ModelDescription& md, 609 const std::string& vo, 610 const std::string& vs, 611 const std::string& bn) const { 612 auto throw_if = [this](const bool b, const std::string& m) { 613 if (b) { 614 this->throwRuntimeError("BehaviourDSLCommon::writeModelCall", m); 615 } 616 }; 617 auto write_variable = [throw_if, &md, &out](const std::string& v, const unsigned short d) { 618 if (d == 0) { 619 out << "this->" << v << "+this->d" << v; 620 } else if (d == 1) { 621 out << "this->" << v; 622 } else { 623 throw_if(true, "invalid depth for the temperature '" + v + 624 "' " 625 "in model '" + 626 md.className + "'"); 627 } 628 }; 629 const auto& bd = this->mb.getBehaviourData(h); 630 throw_if(md.outputs.size() != 1u, "invalid number of outputs for model '" + md.className + "'"); 631 throw_if(!md.constantMaterialProperties.empty(), "constant material properties are not supported yet"); 632 throw_if(md.functions.size() != 1u, "invalid number of functions in model '" + md.className + "'"); 633 const auto& f = md.functions[0]; 634 throw_if(f.modifiedVariables.empty(), "no modified variable for function '" + f.name + "'"); 635 throw_if(f.modifiedVariables.size() != 1u, "invalid number of functions in model '" + md.className + "'"); 636 throw_if(f.name.empty(), "unnamed function"); 637 throw_if((f.usedVariables.empty()) && (!f.useTimeIncrement), "no used variable for function '" + f.name + "'"); 638 const auto sm = this->getTemporaryVariableName(tmpnames, bn); 639 out << "// updating " << vs << "\n" 640 << "mfront::" << md.className << "<Type> " << sm << ";\n" 641 << "" << sm << ".setOutOfBoundsPolicy(this->policy);\n" 642 << "this->" << vo << " = " << sm << "." << f.name << "("; 643 const auto args = [&f] { 644 auto a = std::vector<std::string>{}; 645 for (const auto& uv : f.usedVariables) { 646 a.push_back(uv); 647 } 648 if (f.useTimeIncrement) { 649 a.emplace_back("dt"); 650 } 651 return a; 652 }(); 653 const auto asvn = bd.getExternalNames(bd.getAuxiliaryStateVariables()); 654 for (auto pa = std::begin(args); pa != std::end(args);) { 655 if (*pa == "dt") { 656 out << "this->dt"; 657 ++pa; 658 continue; 659 } 660 const auto a = md.decomposeVariableName(*pa); 661 const auto& ea = md.getVariableDescription(a.first).getExternalName(); 662 if (ea == bd.getExternalName(vs)) { 663 throw_if(a.second != 1, "invalid depth for variable '" + a.first + 664 "' " 665 "in model '" + 666 md.className + "'"); 667 out << "this->" << vs; 668 } else if (std::find(std::begin(asvn), std::end(asvn), ea) != std::end(asvn)) { 669 const auto& av = bd.getAuxiliaryStateVariableDescriptionByExternalName(ea); 670 throw_if(!av.getAttribute<bool>("ComputedByExternalModel", false), 671 "only auxiliary state variable computed by a model are allowed here"); 672 write_variable(av.name, a.second); 673 } else { 674 const auto& en = bd.getExternalStateVariableDescriptionByExternalName(ea); 675 write_variable(en.name, a.second); 676 } 677 if (++pa != std::end(args)) { 678 out << ","; 679 } 680 } 681 out << ");\n"; 682 } 683 CodeBlockOptions()684 BehaviourDSLCommon::CodeBlockOptions::CodeBlockOptions() : p(BehaviourData::BODY), m(BehaviourData::CREATE) { 685 this->hypotheses.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 686 } // end of BehaviourDSLCommon::CodeBlockOptions::CodeBlockOptions 687 688 BehaviourDSLCommon::CodeBlockOptions::~CodeBlockOptions() = default; 689 getBehaviourDescription() const690 const BehaviourDescription& BehaviourDSLCommon::getBehaviourDescription() const { 691 return this->mb; 692 } // end of BehaviourDSLCommon::getBehaviourDescription 693 getClassName() const694 std::string BehaviourDSLCommon::getClassName() const { 695 return this->mb.getClassName(); 696 } // end of BehaviourDSLCommon::getClassName 697 addMaterialLaw(const std::string & m)698 void BehaviourDSLCommon::addMaterialLaw(const std::string& m) { 699 this->mb.addMaterialLaw(m); 700 } // end of BehaviourDSLCommon::addMaterialLaw 701 appendToIncludes(const std::string & c)702 void BehaviourDSLCommon::appendToIncludes(const std::string& c) { 703 this->mb.appendToIncludes(c); 704 } // end of BehaviourDSLCommon::appendToIncludes 705 appendToMembers(const std::string & c)706 void BehaviourDSLCommon::appendToMembers(const std::string& c) { 707 this->mb.appendToMembers(ModellingHypothesis::UNDEFINEDHYPOTHESIS, c, true); 708 } // end of BehaviourDSLCommon::appendToMembers 709 appendToPrivateCode(const std::string & c)710 void BehaviourDSLCommon::appendToPrivateCode(const std::string& c) { 711 this->mb.appendToPrivateCode(ModellingHypothesis::UNDEFINEDHYPOTHESIS, c, true); 712 } // end of BehaviourDSLCommon::appendToPrivateCode 713 appendToSources(const std::string & c)714 void BehaviourDSLCommon::appendToSources(const std::string& c) { 715 this->mb.appendToSources(c); 716 } // end of BehaviourDSLCommon::appendToSources 717 appendToHypothesesList(std::set<Hypothesis> & h,const std::string & v) const718 void BehaviourDSLCommon::appendToHypothesesList(std::set<Hypothesis>& h, const std::string& v) const { 719 if (v == ".+") { 720 const auto& ash = ModellingHypothesis::getModellingHypotheses(); 721 for (const auto& lh : ash) { 722 this->appendToHypothesesList(h, ModellingHypothesis::toString(lh)); 723 } 724 } else { 725 const auto nh = ModellingHypothesis::fromString(v); 726 if (!this->isModellingHypothesisSupported(nh)) { 727 this->throwRuntimeError("BehaviourDSLCommon::appendToHypothesesList", 728 "hypothesis '" + v + "' is not supported by this parser"); 729 } 730 if (this->mb.areModellingHypothesesDefined()) { 731 const auto& bh = this->mb.getModellingHypotheses(); 732 if (bh.find(nh) == bh.end()) { 733 this->throwRuntimeError("BehaviourDSLCommon::appendToHypothesesList", 734 "hypothesis '" + v + 735 "' is not supported by the " 736 "behaviour (This means that one of the " 737 "'@ModellingHypothesis' or '@ModellingHypotheses'" 738 "keyword was used earlier)"); 739 } 740 } 741 if (!h.insert(nh).second) { 742 this->throwRuntimeError("BehaviourDSLCommon::appendToHypothesesList", 743 "hypothesis '" + v + "' multiply defined"); 744 } 745 } 746 } // end of BehaviourDSLCommon::appendToHypothesesList 747 getSymbols(std::map<std::string,std::string> & symbols,const Hypothesis h,const std::string &)748 void BehaviourDSLCommon::getSymbols( 749 std::map<std::string, std::string>& symbols, 750 const Hypothesis h, 751 const std::string&) { 752 addSymbol(symbols, "I\u2082", "Stensor::Id()"); 753 addSymbol(symbols, "I\u2084", "Stensor4::Id()"); 754 addSymbol(symbols, "\u2297", "^"); 755 addSymbol(symbols, "\u22C5", "*"); 756 this->mb.getSymbols(symbols, h); 757 } // end of BehaviourDSLCommon::getSymbols 758 readCodeBlockOptions(CodeBlockOptions & o,const bool s)759 void BehaviourDSLCommon::readCodeBlockOptions(CodeBlockOptions& o, const bool s) { 760 using namespace tfel::utilities; 761 using namespace tfel::material; 762 auto cposition = false; 763 auto cmode = false; 764 const auto dh = [this] { 765 if (this->mb.areModellingHypothesesDefined()) { 766 const auto mh = this->mb.getModellingHypotheses(); 767 if (mh.size() == 1) { 768 return *(mh.begin()); 769 } 770 } 771 return ModellingHypothesis::UNDEFINEDHYPOTHESIS; 772 }(); 773 o.hypotheses.clear(); 774 if (this->current == this->tokens.end()) { 775 o.hypotheses.insert(dh); 776 return; 777 } 778 if (this->current->value != "<") { 779 o.hypotheses.insert(dh); 780 return; 781 } 782 auto options = std::vector<Token>{}; 783 this->readList(options, "BehaviourDSLCommon::readCodeBlockOptions", "<", ">", true); 784 for (const auto& t : options) { 785 if (t.value == "Append") { 786 if (cmode) { 787 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions", 788 "insertion mode already specificed"); 789 } 790 cmode = true; 791 o.m = BehaviourData::CREATEORAPPEND; 792 } else if (t.value == "Replace") { 793 if (cmode) { 794 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions", 795 "insertion mode already specificed"); 796 } 797 cmode = true; 798 o.m = BehaviourData::CREATEORREPLACE; 799 } else if (t.value == "Create") { 800 if (cmode) { 801 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions", 802 "insertion mode already specificed"); 803 } 804 cmode = true; 805 o.m = BehaviourData::CREATE; 806 } else if (t.value == "Body") { 807 if (cposition) { 808 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions", 809 "insertion position already specificed"); 810 } 811 cposition = true; 812 o.p = BehaviourData::BODY; 813 } else if (t.value == "AtBeginning") { 814 if (cposition) { 815 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions", 816 "insertion position already specificed"); 817 } 818 cposition = true; 819 o.p = BehaviourData::AT_BEGINNING; 820 } else if (t.value == "AtEnd") { 821 if (cposition) { 822 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions", 823 "insertion position already specificed"); 824 } 825 cposition = true; 826 o.p = BehaviourData::AT_END; 827 } else if ((t.flag == Token::String) && (t.value.substr(1, t.value.size() - 2) == "+")) { 828 this->appendToHypothesesList(o.hypotheses, t.value.substr(1, t.value.size() - 2)); 829 } else if (ModellingHypothesis::isModellingHypothesis(t.value)) { 830 this->appendToHypothesesList(o.hypotheses, t.value); 831 } else { 832 o.untreated.push_back(t); 833 } 834 } 835 if (o.hypotheses.empty()) { 836 o.hypotheses.insert(dh); 837 } 838 // checks 839 if (!s) { 840 if (o.hypotheses.size() != 1u) { 841 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions: ", 842 "specialisation is not allowed"); 843 } 844 if (*(o.hypotheses.begin()) != dh) { 845 this->throwRuntimeError("BehaviourDSLCommon::readCodeBlockOptions: ", 846 "specialisation is not allowed"); 847 } 848 } 849 } // end of BehaviourDSLCommon::readCodeBlockOptions 850 851 std::shared_ptr<MaterialPropertyDescription> handleMaterialPropertyDescription(const std::string & f)852 BehaviourDSLCommon::handleMaterialPropertyDescription(const std::string& f) { 853 return DSLBase::handleMaterialPropertyDescription(f); 854 } // end of BehaviourDSLCommon::handleMaterialPropertyDescription 855 getModelDescription(const std::string & f)856 ModelDescription BehaviourDSLCommon::getModelDescription(const std::string& f) { 857 if (getVerboseMode() >= VERBOSE_DEBUG) { 858 getLogStream() << "BehaviourDSLCommon::getModelDescription: " 859 << "treating file '" << f << "'\n"; 860 } 861 // getting informations the source files 862 const auto path = SearchPathsHandler::search(f); 863 ModelDSL dsl; 864 try { 865 dsl.setInterfaces({"mfront"}); 866 dsl.analyseFile(path, {}, {}); 867 const auto t = dsl.getTargetsDescription(); 868 if (!t.specific_targets.empty()) { 869 this->throwRuntimeError("BehaviourDSLCommon::getModelDescription", 870 "error while treating file '" + f + 871 "'.\n" 872 "Specific targets are not supported"); 873 } 874 for (const auto& h : t.headers) { 875 this->appendToIncludes("#include\"" + h + "\""); 876 } 877 this->atds.push_back(std::move(t)); 878 this->externalMFrontFiles.insert({path, {"mfront"}}); 879 } catch (std::exception& e) { 880 this->throwRuntimeError("BehaviourDSLCommon::getModelDescription", 881 "error while treating file '" + f + "'\n" + std::string(e.what())); 882 } catch (...) { 883 this->throwRuntimeError("BehaviourDSLCommon::getModelDescription", "error while treating file '" + f + "'"); 884 } 885 const auto& md = dsl.getModelDescription(); 886 this->reserveName(md.className); 887 if (getVerboseMode() >= VERBOSE_DEBUG) { 888 getLogStream() << "BehaviourDSLCommon::getModelDescription: " 889 << "end of file '" << f << "' treatment\n"; 890 } 891 return md; 892 } // end of BehaviourDSLCommon::getModelDescription 893 declareMainVariables()894 void BehaviourDSLCommon::declareMainVariables() { 895 decltype(this->gradients.size()) n = 896 std::min(this->gradients.size(), this->thermodynamic_forces.size()); 897 while (n != 0) { 898 this->mb.addMainVariable(this->gradients.front(), 899 this->thermodynamic_forces.front()); 900 this->gradients.erase(this->gradients.begin()); 901 this->thermodynamic_forces.erase(this->thermodynamic_forces.begin()); 902 --n; 903 } 904 } // end of BehaviourDSLCommon::declareMainVariables 905 treatGradient()906 void BehaviourDSLCommon::treatGradient() { 907 VariableDescriptionContainer ngradients; 908 this->readVarList(ngradients, true); 909 std::for_each(ngradients.begin(), ngradients.end(), 910 [this](const VariableDescription& v) { 911 Gradient g(v); 912 Gradient::setIsIncrementKnownAttribute(g, true); 913 this->gradients.emplace_back(std::move(g)); 914 }); 915 this->declareMainVariables(); 916 } // end of BehaviourDSLCommon::treatGradient 917 treatThermodynamicForce()918 void BehaviourDSLCommon::treatThermodynamicForce() { 919 VariableDescriptionContainer ntfs; 920 this->readVarList(ntfs, true); 921 std::for_each(ntfs.begin(), ntfs.end(), 922 [this](const VariableDescription& f) { 923 this->thermodynamic_forces.emplace_back(f); 924 }); 925 this->declareMainVariables(); 926 } // end of BehaviourDSLCommon::treatThermodynamicForce 927 treatTangentOperatorBlock()928 void BehaviourDSLCommon::treatTangentOperatorBlock() { 929 const char* const m = 930 "BehaviourDSLCommon::treatTangentOperatorBlock"; 931 this->checkNotEndOfFile(m); 932 const auto b = this->current->value; 933 ++(this->current); 934 this->checkNotEndOfFile(m); 935 this->readSpecifiedToken(m, ";"); 936 this->mb.setTangentOperatorBlocks(std::vector<std::string>(1u, b)); 937 } // end of BehaviourDSLCommon::treatTangentOperatorBlock 938 treatTangentOperatorBlocks()939 void BehaviourDSLCommon::treatTangentOperatorBlocks() { 940 const char* const m = 941 "BehaviourDSLCommon::treatTangentOperatorBlocks"; 942 this->checkNotEndOfFile(m); 943 auto values = std::vector<tfel::utilities::Token>{}; 944 this->checkNotEndOfFile(m); 945 this->readList(values, m, "{", "}", false); 946 this->checkNotEndOfFile(m); 947 this->readSpecifiedToken(m, ";"); 948 auto blocks = std::vector<std::string>{}; 949 for (const auto& v : values) { 950 blocks.push_back(v.value); 951 } 952 this->mb.setTangentOperatorBlocks(blocks); 953 } // end of BehaviourDSLCommon::treatTangentOperatorBlocks 954 treatAdditionalTangentOperatorBlock()955 void BehaviourDSLCommon::treatAdditionalTangentOperatorBlock() { 956 const char* const m = 957 "BehaviourDSLCommon::treatAdditionalTangentOperatorBlock"; 958 this->checkNotEndOfFile(m); 959 const auto b = this->current->value; 960 ++(this->current); 961 this->checkNotEndOfFile(m); 962 this->readSpecifiedToken(m, ";"); 963 this->mb.addTangentOperatorBlock(b); 964 } // end of BehaviourDSLCommon::treatAdditionalTangentOperatorBlock 965 treatAdditionalTangentOperatorBlocks()966 void BehaviourDSLCommon::treatAdditionalTangentOperatorBlocks() { 967 const char* const m = 968 "BehaviourDSLCommon::treatAdditionalTangentOperatorBlocks"; 969 this->checkNotEndOfFile(m); 970 auto values = std::vector<tfel::utilities::Token>{}; 971 this->checkNotEndOfFile(m); 972 this->readList(values, m, "{", "}", false); 973 this->checkNotEndOfFile(m); 974 this->readSpecifiedToken(m, ";"); 975 for (const auto& v : values) { 976 this->mb.addTangentOperatorBlock(v.value); 977 } 978 } // end of BehaviourDSLCommon::treatAdditionalTangentOperatorBlock 979 treatModel()980 void BehaviourDSLCommon::treatModel() { 981 if (getVerboseMode() >= VERBOSE_DEBUG) { 982 getLogStream() << "BehaviourDSLCommon::treatModel: begin\n"; 983 } 984 auto md = this->getModelDescription(this->readString("BehaviourDSLCommon::treatModel")); 985 this->mb.addModelDescription(md); 986 if (getVerboseMode() >= VERBOSE_DEBUG) { 987 getLogStream() << "BehaviourDSLCommon::treatModel: end\n"; 988 } 989 this->readSpecifiedToken("BehaviourDSLCommon::treatModel", ";"); 990 } // end of BehaviourDSLCommon::treatModel 991 treatUnsupportedCodeBlockOptions(const CodeBlockOptions & o)992 void BehaviourDSLCommon::treatUnsupportedCodeBlockOptions(const CodeBlockOptions& o) { 993 if (o.untreated.empty()) { 994 return; 995 } 996 std::ostringstream msg; 997 if (o.untreated.size() == 1u) { 998 msg << "option '" << o.untreated[0].value << "' is invalid"; 999 } else { 1000 msg << "the"; 1001 for (const auto& opt : o.untreated) { 1002 msg << " '" << opt.value << "'"; 1003 } 1004 msg << " options are invalid"; 1005 } 1006 this->throwRuntimeError( 1007 "BehaviourDSLCommon::" 1008 "treatUnsupportedCodeBlockOptions", 1009 msg.str()); 1010 } // end of BehaviourDSLCommon::treatUnsupportedCodeBlockOptions 1011 addStaticVariableDescription(const StaticVariableDescription & v)1012 void BehaviourDSLCommon::addStaticVariableDescription(const StaticVariableDescription& v) { 1013 this->mb.addStaticVariable(ModellingHypothesis::UNDEFINEDHYPOTHESIS, v); 1014 } // end of BehaviourDSLCommon::addStaticVariableDescription 1015 getIntegerConstant(const std::string & n) const1016 int BehaviourDSLCommon::getIntegerConstant(const std::string& n) const { 1017 return this->mb.getIntegerConstant(ModellingHypothesis::UNDEFINEDHYPOTHESIS, n); 1018 } // end of BehaviourDSLCommon::getIntegerConstant 1019 getDefaultModellingHypotheses() const1020 std::set<BehaviourDSLCommon::Hypothesis> BehaviourDSLCommon::getDefaultModellingHypotheses() const { 1021 // see the method documentation 1022 return {ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRAIN, 1023 ModellingHypothesis::AXISYMMETRICAL, 1024 ModellingHypothesis::PLANESTRAIN, 1025 ModellingHypothesis::GENERALISEDPLANESTRAIN, 1026 ModellingHypothesis::TRIDIMENSIONAL}; 1027 } // end of BehaviourDSLCommon::getDefaultModellingHypotheses 1028 isModellingHypothesisSupported(const Hypothesis h) const1029 bool BehaviourDSLCommon::isModellingHypothesisSupported(const Hypothesis h) const { 1030 const auto mhs = this->getBehaviourDSLDescription().supportedModellingHypotheses; 1031 return std::find(mhs.cbegin(), mhs.cend(), h) != mhs.end(); 1032 } // end of BehaviourDSLCommon::isModellingHypothesesSupported 1033 getBehaviourFileName() const1034 std::string BehaviourDSLCommon::getBehaviourFileName() const { 1035 return "TFEL/Material/" + this->mb.getClassName() + ".hxx"; 1036 } // end of BehaviourDSLCommon::getBehaviourFileName 1037 getBehaviourDataFileName() const1038 std::string BehaviourDSLCommon::getBehaviourDataFileName() const { 1039 return "TFEL/Material/" + this->mb.getClassName() + "BehaviourData.hxx"; 1040 } // end of BehaviourDSLCommon::getBehaviourDataFileName 1041 getIntegrationDataFileName() const1042 std::string BehaviourDSLCommon::getIntegrationDataFileName() const { 1043 return "TFEL/Material/" + this->mb.getClassName() + "IntegrationData.hxx"; 1044 } // end of BehaviourDSLCommon::getIntegrationDataFileName 1045 getSrcFileName() const1046 std::string BehaviourDSLCommon::getSrcFileName() const { 1047 return this->mb.getClassName() + ".cxx"; 1048 } // end of BehaviourDSLCommon::getSrcFileName 1049 analyseFile(const std::string & fileName_,const std::vector<std::string> & ecmds,const std::map<std::string,std::string> & s)1050 void BehaviourDSLCommon::analyseFile(const std::string& fileName_, 1051 const std::vector<std::string>& ecmds, 1052 const std::map<std::string, std::string>& s) { 1053 this->importFile(fileName_, ecmds, s); 1054 // Adding some stuff 1055 this->endsInputFileProcessing(); 1056 // setting the name of the output files 1057 // targets description 1058 for (const auto& i : this->interfaces) { 1059 i.second->getTargetsDescription(this->td, this->mb); 1060 } 1061 for (auto& l : this->td.libraries) { 1062 insert_if(this->td.getLibrary(l.name).sources, this->getSrcFileName()); 1063 } 1064 insert_if(this->td.headers, this->getBehaviourFileName()); 1065 insert_if(this->td.headers, this->getBehaviourDataFileName()); 1066 insert_if(this->td.headers, this->getIntegrationDataFileName()); 1067 this->completeTargetsDescription(); 1068 } 1069 disableVariableDeclaration()1070 void BehaviourDSLCommon::disableVariableDeclaration() { 1071 if (this->mb.allowsNewUserDefinedVariables()) { 1072 this->completeVariableDeclaration(); 1073 this->mb.disallowNewUserDefinedVariables(); 1074 } 1075 } // end of BehaviourDSLCommon::disableVariableDeclaration 1076 completeVariableDeclaration()1077 void BehaviourDSLCommon::completeVariableDeclaration() { 1078 using namespace mfront::bbrick; 1079 const auto& g = tfel::glossary::Glossary::getGlossary(); 1080 if (getVerboseMode() >= VERBOSE_DEBUG) { 1081 getLogStream() << "BehaviourDSLCommon::completeVariableDeclaration: begin\n"; 1082 } 1083 if ((!this->gradients.empty()) || (!this->thermodynamic_forces.empty())) { 1084 this->throwRuntimeError( 1085 "BehaviourDSLCommon::completeVariableDeclaration", 1086 "The number of gradients does not match the number of " 1087 "thermodynamic forces"); 1088 } 1089 // defining modelling hypotheses 1090 if (!this->mb.areModellingHypothesesDefined()) { 1091 auto dmh = this->getDefaultModellingHypotheses(); 1092 // taking into account restrictin du to the `Plate` othotropic 1093 // axes convention 1094 if ((this->mb.getSymmetryType() == mfront::ORTHOTROPIC) && 1095 (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PLATE)) { 1096 for (auto ph = dmh.begin(); ph != dmh.end();) { 1097 if ((*ph != ModellingHypothesis::TRIDIMENSIONAL) && (*ph != ModellingHypothesis::PLANESTRESS) && 1098 (*ph != ModellingHypothesis::PLANESTRAIN) && (*ph != ModellingHypothesis::GENERALISEDPLANESTRAIN)) { 1099 ph = dmh.erase(ph); 1100 } else { 1101 ++ph; 1102 } 1103 } 1104 } 1105 this->mb.setModellingHypotheses(dmh); 1106 } 1107 const auto& mh = this->mb.getModellingHypotheses(); 1108 // treating bricks 1109 if (!this->bricks.empty()) { 1110 if (getVerboseMode() >= VERBOSE_DEBUG) { 1111 getLogStream() << "BehaviourDSLCommon::completeVariableDeclaration: " 1112 << "treating bricks\n"; 1113 } 1114 for (const auto h : mh) { 1115 auto& d = this->mb.getBehaviourData(h); 1116 RequirementManager r{d, this->mb.useQt()}; 1117 // for(const auto& pb : this->bricks){ 1118 // pb->declareProviders(r,h); 1119 // } 1120 for (const auto& pb : this->bricks) { 1121 pb->addRequirements(r, h); 1122 } 1123 // unmatched requirements 1124 auto umrqs = std::vector<std::string>{}; 1125 const auto& urs = r.getUnresolvedRequirements(); 1126 for (const auto& n : urs) { 1127 const auto s = SupportedTypes{}; 1128 const auto& ur = r.getRequirement(n); 1129 if ((s.getTypeFlag(ur.type) != SupportedTypes::SCALAR) || 1130 (find(ur.aproviders.begin(), ur.aproviders.end(), ProviderIdentifier::MATERIALPROPERTY) == 1131 ur.aproviders.end())) { 1132 umrqs.push_back(ur.name); 1133 } 1134 } 1135 if (!umrqs.empty()) { 1136 std::string msg = "the following requirements can't be met: "; 1137 for (const auto& umrq : umrqs) { 1138 msg += "\n- " + umrq; 1139 } 1140 this->throwRuntimeError("BehaviourDSLCommon::completeVariableDeclaration", msg); 1141 } 1142 for (const auto& n : urs) { 1143 const auto& ur = r.getRequirement(n); 1144 this->mb.addMaterialProperty(h, {ur.type, ur.name, ur.asize, 0u}); 1145 if (!g.contains(ur.name)) { 1146 this->mb.setEntryName(h, ur.name, ur.name); 1147 } 1148 } 1149 } 1150 } 1151 for (const auto& pb : this->bricks) { 1152 pb->completeVariableDeclaration(); 1153 } 1154 if (getVerboseMode() >= VERBOSE_DEBUG) { 1155 auto& log = getLogStream(); 1156 log << "behaviour '" << this->mb.getClassName() << "' supports the following hypotheses: \n"; 1157 for (const auto& h : mh) { 1158 log << " - " << ModellingHypothesis::toString(h); 1159 if (this->mb.hasSpecialisedMechanicalData(h)) { 1160 log << " (specialised)"; 1161 } 1162 log << '\n'; 1163 } 1164 } 1165 // time step scaling factors 1166 if (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, "minimal_time_step_scaling_factor")) { 1167 VariableDescription e("real", "minimal_time_step_scaling_factor", 1u, 0u); 1168 e.description = "minimal value for the time step scaling factor"; 1169 this->mb.addParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, e, 1170 BehaviourData::ALREADYREGISTRED); 1171 this->mb.setParameterDefaultValue( 1172 ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1173 "minimal_time_step_scaling_factor", 0.1); 1174 this->mb.setEntryName(ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1175 "minimal_time_step_scaling_factor", 1176 "minimal_time_step_scaling_factor"); 1177 } 1178 if (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1179 "maximal_time_step_scaling_factor")) { 1180 VariableDescription e("real", "maximal_time_step_scaling_factor", 1u, 0u); 1181 e.description = "maximal value for the time step scaling factor"; 1182 this->mb.addParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, e, 1183 BehaviourData::ALREADYREGISTRED); 1184 this->mb.setParameterDefaultValue( 1185 ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1186 "maximal_time_step_scaling_factor", 1187 std::numeric_limits<double>::max()); 1188 this->mb.setEntryName(ModellingHypothesis::UNDEFINEDHYPOTHESIS, 1189 "maximal_time_step_scaling_factor", 1190 "maximal_time_step_scaling_factor"); 1191 } 1192 // incompatible options 1193 if ((this->mb.getAttribute(BehaviourDescription::computesStiffnessTensor, false)) && 1194 (this->mb.getAttribute(BehaviourDescription::requiresStiffnessTensor, false))) { 1195 this->throwRuntimeError("BehaviourDSLCommon::completeVariableDeclaration", 1196 "internal error, incompatible options for stiffness tensor"); 1197 } 1198 // check of stiffness tensor requirement 1199 if ((this->mb.getBehaviourType() == BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) || 1200 (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR)) { 1201 if ((mh.find(ModellingHypothesis::PLANESTRESS) != mh.end()) || 1202 (mh.find(ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) != mh.end())) { 1203 if (this->mb.getAttribute(BehaviourDescription::requiresStiffnessTensor,false)) { 1204 if (!this->mb.hasAttribute(BehaviourDescription::requiresUnAlteredStiffnessTensor)) { 1205 this->throwRuntimeError("BehaviourDSLCommon::completeVariableDeclaration", 1206 "No option was given to the '@RequireStiffnessTensor' keyword.\n" 1207 "For plane stress hypotheses, it is required to precise whether " 1208 "the expected stiffness tensor is 'Altered' (the plane stress " 1209 "hypothesis is taken into account) or 'UnAltered' (the stiffness " 1210 "tensor is the same as in plane strain)"); 1211 } 1212 } 1213 } 1214 } 1215 if (this->mb.getSymmetryType() == mfront::ORTHOTROPIC) { 1216 // if no orthotropic axes convention is defined, one can't compute 1217 // stiffness tensor, thermal expansion or stress free expansion 1218 // correctly, except for the 3D modelling hypothesis 1219 for (const auto h : this->mb.getDistinctModellingHypotheses()) { 1220 if (((this->mb.areElasticMaterialPropertiesDefined()) && 1221 (this->mb.getElasticMaterialProperties().size() == 9u)) || 1222 ((this->mb.areThermalExpansionCoefficientsDefined()) && 1223 (this->mb.getThermalExpansionCoefficients().size() == 3u)) || 1224 (this->mb.isStressFreeExansionAnisotropic(h))) { 1225 if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::DEFAULT) { 1226 // in this case, only tridimensional case is supported 1227 if (h != ModellingHypothesis::TRIDIMENSIONAL) { 1228 this->throwRuntimeError("BehaviourDSLCommon::completeVariableDeclaration", 1229 "An orthotropic axes convention must be choosen when " 1230 "using one of @ComputeStiffnessTensor, " 1231 "@ComputeThermalExpansion, @Swelling, @AxilalGrowth keywords in behaviours which " 1232 "shall be valid in other modelling hypothesis than " 1233 "'Tridimensional'. This message was triggered because " 1234 "either the thermal expansion or to the stiffness tensor " 1235 "is orthotropic.\n" 1236 "Either restrict the validity of the behaviour to " 1237 "'Tridimensional' (see @ModellingHypothesis) or " 1238 "choose and orthotropic axes convention as on option " 1239 "to the @OrthotropicBehaviour keyword"); 1240 } 1241 } 1242 } 1243 } 1244 } 1245 if (getVerboseMode() >= VERBOSE_DEBUG) { 1246 getLogStream() << "BehaviourDSLCommon::completeVariableDeclaration: end\n"; 1247 } 1248 } // end of BehaviourDSLCommon::completeVariableDeclaration 1249 endsInputFileProcessing()1250 void BehaviourDSLCommon::endsInputFileProcessing() { 1251 if (getVerboseMode() >= VERBOSE_DEBUG) { 1252 getLogStream() << "BehaviourDSLCommon::endsInputFileProcessing: begin\n"; 1253 } 1254 this->disableVariableDeclaration(); 1255 // restrictions on user defined compute stress free expansion 1256 for (const auto h : this->mb.getDistinctModellingHypotheses()) { 1257 const auto& d = this->mb.getBehaviourData(h); 1258 if (d.hasCode(BehaviourData::ComputeStressFreeExpansion)) { 1259 const auto& cb = d.getCodeBlock(BehaviourData::ComputeStressFreeExpansion); 1260 for (const auto& v : cb.members) { 1261 if (d.isLocalVariableName(v)) { 1262 this->throwRuntimeError( 1263 "BehaviourDSLCommon::" 1264 "endsInputFileProcessing: ", 1265 "local variables can't be used in " 1266 "@ComputeStressFreeExpansion blocks " 1267 "(local variables are not initialized yet " 1268 "when the stress free expansions " 1269 "are computed)"); 1270 } 1271 } 1272 } 1273 } 1274 if (this->mb.areSlipSystemsDefined()) { 1275 this->mb.appendToIncludes("#include \"TFEL/Material/" + 1276 this->mb.getClassName() + "SlipSystems.hxx\""); 1277 } 1278 // 1279 if (this->mb.getBehaviourType() == 1280 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 1281 const auto mhs = this->getModellingHypothesesToBeTreated(); 1282 for (const auto h : 1283 {ModellingHypothesis::PLANESTRESS, 1284 ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS}) { 1285 if (mhs.find(h) != mhs.end()) { 1286 if (!this->mb.hasSpecialisedMechanicalData(h)) { 1287 this->mb.specialize(h); 1288 } 1289 } 1290 } 1291 } 1292 // calling interfaces 1293 if (getPedanticMode()) { 1294 this->doPedanticChecks(); 1295 } 1296 for (const auto& pb : this->bricks) { 1297 pb->endTreatment(); 1298 } 1299 if (getVerboseMode() >= VERBOSE_DEBUG) { 1300 getLogStream() << "BehaviourDSLCommon::endsInputFileProcessing: end\n"; 1301 } 1302 } // end of BehaviourDSLCommon::endsInputFileProcessing 1303 1304 /*! 1305 * \return the "true" integration variables (state variables are excluded) 1306 * \param[in] md : mechanical behaviour data 1307 */ getIntegrationVariables(const BehaviourData & md)1308 static VarContainer getIntegrationVariables(const BehaviourData& md) { 1309 const auto& ivs = md.getIntegrationVariables(); 1310 VarContainer v; 1311 for (const auto& iv : ivs) { 1312 if (!md.isStateVariableName(iv.name)) { 1313 v.push_back(iv); 1314 } 1315 } 1316 return v; 1317 } // end of getIntegrationVariables 1318 1319 /*! 1320 * \brief various checks 1321 * \param[in] v : variables 1322 * \param[in] t : variable type 1323 * \param[in] uv : list of all used variables 1324 * \param[in] b1 : check if the variable is used 1325 * \param[in] b2 : check if the variable increment (or rate) is used 1326 * \param[in] b3 : check if glossary name is declared 1327 * \param[in] b4 : check if variable is used in more than one code block (test for local variables) 1328 */ performPedanticChecks(const BehaviourData & md,const VarContainer & v,const std::string & t,const std::map<std::string,unsigned short> & uv,const bool b1=true,const bool b2=true,const bool b3=true,const bool b4=false)1329 static void performPedanticChecks(const BehaviourData& md, 1330 const VarContainer& v, 1331 const std::string& t, 1332 const std::map<std::string, unsigned short>& uv, 1333 const bool b1 = true, 1334 const bool b2 = true, 1335 const bool b3 = true, 1336 const bool b4 = false) { 1337 using namespace tfel::glossary; 1338 const auto& glossary = Glossary::getGlossary(); 1339 auto& log = getLogStream(); 1340 for (const auto& vd : v) { 1341 if (b1) { 1342 const auto p = uv.find(vd.name); 1343 if (p == uv.end()) { 1344 log << "- " << t << " '" << vd.name << "' is unused.\n"; 1345 } else { 1346 if (b4 && p->second == 1) { 1347 log << "- " << t << " '" << vd.name << "' is used in one code block only.\n"; 1348 } 1349 } 1350 } 1351 if (b2) { 1352 if (uv.find("d" + vd.name) == uv.end()) { 1353 log << "- " << t << " increment 'd" << vd.name << "' is unused.\n"; 1354 } 1355 } 1356 if (b3) { 1357 if ((!md.hasGlossaryName(vd.name)) && (!md.hasEntryName(vd.name))) { 1358 log << "- " << t << " '" << vd.name << "' has no glossary name.\n"; 1359 } 1360 } 1361 if (vd.description.empty()) { 1362 auto hasDoc = false; 1363 if (md.hasGlossaryName(vd.name)) { 1364 const auto& e = glossary.getGlossaryEntry(md.getExternalName(vd.name)); 1365 hasDoc = (!e.getShortDescription().empty()) || (!e.getDescription().empty()); 1366 } 1367 if (!hasDoc) { 1368 log << "- " << t << " '" << vd.name << "' has no description.\n"; 1369 } 1370 } 1371 } 1372 } 1373 1374 /*! 1375 * \brief various checks on static variables 1376 * \param[in] v : variables 1377 * \param[in] uv : list of all static variables 1378 */ performPedanticChecks(const StaticVarContainer & v,const std::map<std::string,unsigned short> & uv)1379 static void performPedanticChecks(const StaticVarContainer& v, const std::map<std::string, unsigned short>& uv) { 1380 auto& log = getLogStream(); 1381 for (const auto& vd : v) { 1382 if (uv.find(vd.name) == uv.end()) { 1383 log << "- static variable '" << vd.name << "' is unused.\n"; 1384 } 1385 } 1386 } 1387 doPedanticChecks() const1388 void BehaviourDSLCommon::doPedanticChecks() const { 1389 const auto& hs = this->mb.getDistinctModellingHypotheses(); 1390 auto& log = getLogStream(); 1391 log << "\n* Pedantic checks\n"; 1392 for (auto h : hs) { 1393 const auto& md = this->mb.getBehaviourData(h); 1394 // checks if variables are used 1395 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 1396 log << "\n** Beginning pedantic checks for default modelling hypothesis\n\n"; 1397 } else { 1398 log << "\n** Beginning pedantic checks for modelling hypothesis '" << ModellingHypothesis::toString(h) 1399 << "'\n\n"; 1400 } 1401 // getting all used variables 1402 const auto& cbs = md.getCodeBlockNames(); 1403 auto members = std::map<std::string, unsigned short>{}; // variable names and counts 1404 auto smembers = std::map<std::string, unsigned short>{}; // static variable nanes and counts 1405 for (const auto& cbs_pcbs : cbs) { 1406 const auto& cb = md.getCodeBlock(cbs_pcbs); 1407 if (cb.description.empty()) { 1408 log << "- code block '" << cbs_pcbs << "' has no description\n"; 1409 } 1410 for (const auto& v : cb.members) { 1411 if (members.count(v) == 0) { 1412 members[v] = 1; 1413 } else { 1414 ++(members[v]); 1415 } 1416 } 1417 for (const auto& v : cb.staticMembers) { 1418 if (smembers.count(v) == 0) { 1419 smembers[v] = 1; 1420 } else { 1421 ++(smembers[v]); 1422 } 1423 } 1424 } 1425 performPedanticChecks(md, md.getMaterialProperties(), "material property", members, true, false, true); 1426 const auto& ivs = getIntegrationVariables(md); 1427 performPedanticChecks(md, ivs, "integration variable", members, false, true, false); 1428 performPedanticChecks(md, md.getStateVariables(), "state variable", members); 1429 performPedanticChecks(md, md.getAuxiliaryStateVariables(), "auxiliary state variable", members, true, false); 1430 performPedanticChecks(md, md.getExternalStateVariables(), "external state variable", members); 1431 performPedanticChecks(md, md.getLocalVariables(), "local variable", members, true, false, false, true); 1432 performPedanticChecks(md, md.getParameters(), "parameter", members, true, false); 1433 performPedanticChecks(md.getStaticVariables(), smembers); 1434 } 1435 log << "\n# End of pedantic checks\n"; 1436 } // end of BehaviourDSLCommon::pedanticChecks 1437 1438 std::set<BehaviourDSLCommon::Hypothesis> getModellingHypothesesToBeTreated() const1439 BehaviourDSLCommon::getModellingHypothesesToBeTreated() const { 1440 // modelling hypotheses handled by the interfaces (if at least one 1441 // interface is defined), or by the behaviour 1442 std::set<Hypothesis> mhs; 1443 if (this->interfaces.empty()) { 1444 const auto& bh = this->mb.getModellingHypotheses(); 1445 mhs.insert(bh.begin(), bh.end()); 1446 } else { 1447 // calling the interfaces 1448 for (const auto& i : this->interfaces) { 1449 const auto& ih = i.second->getModellingHypothesesToBeTreated(this->mb); 1450 mhs.insert(ih.begin(), ih.end()); 1451 } 1452 } 1453 return mhs; 1454 } // end of BehaviourDSLCommon::getModellingHypothesesToBeTreated 1455 generateOutputFiles()1456 void BehaviourDSLCommon::generateOutputFiles() { 1457 tfel::system::systemCall::mkdir("src"); 1458 tfel::system::systemCall::mkdir("include"); 1459 tfel::system::systemCall::mkdir("include/TFEL/"); 1460 tfel::system::systemCall::mkdir("include/TFEL/Material"); 1461 //! generating sources du to external material properties and models 1462 std::ofstream behaviourFile("include/" + this->getBehaviourFileName()); 1463 std::ofstream behaviourDataFile("include/" + 1464 this->getBehaviourDataFileName()); 1465 std::ofstream integrationDataFile("include/" + 1466 this->getIntegrationDataFileName()); 1467 std::ofstream srcFile("src/" + this->getSrcFileName()); 1468 if (!behaviourFile) { 1469 this->throwRuntimeError("BehaviourDSLCommon::generateOutputFiles", 1470 "unable to open '" + 1471 this->getBehaviourFileName() + 1472 "' " 1473 "for writing output file"); 1474 } 1475 if (!behaviourDataFile) { 1476 this->throwRuntimeError("BehaviourDSLCommon::generateOutputFiles", 1477 "unable to open '" + 1478 this->getBehaviourDataFileName() + 1479 "' " 1480 "for writing output file"); 1481 } 1482 if (!integrationDataFile) { 1483 this->throwRuntimeError("BehaviourDSLCommon::generateOutputFiles", 1484 "unable to open '" + 1485 this->getIntegrationDataFileName() + 1486 "' " 1487 "for writing output file"); 1488 } 1489 if (!srcFile) { 1490 this->throwRuntimeError("BehaviourDSLCommon::generateOutputFiles", 1491 "unable to open '" + this->getSrcFileName() + 1492 "' " 1493 "for writing output file"); 1494 } 1495 for (const auto& em : this->externalMFrontFiles) { 1496 this->callMFront(em.second, {em.first}); 1497 } 1498 auto write_classes = [this, &behaviourFile, &behaviourDataFile, 1499 &integrationDataFile](const Hypothesis h) { 1500 const auto n = h == ModellingHypothesis::UNDEFINEDHYPOTHESIS 1501 ? "default hypothesis" 1502 : "'" + ModellingHypothesis::toString(h) + "'"; 1503 if (getVerboseMode() >= VERBOSE_DEBUG) { 1504 auto& log = getLogStream(); 1505 log << "BehaviourDSLCommon::generateOutputFiles: " 1506 << "treating " + n + "\n"; 1507 } 1508 // Generating BehaviourData's outputClass 1509 if (getVerboseMode() >= VERBOSE_DEBUG) { 1510 auto& log = getLogStream(); 1511 log << "BehaviourDSLCommon::generateOutputFiles: " 1512 << "writing behaviour data for " + n + "\n"; 1513 } 1514 this->writeBehaviourDataClass(behaviourDataFile, h); 1515 // Generating IntegrationData's outputClass 1516 if (getVerboseMode() >= VERBOSE_DEBUG) { 1517 auto& log = getLogStream(); 1518 log << "BehaviourDSLCommon::generateOutputFiles: " 1519 << "writing integration data for " + n + "\n"; 1520 } 1521 this->writeIntegrationDataClass(integrationDataFile, h); 1522 // Generating Behaviour's outputFile 1523 if (getVerboseMode() >= VERBOSE_DEBUG) { 1524 auto& log = getLogStream(); 1525 log << "BehaviourDSLCommon::generateOutputFiles: " 1526 << "writing behaviour class for " + n + "\n"; 1527 } 1528 this->writeBehaviourClass(behaviourFile, h); 1529 }; 1530 // generate outpout files 1531 this->writeBehaviourDataFileBegin(behaviourDataFile); 1532 this->writeIntegrationDataFileBegin(integrationDataFile); 1533 this->writeBehaviourFileBegin(behaviourFile); 1534 if (this->mb.areSlipSystemsDefined()) { 1535 this->generateSlipSystemsFiles(); 1536 } 1537 const auto mhs = this->getModellingHypothesesToBeTreated(); 1538 if (!this->mb.areAllMechanicalDataSpecialised(mhs)) { 1539 write_classes(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 1540 } 1541 for (const auto& h : mhs) { 1542 if (mb.hasSpecialisedMechanicalData(h)) { 1543 write_classes(h); 1544 } 1545 } 1546 this->writeBehaviourDataFileEnd(behaviourDataFile); 1547 this->writeIntegrationDataFileEnd(integrationDataFile); 1548 this->writeBehaviourFileEnd(behaviourFile); 1549 // Generating behaviour's source file 1550 if (getVerboseMode() >= VERBOSE_DEBUG) { 1551 auto& log = getLogStream(); 1552 log << "BehaviourDSLCommon::generateOutputFiles : writing source file\n"; 1553 } 1554 this->writeSrcFile(srcFile); 1555 // calling the interfaces 1556 for (const auto& i : this->interfaces) { 1557 if (getVerboseMode() >= VERBOSE_DEBUG) { 1558 auto& log = getLogStream(); 1559 log << "BehaviourDSLCommon::generateOutputFiles : " 1560 << "calling interface '" << i.first << "'\n"; 1561 } 1562 i.second->endTreatment(this->mb, this->fd); 1563 } 1564 behaviourFile.close(); 1565 behaviourDataFile.close(); 1566 integrationDataFile.close(); 1567 srcFile.close(); 1568 } 1569 generateSlipSystemsFiles()1570 void BehaviourDSLCommon::generateSlipSystemsFiles() { 1571 using SlipSystemsDescription = BehaviourDescription::SlipSystemsDescription; 1572 using vector = SlipSystemsDescription::vector; 1573 using tensor = SlipSystemsDescription::tensor; 1574 auto throw_if = [this](const bool b, const std::string& m) { 1575 if (b) { 1576 this->throwRuntimeError( 1577 "FiniteStrainSingleCrystalBrick::" 1578 "generateSlipSystems", 1579 m); 1580 } 1581 }; 1582 auto write_vector = [](std::ostream& out, const std::string& v, const std::vector<vector>& ts) { 1583 for (decltype(ts.size()) i = 0; i != ts.size(); ++i) { 1584 const auto& t = ts[i]; 1585 out << v << "[" << i << "] = vector{" 1586 << "real(" << t[0] << ")," 1587 << "real(" << t[1] << ")," 1588 << "real(" << t[2] << ")};\n"; 1589 } 1590 }; 1591 auto write_tensor = [](std::ostream& out, const std::string& mu, const std::vector<tensor>& ts) { 1592 for (decltype(ts.size()) i = 0; i != ts.size(); ++i) { 1593 const auto& t = ts[i]; 1594 out << mu << "[" << i << "] = tensor{" 1595 << "real(" << t[0] << ")," 1596 << "real(" << t[1] << ")," 1597 << "real(" << t[2] << ")," 1598 << "real(" << t[3] << ")," 1599 << "real(" << t[4] << ")," 1600 << "real(" << t[5] << ")," 1601 << "real(" << t[6] << ")," 1602 << "real(" << t[7] << ")," 1603 << "real(" << t[8] << ")};\n"; 1604 } 1605 }; 1606 auto write_stensor = [](std::ostream& out, const std::string& mus, const std::vector<tensor>& ts) { 1607 TFEL_CONSTEXPR const auto cste = tfel::math::Cste<long double>::sqrt2 / 2; 1608 for (decltype(ts.size()) i = 0; i != ts.size(); ++i) { 1609 const auto& t = ts[i]; 1610 out << mus << "[" << i << "] = stensor{" 1611 << "real(" << t[0] << ")," 1612 << "real(" << t[1] << ")," 1613 << "real(" << t[2] << ")," 1614 << "real(" << (t[3] + t[4]) * cste << ")," 1615 << "real(" << (t[5] + t[6]) * cste << ")," 1616 << "real(" << (t[7] + t[8]) * cste << ")};\n"; 1617 } 1618 }; 1619 const auto& sss = this->mb.getSlipSystems(); 1620 const auto nb = sss.getNumberOfSlipSystemsFamilies(); 1621 const auto cn = this->mb.getClassName() + "SlipSystems"; 1622 tfel::system::systemCall::mkdir("include"); 1623 tfel::system::systemCall::mkdir("include/TFEL/"); 1624 tfel::system::systemCall::mkdir("include/TFEL/Material"); 1625 auto file = "include/TFEL/Material/" + cn + ".hxx"; 1626 std::ofstream out(file); 1627 throw_if(!out, "can't open file '" + file + "'"); 1628 out.exceptions(std::ios::badbit | std::ios::failbit); 1629 out << "/*!\n" 1630 << "* \\file " << file << '\n' 1631 << "* \\brief " 1632 << "this file decares the " << cn << " class.\n" 1633 << "* File generated by " << MFrontHeader::getVersionName() << " " 1634 << "version " << MFrontHeader::getVersionNumber() << '\n'; 1635 if (!this->fd.authorName.empty()) { 1636 out << "* \\author " << this->fd.authorName << '\n'; 1637 } 1638 if (!this->fd.date.empty()) { 1639 out << "* \\date " << this->fd.date << '\n'; 1640 } 1641 out << " */\n\n"; 1642 out << "#ifndef LIB_TFEL_MATERIAL_" << makeUpperCase(cn) << "_HXX\n" 1643 << "#define LIB_TFEL_MATERIAL_" << makeUpperCase(cn) << "_HXX\n\n" 1644 << "#if (defined _WIN32 || defined _WIN64)\n" 1645 << "#ifdef min\n" 1646 << "#undef min\n" 1647 << "#endif /* min */\n" 1648 << "#ifdef max\n" 1649 << "#undef max\n" 1650 << "#endif /* max */\n" 1651 << "#ifdef small\n" 1652 << "#undef small\n" 1653 << "#endif /* small */\n" 1654 << "#endif /* (defined _WIN32 || defined _WIN64) */\n\n" 1655 << "#include\"TFEL/Raise.hxx\"\n" 1656 << "#include\"TFEL/Math/tvector.hxx\"\n" 1657 << "#include\"TFEL/Math/stensor.hxx\"\n" 1658 << "#include\"TFEL/Math/tensor.hxx\"\n\n" 1659 << "namespace tfel{\n\n" 1660 << "namespace material{\n\n" 1661 << "template<typename real>\n" 1662 << "struct " << cn << '\n' 1663 << "{\n" 1664 << "//! a simple alias\n" 1665 << "using tensor = tfel::math::tensor<3u,real>;\n" 1666 << "//! a simple alias\n" 1667 << "using vector = tfel::math::tvector<3u,real>;\n" 1668 << "//! a simple alias\n" 1669 << "using stensor = tfel::math::stensor<3u,real>;\n"; 1670 auto nss = size_type{}; 1671 for (size_type idx = 0; idx != nb; ++idx) { 1672 nss += sss.getNumberOfSlipSystems(idx); 1673 } 1674 if (nb == 1u) { 1675 const auto nss0 = sss.getNumberOfSlipSystems(0); 1676 out << "//! number of sliding systems\n" 1677 << "static constexpr const unsigned short Nss" 1678 << " = " << nss << ";\n" 1679 << "//! number of sliding systems (first and uniq family)\n" 1680 << "static constexpr const unsigned short Nss0" 1681 << " = " << nss0 << ";\n"; 1682 } else { 1683 for (size_type idx = 0; idx != nb; ++idx) { 1684 out << "//! number of sliding systems\n" 1685 << "static constexpr const unsigned short Nss" << idx << " = " << sss.getNumberOfSlipSystems(idx) << ";\n"; 1686 } 1687 out << "static constexpr const unsigned short Nss = "; 1688 for (size_type idx = 0; idx != nb;) { 1689 out << "Nss" << idx; 1690 if (++idx != nb) { 1691 out << "+"; 1692 } 1693 } 1694 out << ";\n"; 1695 } 1696 out << "//! tensor of directional sense\n" 1697 << "tfel::math::tvector<Nss,tensor> mu;\n" 1698 << "//! symmetric tensor of directional sense\n" 1699 << "tfel::math::tvector<Nss,stensor> mus;\n" 1700 << "//! normal to slip plane\n" 1701 << "tfel::math::tvector<Nss,vector> np;\n" 1702 << "//! unit vector in the slip direction\n" 1703 << "tfel::math::tvector<Nss,vector> ns;\n"; 1704 for (size_type idx = 0; idx != nb; ++idx) { 1705 out << "//! tensor of directional sense\n" 1706 << "tfel::math::tvector<Nss" << idx << ",tensor> mu" << idx << ";\n" 1707 << "//! symmetric tensor of directional sense\n" 1708 << "tfel::math::tvector<Nss" << idx << ",stensor> mus" << idx << ";\n" 1709 << "//! normal to slip plane\n" 1710 << "tfel::math::tvector<Nss" << idx << ",vector> np" << idx << ";\n" 1711 << "//! unit vector in the slip direction\n" 1712 << "tfel::math::tvector<Nss" << idx << ",vector> ns" << idx << ";\n"; 1713 } 1714 if (this->mb.hasInteractionMatrix()) { 1715 out << "//! interaction matrix\n" 1716 << "tfel::math::tmatrix<Nss,Nss,real> mh;\n"; 1717 out << "//! interaction matrix\n" 1718 << "tfel::math::tmatrix<Nss,Nss,real> him;\n"; 1719 } 1720 if (this->mb.hasDislocationsMeanFreePathInteractionMatrix()) { 1721 out << "tfel::math::tmatrix<Nss,Nss,real> dim;\n"; 1722 } 1723 if (nb != 1u) { 1724 out << "/*!\n" 1725 << " * \\return the gobal index of the jth system of ith family\n" 1726 << " * \\param[in] i: slip system family\n" 1727 << " * \\param[in] j: local slip system index\n" 1728 << " */\n" 1729 << "constexpr unsigned short offset(const unsigned short,\nconst unsigned short) const;\n"; 1730 for (size_type i = 0; i != nb; ++i) { 1731 out << "/*!\n" 1732 << " * \\return the gobal index of the ith system of " << i << "th family\n" 1733 << " * \\param[in] i: local slip system index\n" 1734 << " */\n" 1735 << "constexpr unsigned short offset" << i << "(const unsigned short) const;\n"; 1736 } 1737 } 1738 out << "/*!\n" 1739 << " * \\return true if two systems are coplanar\n" 1740 << " * \\param[in] i: first slip system index\n" 1741 << " * \\param[in] j: second slip system index\n" 1742 << " */\n" 1743 << "bool areCoplanar(const unsigned short,\n" 1744 << " const unsigned short) const;\n" 1745 << "//! return the unique instance of the class\n" 1746 << "static const " << cn << "&\n" 1747 << "getSlidingSystems();\n" 1748 << "//! return the unique instance of the class\n" 1749 << "static const " << cn << "&\n" 1750 << "getSlipSystems();\n" 1751 << "//! return the unique instance of the class\n" 1752 << "static const " << cn << "&\n" 1753 << "getGlidingSystems();\n" 1754 << "private:\n" 1755 << "//! Constructor\n" 1756 << cn << "();\n" 1757 << "//! move constructor (disabled)\n" 1758 << cn << "(" << cn << "&&) = delete;\n" 1759 << "//! copy constructor (disabled)\n" 1760 << cn << "(const " << cn << "&) = delete;\n" 1761 << "//! move operator (disabled)\n" 1762 << cn << "&\n" 1763 << "operator=(" << cn << "&&) = delete;\n" 1764 << "//! copy constructor (disabled)\n" 1765 << cn << "&\n" 1766 << "operator=(const " << cn << "&) = delete;\n" 1767 << "}; // end of struct " << cn << "\n\n" 1768 << "//! a simple alias\n" 1769 << "template<typename real>\n" 1770 << "using " << this->mb.getClassName() << "SlidingSystems " 1771 << "= " << cn << "<real>;\n\n" 1772 << "//! a simple alias\n" 1773 << "template<typename real>\n" 1774 << "using " << this->mb.getClassName() << "GlidingSystems " 1775 << "= " << cn << "<real>;\n\n" 1776 << "} // end of namespace material\n\n" 1777 << "} // end of namespace tfel\n\n" 1778 << "#include\"TFEL/Material/" << cn << ".ixx\"\n\n" 1779 << "#endif /* LIB_TFEL_MATERIAL_" << makeUpperCase(cn) << "_HXX */\n"; 1780 out.close(); 1781 file = "include/TFEL/Material/" + cn + ".ixx"; 1782 out.open(file); 1783 throw_if(!out, "can't open file '" + file + "'"); 1784 out.exceptions(std::ios::badbit | std::ios::failbit); 1785 out.precision(std::numeric_limits<long double>::digits10); 1786 out << "/*!\n" 1787 << "* \\file " << file << '\n' 1788 << "* \\brief " 1789 << "this file implements the " << cn << " class.\n" 1790 << "* File generated by " << MFrontHeader::getVersionName() << " " 1791 << "version " << MFrontHeader::getVersionNumber() << '\n'; 1792 if (!this->fd.authorName.empty()) { 1793 out << "* \\author " << this->fd.authorName << '\n'; 1794 } 1795 if (!this->fd.date.empty()) { 1796 out << "* \\date " << this->fd.date << '\n'; 1797 } 1798 out << " */\n\n"; 1799 out << "#ifndef LIB_TFEL_MATERIAL_" << makeUpperCase(cn) << "_IXX\n" 1800 << "#define LIB_TFEL_MATERIAL_" << makeUpperCase(cn) << "_IXX\n\n" 1801 << "#include\"TFEL/Math/General/MathConstants.hxx\"\n\n" 1802 << "namespace tfel{\n\n" 1803 << "namespace material{\n\n" 1804 << "template<typename real>\n" 1805 << "const " << cn << "<real>&\n" 1806 << cn << "<real>::getSlidingSystems(){\n" 1807 << "static const " << cn << " i;\n" 1808 << "return i;\n" 1809 << "} // end of " << cn << "::getSlidingSystems\n\n" 1810 << "template<typename real>\n" 1811 << "const " << cn << "<real>&\n" 1812 << cn << "<real>::getSlipSystems(){\n" 1813 << "return " << cn << "<real>::getSlidingSystems();\n" 1814 << "} // end of " << cn << "::getSlipSystems\n\n" 1815 << "template<typename real>\n" 1816 << "const " << cn << "<real>&\n" 1817 << cn << "<real>::getGlidingSystems(){\n" 1818 << "return " << cn << "<real>::getSlidingSystems();\n" 1819 << "} // end of " << cn << "::getGlidingSystems\n\n" 1820 << "template<typename real>\n" 1821 << cn << "<real>::" << cn << "(){\n"; 1822 std::vector<tensor> gots; 1823 std::vector<vector> gnss; 1824 std::vector<vector> gnps; 1825 // orientation tensors 1826 for (size_type idx = 0; idx != nb; ++idx) { 1827 const auto& ots = sss.getOrientationTensors(idx); 1828 write_tensor(out, "this->mu" + std::to_string(idx), ots); 1829 gots.insert(gots.end(), ots.begin(), ots.end()); 1830 } 1831 write_tensor(out, "this->mu", gots); 1832 // symmetric orientation tensors 1833 for (size_type idx = 0; idx != nb; ++idx) { 1834 write_stensor(out, "this->mus" + std::to_string(idx), sss.getOrientationTensors(idx)); 1835 } 1836 write_stensor(out, "this->mus", gots); 1837 // normal to slip planes 1838 for (size_type idx = 0; idx != nb; ++idx) { 1839 const auto& nps = sss.getSlipPlaneNormals(idx); 1840 write_vector(out, "this->np" + std::to_string(idx), nps); 1841 gnps.insert(gnps.end(), nps.begin(), nps.end()); 1842 } 1843 write_vector(out, "this->np", gnps); 1844 // slip direction 1845 for (size_type idx = 0; idx != nb; ++idx) { 1846 const auto& nss2 = sss.getSlipDirections(idx); 1847 write_vector(out, "this->ns" + std::to_string(idx), nss2); 1848 gnss.insert(gnss.end(), nss2.begin(), nss2.end()); 1849 } 1850 write_vector(out, "this->ns", gnss); 1851 1852 auto write_imatrix = [&out, &sss, &nb, &nss](const std::vector<long double>& m, const std::string& n) { 1853 const auto ims = sss.getInteractionMatrixStructure(); 1854 auto count = size_type{}; // number of terms of the matrix treated so far 1855 out << "this->" << n << " = {"; 1856 for (size_type idx = 0; idx != nb; ++idx) { 1857 const auto gsi = sss.getSlipSystems(idx); 1858 for (size_type idx2 = 0; idx2 != gsi.size(); ++idx2) { 1859 for (size_type jdx = 0; jdx != nb; ++jdx) { 1860 const auto gsj = sss.getSlipSystems(jdx); 1861 for (size_type jdx2 = 0; jdx2 != gsj.size(); ++jdx2) { 1862 const auto r = ims.getRank(gsi[idx2], gsj[jdx2]); 1863 out << "real(" << m[r] << ")"; 1864 if (++count != nss * nss) { 1865 out << ","; 1866 } 1867 } 1868 } 1869 out << '\n'; 1870 } 1871 } 1872 out << "};\n"; 1873 1874 }; 1875 if (this->mb.hasInteractionMatrix()) { 1876 write_imatrix(sss.getInteractionMatrix(), "mh"); 1877 write_imatrix(sss.getInteractionMatrix(), "him"); 1878 } 1879 if (this->mb.hasDislocationsMeanFreePathInteractionMatrix()) { 1880 write_imatrix(sss.getDislocationsMeanFreePathInteractionMatrix(), "dim"); 1881 } 1882 out << "} // end of " << cn << "::" << cn << "\n\n"; 1883 if (nb != 1u) { 1884 out << "template<typename real>\n" 1885 << "constexpr unsigned short\n" 1886 << cn << "<real>::offset(const unsigned short i,\n" 1887 << "const unsigned short j\n) const{\n" 1888 << "const auto oi = [&i]() -> unsigned short{\n" 1889 << "switch(i){\n"; 1890 for (size_type i = 0; i != nb; ++i) { 1891 out << "case " << i << ":\n"; 1892 if (i == 0) { 1893 out << "return 0;\n" 1894 << "break;\n"; 1895 } else { 1896 out << "return "; 1897 for (size_type j = 0; j != i;) { 1898 out << "Nss" << j; 1899 if (++j != i) { 1900 out << "+"; 1901 } 1902 } 1903 out << ";\n" 1904 << "break;\n"; 1905 } 1906 } 1907 out << "default:\n" 1908 << "tfel::raise<std::out_of_range>(\"" << cn << "::offset: :\"\n\"invalid index" 1909 << "\");\n" 1910 << "}\n" 1911 << "}();\n" 1912 << "return oi+j;\n" 1913 << "} // end of offset\n\n"; 1914 for (size_type i = 0; i != nb; ++i) { 1915 out << "template<typename real>\n" 1916 << "constexpr unsigned short\n" 1917 << cn << "<real>::offset" << i << "(const unsigned short i) const{\n"; 1918 if (i != 0) { 1919 out << "constexpr const unsigned short o = "; 1920 for (size_type j = 0; j != i;) { 1921 out << "Nss" << j; 1922 if (++j != i) { 1923 out << "+"; 1924 } 1925 } 1926 out << ";\n" 1927 << "return o+i;\n"; 1928 } else { 1929 out << "return i;\n"; 1930 } 1931 out << "} // end of offset" << i << "\n\n"; 1932 } 1933 } 1934 out << "template<typename real>\n" 1935 << "bool " << cn << "<real>::areCoplanar(const unsigned short i,\n" 1936 << " const unsigned short j) const{\n"; 1937 std::vector<std::vector<bool>> are_coplanar(nss, std::vector<bool>(nss)); 1938 auto i = size_type{}; 1939 for (size_type idx = 0; idx != nb; ++idx) { 1940 const auto gsi = sss.getSlipSystems(idx); 1941 for (size_type idx2 = 0; idx2 != gsi.size(); ++idx2, ++i) { 1942 auto j = size_type{}; 1943 for (size_type jdx = 0; jdx != nb; ++jdx) { 1944 const auto gsj = sss.getSlipSystems(jdx); 1945 for (size_type jdx2 = 0; jdx2 != gsj.size(); ++jdx2, ++j) { 1946 if (gsi[idx2].is<SlipSystemsDescription::system3d>()) { 1947 const auto& si = gsi[idx2].get<SlipSystemsDescription::system3d>(); 1948 const auto& sj = gsj[jdx2].get<SlipSystemsDescription::system3d>(); 1949 const auto& ni = si.plane; 1950 const auto& nj = sj.plane; 1951 are_coplanar[i][j] = 1952 (std::equal(ni.begin(), ni.end(), nj.begin()) || 1953 std::equal(ni.begin(), ni.end(), nj.begin(), [](const int a, const int b) { return a == -b; })); 1954 } else { 1955 const auto& si = gsi[idx2].get<SlipSystemsDescription::system4d>(); 1956 const auto& sj = gsj[jdx2].get<SlipSystemsDescription::system4d>(); 1957 const auto& ni = si.plane; 1958 const auto& nj = sj.plane; 1959 are_coplanar[i][j] = 1960 (std::equal(ni.begin(), ni.end(), nj.begin()) || 1961 std::equal(ni.begin(), ni.end(), nj.begin(), [](const int a, const int b) { return a == -b; })); 1962 } 1963 } 1964 } 1965 } 1966 } 1967 out << "const auto mi = std::min(i,j);\n" 1968 << "const auto mj = std::max(i,j);\n" 1969 << "switch(mi){\n"; 1970 for (i = 0; i != nss; ++i) { 1971 out << "case " << i << ":\n"; 1972 if (i + 1 == nss) { 1973 out << "return (mi==" << nss - 1 << ")&&(mj==" << nss - 1 << ");\n"; 1974 } else { 1975 out << "switch (mj){\n"; 1976 for (size_type j = i; j != nss; ++j) { 1977 out << "case " << j << ":\n" 1978 << "return " << (are_coplanar[i][j] ? "true" : "false") << ";\n" 1979 << "break;\n"; 1980 } 1981 out << "default:\n" 1982 << "return false;\n" 1983 << "}\n"; 1984 } 1985 out << "break;\n"; 1986 } 1987 out << "default:\n" 1988 << "break;\n" 1989 << "}\n" 1990 << "return false;\n" 1991 << "}\n\n" 1992 << "} // end of namespace material\n\n" 1993 << "} // end of namespace tfel\n\n" 1994 << "#endif /* LIB_TFEL_MATERIAL_" << makeUpperCase(cn) << "_IXX */\n"; 1995 } 1996 declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution(const Hypothesis h,const std::string & n)1997 void BehaviourDSLCommon::declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution( 1998 const Hypothesis h, const std::string& n) { 1999 if (!this->explicitlyDeclaredUsableInPurelyImplicitResolution) { 2000 this->mb.setUsableInPurelyImplicitResolution(h, false); 2001 } 2002 this->mb.declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution(h, n); 2003 } // end of BehaviourDSLCommon::declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution 2004 standardModifier(const Hypothesis h,const std::string & var,const bool addThisPtr)2005 std::string BehaviourDSLCommon::standardModifier(const Hypothesis h, const std::string& var, const bool addThisPtr) { 2006 if ((this->mb.isExternalStateVariableIncrementName(h, var)) || (var == "dT")) { 2007 this->declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution(h, var.substr(1)); 2008 } 2009 if (addThisPtr) { 2010 return "this->" + var; 2011 } 2012 return var; 2013 } // end of BehaviourDSLCommon::standardModifier 2014 tangentOperatorVariableModifier(const Hypothesis h,const std::string & var,const bool addThisPtr)2015 std::string BehaviourDSLCommon::tangentOperatorVariableModifier(const Hypothesis h, 2016 const std::string& var, 2017 const bool addThisPtr) { 2018 return this->standardModifier(h, var, addThisPtr); 2019 } // end of BehaviourDSLCommon::tangentOperatorVariableModifier 2020 treatStrainMeasure()2021 void BehaviourDSLCommon::treatStrainMeasure() { 2022 this->checkNotEndOfFile("BehaviourDSLCommon::treatStrainMeasure", "Expected strain measure name."); 2023 const auto fs = this->current->value; 2024 ++(this->current); 2025 this->readSpecifiedToken("BehaviourDSLCommon::treatStrainMeasure", ";"); 2026 if (fs == "Hencky") { 2027 this->mb.setStrainMeasure(BehaviourDescription::HENCKY); 2028 } else if (fs == "GreenLagrange") { 2029 this->mb.setStrainMeasure(BehaviourDescription::GREENLAGRANGE); 2030 } else if ((fs == "Linearised") || (fs == "Linearized")) { 2031 this->mb.setStrainMeasure(BehaviourDescription::LINEARISED); 2032 } else { 2033 this->throwRuntimeError("BehaviourDSLCommon::treatStrainMeasure", "unsupported strain measure '" + fs + "'"); 2034 } 2035 } // end of BehaviourDSLCommon::treatStrainMeasure 2036 treatPrivate()2037 void BehaviourDSLCommon::treatPrivate() { 2038 auto hs = std::set<Hypothesis>{}; 2039 this->readHypothesesList(hs); 2040 const auto beg = this->current; 2041 for (const auto& h : hs) { 2042 const auto& d = this->mb.getBehaviourData(h); 2043 this->current = beg; 2044 CodeBlockParserOptions o; 2045 o.mn = d.getRegistredMembersNames(); 2046 o.smn = d.getRegistredStaticMembersNames(); 2047 o.qualifyStaticVariables = true; 2048 o.qualifyMemberVariables = true; 2049 o.modifier = std::make_shared<StandardVariableModifier>( 2050 h, [this](const Hypothesis hv, const std::string& v, const bool b) { 2051 return this->standardModifier(hv, v, b); 2052 }); 2053 this->mb.appendToPrivateCode(h, this->readNextBlock(o).code, true); 2054 } 2055 } // end of void BehaviourDSLCommon::treatPrivate 2056 treatMembers()2057 void BehaviourDSLCommon::treatMembers() { 2058 auto hs = std::set<Hypothesis>{}; 2059 this->readHypothesesList(hs); 2060 const auto beg = this->current; 2061 for (const auto& h : hs) { 2062 const auto& d = this->mb.getBehaviourData(h); 2063 this->current = beg; 2064 CodeBlockParserOptions o; 2065 o.mn = d.getRegistredMembersNames(); 2066 o.smn = d.getRegistredStaticMembersNames(); 2067 o.qualifyStaticVariables = true; 2068 o.qualifyMemberVariables = true; 2069 o.modifier = std::make_shared<StandardVariableModifier>( 2070 h, [this](const Hypothesis hv, const std::string& v, const bool b) { 2071 return this->standardModifier(hv, v, b); 2072 }); 2073 this->mb.appendToMembers(h, this->readNextBlock(o).code, true); 2074 } 2075 } // end of BehaviourDSLCommon::treatMembers 2076 treatBrick()2077 void BehaviourDSLCommon::treatBrick() { 2078 using Parameters = AbstractBehaviourBrick::Parameters; 2079 auto& f = BehaviourBrickFactory::getFactory(); 2080 auto parameters = Parameters{}; 2081 this->checkNotEndOfFile("BehaviourDSLCommon::treatBehaviourBrick", 2082 "Expected brick name or '<'."); 2083 if (this->current->value == "<") { 2084 auto options = std::vector<tfel::utilities::Token>{}; 2085 this->readList(options, "BehaviourDSLCommon::treatBehaviourBrick", "<", ">", true); 2086 for (const auto& o : options) { 2087 const auto pos = o.value.find('='); 2088 if (pos != std::string::npos) { 2089 if (pos == 0) { 2090 this->throwRuntimeError("BehaviourDSLCommon::treatBehaviourBrick", 2091 "no parameter name given"); 2092 } 2093 // extracting the name 2094 const auto& n = o.value.substr(0, pos); 2095 if (pos == o.value.size()) { 2096 this->throwRuntimeError("BehaviourDSLCommon::treatBehaviourBrick", 2097 "no option given to the " 2098 "parameter '" + 2099 n + "'"); 2100 } 2101 // extracting the option 2102 parameters.insert({n, o.value.substr(pos + 1)}); 2103 } else { 2104 parameters.insert({o.value, ""}); 2105 } 2106 } 2107 } 2108 this->checkNotEndOfFile("BehaviourDSLCommon::treatBehaviourBrick", 2109 "Expected brick name."); 2110 const auto b = [this]() -> std::string { 2111 if (this->current->flag == tfel::utilities::Token::String) { 2112 return this->readString("BehaviourDSLCommon::treatBehaviourBrick"); 2113 } 2114 const auto r = this->current->value; 2115 ++(this->current); 2116 return r; 2117 }(); 2118 const auto d = [this] { 2119 using namespace tfel::utilities; 2120 using DataMap = std::map<std::string, Data>; 2121 if ((this->current != this->tokens.end()) && 2122 (this->current->value == "{")) { 2123 DataParsingOptions o; 2124 o.allowMultipleKeysInMap = true; 2125 return Data::read(this->current, this->tokens.end(), o).get<DataMap>(); 2126 } 2127 return DataMap(); 2128 }(); 2129 const auto br = f.get(b, *this, this->mb); 2130 br->initialize(parameters, d); 2131 this->readSpecifiedToken("BehaviourDSLCommon::treatBehaviourBrick", ";"); 2132 this->bricks.push_back(std::move(br)); 2133 } // end of BehaviourDSLCommon::treatBrick 2134 treatTangentOperator()2135 void BehaviourDSLCommon::treatTangentOperator() { 2136 using namespace std; 2137 using namespace tfel::material; 2138 using namespace tfel::utilities; 2139 CodeBlockOptions o; 2140 this->readCodeBlockOptions(o, true); 2141 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 2142 auto po = o.untreated.begin(); 2143 const auto poe = o.untreated.end(); 2144 auto ktype = std::string{}; 2145 while (po != poe) { 2146 const auto& opt = *po; 2147 if (opt.flag != Token::Standard) { 2148 continue; 2149 } 2150 for (const auto& to : getFiniteStrainBehaviourTangentOperatorFlags()) { 2151 if (opt.value == 2152 convertFiniteStrainBehaviourTangentOperatorFlagToString(to)) { 2153 ktype = opt.value; 2154 break; 2155 } 2156 } 2157 if (!ktype.empty()) { 2158 o.untreated.erase(po); 2159 break; 2160 } 2161 ++po; 2162 } 2163 if (ktype.empty()) { 2164 ostringstream msg; 2165 msg << "Undefined tangent operator type '" + ktype + 2166 "'. Valid tangent operator type are :\n"; 2167 for (const auto& to : getFiniteStrainBehaviourTangentOperatorFlags()) { 2168 msg << "- " 2169 << convertFiniteStrainBehaviourTangentOperatorFlagToString(to) 2170 << " : " << getFiniteStrainBehaviourTangentOperatorDescription(to) 2171 << '\n'; 2172 } 2173 this->throwRuntimeError("BehaviourDSLCommon::treatTangentOperator", 2174 msg.str()); 2175 } 2176 this->readTangentOperatorCodeBlock( 2177 o, std::string(BehaviourData::ComputeTangentOperator) + "-" + ktype); 2178 for (const auto& h : o.hypotheses) { 2179 if (!this->mb.hasAttribute(h, BehaviourData::hasConsistentTangentOperator)) { 2180 this->mb.setAttribute(h, BehaviourData::hasConsistentTangentOperator, true); 2181 } 2182 } 2183 } else { 2184 this->readTangentOperatorCodeBlock(o, 2185 BehaviourData::ComputeTangentOperator); 2186 for (const auto& h : o.hypotheses) { 2187 this->mb.setAttribute(h, BehaviourData::hasConsistentTangentOperator, true); 2188 } 2189 } 2190 } // end of BehaviourDSLCommon::treatTangentOperator 2191 readTangentOperatorCodeBlock(const CodeBlockOptions & o,const std::string & n)2192 void BehaviourDSLCommon::readTangentOperatorCodeBlock( 2193 const CodeBlockOptions& o, const std::string& n) { 2194 this->treatUnsupportedCodeBlockOptions(o); 2195 this->readCodeBlock(*this, o, n, 2196 &BehaviourDSLCommon::tangentOperatorVariableModifier, 2197 true); 2198 } // end of BehaviourDSLCommon::readTangentOperatorCodeBlock 2199 treatIsTangentOperatorSymmetric()2200 void BehaviourDSLCommon::treatIsTangentOperatorSymmetric() { 2201 auto hs = std::set<Hypothesis>{}; 2202 this->readHypothesesList(hs); 2203 this->checkNotEndOfFile("BehaviourDSLCommon::treatIsTangentOperatorSymmetric : ", "Expected 'true' or 'false'."); 2204 auto b = this->readBooleanValue("BehaviourDSLCommon::treatIsTangentOperatorSymmetric"); 2205 this->readSpecifiedToken("BehaviourDSLCommon::treatIsTangentOperatorSymmetric", ";"); 2206 for (const auto& h : hs) { 2207 this->mb.setAttribute(h, BehaviourData::isConsistentTangentOperatorSymmetric, b); 2208 } 2209 } // end of BehaviourDSLCommon::treatTangentOperator 2210 treatLibrary()2211 void BehaviourDSLCommon::treatLibrary() { 2212 const auto& l = this->readOnlyOneToken(); 2213 if (!isValidLibraryName(l)) { 2214 this->throwRuntimeError("BehaviourDSLCommon::treatLibrary", 2215 "invalid library name '" + l + "'"); 2216 } 2217 this->mb.setLibrary(l); 2218 } // end of BehaviourDSLCommon::treatLibrary 2219 treatComputeThermalExpansion()2220 void BehaviourDSLCommon::treatComputeThermalExpansion() { 2221 using namespace tfel::utilities; 2222 using ExternalMFrontMaterialProperty = BehaviourDescription::ExternalMFrontMaterialProperty; 2223 using DataMap = std::map<std::string, Data>; 2224 const std::string m("BehaviourDSLCommon::treatComputeThermalExpansion"); 2225 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 2226 const auto n = "thermal_expansion_reference_temperature"; 2227 auto throw_if = [this, m](const bool b, const std::string& msg) { 2228 if (b) { 2229 this->throwRuntimeError(m, msg); 2230 } 2231 }; 2232 auto addTref = [this, throw_if, h, n](const double v) { 2233 if (this->mb.hasParameter(h, n)) { 2234 const auto Tref = this->mb.getFloattingPointParameterDefaultValue(h, n); 2235 throw_if(tfel::math::ieee754::fpclassify(Tref - v) != FP_ZERO, "inconsistent reference temperature"); 2236 } else { 2237 VariableDescription Tref("temperature", n, 1u, 0u); 2238 Tref.description = 2239 "value of the reference temperature for " 2240 "the computation of the thermal expansion"; 2241 this->mb.addParameter(h, Tref, BehaviourData::ALREADYREGISTRED); 2242 this->mb.setParameterDefaultValue(h, n, v); 2243 this->mb.setEntryName(h, n, "ThermalExpansionReferenceTemperature"); 2244 } 2245 }; 2246 auto addTi = [this, h](const double v) { 2247 VariableDescription Ti("temperature", "initial_geometry_reference_temperature", 1u, 0u); 2248 Ti.description = "value of the temperature when the initial geometry was measured"; 2249 this->mb.addParameter(h, Ti, BehaviourData::ALREADYREGISTRED); 2250 this->mb.setParameterDefaultValue(h, "initial_geometry_reference_temperature", v); 2251 this->mb.setEntryName(h, "initial_geometry_reference_temperature", "ReferenceTemperatureForInitialGeometry"); 2252 }; // end of addTi 2253 throw_if(this->mb.getAttribute<bool>(BehaviourDescription::requiresThermalExpansionCoefficientTensor, false), 2254 "@ComputeThermalExpansion can be used along with " 2255 "@RequireThermalExpansionCoefficientTensor"); 2256 const auto& acs = this->readMaterialPropertyOrArrayOfMaterialProperties(m); 2257 this->checkNotEndOfFile(m); 2258 if (this->current->value == "{") { 2259 const auto data = Data::read(this->current, this->tokens.end()).get<DataMap>(); 2260 throw_if(data.size() != 1u, 2261 "invalid number of data. " 2262 "Only the 'reference_temperature' is expected"); 2263 const auto pd = data.begin(); 2264 throw_if(pd->first != "reference_temperature", 2265 "the only data expected is " 2266 "'reference_temperature' (read '" + 2267 pd->first + "')"); 2268 throw_if(!pd->second.is<double>(), "invalid type for data 'reference_temperature'"); 2269 addTref(pd->second.get<double>()); 2270 } 2271 this->readSpecifiedToken(m, ";"); 2272 throw_if((acs.size() != 1u) && (acs.size() != 3u), "invalid number of file names given"); 2273 if (acs.size() == 3u) { 2274 // the material shall have been declared orthotropic 2275 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, 2276 "the mechanical behaviour must be orthotropic " 2277 "to give more than one thermal expansion coefficient."); 2278 } 2279 for (const auto& a : acs) { 2280 if (a.is<ExternalMFrontMaterialProperty>()) { 2281 const auto& mpd = *(a.get<ExternalMFrontMaterialProperty>().mpd); 2282 if (mpd.staticVars.contains("ReferenceTemperature")) { 2283 const auto Tref = mpd.staticVars.get("ReferenceTemperature"); 2284 addTref(Tref.value); 2285 } else { 2286 if (getVerboseMode() != VERBOSE_QUIET) { 2287 auto& os = getLogStream(); 2288 os << "no reference temperature in material property '"; 2289 if (mpd.material.empty()) { 2290 os << mpd.material << '_'; 2291 } 2292 os << mpd.law << "'\n"; 2293 } 2294 } 2295 } 2296 } 2297 if (acs.size() == 1u) { 2298 this->mb.setThermalExpansionCoefficient(acs.front()); 2299 } else { 2300 this->mb.setThermalExpansionCoefficients(acs[0], acs[1], acs[2]); 2301 } 2302 if (!this->mb.hasParameter(h, n)) { 2303 addTref(293.15); 2304 } 2305 if (!this->mb.hasParameter(h, "initial_geometry_reference_temperature")) { 2306 addTi(293.15); 2307 } 2308 } // end of BehaviourDSLCommon::treatComputeThermalExpansion 2309 treatElasticMaterialProperties()2310 void BehaviourDSLCommon::treatElasticMaterialProperties() { 2311 if (this->mb.getAttribute<bool>(BehaviourDescription::requiresStiffnessTensor, false)) { 2312 this->throwRuntimeError("BehaviourDSLCommon::treatElasticMaterialProperties", 2313 "@ElasticMaterialProperties can not be used along with " 2314 "@RequireStiffnessTensor"); 2315 } 2316 this->readElasticMaterialProperties(); 2317 } 2318 extractMaterialProperty(const std::string & m,const tfel::utilities::Token & t)2319 BehaviourDescription::MaterialProperty BehaviourDSLCommon::extractMaterialProperty(const std::string& m, 2320 const tfel::utilities::Token& t) { 2321 if (t.flag == tfel::utilities::Token::String) { 2322 // file name of formula 2323 const auto f = t.value.substr(1, t.value.size() - 2); 2324 if (tfel::utilities::ends_with(f, ".mfront")) { 2325 // file name 2326 BehaviourDescription::ExternalMFrontMaterialProperty mp; 2327 mp.mpd = this->handleMaterialPropertyDescription(f); 2328 return std::move(mp); 2329 } else { 2330 BehaviourDescription::AnalyticMaterialProperty mp; 2331 mp.f = f; 2332 return std::move(mp); 2333 } 2334 } 2335 BehaviourDescription::ConstantMaterialProperty mp; 2336 try { 2337 mp.value = std::stold(t.value); 2338 } catch (std::exception& e) { 2339 this->throwRuntimeError(m, "can't convert token '" + t.value + 2340 "' to long double " 2341 "(" + 2342 std::string(e.what()) + ")"); 2343 } 2344 return std::move(mp); 2345 } 2346 2347 std::vector<BehaviourDescription::MaterialProperty> readMaterialPropertyOrArrayOfMaterialProperties(const std::string & m)2348 BehaviourDSLCommon::readMaterialPropertyOrArrayOfMaterialProperties(const std::string& m) { 2349 auto mps = std::vector<BehaviourDescription::MaterialProperty>{}; 2350 this->checkNotEndOfFile(m); 2351 if (this->current->value == "{") { 2352 auto mpv = std::vector<tfel::utilities::Token>{}; 2353 this->readList(mpv, m, "{", "}", false); 2354 for (const auto& t : mpv) { 2355 mps.push_back(this->extractMaterialProperty(m, t)); 2356 } 2357 } else { 2358 mps.push_back(this->extractMaterialProperty(m, *(this->current))); 2359 ++(this->current); 2360 } 2361 return mps; 2362 } 2363 readElasticMaterialProperties()2364 void BehaviourDSLCommon::readElasticMaterialProperties() { 2365 const auto& emps = 2366 this->readMaterialPropertyOrArrayOfMaterialProperties("BehaviourDSLCommon::readElasticMaterialProperties"); 2367 this->readSpecifiedToken("BehaviourDSLCommon::readElasticMaterialProperties", ";"); 2368 if ((emps.size() != 2u) && (emps.size() != 9u)) { 2369 this->throwRuntimeError("BehaviourDSLCommon::readElasticMaterialProperties", 2370 "invalid number of file names given"); 2371 } 2372 if (emps.size() == 9u) { 2373 // the material shall have been declared orthotropic 2374 if (this->mb.getSymmetryType() != mfront::ORTHOTROPIC) { 2375 this->throwRuntimeError("BehaviourDSLCommon::readElasticMaterialProperties", 2376 "the mechanical behaviour must be orthotropic to give more than " 2377 "two elastic material properties."); 2378 } 2379 setElasticSymmetryType(this->mb, mfront::ORTHOTROPIC); 2380 } else { 2381 setElasticSymmetryType(this->mb, mfront::ISOTROPIC); 2382 } 2383 this->mb.setElasticMaterialProperties(emps); 2384 } 2385 treatComputeStiffnessTensor()2386 void BehaviourDSLCommon::treatComputeStiffnessTensor() { 2387 if (this->mb.getAttribute<bool>(BehaviourDescription::requiresStiffnessTensor, false)) { 2388 this->throwRuntimeError("BehaviourDSLCommon::treatComputeStiffnessTensor", 2389 "@ComputeStiffnessTensor can be used along with " 2390 "@RequireStiffnessTensor"); 2391 } 2392 if (this->current->value == "<") { 2393 this->treatStiffnessTensorOption(); 2394 } 2395 this->readElasticMaterialProperties(); 2396 this->mb.setAttribute(BehaviourDescription::computesStiffnessTensor, true, false); 2397 } // end of BehaviourDSLCommon::treatComputeStiffnessTensor 2398 treatHillTensor()2399 void BehaviourDSLCommon::treatHillTensor() { 2400 if (this->mb.getSymmetryType() != mfront::ORTHOTROPIC) { 2401 this->throwRuntimeError("BehaviourDSLCommon::treatHillTensor", 2402 "the mechanical behaviour must be orthotropic to define " 2403 "a Hill tensor."); 2404 } 2405 this->checkNotEndOfFile("BehaviourDSLCommon::treatModellingHypothesis"); 2406 // variable name 2407 if (!this->isValidIdentifier(this->current->value)) { 2408 this->throwRuntimeError("BehaviourDSLCommon::treatHillTensor: ", 2409 "variable name is not valid " 2410 "(read '" + 2411 this->current->value + "')."); 2412 } 2413 auto v = VariableDescription{"tfel::math::st2tost2<N,stress>", this->current->value, 1u, this->current->line}; 2414 v.description = "Hill tensor"; 2415 ++(this->current); 2416 // Hill coefficients 2417 const auto& hcs = this->readMaterialPropertyOrArrayOfMaterialProperties("BehaviourDSLCommon::treatHillTensor"); 2418 this->readSpecifiedToken("BehaviourDSLCommon::treatHillTensor", ";"); 2419 if (hcs.size() != 6u) { 2420 this->throwRuntimeError("BehaviourDSLCommon::treatHillTensor", "invalid number of hill coefficients"); 2421 } 2422 this->mb.addHillTensor(v, hcs); 2423 } // end of BehaviourDSLCommon::treatHillTensor 2424 treatModellingHypothesis()2425 void BehaviourDSLCommon::treatModellingHypothesis() { 2426 this->checkNotEndOfFile("BehaviourDSLCommon::treatModellingHypothesis"); 2427 const auto h = ModellingHypothesis::fromString(this->current->value); 2428 ++(this->current); 2429 this->checkNotEndOfFile("BehaviourDSLCommon::treatModellingHypothesis"); 2430 this->readSpecifiedToken("BehaviourDSLCommon::treatModellingHypothesis", ";"); 2431 if (!this->isModellingHypothesisSupported(h)) { 2432 this->throwRuntimeError("BehaviourDSLCommon::treatModellingHypothesis", 2433 "unsupported modelling hypothesis '" + ModellingHypothesis::toString(h) + "'"); 2434 } 2435 std::set<Hypothesis> hypotheses; 2436 hypotheses.insert(h); 2437 this->mb.setModellingHypotheses(hypotheses); 2438 } // end of BehaviourDSLCommon::treatModellingHypothesis 2439 treatModellingHypotheses()2440 void BehaviourDSLCommon::treatModellingHypotheses() { 2441 using namespace tfel::utilities; 2442 auto hypotheses = std::set<Hypothesis>{}; 2443 auto values = std::vector<Token>{}; 2444 this->checkNotEndOfFile("BehaviourDSLCommon::treatModellingHypotheses"); 2445 this->readList(values, "BehaviourDSLCommon::treatModellingHypotheses", "{", "}", false); 2446 this->checkNotEndOfFile("BehaviourDSLCommon::treatModellingHypotheses"); 2447 this->readSpecifiedToken("BehaviourDSLCommon::treatModellingHypotheses", ";"); 2448 for (const auto& v : values) { 2449 if (v.flag == Token::String) { 2450 this->appendToHypothesesList(hypotheses, v.value.substr(1, v.value.size() - 2)); 2451 } else { 2452 this->appendToHypothesesList(hypotheses, v.value); 2453 } 2454 } 2455 if (hypotheses.empty()) { 2456 this->throwRuntimeError("BehaviourDSLCommon::treatModellingHypotheses", "no hypothesis declared"); 2457 } 2458 this->mb.setModellingHypotheses(hypotheses); 2459 } // end of BehaviourDSLCommon::treatModellingHypotheses 2460 treatUsableInPurelyImplicitResolution()2461 void BehaviourDSLCommon::treatUsableInPurelyImplicitResolution() { 2462 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 2463 this->readSpecifiedToken("BehaviourDSLCommon::treatUsableInPurelyImplicitResolution", ";"); 2464 if (this->explicitlyDeclaredUsableInPurelyImplicitResolution) { 2465 this->throwRuntimeError("BehaviourDSLCommon::treatUsableInPurelyImplicitResolution", 2466 "keyword '@UsableInPurelyImplicitResolution' already called"); 2467 } 2468 this->explicitlyDeclaredUsableInPurelyImplicitResolution = true; 2469 this->mb.setUsableInPurelyImplicitResolution(h, true); 2470 } // end of BehaviourDSLCommon::treatUsableInPurelyImplicitResolution 2471 treatParameterMethod(const Hypothesis h)2472 void BehaviourDSLCommon::treatParameterMethod(const Hypothesis h) { 2473 using namespace std; 2474 using namespace tfel::utilities; 2475 const auto n = tfel::unicode::getMangledString(this->current->value); 2476 ++(this->current); 2477 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameterMethod"); 2478 this->readSpecifiedToken("BehaviourDSLCommon::treatParameterMethod", "."); 2479 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameterMethod"); 2480 if (this->current->value == "setDefaultValue") { 2481 ++(this->current); 2482 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameterMethod"); 2483 this->readSpecifiedToken("BehaviourDSLCommon::treatParameterMethod", "("); 2484 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameterMethod"); 2485 double value = tfel::utilities::convert<double>(this->current->value); 2486 ++(this->current); 2487 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameterMethod"); 2488 this->readSpecifiedToken("BehaviourDSLCommon::treatParameterMethod", ")"); 2489 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameterMethod"); 2490 this->readSpecifiedToken("BehaviourDSLCommon::treatParameterMethod", ";"); 2491 this->mb.setParameterDefaultValue(h, n, value); 2492 } else { 2493 --(this->current); 2494 --(this->current); 2495 this->treatVariableMethod(h); 2496 } 2497 } // end of BehaviourDSLCommon::treatParameterMethod 2498 isCallableVariable(const Hypothesis h,const std::string & n) const2499 bool BehaviourDSLCommon::isCallableVariable(const Hypothesis h, 2500 const std::string& n) const { 2501 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 2502 for (const auto& g : this->gradients) { 2503 if (g.name == n) { 2504 return true; 2505 } 2506 } 2507 for (const auto& f : this->thermodynamic_forces) { 2508 if (f.name == n) { 2509 return true; 2510 } 2511 } 2512 if (this->mb.isGradientName(n) || this->mb.isThermodynamicForceName(n)) { 2513 return true; 2514 } 2515 } 2516 return ((this->mb.isMaterialPropertyName(h, n)) || 2517 (this->mb.isStateVariableName(h, n)) || 2518 (this->mb.isAuxiliaryStateVariableName(h, n)) || 2519 (this->mb.isExternalStateVariableName(h, n)) || 2520 (this->mb.isLocalVariableName(h, n)) || 2521 (this->mb.isStaticVariableName(h, n)) || 2522 (this->mb.isParameterName(h, n)) || 2523 (this->mb.isIntegrationVariableName(h, n))); 2524 } // end of BehaviourDSLCommon::isCallableVariable 2525 treatSetGlossaryNameMethod()2526 std::string BehaviourDSLCommon::treatSetGlossaryNameMethod() { 2527 using namespace tfel::utilities; 2528 using namespace tfel::glossary; 2529 const auto& glossary = Glossary::getGlossary(); 2530 this->checkNotEndOfFile("BehaviourDSLCommon::treatSetGlossaryMethod"); 2531 this->readSpecifiedToken("BehaviourDSLCommon::treatSetGlossaryMethod", 2532 "setGlossaryName"); 2533 this->readSpecifiedToken("BehaviourDSLCommon::treatSetGlossaryMethod", "("); 2534 this->checkNotEndOfFile("BehaviourDSLCommon::treatSetGlossaryMethod"); 2535 if (this->current->flag != Token::String) { 2536 this->throwRuntimeError("BehaviourDSLCommon::treatSetGlossaryMethod: ", 2537 "expected to read a string"); 2538 } 2539 const auto& g = 2540 this->current->value.substr(1, this->current->value.size() - 2); 2541 if (!glossary.contains(g)) { 2542 this->throwRuntimeError("BehaviourDSLCommon::treatSetGlossaryMethod: ", 2543 "'" + g + "' is not a glossary name"); 2544 } 2545 ++(this->current); 2546 this->checkNotEndOfFile("BehaviourDSLCommon::treatSetGlossaryMethod"); 2547 this->readSpecifiedToken("BehaviourDSLCommon::treatSetGlossaryMethod", ")"); 2548 return g; 2549 } // end of treatSetGlossaryNameMethod 2550 treatSetEntryNameMethod()2551 std::string BehaviourDSLCommon::treatSetEntryNameMethod() { 2552 using namespace tfel::utilities; 2553 this->checkNotEndOfFile("BehaviourDSLCommon::treatSetEntryNameMethod"); 2554 this->readSpecifiedToken("BehaviourDSLCommon::treatSetEntryNameMethod", 2555 "setEntryName"); 2556 this->checkNotEndOfFile("BehaviourDSLCommon::treatSetEntryNameMethod"); 2557 this->readSpecifiedToken("BehaviourDSLCommon::treatSetEntryNameMethod", "("); 2558 this->checkNotEndOfFile("BehaviourDSLCommon::treatSetEntryNameMethod"); 2559 if (this->current->flag != Token::String) { 2560 this->throwRuntimeError("BehaviourDSLCommon::treatSetEntryNameMethod: ", 2561 "expected to read a string"); 2562 } 2563 const auto& e = 2564 this->current->value.substr(1, this->current->value.size() - 2); 2565 if (!this->isValidIdentifier(e)) { 2566 this->throwRuntimeError("BehaviourDSLCommon::treatSetEntryNameMethod: ", 2567 "invalid entry name '" + e + "'"); 2568 } 2569 ++(this->current); 2570 this->readSpecifiedToken("BehaviourDSLCommon::treatSetEntryNameMethod", 2571 ")"); 2572 return e; 2573 } // end of treatSetEntryNameMethod 2574 treatGradientMethod()2575 void BehaviourDSLCommon::treatGradientMethod() { 2576 const auto n = tfel::unicode::getMangledString(this->current->value); 2577 ++(this->current); 2578 this->checkNotEndOfFile("BehaviourDSLCommon::treatGradientMethod"); 2579 this->readSpecifiedToken("BehaviourDSLCommon::treatGradientMethod", "."); 2580 this->checkNotEndOfFile("BehaviourDSLCommon::treatGradientMethod"); 2581 if (this->current->value == "setGlossaryName") { 2582 const auto gn = this->treatSetGlossaryNameMethod(); 2583 bool treated = false; 2584 for (auto& g : this->gradients) { 2585 if (g.name == n) { 2586 g.setGlossaryName(gn); 2587 treated = true; 2588 break; 2589 } 2590 } 2591 if (!treated) { 2592 if (!this->mb.isGradientName(n)) { 2593 this->throwRuntimeError( 2594 "BehaviourDSLCommon::treatGradientMethod", 2595 "invalid call, '" + 2596 n + "' is not a registred gradient"); 2597 } 2598 this->mb.setGlossaryName(n, gn); 2599 } 2600 } else if (this->current->value == "setEntryName") { 2601 const auto e = this->treatSetEntryNameMethod(); 2602 bool treated = false; 2603 for (auto& g : this->gradients) { 2604 if (g.name == n) { 2605 g.setEntryName(e); 2606 treated = true; 2607 break; 2608 } 2609 } 2610 if (!treated) { 2611 if (!this->mb.isGradientName(n)) { 2612 this->throwRuntimeError( 2613 "BehaviourDSLCommon::treatGradientMethod", 2614 "invalid call, '" + 2615 n + "' is not a registred gradient"); 2616 } 2617 this->mb.setEntryName(n, e); 2618 } 2619 } else { 2620 this->throwRuntimeError( 2621 "BehaviourDSLCommon::treatGradientMethod", 2622 "unsupported method '" + this->current->value + "'"); 2623 } 2624 this->checkNotEndOfFile("BehaviourDSLCommon::treatGradientMethod"); 2625 this->readSpecifiedToken("BehaviourDSLCommon::treatGradientMethod", ";"); 2626 } // end of BehaviourDSLCommon::treatGradientMethod 2627 treatThermodynamicForceMethod()2628 void BehaviourDSLCommon::treatThermodynamicForceMethod() { 2629 const auto n = tfel::unicode::getMangledString(this->current->value); 2630 ++(this->current); 2631 this->checkNotEndOfFile( 2632 "BehaviourDSLCommon::treatThermodynamicForceMethod"); 2633 this->readSpecifiedToken( 2634 "BehaviourDSLCommon::treatThermodynamicForceMethod", "."); 2635 this->checkNotEndOfFile("BehaviourDSLCommon::treatThermodynamicForceMethod"); 2636 if (this->current->value == "setGlossaryName") { 2637 const auto gn = this->treatSetGlossaryNameMethod(); 2638 bool treated = false; 2639 for (auto& f : this->thermodynamic_forces) { 2640 if (f.name == n) { 2641 f.setGlossaryName(gn); 2642 treated = true; 2643 break; 2644 } 2645 } 2646 if (!treated) { 2647 if (!this->mb.isThermodynamicForceName(n)) { 2648 this->throwRuntimeError( 2649 "BehaviourDSLCommon::treatThermodynamicForceMethod", 2650 "invalid call, '" + 2651 n + "' is not a registred thermodynamic force"); 2652 } 2653 this->mb.setGlossaryName(n, gn); 2654 } 2655 } else if (this->current->value == "setEntryName") { 2656 const auto e = this->treatSetEntryNameMethod(); 2657 bool treated = false; 2658 for (auto& f : this->thermodynamic_forces) { 2659 if (f.name == n) { 2660 f.setEntryName(e); 2661 treated = true; 2662 break; 2663 } 2664 } 2665 if (!treated) { 2666 if (!this->mb.isThermodynamicForceName(n)) { 2667 this->throwRuntimeError( 2668 "BehaviourDSLCommon::treatThermodynamicForceMethod", 2669 "invalid call, '" + 2670 n + "' is not a registred thermodynamic force"); 2671 } 2672 this->mb.setEntryName(n, e); 2673 } 2674 } else { 2675 this->throwRuntimeError( 2676 "BehaviourDSLCommon::treatThermodynamicForceMethod", 2677 "unsupported method '" + this->current->value + "'"); 2678 } 2679 this->checkNotEndOfFile( 2680 "BehaviourDSLCommon::treatThermodynamicForceMethod"); 2681 this->readSpecifiedToken( 2682 "BehaviourDSLCommon::treatThermodynamicForceMethod", ";"); 2683 } // end of BehaviourDSLCommon::treatThermodynamicForceMethod 2684 treatVariableMethod(const Hypothesis h)2685 void BehaviourDSLCommon::treatVariableMethod(const Hypothesis h) { 2686 const auto n = tfel::unicode::getMangledString(this->current->value); 2687 ++(this->current); 2688 this->checkNotEndOfFile("BehaviourDSLCommon::treatVariableMethod"); 2689 this->readSpecifiedToken("BehaviourDSLCommon::treatVariableMethod", "."); 2690 this->checkNotEndOfFile("BehaviourDSLCommon::treatVariableMethod"); 2691 if (this->current->value == "setGlossaryName") { 2692 this->mb.setGlossaryName(h, n, this->treatSetGlossaryNameMethod()); 2693 } else if (this->current->value == "setEntryName") { 2694 this->mb.setEntryName(h, n, this->treatSetEntryNameMethod()); 2695 } else { 2696 this->treatUnknownVariableMethod(h, n); 2697 } 2698 this->checkNotEndOfFile("BehaviourDSLCommon::treatVariableMethod"); 2699 this->readSpecifiedToken("BehaviourDSLCommon::treatVariableMethod", ";"); 2700 } // end of BehaviourDSLCommon::treatVariableMethod 2701 treatUnknownVariableMethod(const Hypothesis,const std::string & n)2702 void BehaviourDSLCommon::treatUnknownVariableMethod(const Hypothesis, const std::string& n) { 2703 this->throwRuntimeError("BehaviourDSLCommon::treatUnknownVariableMethod : ", 2704 "unknown method '" + this->current->value + "' for variable '" + n + 2705 "', " 2706 "valid methods are 'setGlossaryName' or 'setEntryName'"); 2707 } // end of BehaviourDSLCommon::treatUnknownVariableMethod 2708 treatUnknownKeyword()2709 void BehaviourDSLCommon::treatUnknownKeyword() { 2710 TokensContainer::const_iterator p2; 2711 auto treated = false; 2712 --(this->current); 2713 const auto key = this->current->value; 2714 ++(this->current); 2715 this->checkNotEndOfFile("BehaviourDSLCommon::treatUnknownKeyword"); 2716 for (const auto& b : bricks) { 2717 auto p = b->treatKeyword(key, this->current, this->tokens.end()); 2718 if (p.first) { 2719 if (treated) { 2720 if (p2 != p.second) { 2721 this->throwRuntimeError("BehaviourDSLCommon::treatUnknownKeyword", "the keyword '" + key + 2722 "' has been treated " 2723 "by two interfaces/analysers but " 2724 "results were differents"); 2725 } 2726 } 2727 p2 = p.second; 2728 treated = true; 2729 } 2730 } 2731 if (!treated) { 2732 if (this->current->value == "[") { 2733 ++(this->current); 2734 this->checkNotEndOfFile("BehaviourDSLCommon::treatUnknownKeyword"); 2735 auto s = std::vector<std::string>{}; 2736 while (this->current->value != "]") { 2737 this->checkNotEndOfFile("BehaviourDSLCommon::treatUnknownKeyword"); 2738 const auto t = [this]() -> std::string { 2739 if (this->current->flag == tfel::utilities::Token::String) { 2740 return this->current->value.substr(1, this->current->value.size() - 2); 2741 } 2742 return this->current->value; 2743 }(); 2744 ++(this->current); 2745 this->checkNotEndOfFile("BehaviourDSLCommon::treatUnknownKeyword"); 2746 if (std::find(s.begin(), s.end(), t) == s.end()) { 2747 s.push_back(t); 2748 } 2749 if (this->current->value != "]") { 2750 this->readSpecifiedToken("BehaviourDSLCommon::treatUnknownKeyword", ","); 2751 this->checkNotEndOfFile("BehaviourDSLCommon::treatUnknownKeyword"); 2752 if (this->current->value == "]") { 2753 this->throwRuntimeError("BehaviourDSLCommon::treatUnknownKeyword", "unexpected token ']'"); 2754 } 2755 } 2756 } 2757 ++(this->current); 2758 for (auto& i : this->interfaces) { 2759 auto p = i.second->treatKeyword(this->mb, key, s, this->current, this->tokens.end()); 2760 if (p.first) { 2761 if (treated) { 2762 if (p2 != p.second) { 2763 this->throwRuntimeError("BehaviourDSLCommon::treatUnknownKeyword", 2764 "the keyword '" + key + 2765 "' has been treated " 2766 "by two interfaces/analysers but " 2767 "results were differents"); 2768 } 2769 } 2770 p2 = p.second; 2771 treated = true; 2772 } 2773 } 2774 if (!treated) { 2775 this->ignoreKeyWord(key); 2776 return; 2777 } 2778 } else { 2779 for (const auto& i : this->interfaces) { 2780 auto p = i.second->treatKeyword(this->mb, key, {}, this->current, this->tokens.end()); 2781 if (p.first) { 2782 if (treated) { 2783 if (p2 != p.second) { 2784 this->throwRuntimeError("BehaviourDSLCommon::treatUnknownKeyword", 2785 "the keyword '" + key + 2786 "' has been treated " 2787 "by two interfaces/analysers but " 2788 "results were differents"); 2789 } 2790 } 2791 p2 = p.second; 2792 treated = true; 2793 } 2794 } 2795 } 2796 } 2797 if (!treated) { 2798 DSLBase::treatUnknownKeyword(); 2799 } 2800 this->current = p2; 2801 } // end of BehaviourDSLCommon::treatUnknownKeyword 2802 treatUseQt()2803 void BehaviourDSLCommon::treatUseQt() { 2804 this->checkNotEndOfFile("BehaviourDSLCommon::treatUseQt : ", "Expected 'true' or 'false'."); 2805 if (this->current->value == "true") { 2806 this->mb.setUseQt(true); 2807 } else if (this->current->value == "false") { 2808 this->mb.setUseQt(false); 2809 } else { 2810 this->throwRuntimeError("BehaviourDSLCommon::treatUseQt", 2811 "Expected to read 'true' or 'false' instead of '" + this->current->value + "."); 2812 } 2813 ++(this->current); 2814 this->readSpecifiedToken("BehaviourDSLCommon::treatUseQt", ";"); 2815 } // end of BehaviourDSLCommon::treatUseQt 2816 treatIsotropicBehaviour()2817 void BehaviourDSLCommon::treatIsotropicBehaviour() { 2818 if (this->mb.getSymmetryType() != mfront::ISOTROPIC) { 2819 this->throwRuntimeError("BehaviourDSLCommon::treatIsotropicBehaviour", 2820 "this behaviour has been declared orthotropic"); 2821 } 2822 this->readSpecifiedToken("BehaviourDSLCommon::treatIsotropicBehaviour", ";"); 2823 } // end of BehaviourDSLCommon::treatIsotropicBehaviour 2824 treatOrthotropicBehaviour()2825 void BehaviourDSLCommon::treatOrthotropicBehaviour() { 2826 using namespace tfel::material; 2827 auto c = OrthotropicAxesConvention::DEFAULT; 2828 this->checkNotEndOfFile("BehaviourDSLCommon::treatOrthotropicBehaviour"); 2829 if (this->current->value == "<") { 2830 this->readSpecifiedToken("BehaviourDSLCommon::treatOrthotropicBehaviour", "<"); 2831 this->checkNotEndOfFile("BehaviourDSLCommon::treatOrthotropicBehaviour"); 2832 if (this->current->value == "Pipe") { 2833 ++this->current; 2834 c = OrthotropicAxesConvention::PIPE; 2835 } else if (this->current->value == "Plate") { 2836 ++this->current; 2837 c = OrthotropicAxesConvention::PLATE; 2838 } else if (this->current->value == "Default") { 2839 ++this->current; 2840 } else { 2841 this->throwRuntimeError("BehaviourDSLCommon::treatOrthotropicBehaviour", 2842 "unsupported orthotropic axes convention"); 2843 } 2844 this->readSpecifiedToken("BehaviourDSLCommon::treatOrthotropicBehaviour", ">"); 2845 } 2846 this->readSpecifiedToken("BehaviourDSLCommon::treatOrthotropicBehaviour", ";"); 2847 this->mb.setSymmetryType(mfront::ORTHOTROPIC); 2848 this->mb.setOrthotropicAxesConvention(c); 2849 } // end of BehaviourDSLCommon::treatOrthotropicBehaviour 2850 treatIsotropicElasticBehaviour()2851 void BehaviourDSLCommon::treatIsotropicElasticBehaviour() { 2852 this->readSpecifiedToken("BehaviourDSLCommon::treatIsotropicElasticBehaviour", ";"); 2853 if (this->mb.getSymmetryType() != mfront::ORTHOTROPIC) { 2854 this->throwRuntimeError("BehaviourDSLCommon::treatIsotropicElasticBehaviour", 2855 "this behaviour has not been declared orthotropic"); 2856 } 2857 this->mb.setElasticSymmetryType(mfront::ISOTROPIC); 2858 } // end of BehaviourDSLCommon::treatIsotropicElasticBehaviour 2859 treatRequireStiffnessOperator()2860 void BehaviourDSLCommon::treatRequireStiffnessOperator() { 2861 if (getVerboseMode() >= VERBOSE_LEVEL2) { 2862 getLogStream() << "BehaviourDSLCommon::treatRequireStiffnessOperator : " 2863 << "@RequireStiffnessOperator is deprecated\n" 2864 << "You shall use @RequireStiffnessTensor instead\n"; 2865 } 2866 this->treatRequireStiffnessTensor(); 2867 } // end of BehaviourDSLCommon::treatRequireStiffnessOperator 2868 treatStiffnessTensorOption()2869 void BehaviourDSLCommon::treatStiffnessTensorOption() { 2870 this->readSpecifiedToken("BehaviourDSLCommon::treatStiffnessTensorOption", "<"); 2871 this->checkNotEndOfFile("BehaviourDSLCommon::treatStiffnessTensorOption"); 2872 if (this->current->value == "UnAltered") { 2873 this->mb.setAttribute(BehaviourDescription::requiresUnAlteredStiffnessTensor, true, false); 2874 } else if (this->current->value == "Altered") { 2875 this->mb.setAttribute(BehaviourDescription::requiresUnAlteredStiffnessTensor, false, false); 2876 } else { 2877 this->throwRuntimeError("BehaviourDSLCommon::treatStiffnessTensorOption : ", 2878 "expected 'Altered' or 'UnAltered' option " 2879 "(read '" + 2880 this->current->value + "')"); 2881 } 2882 ++(this->current); 2883 this->readSpecifiedToken("BehaviourDSLCommon::treatStiffnessTensorOption", ">"); 2884 } 2885 treatRequireStiffnessTensor()2886 void BehaviourDSLCommon::treatRequireStiffnessTensor() { 2887 if (this->mb.hasAttribute(BehaviourDescription::computesStiffnessTensor)) { 2888 this->throwRuntimeError("BehaviourDSLCommon::treatRequireStiffnessTensor", 2889 "@RequireStiffnessTensor can be used along with " 2890 "@ComputeStiffnessTensor"); 2891 } 2892 this->checkNotEndOfFile("BehaviourDSLCommon::treatRequireStiffnessTensor"); 2893 if (this->current->value == "<") { 2894 this->treatStiffnessTensorOption(); 2895 } 2896 this->readSpecifiedToken("BehaviourDSLCommon::treatRequireStiffnessTensor", ";"); 2897 this->mb.setAttribute(BehaviourDescription::requiresStiffnessTensor, true, false); 2898 } // end of BehaviourDSLCommon::treatRequireStiffnessTensor 2899 treatRequireThermalExpansionCoefficientTensor()2900 void BehaviourDSLCommon::treatRequireThermalExpansionCoefficientTensor() { 2901 this->readSpecifiedToken("BehaviourDSLCommon::treatRequireThermalExpansionCoefficientTensor", ";"); 2902 this->mb.setAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor, true, false); 2903 } // end of BehaviourDSLCommon::treatRequireThermalExpansionCoefficientTensor 2904 setMaterialKnowledgeIdentifier(const std::string & i)2905 void BehaviourDSLCommon::setMaterialKnowledgeIdentifier(const std::string& i) { 2906 if (!isValidBehaviourName(i)) { 2907 this->throwRuntimeError("BehaviourDSLCommon::setMaterialKnowledgeIdentifier", 2908 "invalid behaviour name '" + i+ "'"); 2909 } 2910 this->mb.setBehaviourName(i); 2911 if (!isValidIdentifier(this->mb.getClassName())) { 2912 this->throwRuntimeError("BehaviourDSLCommon::setMaterialKnowledgeIdentifier", 2913 "resulting class name is not valid (read '" + 2914 this->mb.getClassName() + "')"); 2915 } 2916 } // end of BehaviourDSLCommon::setMaterialKnowledgeIdentifier 2917 treatBehaviour()2918 void BehaviourDSLCommon::treatBehaviour() { 2919 const auto& b = this->readOnlyOneToken(); 2920 if (!isValidBehaviourName(b)) { 2921 this->throwRuntimeError("BehaviourDSLCommon::treatBehaviour", 2922 "invalid behaviour name '" + b + "'"); 2923 } 2924 if (this->overriden_implementation_name.empty()) { 2925 this->setMaterialKnowledgeIdentifier(b); 2926 } 2927 } // end of BehaviourDSLCommon::treatBehaviour 2928 readStringList(std::vector<std::string> & cont)2929 void BehaviourDSLCommon::readStringList(std::vector<std::string>& cont) { 2930 this->checkNotEndOfFile("BehaviourDSLCommon::readStringList", "Cannot read interface name."); 2931 auto endOfTreatment = false; 2932 while ((this->current != this->tokens.end()) && (!endOfTreatment)) { 2933 const auto s = this->current->value; 2934 if (!isValidIdentifier(s)) { 2935 --(this->current); 2936 this->throwRuntimeError("BehaviourDSLCommon::readStringList", "interface name is not valid (read '" + s + "')"); 2937 } 2938 ++(this->current); 2939 this->checkNotEndOfFile("BehaviourDSLCommon::readStringList"); 2940 if (this->current->value == ",") { 2941 ++(this->current); 2942 } else if (this->current->value == ";") { 2943 endOfTreatment = true; 2944 ++(this->current); 2945 } else { 2946 this->throwRuntimeError("BehaviourDSLCommon::readStringList", "',' or ';' expected after '" + s + "'"); 2947 } 2948 if (find(cont.begin(), cont.end(), s) != cont.end()) { 2949 this->throwRuntimeError("BehaviourDSLCommon::readStringList", "'" + s + "' has already been registred.\n"); 2950 } 2951 cont.push_back(s); 2952 } 2953 if (!endOfTreatment) { 2954 --(this->current); 2955 this->throwRuntimeError("BehaviourDSLCommon::readStringList", "Expected ';' before end of file."); 2956 } 2957 } 2958 readHypothesesList()2959 std::set<BehaviourDSLCommon::Hypothesis> BehaviourDSLCommon::readHypothesesList() { 2960 std::set<Hypothesis> mh; 2961 this->readHypothesesList(mh); 2962 return mh; 2963 } // end of BehaviourDSLCommon::readHypothesesList 2964 readHypothesesList(std::set<Hypothesis> & h)2965 void BehaviourDSLCommon::readHypothesesList(std::set<Hypothesis>& h) { 2966 h.clear(); 2967 if (this->current == this->tokens.end()) { 2968 h.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 2969 return; 2970 } 2971 if (this->current->value != "<") { 2972 h.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 2973 return; 2974 } 2975 auto values = std::vector<tfel::utilities::Token>{}; 2976 this->readList(values, "BehaviourDSLCommon::readHypothesesList", "<", ">", true); 2977 for (const auto& v : values) { 2978 if (v.flag == tfel::utilities::Token::String) { 2979 this->appendToHypothesesList(h, v.value.substr(1, v.value.size() - 2)); 2980 } else { 2981 this->appendToHypothesesList(h, v.value); 2982 } 2983 } 2984 if (h.empty()) { 2985 h.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 2986 } 2987 } // end of BehaviourDSLCommon::readHypothesesList 2988 readVariableList(VariableDescriptionContainer & v,std::set<Hypothesis> & h,void (BehaviourDescription::* m)(const Hypothesis,const VariableDescriptionContainer &,const BehaviourData::RegistrationStatus),const bool b1)2989 void BehaviourDSLCommon::readVariableList(VariableDescriptionContainer& v, 2990 std::set<Hypothesis>& h, 2991 void (BehaviourDescription::*m)(const Hypothesis, 2992 const VariableDescriptionContainer&, 2993 const BehaviourData::RegistrationStatus), 2994 const bool b1) { 2995 h.clear(); 2996 v.clear(); 2997 this->readHypothesesList(h); 2998 this->readVarList(v, b1); 2999 this->addVariableList(h, v, m); 3000 } // end of BehaviourDSLCommon::readVariableList 3001 addVariableList(const std::set<Hypothesis> & hypotheses,const VariableDescriptionContainer & v,void (BehaviourDescription::* m)(const Hypothesis,const VariableDescriptionContainer &,const BehaviourData::RegistrationStatus))3002 void BehaviourDSLCommon::addVariableList(const std::set<Hypothesis>& hypotheses, 3003 const VariableDescriptionContainer& v, 3004 void (BehaviourDescription::*m)(const Hypothesis, 3005 const VariableDescriptionContainer&, 3006 const BehaviourData::RegistrationStatus)) { 3007 for (const auto& h : hypotheses) { 3008 (this->mb.*m)(h, v, BehaviourData::UNREGISTRED); 3009 } 3010 } // end of BehaviourDSLCommon::addVariableList 3011 treatCoef()3012 void BehaviourDSLCommon::treatCoef() { 3013 VarContainer v; 3014 auto h = std::set<Hypothesis>{}; 3015 this->readVariableList(v, h, &BehaviourDescription::addMaterialProperties, true); 3016 } // end of BehaviourDSLCommon::treatCoef 3017 treatLocalVar()3018 void BehaviourDSLCommon::treatLocalVar() { 3019 VarContainer v; 3020 auto h = std::set<Hypothesis>{}; 3021 this->readVariableList(v, h, &BehaviourDescription::addLocalVariables, true); 3022 } // end of BehaviourDSLCommon::treatLocalVar 3023 treatInterface()3024 void BehaviourDSLCommon::treatInterface() { 3025 auto& mbif = BehaviourInterfaceFactory::getBehaviourInterfaceFactory(); 3026 auto inames = std::vector<std::string>{}; 3027 this->readStringList(inames); 3028 for (const auto& i : inames) { 3029 if (this->interfaces.count(i) == 0) { 3030 this->interfaces.insert({i, mbif.getInterface(i)}); 3031 } 3032 } 3033 } // end of BehaviourDSLCommon::treatInterface 3034 setInterfaces(const std::set<std::string> & inames)3035 void BehaviourDSLCommon::setInterfaces(const std::set<std::string>& inames) { 3036 auto& mbif = BehaviourInterfaceFactory::getBehaviourInterfaceFactory(); 3037 for (const auto& i : inames) { 3038 if (this->interfaces.count(i) == 0) { 3039 this->interfaces.insert({i, mbif.getInterface(i)}); 3040 } 3041 } 3042 } // end of BehaviourDSLCommon::setInterfaces 3043 treatAPrioriTimeStepScalingFactor()3044 void BehaviourDSLCommon::treatAPrioriTimeStepScalingFactor() { 3045 this->readCodeBlock(*this, BehaviourData::APrioriTimeStepScalingFactor, &BehaviourDSLCommon::standardModifier, true, 3046 true); 3047 } 3048 treatIntegrator()3049 void BehaviourDSLCommon::treatIntegrator() { 3050 this->readCodeBlock(*this, BehaviourData::Integrator, &BehaviourDSLCommon::standardModifier, true, true); 3051 } // end of BehaviourDSLCommon::treatIntegrator 3052 treatAPosterioriTimeStepScalingFactor()3053 void BehaviourDSLCommon::treatAPosterioriTimeStepScalingFactor() { 3054 this->readCodeBlock(*this, BehaviourData::APosterioriTimeStepScalingFactor, &BehaviourDSLCommon::standardModifier, 3055 true, true); 3056 } 3057 treatStateVariable()3058 void BehaviourDSLCommon::treatStateVariable() { 3059 VarContainer v; 3060 auto h = std::set<Hypothesis>{}; 3061 this->readVariableList(v, h, &BehaviourDescription::addStateVariables, true); 3062 } // end of BehaviourDSLCommon::treatStateVariable 3063 treatAuxiliaryStateVariable()3064 void BehaviourDSLCommon::treatAuxiliaryStateVariable() { 3065 VarContainer v; 3066 auto h = std::set<Hypothesis>{}; 3067 this->readVariableList(v, h, &BehaviourDescription::addAuxiliaryStateVariables, true); 3068 } // end of BehaviourDSLCommon::treatAuxiliaryStateVariable 3069 treatExternalStateVariable()3070 void BehaviourDSLCommon::treatExternalStateVariable() { 3071 VarContainer v; 3072 auto h = std::set<Hypothesis>{}; 3073 this->readVariableList(v, h, &BehaviourDescription::addExternalStateVariables, true); 3074 } // end of BehaviourDSLCommon::treatExternalStateVariable() 3075 treatBounds()3076 void BehaviourDSLCommon::treatBounds() { 3077 auto hs = std::set<Hypothesis>{}; 3078 this->readHypothesesList(hs); 3079 auto b = this->current; 3080 for (const auto& h : hs) { 3081 this->current = b; 3082 const auto r = this->readVariableBounds(); 3083 const auto v = extractVariableNameAndArrayPosition(r.first); 3084 if (std::get<1>(v)) { 3085 this->mb.setBounds(h, std::get<0>(v), std::get<2>(v), r.second); 3086 } else { 3087 this->mb.setBounds(h, std::get<0>(v), r.second); 3088 } 3089 } 3090 this->readSpecifiedToken("BehaviourDSLCommon::treatBounds", ";"); 3091 } // end of BehaviourDSLCommon::treatBounds 3092 treatPhysicalBounds()3093 void BehaviourDSLCommon::treatPhysicalBounds() { 3094 auto hs = std::set<Hypothesis>{}; 3095 this->readHypothesesList(hs); 3096 auto b = current; 3097 for (const auto& h : hs) { 3098 this->current = b; 3099 const auto bounds = this->readVariableBounds(); 3100 this->mb.setPhysicalBounds(h, bounds.first, bounds.second); 3101 } 3102 this->readSpecifiedToken("BehaviourDSLCommon::treatBounds", ";"); 3103 } // end of BehaviourDSLCommon::treatPhysicalBounds 3104 registerDefaultVarNames()3105 void BehaviourDSLCommon::registerDefaultVarNames() { 3106 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 3107 // all available tangent operators for finite strain behaviours 3108 const auto tos = tfel::material::getFiniteStrainBehaviourTangentOperatorFlags(); 3109 // stiffness tensor 3110 this->mb.registerMemberName(h, "D"); 3111 // stiffness tensor at the end of the time step 3112 this->mb.registerMemberName(h, "D_tdt"); 3113 // tangent operator 3114 this->mb.registerMemberName(h, "Dt"); 3115 this->reserveName("N"); 3116 this->reserveName("Type"); 3117 this->reserveName("use_qt"); 3118 this->reserveName("src1"); 3119 this->reserveName("src2"); 3120 this->reserveName("policy_value"); 3121 this->reserveName("integrate"); 3122 this->reserveName("Psi_s"); 3123 this->reserveName("Psi_d"); 3124 this->reserveName("thermal_expansion_reference_temperature"); 3125 this->reserveName("initial_geometry_reference_temperature"); 3126 this->mb.registerMemberName(h, "computeThermodynamicForces"); 3127 this->mb.registerMemberName(h, "computeFinalThermodynamicForces"); 3128 this->mb.registerMemberName(h, "computeStressFreeExpansion"); 3129 this->mb.registerMemberName(h, "computeInternalEnergy"); 3130 this->mb.registerMemberName(h, "computeDissipatedEnergy"); 3131 this->mb.registerMemberName(h, "computeFdF"); 3132 this->mb.registerMemberName(h, "updateIntegrationVariables"); 3133 this->mb.registerMemberName(h, "updateStateVariables"); 3134 this->mb.registerMemberName(h, "updateAuxiliaryStateVariables"); 3135 this->mb.registerMemberName(h, "getTangentOperator"); 3136 this->mb.registerMemberName(h, "getMinimalTimeStepScalingFactor"); 3137 this->mb.registerMemberName(h, "computeAPrioriTimeStepScalingFactor"); 3138 this->mb.registerMemberName(h, "computeAPrioriTimeStepScalingFactorII"); 3139 this->mb.registerMemberName(h, "computeAPosterioriTimeStepScalingFactor"); 3140 this->mb.registerMemberName(h, "computeAPosterioriTimeStepScalingFactorII"); 3141 this->reserveName("computeTangentOperator_"); 3142 this->mb.registerMemberName(h, "computeConsistentTangentOperator"); 3143 for (const auto& to : tos) { 3144 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(to); 3145 this->mb.registerMemberName(h, ktype); 3146 this->mb.registerMemberName(h, "computeConsistentTangentOperator_" + ktype); 3147 this->mb.registerMemberName(h, "tangentOperator_" + ktype); 3148 } 3149 this->reserveName("tangentOperator_sk2"); 3150 this->reserveName("computePredictionOperator"); 3151 for (const auto& to : tos) { 3152 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(to); 3153 this->mb.registerMemberName(h, "computePredictionOperator_" + ktype); 3154 } 3155 this->reserveName("smt"); 3156 this->reserveName("smflag"); 3157 this->reserveName("dl0_l0"); 3158 this->reserveName("dl1_l0"); 3159 this->reserveName("dl01_l0"); 3160 this->reserveName("alpha_Ti"); 3161 this->reserveName("alpha0_Ti"); 3162 this->reserveName("alpha1_Ti"); 3163 this->reserveName("alpha2_Ti"); 3164 this->reserveName("alpha_T_t"); 3165 this->reserveName("alpha_T_t_dt"); 3166 this->reserveName("alpha0_T_t"); 3167 this->reserveName("alpha0_T_t_dt"); 3168 this->reserveName("alpha1_T_t"); 3169 this->reserveName("alpha1_T_t_dt"); 3170 this->reserveName("alpha2_T_t"); 3171 this->reserveName("alpha2_T_t_dt"); 3172 this->reserveName("TangentOperator"); 3173 this->reserveName("StressFreeExpansionType"); 3174 this->reserveName("behaviourData"); 3175 this->reserveName("time_scaling_factor"); 3176 this->reserveName("mp_bounds_check_status"); 3177 } // end of BehaviourDSLCommon::registerDefaultVarNames 3178 reserveName(const std::string & n)3179 void BehaviourDSLCommon::reserveName(const std::string& n) { 3180 this->mb.reserveName(ModellingHypothesis::UNDEFINEDHYPOTHESIS, n); 3181 } 3182 isNameReserved(const std::string & n) const3183 bool BehaviourDSLCommon::isNameReserved(const std::string& n) const { return this->mb.isNameReserved(n); } 3184 writeVariablesDeclarations(std::ostream & f,const VariableDescriptionContainer & v,const std::string & prefix,const std::string & suffix,const std::string & fileName,const bool useTimeDerivative) const3185 void BehaviourDSLCommon::writeVariablesDeclarations(std::ostream& f, 3186 const VariableDescriptionContainer& v, 3187 const std::string& prefix, 3188 const std::string& suffix, 3189 const std::string& fileName, 3190 const bool useTimeDerivative) const { 3191 for (const auto& e : v) { 3192 this->writeVariableDeclaration(f, e, prefix, suffix, fileName, useTimeDerivative); 3193 } 3194 } // end of BehaviourDSLCommon::writeVariablesDeclarations 3195 writeVariableDeclaration(std::ostream & f,const VariableDescription & v,const std::string & prefix,const std::string & suffix,const std::string & fileName,const bool useTimeDerivative) const3196 void BehaviourDSLCommon::writeVariableDeclaration(std::ostream& f, 3197 const VariableDescription& v, 3198 const std::string& prefix, 3199 const std::string& suffix, 3200 const std::string& fileName, 3201 const bool useTimeDerivative) const { 3202 const auto n = prefix + v.name + suffix; 3203 const auto t = (!useTimeDerivative) ? v.type : this->getTimeDerivativeType(v.type); 3204 if ((!getDebugMode()) && (v.lineNumber != 0u)) { 3205 f << "#line " << v.lineNumber << " \"" << fileName << "\"\n"; 3206 } 3207 if (v.arraySize == 1u) { 3208 f << t << " " << n << ";\n"; 3209 } else { 3210 if (this->mb.useDynamicallyAllocatedVector(v.arraySize)) { 3211 f << "tfel::math::vector<" << t << " > " << n << ";\n"; 3212 } else { 3213 f << "tfel::math::tvector<" << v.arraySize << ", " << t << " > " << n << ";\n"; 3214 } 3215 } 3216 } // end of BehaviourDSLCommon::writeVariableDeclaration 3217 writeIncludes(std::ostream & file) const3218 void BehaviourDSLCommon::writeIncludes(std::ostream& file) const { 3219 if ((!file) || (!file.good())) { 3220 this->throwRuntimeError("BehaviourDSLCommon::writeIncludes", "output file is not valid"); 3221 } 3222 const auto& h = this->mb.getIncludes(); 3223 if (!h.empty()) { 3224 file << h << '\n'; 3225 } 3226 } 3227 writeNamespaceBegin(std::ostream & file) const3228 void BehaviourDSLCommon::writeNamespaceBegin(std::ostream& file) const { 3229 if ((!file) || (!file.good())) { 3230 this->throwRuntimeError("BehaviourDSLCommon::writeNamespaceBegin", "output file is not valid"); 3231 } 3232 file << "namespace tfel{\n\n" 3233 << "namespace material{\n\n"; 3234 } 3235 writeNamespaceEnd(std::ostream & file) const3236 void BehaviourDSLCommon::writeNamespaceEnd(std::ostream& file) const { 3237 if ((!file) || (!file.good())) { 3238 this->throwRuntimeError("BehaviourDSLCommon::writeNamespaceEnd", "output file is not valid"); 3239 } 3240 file << "} // end of namespace material\n\n" 3241 << "} // end of namespace tfel\n\n"; 3242 } 3243 writeStandardTFELTypedefs(std::ostream & file) const3244 void BehaviourDSLCommon::writeStandardTFELTypedefs(std::ostream& file) const { 3245 if ((!file) || (!file.good())) { 3246 this->throwRuntimeError("BehaviourDSLCommon::writeStandardTFELTypedefs", "output file is not valid"); 3247 } 3248 file << "using ushort = unsigned short;\n"; 3249 if (this->mb.useQt()) { 3250 file << "using Types = tfel::config::Types<N,Type,use_qt>;\n"; 3251 } else { 3252 file << "using Types = tfel::config::Types<N,Type,false>;\n"; 3253 } 3254 file << "using real = typename Types::real;\n" 3255 << "using time = typename Types::time;\n" 3256 << "using length = typename Types::length;\n" 3257 << "using frequency = typename Types::frequency;\n" 3258 << "using stress = typename Types::stress;\n" 3259 << "using strain = typename Types::strain;\n" 3260 << "using strainrate = typename Types::strainrate;\n" 3261 << "using stressrate = typename Types::stressrate;\n" 3262 << "using temperature = typename Types::temperature;\n" 3263 << "using thermalexpansion = typename Types::thermalexpansion;\n" 3264 << "using thermalconductivity = typename Types::thermalconductivity;\n" 3265 << "using massdensity = typename Types::massdensity;\n" 3266 << "using energydensity = typename Types::energydensity;\n" 3267 << "using TVector = typename Types::TVector;\n" 3268 << "using Stensor = typename Types::Stensor;\n" 3269 << "using Stensor4 = typename Types::Stensor4;\n" 3270 << "using FrequencyStensor = typename Types::FrequencyStensor;\n" 3271 << "using ForceTVector = typename Types::ForceTVector;\n" 3272 << "using StressStensor = typename Types::StressStensor;\n" 3273 << "using StressRateStensor = typename Types::StressRateStensor;\n" 3274 << "using DisplacementTVector = typename Types::DisplacementTVector;\n" 3275 << "using StrainStensor = typename Types::StrainStensor;\n" 3276 << "using StrainRateStensor = typename Types::StrainRateStensor;\n" 3277 << "using StiffnessTensor = typename Types::StiffnessTensor;\n" 3278 << "using Tensor = typename Types::Tensor;\n" 3279 << "using FrequencyTensor = typename Types::FrequencyTensor;\n" 3280 << "using StressTensor = typename Types::StressTensor;\n" 3281 << "using ThermalExpansionCoefficientTensor = typename Types::ThermalExpansionCoefficientTensor;\n" 3282 << "using DeformationGradientTensor = typename Types::DeformationGradientTensor;\n" 3283 << "using DeformationGradientRateTensor = typename Types::DeformationGradientRateTensor;\n" 3284 << "using TemperatureGradient = typename Types::TemperatureGradient;\n" 3285 << "using HeatFlux = typename Types::HeatFlux;\n"; 3286 // tangent operator 3287 if (this->mb.hasTangentOperator()) { 3288 file << "using TangentOperator = " << this->mb.getTangentOperatorType() 3289 << ";\n"; 3290 } 3291 // physical constants 3292 file << "using PhysicalConstants = tfel::PhysicalConstants<real>;\n"; 3293 } // end of BehaviourDSLCommon::writeStandardTFELTypedefs 3294 getIntegrationVariablesIncrementsInitializers(const Hypothesis h) const3295 std::string BehaviourDSLCommon::getIntegrationVariablesIncrementsInitializers(const Hypothesis h) const { 3296 std::ostringstream f; 3297 const auto& vc = this->mb.getBehaviourData(h).getIntegrationVariables(); 3298 for (auto p = vc.begin(); p != vc.end(); ++p) { 3299 const auto& v = *p; 3300 const auto flag = getTypeFlag(v.type); 3301 const auto n = v.name; 3302 const auto t = (!this->useStateVarTimeDerivative) ? v.type : this->getTimeDerivativeType(v.type); 3303 if (p != vc.begin()) { 3304 f << ",\n"; 3305 } 3306 if (flag == SupportedTypes::SCALAR) { 3307 if (this->mb.useDynamicallyAllocatedVector(v.arraySize)) { 3308 f << "d" << n << "(" << v.arraySize << "," << t << "(0))"; 3309 } else { 3310 f << "d" << n << "(" << t << "(0))"; 3311 } 3312 } else if ((flag == SupportedTypes::TVECTOR) || (flag == SupportedTypes::STENSOR) || 3313 (flag == SupportedTypes::TENSOR)) { 3314 std::string traits; 3315 if (flag == SupportedTypes::TVECTOR) { 3316 traits = "VectorTraits"; 3317 } else if (flag == SupportedTypes::STENSOR) { 3318 traits = "StensorTraits"; 3319 } else if (flag == SupportedTypes::TENSOR) { 3320 traits = "TensorTraits"; 3321 } else { 3322 this->throwRuntimeError("BehaviourDSLCommon::getIntegrationVariablesIncrementsInitializers", 3323 "internal error, tag unsupported"); 3324 } 3325 if (v.arraySize == 1u) { 3326 f << "d" << n << "(typename tfel::math::" + traits + "<" << t << ">::NumType(0))"; 3327 } else { 3328 if (this->mb.useDynamicallyAllocatedVector(v.arraySize)) { 3329 f << "d" << n << "(" << v.arraySize << "," << t << "(typename tfel::math::" + traits + "<" << t 3330 << ">::NumType(0)))"; 3331 } else { 3332 f << "d" << n << "(" << t << "(typename tfel::math::" + traits + "<" << t << ">::NumType(0)))"; 3333 } 3334 } 3335 } else { 3336 this->throwRuntimeError("BehaviourDSLCommon::getIntegrationVariablesIncrementsInitializers", 3337 "internal error, tag unsupported"); 3338 } 3339 } 3340 return f.str(); 3341 } // end of SupportedTypes::getIntegrationVariablesInitializers 3342 checkBehaviourDataFile(std::ostream & os) const3343 void BehaviourDSLCommon::checkBehaviourDataFile(std::ostream& os) const { 3344 if ((!os) || (!os.good())) { 3345 this->throwRuntimeError("BehaviourDSLCommon::checkBehaviourDataOutputFile", "output file is not valid"); 3346 } 3347 } 3348 writeBehaviourDataFileHeader(std::ostream & os) const3349 void BehaviourDSLCommon::writeBehaviourDataFileHeader(std::ostream& os) const { 3350 this->checkBehaviourDataFile(os); 3351 os << "/*!\n" 3352 << "* \\file " << this->getBehaviourDataFileName() << '\n' 3353 << "* \\brief " 3354 << "this file implements the " << this->mb.getClassName() << "BehaviourData" 3355 << " class.\n" 3356 << "* File generated by " << MFrontHeader::getVersionName() << " " 3357 << "version " << MFrontHeader::getVersionNumber() << '\n'; 3358 if (!this->fd.authorName.empty()) { 3359 os << "* \\author " << this->fd.authorName << '\n'; 3360 } 3361 if (!this->fd.date.empty()) { 3362 os << "* \\date " << this->fd.date << '\n'; 3363 } 3364 os << " */\n\n"; 3365 } 3366 writeBehaviourDataFileHeaderBegin(std::ostream & os) const3367 void BehaviourDSLCommon::writeBehaviourDataFileHeaderBegin(std::ostream& os) const { 3368 this->checkBehaviourDataFile(os); 3369 os << "#ifndef LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_BEHAVIOUR_DATA_HXX\n"; 3370 os << "#define LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_BEHAVIOUR_DATA_HXX\n\n"; 3371 } 3372 writeBehaviourDataFileHeaderEnd(std::ostream & os) const3373 void BehaviourDSLCommon::writeBehaviourDataFileHeaderEnd(std::ostream& os) const { 3374 this->checkBehaviourDataFile(os); 3375 os << "#endif /* LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_BEHAVIOUR_DATA_HXX */\n"; 3376 } 3377 writeBehaviourDataStandardTFELIncludes(std::ostream & os) const3378 void BehaviourDSLCommon::writeBehaviourDataStandardTFELIncludes(std::ostream& os) const { 3379 auto b1 = false; 3380 auto b2 = false; 3381 this->checkBehaviourDataFile(os); 3382 os << "#include<limits>\n" 3383 << "#include<string>\n" 3384 << "#include<sstream>\n" 3385 << "#include<iostream>\n" 3386 << "#include<stdexcept>\n" 3387 << "#include<algorithm>\n\n" 3388 << "#include\"TFEL/Raise.hxx\"\n" 3389 << "#include\"TFEL/PhysicalConstants.hxx\"\n" 3390 << "#include\"TFEL/Config/TFELConfig.hxx\"\n" 3391 << "#include\"TFEL/Config/TFELTypes.hxx\"\n" 3392 << "#include\"TFEL/Metaprogramming/StaticAssert.hxx\"\n" 3393 << "#include\"TFEL/TypeTraits/IsFundamentalNumericType.hxx\"\n" 3394 << "#include\"TFEL/TypeTraits/IsReal.hxx\"\n" 3395 << "#include\"TFEL/Math/General/IEEE754.hxx\"\n"; 3396 if (this->mb.useQt()) { 3397 os << "#include\"TFEL/Math/General/BaseCast.hxx\"\n"; 3398 } 3399 this->mb.requiresTVectorOrVectorIncludes(b1, b2); 3400 if (b1) { 3401 os << "#include\"TFEL/Math/tvector.hxx\"\n" 3402 << "#include\"TFEL/Math/Vector/tvectorIO.hxx\"\n"; 3403 } 3404 if (b2) { 3405 os << "#include\"TFEL/Math/vector.hxx\"\n"; 3406 } 3407 os << "#include\"TFEL/Math/stensor.hxx\"\n" 3408 << "#include\"TFEL/Math/Stensor/StensorView.hxx\"\n" 3409 << "#include\"TFEL/Math/Stensor/StensorConceptIO.hxx\"\n" 3410 << "#include\"TFEL/Math/tmatrix.hxx\"\n" 3411 << "#include\"TFEL/Math/Matrix/tmatrixIO.hxx\"\n" 3412 << "#include\"TFEL/Math/st2tost2.hxx\"\n" 3413 << "#include\"TFEL/Math/ST2toST2/ST2toST2ConceptIO.hxx\"\n" 3414 << "#include\"TFEL/Math/ST2toST2/ST2toST2View.hxx\"\n"; 3415 if ((this->mb.getBehaviourType() == 3416 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) || 3417 (this->mb.getBehaviourType() == 3418 BehaviourDescription::GENERALBEHAVIOUR)) { 3419 os << "#include\"TFEL/Math/tensor.hxx\"\n" 3420 << "#include\"TFEL/Math/Tensor/TensorConceptIO.hxx\"\n" 3421 << "#include\"TFEL/Math/t2tot2.hxx\"\n" 3422 << "#include\"TFEL/Math/T2toT2/T2toT2ConceptIO.hxx\"\n" 3423 << "#include\"TFEL/Math/t2tost2.hxx\"\n" 3424 << "#include\"TFEL/Math/T2toST2/T2toST2ConceptIO.hxx\"\n" 3425 << "#include\"TFEL/Math/st2tot2.hxx\"\n" 3426 << "#include\"TFEL/Math/ST2toT2/ST2toT2ConceptIO.hxx\"\n" 3427 << "#include\"TFEL/Math/ST2toST2/ConvertToTangentModuli.hxx\"\n" 3428 << "#include\"TFEL/Math/ST2toST2/ConvertSpatialModuliToKirchhoffJaumanRateModuli.hxx\"\n" 3429 << "#include\"TFEL/Material/FiniteStrainBehaviourTangentOperator.hxx\"\n"; 3430 } 3431 if (this->mb.getBehaviourType() == BehaviourDescription::GENERALBEHAVIOUR) { 3432 os << "#include\"TFEL/Math/T2toT2/T2toT2View.hxx\"\n" 3433 << "#include\"TFEL/Math/T2toST2/T2toST2View.hxx\"\n" 3434 << "#include\"TFEL/Math/ST2toT2/ST2toT2View.hxx\"\n"; 3435 } 3436 os << "#include\"TFEL/Material/ModellingHypothesis.hxx\"\n\n"; 3437 } // end of BehaviourDSLCommon::writeBehaviourDataStandardTFELIncludes 3438 writeBehaviourDataDefaultMembers(std::ostream & os) const3439 void BehaviourDSLCommon::writeBehaviourDataDefaultMembers(std::ostream& os) const { 3440 this->checkBehaviourDataFile(os); 3441 if (this->mb.getAttribute(BehaviourDescription::requiresStiffnessTensor, false)) { 3442 os << "//! stiffness tensor computed by the calling solver\n" 3443 << "StiffnessTensor D;\n"; 3444 } 3445 if (this->mb.getAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor, false)) { 3446 os << "ThermalExpansionCoefficientTensor A;\n"; 3447 } 3448 for (const auto& mv : this->mb.getMainVariables()) { 3449 if (Gradient::isIncrementKnown(mv.first)) { 3450 os << mv.first.type << " " << mv.first.name << ";\n\n"; 3451 } else { 3452 os << mv.first.type << " " << mv.first.name << "0;\n\n"; 3453 } 3454 os << mv.second.type << " " << mv.second.name << ";\n\n"; 3455 } 3456 } 3457 writeBehaviourDataStandardTFELTypedefs(std::ostream & os) const3458 void BehaviourDSLCommon::writeBehaviourDataStandardTFELTypedefs(std::ostream& os) const { 3459 this->checkBehaviourDataFile(os); 3460 os << "static " << constexpr_c << " unsigned short TVectorSize = N;\n" 3461 << "typedef tfel::math::StensorDimeToSize<N> StensorDimeToSize;\n" 3462 << "static " << constexpr_c << " unsigned short StensorSize = " 3463 << "StensorDimeToSize::value;\n" 3464 << "typedef tfel::math::TensorDimeToSize<N> TensorDimeToSize;\n" 3465 << "static " << constexpr_c << " unsigned short TensorSize = " 3466 << "TensorDimeToSize::value;\n\n"; 3467 this->writeStandardTFELTypedefs(os); 3468 os << '\n'; 3469 } 3470 writeBehaviourDataDisabledConstructors(std::ostream & os) const3471 void BehaviourDSLCommon::writeBehaviourDataDisabledConstructors(std::ostream& os) const { 3472 this->checkBehaviourDataFile(os); 3473 } 3474 writeBehaviourDataConstructors(std::ostream & os,const Hypothesis h) const3475 void BehaviourDSLCommon::writeBehaviourDataConstructors(std::ostream& os, const Hypothesis h) const { 3476 const auto& md = this->mb.getBehaviourData(h); 3477 this->checkBehaviourDataFile(os); 3478 os << "/*!\n" 3479 << "* \\brief Default constructor\n" 3480 << "*/\n" 3481 << this->mb.getClassName() << "BehaviourData()\n" 3482 << "{}\n\n" 3483 << "/*!\n" 3484 << "* \\brief copy constructor\n" 3485 << "*/\n" 3486 << this->mb.getClassName() << "BehaviourData(const " << this->mb.getClassName() << "BehaviourData& src)\n" 3487 << ": "; 3488 auto first = true; 3489 if (this->mb.getAttribute(BehaviourDescription::requiresStiffnessTensor, false)) { 3490 os << "D(src.D)"; 3491 first = false; 3492 } 3493 if (this->mb.getAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor, false)) { 3494 if (!first) { 3495 os << ",\n"; 3496 } 3497 os << "A(src.A)"; 3498 first = false; 3499 } 3500 for (const auto& mv : this->mb.getMainVariables()) { 3501 if (!first) { 3502 os << ",\n"; 3503 } 3504 if (Gradient::isIncrementKnown(mv.first)) { 3505 os << mv.first.name << "(src." << mv.first.name << "),\n"; 3506 } else { 3507 os << mv.first.name << "0(src." << mv.first.name << "0),\n"; 3508 } 3509 os << mv.second.name << "(src." << mv.second.name << ")"; 3510 first = false; 3511 } 3512 for (const auto& v : md.getMaterialProperties()) { 3513 os << ",\n"; 3514 os << v.name << "(src." << v.name << ")"; 3515 } 3516 for (const auto& v : md.getStateVariables()) { 3517 os << ",\n"; 3518 os << v.name << "(src." << v.name << ")"; 3519 } 3520 for (const auto& v : md.getAuxiliaryStateVariables()) { 3521 os << ",\n"; 3522 os << v.name << "(src." << v.name << ")"; 3523 } 3524 for (const auto& v : md.getExternalStateVariables()) { 3525 os << ",\n"; 3526 os << v.name << "(src." << v.name << ")"; 3527 } 3528 os << "\n{}\n\n"; 3529 // Creating constructor for external interfaces 3530 for (const auto& i : this->interfaces) { 3531 if (i.second->isBehaviourConstructorRequired(h, this->mb)) { 3532 i.second->writeBehaviourDataConstructor(os, h, this->mb); 3533 } 3534 } 3535 } // end of BehaviourDSLCommon::WriteBehaviourDataConstructors 3536 writeBehaviourDataAssignementOperator(std::ostream & os,const Hypothesis h) const3537 void BehaviourDSLCommon::writeBehaviourDataAssignementOperator(std::ostream& os, const Hypothesis h) const { 3538 const auto& md = this->mb.getBehaviourData(h); 3539 this->checkBehaviourDataFile(os); 3540 os << "/*\n" 3541 << "* \\brief Assignement operator\n" 3542 << "*/\n" 3543 << this->mb.getClassName() << "BehaviourData&\n" 3544 << "operator=(const " << this->mb.getClassName() << "BehaviourData& src){\n"; 3545 for (const auto& dv : this->mb.getMainVariables()) { 3546 if (Gradient::isIncrementKnown(dv.first)) { 3547 os << "this->" << dv.first.name << " = src." << dv.first.name << ";\n"; 3548 } else { 3549 os << "this->" << dv.first.name << "0 = src." << dv.first.name << "0;\n"; 3550 } 3551 os << "this->" << dv.second.name << " = src." << dv.second.name << ";\n"; 3552 } 3553 for (const auto& mp : md.getMaterialProperties()) { 3554 os << "this->" << mp.name << " = src." << mp.name << ";\n"; 3555 } 3556 for (const auto& iv : md.getStateVariables()) { 3557 os << "this->" << iv.name << " = src." << iv.name << ";\n"; 3558 } 3559 for (const auto& iv : md.getAuxiliaryStateVariables()) { 3560 os << "this->" << iv.name << " = src." << iv.name << ";\n"; 3561 } 3562 for (const auto& ev : md.getExternalStateVariables()) { 3563 os << "this->" << ev.name << " = src." << ev.name << ";\n"; 3564 } 3565 os << "return *this;\n" 3566 << "}\n\n"; 3567 } // end of BehaviourDSLCommon::writeBehaviourAssignementOperator 3568 writeBehaviourDataExport(std::ostream & os,const Hypothesis h) const3569 void BehaviourDSLCommon::writeBehaviourDataExport(std::ostream& os, const Hypothesis h) const { 3570 this->checkBehaviourDataFile(os); 3571 for (const auto& i : this->interfaces) { 3572 i.second->exportMechanicalData(os, h, this->mb); 3573 } 3574 } 3575 writeBehaviourDataPublicMembers(std::ostream & os) const3576 void BehaviourDSLCommon::writeBehaviourDataPublicMembers(std::ostream& os) const { 3577 this->checkBehaviourDataFile(os); 3578 if (this->mb.getAttribute(BehaviourDescription::requiresStiffnessTensor, false)) { 3579 os << "StiffnessTensor& getStiffnessTensor()\n" 3580 << "{\nreturn this->D;\n}\n\n" 3581 << "const StiffnessTensor& getStiffnessTensor() const\n" 3582 << "{\nreturn this->D;\n}\n\n"; 3583 } 3584 if (this->mb.getAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor, false)) { 3585 os << "ThermalExpansionCoefficientTensor& " 3586 << "getThermalExpansionCoefficientTensor()\n" 3587 << "{\nreturn this->A;\n}\n\n" 3588 << "const ThermalExpansionCoefficientTensor& " 3589 << "getThermalExpansionCoefficientTensor() const\n" 3590 << "{\nreturn this->A;\n}\n\n"; 3591 } 3592 } // end of BehaviourDSLCommon::writeBehaviourDataPublicMembers 3593 writeBehaviourDataClassHeader(std::ostream & os) const3594 void BehaviourDSLCommon::writeBehaviourDataClassHeader(std::ostream& os) const { 3595 this->checkBehaviourDataFile(os); 3596 os << "/*!\n" 3597 << "* \\class " << this->mb.getClassName() << "BehaviourData\n" 3598 << "* \\brief This class implements the " << this->mb.getClassName() << "BehaviourData" 3599 << " .\n" 3600 << "* \\param H, modelling hypothesis.\n" 3601 << "* \\param typename Type, numerical type.\n" 3602 << "* \\param bool use_qt, conditional saying if quantities are use.\n"; 3603 if (!this->fd.authorName.empty()) { 3604 os << "* \\author " << this->fd.authorName << '\n'; 3605 } 3606 if (!this->fd.date.empty()) { 3607 os << "* \\date " << this->fd.date << '\n'; 3608 } 3609 os << "*/\n"; 3610 } 3611 writeBehaviourDataForwardDeclarations(std::ostream & os) const3612 void BehaviourDSLCommon::writeBehaviourDataForwardDeclarations(std::ostream& os) const { 3613 this->checkBehaviourDataFile(os); 3614 os << "//! \\brief forward declaration\n" 3615 << "template<ModellingHypothesis::Hypothesis hypothesis,typename,bool>\n" 3616 << "class " << this->mb.getClassName() << "BehaviourData;\n\n" 3617 << "//! \\brief forward declaration\n" 3618 << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n" 3619 << "class " << this->mb.getClassName() << "IntegrationData;\n\n"; 3620 if (this->mb.useQt()) { 3621 os << "//! \\brief forward declaration\n"; 3622 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n"; 3623 os << "std::ostream&\n operator <<(std::ostream&,"; 3624 os << "const " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,use_qt>&);\n\n"; 3625 } else { 3626 os << "//! \\brief forward declaration\n"; 3627 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n"; 3628 os << "std::ostream&\n operator <<(std::ostream&,"; 3629 os << "const " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,false>&);\n\n"; 3630 } 3631 // maintenant, il faut déclarer toutes les spécialisations partielles... 3632 for (const auto& h : this->mb.getModellingHypotheses()) { 3633 if (this->mb.hasSpecialisedMechanicalData(h)) { 3634 if (this->mb.useQt()) { 3635 os << "//! \\brief forward declaration\n" 3636 << "template<typename Type,bool use_qt>\n" 3637 << "std::ostream&\n operator <<(std::ostream&," 3638 << "const " << this->mb.getClassName() 3639 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 3640 << ",Type,use_qt>&);\n\n"; 3641 } else { 3642 os << "//! \\brief forward declaration\n" 3643 << "template<typename Type>\n" 3644 << "std::ostream&\n operator <<(std::ostream&," 3645 << "const " << this->mb.getClassName() 3646 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 3647 << ",Type,false>&);\n\n"; 3648 } 3649 } 3650 } 3651 } 3652 writeBehaviourDataClassBegin(std::ostream & os,const Hypothesis h) const3653 void BehaviourDSLCommon::writeBehaviourDataClassBegin(std::ostream& os, const Hypothesis h) const { 3654 this->checkBehaviourDataFile(os); 3655 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 3656 if (this->mb.useQt()) { 3657 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n"; 3658 os << "class " << this->mb.getClassName() << "BehaviourData\n"; 3659 } else { 3660 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n"; 3661 os << "class " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,false>\n"; 3662 } 3663 } else { 3664 if (this->mb.useQt()) { 3665 os << "template<typename Type,bool use_qt>\n"; 3666 os << "class " << this->mb.getClassName() 3667 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>\n"; 3668 } else { 3669 os << "template<typename Type>\n"; 3670 os << "class " << this->mb.getClassName() 3671 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>\n"; 3672 } 3673 } 3674 os << "{\n\n"; 3675 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 3676 os << "static " << constexpr_c << " ModellingHypothesis::Hypothesis hypothesis = " 3677 << "ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ";\n"; 3678 } 3679 os << "static " << constexpr_c << " unsigned short N = ModellingHypothesisToSpaceDimension<hypothesis>::value;\n" 3680 << "TFEL_STATIC_ASSERT(N==1||N==2||N==3);\n" 3681 << "TFEL_STATIC_ASSERT(tfel::typetraits::" 3682 << "IsFundamentalNumericType<Type>::cond);\n" 3683 << "TFEL_STATIC_ASSERT(tfel::typetraits::IsReal<Type>::cond);\n\n" 3684 << "friend std::ostream& operator<< <>(std::ostream&,const " << this->mb.getClassName() << "BehaviourData&);\n\n" 3685 << "/* integration data is declared friend to access" 3686 << " driving variables at the beginning of the time step */\n"; 3687 if (this->mb.useQt()) { 3688 os << "friend class " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,use_qt>;\n\n"; 3689 } else { 3690 os << "friend class " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>;\n\n"; 3691 } 3692 } 3693 writeBehaviourDataClassEnd(std::ostream & os) const3694 void BehaviourDSLCommon::writeBehaviourDataClassEnd(std::ostream& os) const { 3695 this->checkBehaviourDataFile(os); 3696 os << "}; // end of " << this->mb.getClassName() << "BehaviourData" 3697 << "class\n\n"; 3698 } 3699 writeBehaviourDataMaterialProperties(std::ostream & os,const Hypothesis h) const3700 void BehaviourDSLCommon::writeBehaviourDataMaterialProperties(std::ostream& os, const Hypothesis h) const { 3701 this->checkBehaviourDataFile(os); 3702 this->writeVariablesDeclarations(os, this->mb.getBehaviourData(h).getMaterialProperties(), "", "", 3703 this->fd.fileName, false); 3704 os << '\n'; 3705 } 3706 writeBehaviourDataStateVariables(std::ostream & os,const Hypothesis h) const3707 void BehaviourDSLCommon::writeBehaviourDataStateVariables(std::ostream& os, const Hypothesis h) const { 3708 this->checkBehaviourDataFile(os); 3709 const auto& d = this->mb.getBehaviourData(h); 3710 this->writeVariablesDeclarations(os, d.getStateVariables(), "", "", this->fd.fileName, false); 3711 this->writeVariablesDeclarations(os, d.getAuxiliaryStateVariables(), "", "", this->fd.fileName, false); 3712 this->writeVariablesDeclarations(os, d.getExternalStateVariables(), "", "", this->fd.fileName, false); 3713 os << '\n'; 3714 } 3715 writeBehaviourDataOutputOperator(std::ostream & os,const Hypothesis h) const3716 void BehaviourDSLCommon::writeBehaviourDataOutputOperator(std::ostream& os, const Hypothesis h) const { 3717 this->checkBehaviourFile(os); 3718 const auto& d = this->mb.getBehaviourData(h); 3719 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 3720 if (this->mb.useQt()) { 3721 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n"; 3722 os << "std::ostream&\n"; 3723 os << "operator <<(std::ostream& os,"; 3724 os << "const " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,use_qt>& b)\n"; 3725 } else { 3726 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n"; 3727 os << "std::ostream&\n"; 3728 os << "operator <<(std::ostream& os,"; 3729 os << "const " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,false>& b)\n"; 3730 } 3731 } else { 3732 if (this->mb.useQt()) { 3733 os << "template<typename Type,bool use_qt>\n"; 3734 os << "std::ostream&\n"; 3735 os << "operator <<(std::ostream& os,"; 3736 os << "const " << this->mb.getClassName() 3737 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 3738 << ",Type,use_qt>& b)\n"; 3739 } else { 3740 os << "template<typename Type>\n"; 3741 os << "std::ostream&\n"; 3742 os << "operator <<(std::ostream& os,"; 3743 os << "const " << this->mb.getClassName() 3744 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 3745 << ",Type,false>& b)\n"; 3746 } 3747 } 3748 os << "{\n"; 3749 for (const auto& v : this->mb.getMainVariables()) { 3750 if (Gradient::isIncrementKnown(v.first)) { 3751 os << "os << \"" << displayName(v.first) << " : \" << b." 3752 << v.first.name << " << '\\n';\n"; 3753 } else { 3754 if (getUnicodeOutputOption()) { 3755 os << "os << \"" << displayName(v.first) << "\u2080 : \" << b." 3756 << v.first.name << "0 << '\\n';\n"; 3757 } else { 3758 os << "os << \"" << displayName(v.first) << "0 : \" << b." 3759 << v.first.name << "0 << '\\n';\n"; 3760 } 3761 } 3762 os << "os << \"" << displayName(v.second) << " : \" << b." 3763 << v.second.name << " << '\\n';\n"; 3764 } 3765 for (const auto& v : d.getMaterialProperties()) { 3766 os << "os << \"" << displayName(v) << " : \" << b." << v.name << " << '\\n';\n"; 3767 } 3768 for (const auto& v : d.getStateVariables()) { 3769 os << "os << \"" << displayName(v) << " : \" << b." << v.name << " << '\\n';\n"; 3770 } 3771 for (const auto& v : d.getAuxiliaryStateVariables()) { 3772 os << "os << \"" << displayName(v) << " : \" << b." << v.name << " << '\\n';\n"; 3773 } 3774 for (const auto& v : d.getExternalStateVariables()) { 3775 os << "os << \"" << displayName(v) << " : \" << b." << v.name << " << '\\n';\n"; 3776 } 3777 os << "return os;\n" 3778 << "}\n\n"; 3779 } // BehaviourDSLCommon::writeBehaviourDataOutputOperator 3780 writeBehaviourDataFileBegin(std::ostream & os) const3781 void BehaviourDSLCommon::writeBehaviourDataFileBegin(std::ostream& os) const { 3782 this->checkBehaviourDataFile(os); 3783 this->writeBehaviourDataFileHeader(os); 3784 this->writeBehaviourDataFileHeaderBegin(os); 3785 this->writeBehaviourDataStandardTFELIncludes(os); 3786 this->writeIncludes(os); 3787 // includes specific to interfaces 3788 for (const auto& i : this->interfaces) { 3789 i.second->writeInterfaceSpecificIncludes(os, this->mb); 3790 } 3791 this->writeNamespaceBegin(os); 3792 this->writeBehaviourDataForwardDeclarations(os); 3793 } // end of BehaviourDSLCommon::writeBehaviourDataFile 3794 writeBehaviourDataClass(std::ostream & os,const Hypothesis h) const3795 void BehaviourDSLCommon::writeBehaviourDataClass(std::ostream& os, const Hypothesis h) const { 3796 this->checkBehaviourDataFile(os); 3797 this->writeBehaviourDataClassBegin(os, h); 3798 this->writeBehaviourDataStandardTFELTypedefs(os); 3799 os << "protected:\n\n"; 3800 this->writeBehaviourDataDefaultMembers(os); 3801 this->writeBehaviourDataMaterialProperties(os, h); 3802 this->writeBehaviourDataStateVariables(os, h); 3803 os << "public:\n\n"; 3804 this->writeBehaviourDataDisabledConstructors(os); 3805 this->writeBehaviourDataConstructors(os, h); 3806 this->writeBehaviourDataMainVariablesSetters(os); 3807 this->writeBehaviourDataPublicMembers(os); 3808 this->writeBehaviourDataAssignementOperator(os, h); 3809 this->writeBehaviourDataExport(os, h); 3810 this->writeBehaviourDataClassEnd(os); 3811 this->writeBehaviourDataOutputOperator(os, h); 3812 } 3813 writeBehaviourDataFileEnd(std::ostream & os) const3814 void BehaviourDSLCommon::writeBehaviourDataFileEnd(std::ostream& os) const { 3815 this->writeNamespaceEnd(os); 3816 this->writeBehaviourDataFileHeaderEnd(os); 3817 } // end of BehaviourDSLCommon::writeBehaviourDataFileEnd 3818 checkBehaviourFile(std::ostream & os) const3819 void BehaviourDSLCommon::checkBehaviourFile(std::ostream& os) const { 3820 if ((!os) || (!os.good())) { 3821 this->throwRuntimeError("BehaviourDSLCommon::checkBehaviourDataOutputFile", "output file is not valid"); 3822 } 3823 } 3824 writeBehaviourForwardDeclarations(std::ostream & os) const3825 void BehaviourDSLCommon::writeBehaviourForwardDeclarations(std::ostream& os) const { 3826 this->checkBehaviourFile(os); 3827 os << "//! \\brief forward declaration\n" 3828 << "template<ModellingHypothesis::Hypothesis,typename Type,bool use_qt>\n" 3829 << "class " << this->mb.getClassName() << ";\n\n"; 3830 if (this->mb.useQt()) { 3831 os << "//! \\brief forward declaration\n" 3832 << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n" 3833 << "std::ostream&\n operator <<(std::ostream&," 3834 << "const " << this->mb.getClassName() << "<hypothesis,Type,use_qt>&);\n\n"; 3835 } else { 3836 os << "//! \\brief forward declaration\n" 3837 << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n" 3838 << "std::ostream&\n operator <<(std::ostream&," 3839 << "const " << this->mb.getClassName() << "<hypothesis,Type,false>&);\n\n"; 3840 } 3841 // maintenant, il faut déclarer toutes les spécialisations partielles... 3842 const auto& mh = this->mb.getModellingHypotheses(); 3843 for (const auto& h : mh) { 3844 if (this->mb.hasSpecialisedMechanicalData(h)) { 3845 if (this->mb.useQt()) { 3846 os << "//! \\brief forward declaration\n" 3847 << "template<typename Type,bool use_qt>\n" 3848 << "std::ostream&\n operator <<(std::ostream&," 3849 << "const " << this->mb.getClassName() 3850 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>&);\n\n"; 3851 } else { 3852 os << "//! \\brief forward declaration\n" 3853 << "template<typename Type>\n" 3854 << "std::ostream&\n operator <<(std::ostream&," 3855 << "const " << this->mb.getClassName() 3856 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>&);\n\n"; 3857 } 3858 } 3859 } 3860 } // end of BehaviourDSLCommon::writeBehaviourClassForwardDeclarations 3861 writeBehaviourClassBegin(std::ostream & os,const Hypothesis h) const3862 void BehaviourDSLCommon::writeBehaviourClassBegin(std::ostream& os, const Hypothesis h) const { 3863 this->checkBehaviourFile(os); 3864 os << "/*!\n"; 3865 os << "* \\class " << this->mb.getClassName() << '\n'; 3866 os << "* \\brief This class implements the " << this->mb.getClassName() << " behaviour.\n"; 3867 os << "* \\param hypothesis, modelling hypothesis.\n"; 3868 os << "* \\param Type, numerical type.\n"; 3869 if (this->mb.useQt()) { 3870 os << "* \\param use_qt, conditional " 3871 << "saying if quantities are use.\n"; 3872 } 3873 if (!this->fd.authorName.empty()) { 3874 os << "* \\author " << this->fd.authorName << '\n'; 3875 } 3876 if (!this->fd.date.empty()) { 3877 os << "* \\date " << this->fd.date << '\n'; 3878 } 3879 if (!this->fd.description.empty()) { 3880 os << this->fd.description << '\n'; 3881 } 3882 os << "*/\n"; 3883 const auto btype = this->mb.getBehaviourTypeFlag(); 3884 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 3885 if (this->mb.useQt()) { 3886 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n"; 3887 os << "class " << this->mb.getClassName() << " final\n"; 3888 os << ": public MechanicalBehaviour<" << btype << ",hypothesis,Type,use_qt>,\n"; 3889 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 3890 os << "public " << this->mb.getClassName() << "Profiler,\n"; 3891 } 3892 os << "public " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,use_qt>,\n"; 3893 os << "public " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,use_qt>"; 3894 this->writeBehaviourParserSpecificInheritanceRelationship(os); 3895 } else { 3896 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n"; 3897 os << "class " << this->mb.getClassName() << "<hypothesis,Type,false> final\n"; 3898 os << ": public MechanicalBehaviour<" << btype << ",hypothesis,Type,false>,\n"; 3899 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 3900 os << "public " << this->mb.getClassName() << "Profiler,\n"; 3901 } 3902 os << "public " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,false>,\n"; 3903 os << "public " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>"; 3904 this->writeBehaviourParserSpecificInheritanceRelationship(os); 3905 } 3906 } else { 3907 if (this->mb.useQt()) { 3908 os << "template<typename Type,bool use_qt>\n"; 3909 os << "class " << this->mb.getClassName() 3910 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt> final\n"; 3911 os << ": public MechanicalBehaviour<" << btype 3912 << ",ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>,\n"; 3913 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 3914 os << "public " << this->mb.getClassName() << "Profiler,\n"; 3915 } 3916 os << "public " << this->mb.getClassName() 3917 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>,\n"; 3918 os << "public " << this->mb.getClassName() 3919 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>"; 3920 this->writeBehaviourParserSpecificInheritanceRelationship(os); 3921 } else { 3922 os << "template<typename Type>\n"; 3923 os << "class " << this->mb.getClassName() 3924 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false> final\n"; 3925 os << ": public MechanicalBehaviour<" << btype 3926 << ",ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>,\n"; 3927 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 3928 os << "public " << this->mb.getClassName() << "Profiler,\n"; 3929 } 3930 os << "public " << this->mb.getClassName() 3931 << "BehaviourData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>,\n"; 3932 os << "public " << this->mb.getClassName() 3933 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>"; 3934 } 3935 } 3936 os << "{\n\n"; 3937 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 3938 os << "static " << constexpr_c << " ModellingHypothesis::Hypothesis hypothesis = " 3939 << "ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ";\n"; 3940 } 3941 os << "static " << constexpr_c << " unsigned short N = ModellingHypothesisToSpaceDimension<hypothesis>::value;\n\n"; 3942 os << "TFEL_STATIC_ASSERT(N==1||N==2||N==3);\n"; 3943 os << "TFEL_STATIC_ASSERT(tfel::typetraits::" 3944 << "IsFundamentalNumericType<Type>::cond);\n"; 3945 os << "TFEL_STATIC_ASSERT(tfel::typetraits::IsReal<Type>::cond);\n\n"; 3946 os << "friend std::ostream& operator<< <>(std::ostream&,const "; 3947 os << this->mb.getClassName() << "&);\n\n"; 3948 } 3949 writeBehaviourFileHeader(std::ostream & os) const3950 void BehaviourDSLCommon::writeBehaviourFileHeader(std::ostream& os) const { 3951 this->checkBehaviourFile(os); 3952 os << "/*!\n" 3953 << "* \\file " << this->getBehaviourFileName() << '\n' 3954 << "* \\brief " 3955 << "this file implements the " << this->mb.getClassName() << " Behaviour.\n" 3956 << "* File generated by " << MFrontHeader::getVersionName() << " " 3957 << "version " << MFrontHeader::getVersionNumber() << '\n'; 3958 if (!this->fd.authorName.empty()) { 3959 os << "* \\author " << this->fd.authorName << '\n'; 3960 } 3961 if (!this->fd.date.empty()) { 3962 os << "* \\date " << this->fd.date << '\n'; 3963 } 3964 os << " */\n\n"; 3965 } 3966 writeBehaviourFileHeaderBegin(std::ostream & os) const3967 void BehaviourDSLCommon::writeBehaviourFileHeaderBegin(std::ostream& os) const { 3968 this->checkBehaviourFile(os); 3969 os << "#ifndef LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_HXX\n" 3970 << "#define LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_HXX\n\n"; 3971 } 3972 writeBehaviourFileHeaderEnd(std::ostream & os) const3973 void BehaviourDSLCommon::writeBehaviourFileHeaderEnd(std::ostream& os) const { 3974 this->checkBehaviourFile(os); 3975 os << "#endif /* LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_HXX */\n"; 3976 } 3977 writeBehaviourClassEnd(std::ostream & os) const3978 void BehaviourDSLCommon::writeBehaviourClassEnd(std::ostream& os) const { 3979 this->checkBehaviourFile(os); 3980 os << "}; // end of " << this->mb.getClassName() << " class\n\n"; 3981 } 3982 treatUpdateAuxiliaryStateVariables()3983 void BehaviourDSLCommon::treatUpdateAuxiliaryStateVariables() { 3984 this->readCodeBlock(*this, BehaviourData::UpdateAuxiliaryStateVariables, &BehaviourDSLCommon::standardModifier, 3985 true, true); 3986 } // end of BehaviourDSLCommon::treatUpdateAuxiliaryStateVarBase 3987 treatComputeStressFreeExpansion()3988 void BehaviourDSLCommon::treatComputeStressFreeExpansion() { 3989 this->readCodeBlock(*this, BehaviourData::ComputeStressFreeExpansion, &BehaviourDSLCommon::standardModifier, true, 3990 true); 3991 } // end of BehaviourDSLCommon::treatComputeStressFreeExpansion 3992 treatSwelling()3993 void BehaviourDSLCommon::treatSwelling() { 3994 using VolumeSwelling = BehaviourData::VolumeSwellingStressFreeExpansion; 3995 using IsotropicSwelling = BehaviourData::IsotropicStressFreeExpansion; 3996 using OrthotropicSwelling = BehaviourData::OrthotropicStressFreeExpansion; 3997 using OrthotropicSwellingII = BehaviourData::OrthotropicStressFreeExpansionII; 3998 auto throw_if = [this](const bool b, const std::string& m) { 3999 if (b) { 4000 this->throwRuntimeError("BehaviourDSLCommon::treatSwelling", m); 4001 } 4002 }; 4003 enum { VOLUME, LINEAR, ORTHOTROPIC, UNDEFINED } etype = UNDEFINED; 4004 const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 4005 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 4006 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 4007 "the @Swelling keyword is only valid for small or " 4008 "finite strain behaviours"); 4009 this->checkNotEndOfFile("BehaviourDSLCommon::treatSwelling"); 4010 if (this->current->value == "<") { 4011 auto options = std::vector<tfel::utilities::Token>{}; 4012 this->readList(options, "BehaviourDSLCommon::treatSwelling", "<", ">", true); 4013 for (const auto& o : options) { 4014 this->checkNotEndOfFile("BehaviourDSLCommon::treatSwelling"); 4015 if (o.value == "Orthotropic") { 4016 throw_if(etype != UNDEFINED, 4017 "error while treating option " 4018 "'Orthotropic', swelling type already defined"); 4019 etype = ORTHOTROPIC; 4020 } else if (o.value == "Volume") { 4021 throw_if(etype != UNDEFINED, 4022 "error while treating option " 4023 "'Volume', swelling type already defined"); 4024 etype = VOLUME; 4025 } else if (o.value == "Linear") { 4026 throw_if(etype != UNDEFINED, 4027 "error while treating option " 4028 "'Linear', swelling type already defined"); 4029 etype = LINEAR; 4030 } else { 4031 throw_if(true, "unsupported option '" + o.value + "'"); 4032 } 4033 } 4034 } 4035 throw_if(etype == UNDEFINED, 4036 "the user must explicitly state if " 4037 "what kind of swelling is expected using" 4038 "one of the options 'Linear', 'Volume' or 'Orthotropic'"); 4039 const auto sd = this->readStressFreeExpansionHandler(); 4040 this->readSpecifiedToken("BehaviourDSLCommon::treatSwelling", ";"); 4041 if (sd.size() == 1) { 4042 throw_if(sd[0].is<BehaviourData::NullExpansion>(), "a null swelling is not allowed here"); 4043 if (etype == VOLUME) { 4044 VolumeSwelling vs = {sd[0]}; 4045 this->mb.addStressFreeExpansion(uh, vs); 4046 } else if (etype == LINEAR) { 4047 IsotropicSwelling is = {sd[0]}; 4048 this->mb.addStressFreeExpansion(uh, is); 4049 } else if (etype == ORTHOTROPIC) { 4050 throw_if(!sd[0].is<BehaviourData::SFED_ESV>(), "one expects a external state variable name here"); 4051 OrthotropicSwellingII os = {sd[0].get<BehaviourData::SFED_ESV>()}; 4052 this->mb.addStressFreeExpansion(uh, os); 4053 } else { 4054 throw_if(true, "internal error"); 4055 } 4056 } else if (sd.size() == 3) { 4057 throw_if(etype != ORTHOTROPIC, 4058 "the 'Orthotropic' option must be " 4059 "used for an orthotropic swelling"); 4060 throw_if(sd[0].is<BehaviourData::NullExpansion>() && sd[1].is<BehaviourData::NullExpansion>() && 4061 sd[2].is<BehaviourData::NullExpansion>(), 4062 "all swelling component are null"); 4063 OrthotropicSwelling os = {sd[0], sd[1], sd[2]}; 4064 this->mb.addStressFreeExpansion(uh, os); 4065 } else { 4066 throw_if(true, "invalid number of swelling handler (shall be 1 or 3, " + std::to_string(sd.size()) + " given)"); 4067 } 4068 } // end of BehaviourDSLCommon::treatSwelling 4069 readStressFreeExpansionHandler(const tfel::utilities::Token & t)4070 BehaviourData::StressFreeExpansionHandler BehaviourDSLCommon::readStressFreeExpansionHandler( 4071 const tfel::utilities::Token& t) { 4072 auto throw_if = [this](const bool b, const std::string& m) { 4073 if (b) { 4074 this->throwRuntimeError("BehaviourDSLCommon::readStressFreeExpansionHandler", m); 4075 } 4076 }; 4077 if (t.flag == tfel::utilities::Token::String) { 4078 // using an external model 4079 const auto md = this->getModelDescription(t.value.substr(1, t.value.size() - 2)); 4080 // check that the variable 4081 auto ptr = std::make_shared<ModelDescription>(md); 4082 return {ptr}; 4083 } 4084 if (t.value == "0") { 4085 return {BehaviourData::NullExpansion{}}; 4086 } 4087 throw_if(!CxxTokenizer::isValidIdentifier(t.value, true), "unexpected token '" + t.value + 4088 "', expected " 4089 "external state variable name"); 4090 // using an external state variable 4091 // defining modelling hypotheses 4092 if (!this->mb.areModellingHypothesesDefined()) { 4093 this->mb.setModellingHypotheses(this->getDefaultModellingHypotheses()); 4094 } 4095 for (const auto h : this->mb.getDistinctModellingHypotheses()) { 4096 throw_if(!this->mb.isExternalStateVariableName(h, t.value), "no external state variable named '" + t.value + 4097 "' " 4098 "has been declared"); 4099 } 4100 return {BehaviourData::SFED_ESV{t.value}}; 4101 } // end of BehaviourDSLCommon::readStressFreeExpansionHandler 4102 readStressFreeExpansionHandler()4103 std::vector<BehaviourData::StressFreeExpansionHandler> BehaviourDSLCommon::readStressFreeExpansionHandler() { 4104 auto throw_if = [this](const bool b, const std::string& m) { 4105 if (b) { 4106 this->throwRuntimeError("BehaviourDSLCommon::readStressFreeExpansionHandler", m); 4107 } 4108 }; 4109 auto sda = std::vector<tfel::utilities::Token>{}; 4110 auto sd = std::vector<BehaviourData::StressFreeExpansionHandler>{}; 4111 this->checkNotEndOfFile("BehaviourDSLCommon::treatSwelling"); 4112 if (this->current->value == "{") { 4113 this->readList(sda, "BehaviourDSLCommon::readCodeBlockOptions", "{", "}", true); 4114 } else { 4115 sda.push_back(*(this->current)); 4116 ++(this->current); 4117 } 4118 if (sda.size() == 1u) { 4119 sd.push_back(this->readStressFreeExpansionHandler(sda[0])); 4120 } else if (sda.size() == 3u) { 4121 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, 4122 "orthotropic swelling is only supported for " 4123 "orthotropic behaviours"); 4124 sd.push_back(this->readStressFreeExpansionHandler(sda[0])); 4125 sd.push_back(this->readStressFreeExpansionHandler(sda[1])); 4126 sd.push_back(this->readStressFreeExpansionHandler(sda[2])); 4127 } else { 4128 throw_if(true, 4129 "invalid number of swelling description " 4130 "(expected one or three descriptions)"); 4131 } 4132 return sd; 4133 } // end of BehaviourDSLCommon::readStressFreeExpansionHandler 4134 treatAxialGrowth()4135 void BehaviourDSLCommon::treatAxialGrowth() { 4136 using AxialGrowth = BehaviourData::AxialGrowth; 4137 const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 4138 auto throw_if = [this](const bool b, const std::string& m) { 4139 if (b) { 4140 this->throwRuntimeError("BehaviourDSLCommon::treatAxialGrowth", m); 4141 } 4142 }; 4143 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 4144 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 4145 "the @AxialGrowth keyword is only valid for small or " 4146 "finite strain behaviours"); 4147 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, "@AxialGrowth is only valid for orthotropic behaviour"); 4148 this->checkNotEndOfFile("BehaviourDSLCommon::treatAxialGrowth"); 4149 auto s = this->readStressFreeExpansionHandler(*(this->current)); 4150 ++(this->current); 4151 this->readSpecifiedToken("BehaviourDSLCommon::treatAxialGrowth", ";"); 4152 this->mb.addStressFreeExpansion(uh, AxialGrowth{s}); 4153 } // end of BehaviourDSLCommon::treatAxialGrowth 4154 treatRelocation()4155 void BehaviourDSLCommon::treatRelocation() { 4156 using Relocation = BehaviourData::Relocation; 4157 auto throw_if = [this](const bool b, const std::string& m) { 4158 if (b) { 4159 this->throwRuntimeError("BehaviourDSLCommon::treatRelocation", m); 4160 } 4161 }; 4162 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 4163 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 4164 "the @Relocation keyword is only valid for small or " 4165 "finite strain behaviours"); 4166 if (!this->mb.areModellingHypothesesDefined()) { 4167 this->mb.setModellingHypotheses(this->getDefaultModellingHypotheses()); 4168 } 4169 const auto& mh = this->mb.getModellingHypotheses(); 4170 throw_if((mh.find(ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) == mh.end()) && 4171 (mh.find(ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRAIN) == mh.end()) && 4172 (mh.find(ModellingHypothesis::GENERALISEDPLANESTRAIN) == mh.end()), 4173 "the @Relocation keyword has not effect on this behaviour as the none of " 4174 "the following hypothesis is supported:\n" 4175 "- AxisymmetricalGeneralisedPlaneStress\n" 4176 "- AxisymmetricalGeneralisedPlaneStrain\n" 4177 "- GeneralisedPlaneStrain"); 4178 this->checkNotEndOfFile("BehaviourDSLCommon::treatRelocation"); 4179 const auto s = this->readStressFreeExpansionHandler(*(this->current)); 4180 ++(this->current); 4181 this->readSpecifiedToken("BehaviourDSLCommon::treatRelocation", ";"); 4182 auto add = [this, &mh, &s](const Hypothesis h) { 4183 if (mh.find(h) != mh.end()) { 4184 this->mb.addStressFreeExpansion(h, Relocation{s}); 4185 } 4186 }; 4187 add(ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS); 4188 add(ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRAIN); 4189 add(ModellingHypothesis::GENERALISEDPLANESTRAIN); 4190 } // end of BehaviourDSLCommon::treatRelocation 4191 writeBehaviourUpdateIntegrationVariables(std::ostream & os,const Hypothesis h) const4192 void BehaviourDSLCommon::writeBehaviourUpdateIntegrationVariables(std::ostream& os, const Hypothesis h) const { 4193 const auto& d = this->mb.getBehaviourData(h); 4194 this->checkBehaviourFile(os); 4195 os << "/*!\n" 4196 << "* \\brief Update internal variables at end of integration\n" 4197 << "*/\n" 4198 << "void updateIntegrationVariables()"; 4199 if (!d.getIntegrationVariables().empty()) { 4200 os << "{\n"; 4201 for (const auto& v : d.getIntegrationVariables()) { 4202 if (!d.isStateVariableName(v.name)) { 4203 if (d.isMemberUsedInCodeBlocks(v.name)) { 4204 os << "this->" << v.name << " += " 4205 << "this->d" << v.name << ";\n"; 4206 } 4207 } 4208 } 4209 os << "}\n\n"; 4210 } else { 4211 os << "\n{}\n\n"; 4212 } 4213 } // end of BehaviourDSLCommon::writeBehaviourUpdateIntegrationVariables 4214 writeBehaviourUpdateStateVariables(std::ostream & os,const Hypothesis h) const4215 void BehaviourDSLCommon::writeBehaviourUpdateStateVariables(std::ostream& os, const Hypothesis h) const { 4216 const auto& d = this->mb.getBehaviourData(h); 4217 this->checkBehaviourFile(os); 4218 os << "/*!\n" 4219 << "* \\brief Update internal variables at end of integration\n" 4220 << "*/\n" 4221 << "void updateStateVariables()"; 4222 if (!d.getStateVariables().empty()) { 4223 os << "{\n"; 4224 for (const auto& v : d.getStateVariables()) { 4225 os << "this->" << v.name << " += " 4226 << "this->d" << v.name << ";\n"; 4227 } 4228 os << "}\n\n"; 4229 } else { 4230 os << "\n{}\n\n"; 4231 } 4232 } // end of BehaviourDSLCommon::writeBehaviourUpdateStateVariables 4233 writeBehaviourUpdateAuxiliaryStateVariables(std::ostream & os,const Hypothesis h) const4234 void BehaviourDSLCommon::writeBehaviourUpdateAuxiliaryStateVariables(std::ostream& os, const Hypothesis h) const { 4235 os << "/*!\n" 4236 << "* \\brief Update auxiliary state variables at end of integration\n" 4237 << "*/\n" 4238 << "void updateAuxiliaryStateVariables()"; 4239 const auto& em = this->mb.getModelsDescriptions(); 4240 if ((this->mb.hasCode(h, BehaviourData::UpdateAuxiliaryStateVariables)) || (!em.empty())) { 4241 os << "{\n" 4242 << "using namespace std;\n" 4243 << "using namespace tfel::math;\n"; 4244 for (const auto& m : em) { 4245 if (m.outputs.size() == 1) { 4246 const auto vn = m.outputs[0].name; 4247 os << "this->" << vn << " += this->d" << vn << ";\n"; 4248 } else { 4249 this->throwRuntimeError("BehaviourDSLCommon::writeBehaviourUpdateAuxiliaryStateVariables", 4250 "only models with one output are supported"); 4251 } 4252 } 4253 if (this->mb.hasCode(h, BehaviourData::UpdateAuxiliaryStateVariables)) { 4254 writeMaterialLaws(os, this->mb.getMaterialLaws()); 4255 os << this->mb.getCode(h, BehaviourData::UpdateAuxiliaryStateVariables) << "\n"; 4256 } 4257 os << "}\n\n"; 4258 } else { 4259 os << "\n{}\n\n"; 4260 } 4261 } // end of BehaviourDSLCommon::writeBehaviourUpdateAuxiliaryStateVariables 4262 writeBehaviourComputeInternalEnergy(std::ostream & os,const Hypothesis h) const4263 void BehaviourDSLCommon::writeBehaviourComputeInternalEnergy(std::ostream& os, const Hypothesis h) const { 4264 os << "/*!\n" 4265 << "* \\brief Update the internal energy at end of the time step\n" 4266 << "* \\param[in] Psi_s: internal energy at end of the time step\n" 4267 << "*/\n" 4268 << "void computeInternalEnergy(real& Psi_s) const"; 4269 if (this->mb.hasCode(h, BehaviourData::ComputeInternalEnergy)) { 4270 os << "{\n" 4271 << "using namespace std;\n" 4272 << "using namespace tfel::math;\n"; 4273 writeMaterialLaws(os, this->mb.getMaterialLaws()); 4274 os << this->mb.getCode(h, BehaviourData::ComputeInternalEnergy) << "\n}\n\n"; 4275 } else { 4276 os << "\n{\nPsi_s=0;\n}\n\n"; 4277 } 4278 } // end of BehaviourDSLCommon::writeBehaviourComputeInternalEnergy 4279 writeBehaviourComputeDissipatedEnergy(std::ostream & os,const Hypothesis h) const4280 void BehaviourDSLCommon::writeBehaviourComputeDissipatedEnergy(std::ostream& os, const Hypothesis h) const { 4281 os << "/*!\n" 4282 << "* \\brief Update the dissipated energy at end of the time step\n" 4283 << "* \\param[in] Psi_d: dissipated energy at end of the time step\n" 4284 << "*/\n" 4285 << "void computeDissipatedEnergy(real& Psi_d) const"; 4286 if (this->mb.hasCode(h, BehaviourData::ComputeDissipatedEnergy)) { 4287 os << "{\n" 4288 << "using namespace std;\n" 4289 << "using namespace tfel::math;\n"; 4290 writeMaterialLaws(os, this->mb.getMaterialLaws()); 4291 os << this->mb.getCode(h, BehaviourData::ComputeDissipatedEnergy) << "\n}\n\n"; 4292 } else { 4293 os << "\n{\nPsi_d=0;\n}\n\n"; 4294 } 4295 } // end of BehaviourDSLCommon::writeBehaviourComputeDissipatedEnergy 4296 hasUserDefinedTangentOperatorCode(const Hypothesis h) const4297 bool BehaviourDSLCommon::hasUserDefinedTangentOperatorCode(const Hypothesis h) const { 4298 using tfel::material::getFiniteStrainBehaviourTangentOperatorFlags; 4299 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 4300 // all available tangent operators for finite strain behaviours 4301 const auto tos = getFiniteStrainBehaviourTangentOperatorFlags(); 4302 // search tangent operators defined by the user 4303 for (const auto& t : tos) { 4304 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 4305 if (this->mb.hasCode(h, std::string(BehaviourData::ComputeTangentOperator) + '-' + ktype)) { 4306 return true; 4307 } 4308 } 4309 } else { 4310 if (this->mb.hasCode(h, BehaviourData::ComputeTangentOperator)) { 4311 return true; 4312 } 4313 } 4314 return false; 4315 } // end of BehaviourDSLCommon::hasUserDefinedTangentOperatorCode 4316 writeBehaviourIntegrator(std::ostream & os,const Hypothesis h) const4317 void BehaviourDSLCommon::writeBehaviourIntegrator(std::ostream& os, const Hypothesis h) const { 4318 const auto btype = this->mb.getBehaviourTypeFlag(); 4319 this->checkBehaviourFile(os); 4320 os << "/*!\n" 4321 << "* \\brief Integrate behaviour over the time step\n" 4322 << "*/\n" 4323 << "IntegrationResult\n" 4324 << "integrate(const SMFlag smflag, const SMType smt) override{\n" 4325 << "using namespace std;\n" 4326 << "using namespace tfel::math;\n"; 4327 writeMaterialLaws(os, this->mb.getMaterialLaws()); 4328 if ((this->mb.getBehaviourType() == BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) || 4329 (this->mb.getBehaviourType() == BehaviourDescription::COHESIVEZONEMODEL)|| 4330 (this->mb.getBehaviourType() == BehaviourDescription::GENERALBEHAVIOUR)) { 4331 if (this->mb.useQt()) { 4332 os << "raise_if(smflag!=MechanicalBehaviour<" << btype << ",hypothesis,Type,use_qt>::STANDARDTANGENTOPERATOR,\n" 4333 << "\"invalid tangent operator flag\");\n"; 4334 } else { 4335 os << "raise_if(smflag!=MechanicalBehaviour<" << btype << ",hypothesis,Type,false>::STANDARDTANGENTOPERATOR,\n" 4336 << "\"invalid tangent operator flag\");\n"; 4337 } 4338 } 4339 os << "bool computeTangentOperator_ = smt!=NOSTIFFNESSREQUESTED;\n"; 4340 if (this->mb.hasCode(h, BehaviourData::ComputePredictor)) { 4341 os << this->mb.getCode(h, BehaviourData::ComputePredictor) << '\n'; 4342 } 4343 if (this->mb.hasCode(h, BehaviourData::Integrator)) { 4344 os << this->mb.getCode(h, BehaviourData::Integrator) << '\n'; 4345 } 4346 os << "this->updateIntegrationVariables();\n" 4347 << "this->updateStateVariables();\n" 4348 << "this->updateAuxiliaryStateVariables();\n"; 4349 for (const auto& v : this->mb.getBehaviourData(h).getPersistentVariables()) { 4350 this->writePhysicalBoundsChecks(os, v, false); 4351 } 4352 for (const auto& v : this->mb.getBehaviourData(h).getPersistentVariables()) { 4353 this->writeBoundsChecks(os, v, false); 4354 } 4355 if (this->hasUserDefinedTangentOperatorCode(h)) { 4356 os << "if(computeTangentOperator_){\n"; 4357 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 4358 os << "if(!this->computeConsistentTangentOperator(smflag,smt)){\n"; 4359 } else { 4360 os << "if(!this->computeConsistentTangentOperator(smt)){\n"; 4361 } 4362 if (this->mb.useQt()) { 4363 os << "return MechanicalBehaviour<" << btype << ",hypothesis,Type,use_qt>::FAILURE;\n"; 4364 } else { 4365 os << "return MechanicalBehaviour<" << btype << ",hypothesis,Type,false>::FAILURE;\n"; 4366 } 4367 os << "}\n"; 4368 os << "}\n"; 4369 } 4370 if (this->mb.useQt()) { 4371 os << "return MechanicalBehaviour<" << btype << ",hypothesis,Type,use_qt>::SUCCESS;\n"; 4372 } else { 4373 os << "return MechanicalBehaviour<" << btype << ",hypothesis,Type,false>::SUCCESS;\n"; 4374 } 4375 os << "}\n\n"; 4376 } 4377 writeBehaviourDisabledConstructors(std::ostream & os) const4378 void BehaviourDSLCommon::writeBehaviourDisabledConstructors(std::ostream& os) const { 4379 this->checkBehaviourFile(os); 4380 os << "//! \\brief Default constructor (disabled)\n" 4381 << this->mb.getClassName() << "() =delete ;\n" 4382 << "//! \\brief Copy constructor (disabled)\n" 4383 << this->mb.getClassName() << "(const " << this->mb.getClassName() << "&) = delete;\n" 4384 << "//! \\brief Assignement operator (disabled)\n" 4385 << this->mb.getClassName() << "& operator = (const " << this->mb.getClassName() << "&) = delete;\n\n"; 4386 } 4387 writeBehaviourSetOutOfBoundsPolicy(std::ostream & os) const4388 void BehaviourDSLCommon::writeBehaviourSetOutOfBoundsPolicy(std::ostream& os) const { 4389 this->checkBehaviourFile(os); 4390 os << "/*!\n" 4391 << "* \\brief set the policy for \"out of bounds\" conditions\n" 4392 << "*/\n" 4393 << "void\nsetOutOfBoundsPolicy(const OutOfBoundsPolicy policy_value){\n" 4394 << "this->policy = policy_value;\n" 4395 << "} // end of setOutOfBoundsPolicy\n\n"; 4396 } // end of BehaviourDSLCommon::writeBehaviourSetOutOfBoundsPolicy 4397 writeBoundsChecks(std::ostream & os,const VariableDescription & v,const std::string & n,const bool b)4398 static void writeBoundsChecks(std::ostream& os, const VariableDescription& v, const std::string& n, const bool b) { 4399 if (!v.hasBounds()) { 4400 return; 4401 } 4402 const auto& bounds = v.getBounds(); 4403 if (bounds.boundsType == VariableBoundsDescription::LOWER) { 4404 os << "BoundsCheck<N>::lowerBoundCheck(\"" << n << "\",this->" << n << "," 4405 << "static_cast<real>(" << bounds.lowerBound << "),this->policy);\n"; 4406 if (b) { 4407 os << "BoundsCheck<N>::lowerBoundCheck(\"" << n << "+d" << n << "\",this->" << n << "+this->d" << n << "," 4408 << "static_cast<real>(" << bounds.lowerBound << "),this->policy);\n"; 4409 } 4410 } else if (bounds.boundsType == VariableBoundsDescription::UPPER) { 4411 os << "BoundsCheck<N>::upperBoundCheck(\"" << n << "\",this->" << n << "," 4412 << "static_cast<real>(" << bounds.upperBound << "),this->policy);\n"; 4413 if (b) { 4414 os << "BoundsCheck<N>::upperBoundCheck(\"" << n << "+d" << n << "\",this->" << n << "+this->d" << n << "," 4415 << "static_cast<real>(" << bounds.upperBound << "),this->policy);\n"; 4416 } 4417 } else if (bounds.boundsType == VariableBoundsDescription::LOWERANDUPPER) { 4418 os << "BoundsCheck<N>::lowerAndUpperBoundsChecks(\"" << n << "\",this->" << n << "," 4419 << "static_cast<real>(" << bounds.lowerBound << ")," 4420 << "static_cast<real>(" << bounds.upperBound << "),this->policy);\n"; 4421 if (b) { 4422 os << "BoundsCheck<N>::lowerAndUpperBoundsChecks(\"" << n << "+d" << n << "\",this->" << n << "+this->d" << n 4423 << "," 4424 << "static_cast<real>(" << bounds.lowerBound << ")," 4425 << "static_cast<real>(" << bounds.upperBound << "),this->policy);\n"; 4426 } 4427 } else { 4428 tfel::raise( 4429 "BehaviourDSLCommon::writeBoundsChecks: " 4430 "internal error (unsupported bounds type)"); 4431 } 4432 } // end of writeBoundsChecks 4433 writeBoundsChecks(std::ostream & os,const VariableDescription & v,const bool b) const4434 void BehaviourDSLCommon::writeBoundsChecks(std::ostream& os, const VariableDescription& v, const bool b) const { 4435 if (v.arraySize == 1u) { 4436 mfront::writeBoundsChecks(os, v, v.name, b); 4437 } else { 4438 for (unsigned short i = 0; i != v.arraySize; ++i) { 4439 mfront::writeBoundsChecks(os, v, v.name + '[' + std::to_string(i) + ']', b); 4440 } 4441 } 4442 } // end of BehaviourDSLCommon::writeBoundsChecks 4443 writePhysicalBoundsChecks(std::ostream & os,const VariableDescription & v,const std::string & n,const bool b)4444 static void writePhysicalBoundsChecks(std::ostream& os, 4445 const VariableDescription& v, 4446 const std::string& n, 4447 const bool b) { 4448 if (!v.hasPhysicalBounds()) { 4449 return; 4450 } 4451 const auto& bounds = v.getPhysicalBounds(); 4452 if (bounds.boundsType == VariableBoundsDescription::LOWER) { 4453 os << "BoundsCheck<N>::lowerBoundCheck(\"" << n << "\",this->" << n << "," 4454 << "static_cast<real>(" << bounds.lowerBound << "));\n"; 4455 if (b) { 4456 os << "BoundsCheck<N>::lowerBoundCheck(\"" << n << "+d" << n << "\",this->" << n << "+this->d" << n << "," 4457 << "static_cast<real>(" << bounds.lowerBound << "));\n"; 4458 } 4459 } else if (bounds.boundsType == VariableBoundsDescription::UPPER) { 4460 os << "BoundsCheck<N>::upperBoundCheck(\"" << n << "\",this->" << n << "," 4461 << "static_cast<real>(" << bounds.upperBound << "));\n"; 4462 if (b) { 4463 os << "BoundsCheck<N>::upperBoundCheck(\"" << n << "+d" << n << "\",this->" << n << "+this->d" << n << "," 4464 << "static_cast<real>(" << bounds.upperBound << "));\n"; 4465 } 4466 } else if (bounds.boundsType == VariableBoundsDescription::LOWERANDUPPER) { 4467 os << "BoundsCheck<N>::lowerAndUpperBoundsChecks(\"" << n << "\",this->" << n << "," 4468 << "static_cast<real>(" << bounds.lowerBound << ")," 4469 << "static_cast<real>(" << bounds.upperBound << "));\n"; 4470 if (b) { 4471 os << "BoundsCheck<N>::lowerAndUpperBoundsChecks(\"" << n << "+d" << n << "\",this->" << n << "+this->d" << n 4472 << "," 4473 << "static_cast<real>(" << bounds.lowerBound << ")," 4474 << "static_cast<real>(" << bounds.upperBound << "));\n"; 4475 } 4476 } else { 4477 tfel::raise( 4478 "BehaviourDSLCommon::writePhysicalBoundsChecks: " 4479 "internal error (unsupported bounds type)"); 4480 } 4481 } // end of writePhysicalBoundsChecks 4482 writePhysicalBoundsChecks(std::ostream & os,const VariableDescription & v,const bool b) const4483 void BehaviourDSLCommon::writePhysicalBoundsChecks(std::ostream& os, 4484 const VariableDescription& v, 4485 const bool b) const { 4486 if (v.arraySize == 1u) { 4487 mfront::writePhysicalBoundsChecks(os, v, v.name, b); 4488 } else { 4489 for (unsigned short i = 0; i != v.arraySize; ++i) { 4490 mfront::writePhysicalBoundsChecks(os, v, v.name + '[' + std::to_string(i) + ']', b); 4491 } 4492 } 4493 } // end of BehaviourDSLCommon::writePhysicalBoundsChecks 4494 writeBehaviourCheckBounds(std::ostream & os,const Hypothesis h) const4495 void BehaviourDSLCommon::writeBehaviourCheckBounds(std::ostream& os, const Hypothesis h) const { 4496 auto write_physical_bounds = [this, &os](const VariableDescriptionContainer& c, const bool b) { 4497 for (const auto& v : c) { 4498 this->writePhysicalBoundsChecks(os, v, b); 4499 } 4500 }; 4501 auto write_bounds = [this, &os](const VariableDescriptionContainer& c, const bool b) { 4502 for (const auto& v : c) { 4503 this->writeBoundsChecks(os, v, b); 4504 } 4505 }; 4506 const auto& md = this->mb.getBehaviourData(h); 4507 this->checkBehaviourFile(os); 4508 os << "/*!\n" 4509 << "* \\brief check bounds\n" 4510 << "*/\n" 4511 << "void checkBounds() const{\n"; 4512 write_physical_bounds(md.getMaterialProperties(), false); 4513 write_physical_bounds(md.getPersistentVariables(), false); 4514 write_physical_bounds(md.getExternalStateVariables(), true); 4515 write_physical_bounds(md.getLocalVariables(), false); 4516 write_bounds(md.getMaterialProperties(), false); 4517 write_bounds(md.getPersistentVariables(), false); 4518 write_bounds(md.getExternalStateVariables(), true); 4519 write_bounds(md.getLocalVariables(), false); 4520 os << "} // end of checkBounds\n\n"; 4521 } // end of BehaviourDSLCommon::writeBehaviourCheckBounds 4522 getBehaviourConstructorsInitializers(const Hypothesis h) const4523 std::string BehaviourDSLCommon::getBehaviourConstructorsInitializers(const Hypothesis h) const { 4524 // variable initialisation 4525 auto init = std::string(); 4526 auto append = [&init](const std::string& s) { 4527 if (s.empty()) { 4528 return; 4529 } 4530 if (!init.empty()) { 4531 init += ",\n"; 4532 } 4533 init += s; 4534 }; 4535 append(this->getIntegrationVariablesIncrementsInitializers(h)); 4536 append(this->getLocalVariablesInitializers(h)); 4537 // tangent operator blocks 4538 const auto& blocks = this->mb.getTangentOperatorBlocks(); 4539 if (this->mb.hasTrivialTangentOperatorStructure()) { 4540 tfel::raise_if( 4541 ((blocks.size() != 1u) || (blocks.front().first.arraySize != 1u) || 4542 (blocks.front().second.arraySize != 1u)), 4543 "BehaviourDSLCommon::getBehaviourConstructorsInitializers: internal error"); 4544 if (this->mb.getBehaviourType() != 4545 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 4546 append(this->mb.getTangentOperatorBlockName(blocks.front()) + "(Dt)"); 4547 } 4548 } else { 4549 tfel::math::tvector<10, int> offset; 4550 tfel::fsalgo::fill<10>::exe(offset.begin(), 0); 4551 auto update_offset = [&offset](const SupportedTypes::TypeSize s1, 4552 const SupportedTypes::TypeSize s2) { 4553 offset[0] += s1.getScalarSize() * s2.getScalarSize(); 4554 offset[1] += s1.getTVectorSize() * s2.getTVectorSize(); 4555 offset[2] += s1.getStensorSize() * s2.getStensorSize(); 4556 offset[3] += s1.getTensorSize() * s2.getTensorSize(); 4557 offset[4] += s1.getScalarSize() * s2.getTVectorSize() + 4558 s2.getScalarSize() * s1.getTVectorSize(); 4559 offset[5] += s1.getScalarSize() * s2.getStensorSize() + 4560 s2.getScalarSize() * s1.getStensorSize(); 4561 offset[6] += s1.getScalarSize() * s2.getTensorSize() + 4562 s2.getScalarSize() * s1.getTensorSize(); 4563 offset[7] += s1.getTVectorSize() * s2.getStensorSize() + 4564 s2.getTVectorSize() * s1.getStensorSize(); 4565 offset[8] += s1.getTVectorSize() * s2.getTensorSize() + 4566 s2.getTVectorSize() * s1.getTensorSize(); 4567 offset[9] += s1.getStensorSize() * s2.getTensorSize() + 4568 s2.getStensorSize() * s1.getTensorSize(); 4569 }; 4570 auto get_offset = [&offset]() -> std::string { 4571 const char* sizes[10] = {"", 4572 "TVectorSize*TVectorSize", 4573 "StensorSize*StensorSize", 4574 "TensorSize*TensorSize", 4575 "TVectorSize", 4576 "StensorSize", 4577 "TensorSize", 4578 "TVectorSize*StensorSize", 4579 "TVectorSize*TensorSize", 4580 "StensorSize*TensorSize"}; 4581 std::string o; 4582 if (offset[0] != 0) { 4583 o += std::to_string(offset[0]); 4584 } 4585 for (int i = 1; i != 10; ++i) { 4586 if (offset[i] != 0) { 4587 if (!o.empty()) { 4588 o += "+"; 4589 } 4590 if (offset[i] != 1) { 4591 o += std::to_string(offset[i]) + "*"; 4592 } 4593 o += sizes[i]; 4594 } 4595 } 4596 if (o.empty()) { 4597 return "0"; 4598 } 4599 return o; 4600 }; 4601 // write blocks 4602 for (const auto& b : blocks) { 4603 const auto& v1 = b.first; 4604 const auto& v2 = b.second; 4605 if ((v1.arraySize != 1u) || (v2.arraySize != 1u)) { 4606 break; 4607 } 4608 auto throw_unsupported_block = [&v1, &v2] { 4609 tfel::raise( 4610 "BehaviourDSLCommon::getBehaviourConstructorsInitializers:" 4611 "tangent operator blocks associated with " 4612 "the derivative of '" + 4613 displayName(v1) + "' (of type '" + v1.type + "') with respect to '" + 4614 displayName(v2) + "' (of type '" + v2.type + "') is not supported"); 4615 }; 4616 const auto bn = this->mb.getTangentOperatorBlockName(b); 4617 if (v1.getTypeFlag() == SupportedTypes::SCALAR) { 4618 const auto o = get_offset(); 4619 if (v2.getTypeFlag() == SupportedTypes::SCALAR) { 4620 append(bn + "(Dt[" + o + "])"); 4621 } else if ((v2.getTypeFlag() == SupportedTypes::STENSOR) || 4622 (v2.getTypeFlag() == SupportedTypes::TENSOR)) { 4623 if (o != "0") { 4624 append(bn + "(Dt.begin()+" + o + ")"); 4625 } else { 4626 append(bn + "(Dt.begin())"); 4627 } 4628 } else { 4629 throw_unsupported_block(); 4630 } 4631 } else if (v1.getTypeFlag() == SupportedTypes::TVECTOR) { 4632 if ((v2.getTypeFlag() == SupportedTypes::SCALAR) || 4633 (v2.getTypeFlag() == SupportedTypes::TVECTOR)) { 4634 const auto o = get_offset(); 4635 if (o != "0") { 4636 append(bn + "(Dt.begin()+" + o + ")"); 4637 } else { 4638 append(bn + "(Dt.begin())"); 4639 } 4640 } else { 4641 throw_unsupported_block(); 4642 } 4643 } else if (v1.getTypeFlag() == SupportedTypes::STENSOR) { 4644 if ((v2.getTypeFlag() == SupportedTypes::SCALAR) || 4645 (v2.getTypeFlag() == SupportedTypes::STENSOR) || 4646 (v2.getTypeFlag() == SupportedTypes::TENSOR)) { 4647 const auto o = get_offset(); 4648 if (o != "0") { 4649 append(bn + "(Dt.begin()+" + o + ")"); 4650 } else { 4651 append(bn + "(Dt.begin())"); 4652 } 4653 } else { 4654 throw_unsupported_block(); 4655 } 4656 } else if (v1.getTypeFlag() == SupportedTypes::TENSOR) { 4657 if ((v2.getTypeFlag() == SupportedTypes::SCALAR) || 4658 (v2.getTypeFlag() == SupportedTypes::STENSOR) || 4659 (v2.getTypeFlag() == SupportedTypes::TENSOR)) { 4660 const auto o = get_offset(); 4661 if (o != "0") { 4662 append(bn + "(Dt.begin()+" + o + ")"); 4663 } else { 4664 append(bn + "(Dt.begin())"); 4665 } 4666 } else { 4667 throw_unsupported_block(); 4668 } 4669 } else { 4670 throw_unsupported_block(); 4671 } 4672 update_offset(v1.getTypeSize(), v2.getTypeSize()); 4673 } 4674 } 4675 return init; 4676 } // end of BehaviourDSLCommon::getBehaviourConstructorsInitializers 4677 getLocalVariablesInitializers(const Hypothesis) const4678 std::string BehaviourDSLCommon::getLocalVariablesInitializers(const Hypothesis) const{ 4679 return {}; 4680 } // end of BehaviourDSLCommon::getLocalVariablesInitializers 4681 writeBehaviourConstructors(std::ostream & os,const Hypothesis h) const4682 void BehaviourDSLCommon::writeBehaviourConstructors(std::ostream& os, const Hypothesis h) const { 4683 auto tmpnames = std::vector<std::string>{}; 4684 auto write_body = [this, &os, &tmpnames, h] { 4685 os << "using namespace std;\n" 4686 << "using namespace tfel::math;\n" 4687 << "using std::vector;\n"; 4688 writeMaterialLaws(os, this->mb.getMaterialLaws()); 4689 this->writeBehaviourParameterInitialisation(os, h); 4690 // calling models 4691 for (const auto& m : this->mb.getModelsDescriptions()) { 4692 if (m.outputs.size() == 1) { 4693 const auto vn = m.outputs[0].name; 4694 this->writeModelCall(os, tmpnames, h, m, "d" + vn, vn, "em"); 4695 os << "this->d" << vn << " -= this->" << vn << ";\n"; 4696 } else { 4697 this->throwRuntimeError("BehaviourDSLCommon::writeBehaviourInitializeMethod", 4698 "only models with one output are supported yet"); 4699 } 4700 } 4701 this->writeBehaviourLocalVariablesInitialisation(os, h); 4702 }; 4703 this->checkBehaviourFile(os); 4704 // initializers 4705 const auto& init = this->getBehaviourConstructorsInitializers(h); 4706 // writing constructors 4707 os << "/*!\n" 4708 << "* \\brief Constructor\n" 4709 << "*/\n"; 4710 if (this->mb.useQt()) { 4711 os << this->mb.getClassName() << "(" 4712 << "const " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,use_qt>& src1,\n" 4713 << "const " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,use_qt>& src2)\n" 4714 << ": " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,use_qt>(src1),\n" 4715 << this->mb.getClassName() << "IntegrationData<hypothesis,Type,use_qt>(src2)"; 4716 } else { 4717 os << this->mb.getClassName() << "(" 4718 << "const " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,false>& src1,\n" 4719 << "const " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>& src2)\n" 4720 << ": " << this->mb.getClassName() << "BehaviourData<hypothesis,Type,false>(src1),\n" 4721 << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>(src2)"; 4722 } 4723 if (!init.empty()) { 4724 os << ",\n" << init; 4725 } 4726 os << "\n{\n"; 4727 write_body(); 4728 os << "}\n\n"; 4729 // constructor specific to interfaces 4730 for (const auto& i : this->interfaces) { 4731 if (i.second->isBehaviourConstructorRequired(h, this->mb)) { 4732 i.second->writeBehaviourConstructorHeader(os, this->mb, h, init); 4733 os << "\n{\n"; 4734 write_body(); 4735 i.second->writeBehaviourConstructorBody(os, this->mb, h); 4736 os << "}\n\n"; 4737 } 4738 } 4739 } 4740 writeHillTensorComputation(std::ostream & out,const std::string & H,const BehaviourDescription::HillTensor & h,std::function<std::string (const MaterialPropertyInput &)> & f) const4741 void BehaviourDSLCommon::writeHillTensorComputation( 4742 std::ostream& out, 4743 const std::string& H, 4744 const BehaviourDescription::HillTensor& h, 4745 std::function<std::string(const MaterialPropertyInput&)>& f) const { 4746 auto throw_if = [this](const bool b, const std::string& m) { 4747 if (b) { 4748 this->throwRuntimeError("BehaviourDSLCommon::writeHillTensorComputation", m); 4749 } 4750 }; 4751 throw_if(this->mb.getSymmetryType() == mfront::ISOTROPIC, "material is not orthotropic"); 4752 for (decltype(h.c.size()) i = 0; i != h.c.size(); ++i) { 4753 this->writeMaterialPropertyCheckBoundsEvaluation(out, h.c[i], f); 4754 } 4755 if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PIPE) { 4756 out << H << " = tfel::material::computeHillTensor<hypothesis," 4757 << "OrthotropicAxesConvention::PIPE,stress>("; 4758 } else if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PLATE) { 4759 out << H << " = tfel::material::computeHillTensor<hypothesis," 4760 << "OrthotropicAxesConvention::PLATE,stress>("; 4761 } else { 4762 out << H << " = tfel::material::computeHillTensor<hypothesis," 4763 << "OrthotropicAxesConvention::DEFAULT,stress>("; 4764 } 4765 for (decltype(h.c.size()) i = 0; i != h.c.size();) { 4766 this->writeMaterialPropertyEvaluation(out, h.c[i], f); 4767 if (++i != h.c.size()) { 4768 out << ",\n"; 4769 } 4770 } 4771 out << ");\n"; 4772 } // end of BehaviourDSLCommon::writeHillTensorComputation 4773 writeStiffnessTensorComputation(std::ostream & out,const std::string & D,std::function<std::string (const MaterialPropertyInput &)> & f) const4774 void BehaviourDSLCommon::writeStiffnessTensorComputation( 4775 std::ostream& out, const std::string& D, std::function<std::string(const MaterialPropertyInput&)>& f) const { 4776 const auto& emps = this->mb.getElasticMaterialProperties(); 4777 if ((this->mb.getSymmetryType() == mfront::ISOTROPIC) && (this->mb.getElasticSymmetryType() != mfront::ISOTROPIC)) { 4778 this->throwRuntimeError("BehaviourDSLCommon::writeStiffnessTensorComputation", 4779 "inconsistent symmetry type for the material and " 4780 "the elastic behaviour."); 4781 } 4782 bool ua = true; 4783 if (!this->mb.hasAttribute(BehaviourDescription::requiresUnAlteredStiffnessTensor)) { 4784 const auto& mh = this->mb.getModellingHypotheses(); 4785 if ((mh.find(ModellingHypothesis::PLANESTRESS) != mh.end()) || 4786 (mh.find(ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) != mh.end())) { 4787 this->throwRuntimeError("BehaviourDSLCommon::writeStiffnessTensorComputation", 4788 "For plane stress hypotheses, it is required to precise whether " 4789 "the expected stiffness tensor is 'Altered' (the plane stress " 4790 "hypothesis is taken into account) or 'UnAltered' (the stiffness " 4791 "tensor is the same as in plane strain). " 4792 "See the '@ComputeStiffnessTensor' documentation"); 4793 } 4794 } else { 4795 ua = this->mb.getAttribute<bool>(BehaviourDescription::requiresUnAlteredStiffnessTensor); 4796 } 4797 if (this->mb.getElasticSymmetryType() == mfront::ISOTROPIC) { 4798 if (emps.size() != 2u) { 4799 this->throwRuntimeError("BehaviourDSLCommon::writeStiffnessTensorComputation", 4800 "invalid number of material properties"); 4801 } 4802 this->writeMaterialPropertyCheckBoundsEvaluation(out, emps[0], f); 4803 this->writeMaterialPropertyCheckBoundsEvaluation(out, emps[1], f); 4804 if (ua) { 4805 out << "tfel::material::computeIsotropicStiffnessTensor<hypothesis,StiffnessTensorAlterationCharacteristic::" 4806 "UNALTERED" 4807 << ">(" << D << ","; 4808 } else { 4809 out << "tfel::material::computeIsotropicStiffnessTensor<hypothesis,StiffnessTensorAlterationCharacteristic::" 4810 "ALTERED" 4811 << ">(" << D << ","; 4812 } 4813 this->writeMaterialPropertyEvaluation(out, emps[0], f); 4814 out << ",\n"; 4815 this->writeMaterialPropertyEvaluation(out, emps[1], f); 4816 out << ");\n"; 4817 } else if (this->mb.getElasticSymmetryType() == mfront::ORTHOTROPIC) { 4818 if (emps.size() != 9u) { 4819 this->throwRuntimeError("BehaviourDSLCommon::writeStiffnessTensorComputation", 4820 "invalid number of material properties"); 4821 } 4822 for (decltype(emps.size()) i = 0; i != emps.size(); ++i) { 4823 this->writeMaterialPropertyCheckBoundsEvaluation(out, emps[i], f); 4824 } 4825 if (ua) { 4826 if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PIPE) { 4827 out << "tfel::material::computeOrthotropicStiffnessTensor<hypothesis," 4828 << "StiffnessTensorAlterationCharacteristic::UNALTERED," 4829 << "OrthotropicAxesConvention::PIPE>(" << D << ","; 4830 } else if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PLATE) { 4831 out << "tfel::material::computeOrthotropicStiffnessTensor<hypothesis," 4832 << "StiffnessTensorAlterationCharacteristic::UNALTERED," 4833 << "OrthotropicAxesConvention::PLATE>(" << D << ","; 4834 } else { 4835 out << "tfel::material::computeOrthotropicStiffnessTensor<hypothesis," 4836 << "StiffnessTensorAlterationCharacteristic::UNALTERED," 4837 << "OrthotropicAxesConvention::DEFAULT>(" << D << ","; 4838 } 4839 } else { 4840 if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PIPE) { 4841 out << "tfel::material::computeOrthotropicStiffnessTensor<hypothesis," 4842 << "StiffnessTensorAlterationCharacteristic::ALTERED," 4843 << "OrthotropicAxesConvention::PIPE>(" << D << ","; 4844 } else if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PLATE) { 4845 out << "tfel::material::computeOrthotropicStiffnessTensor<hypothesis," 4846 << "StiffnessTensorAlterationCharacteristic::ALTERED," 4847 << "OrthotropicAxesConvention::PLATE>(" << D << ","; 4848 } else { 4849 out << "tfel::material::computeOrthotropicStiffnessTensor<hypothesis," 4850 << "StiffnessTensorAlterationCharacteristic::ALTERED," 4851 << "OrthotropicAxesConvention::DEFAULT>(" << D << ","; 4852 } 4853 } 4854 for (decltype(emps.size()) i = 0; i != emps.size();) { 4855 this->writeMaterialPropertyEvaluation(out, emps[i], f); 4856 if (++i != emps.size()) { 4857 out << ",\n"; 4858 } 4859 } 4860 out << ");\n"; 4861 } else { 4862 this->throwRuntimeError("BehaviourDSLCommon::writeStiffnessTensorComputation", 4863 "unsupported elastic symmetry type"); 4864 } 4865 } // end of BehaviourDSLCommon::writeStiffnessTensorComputation 4866 writeExternalMFrontMaterialPropertyArguments(std::ostream & out,const BehaviourDescription::MaterialProperty & m,std::function<std::string (const MaterialPropertyInput &)> & f) const4867 void BehaviourDSLCommon::writeExternalMFrontMaterialPropertyArguments( 4868 std::ostream& out, 4869 const BehaviourDescription::MaterialProperty& m, 4870 std::function<std::string(const MaterialPropertyInput&)>& f) const { 4871 const auto& cmp = m.get<BehaviourDescription::ExternalMFrontMaterialProperty>(); 4872 const auto& mpd = *(cmp.mpd); 4873 out << '('; 4874 if (!mpd.inputs.empty()) { 4875 const auto& inputs = this->mb.getMaterialPropertyInputs(mpd); 4876 auto pi = std::begin(inputs); 4877 const auto pie = std::end(inputs); 4878 while (pi != pie) { 4879 out << f(*pi); 4880 if (++pi != pie) { 4881 out << ","; 4882 } 4883 } 4884 } 4885 out << ")"; 4886 } 4887 writeMaterialPropertyCheckBoundsEvaluation(std::ostream & out,const BehaviourDescription::MaterialProperty & m,std::function<std::string (const MaterialPropertyInput &)> & f) const4888 void BehaviourDSLCommon::writeMaterialPropertyCheckBoundsEvaluation( 4889 std::ostream& out, 4890 const BehaviourDescription::MaterialProperty& m, 4891 std::function<std::string(const MaterialPropertyInput&)>& f) const { 4892 if (m.is<BehaviourDescription::ExternalMFrontMaterialProperty>()) { 4893 const auto& cmp = m.get<BehaviourDescription::ExternalMFrontMaterialProperty>(); 4894 const auto& mpd = *(cmp.mpd); 4895 if ((!hasBounds(mpd.inputs)) && (!(hasPhysicalBounds(mpd.inputs)))) { 4896 return; 4897 } 4898 const auto& n = MFrontMaterialPropertyInterface().getFunctionName(mpd); 4899 out << "{\n // check bounds for material property '" << n << "'\n" 4900 << "const auto " << n << "_bounds_check_status = " << n << "_checkBounds"; 4901 this->writeExternalMFrontMaterialPropertyArguments(out, cmp, f); 4902 out << ";\n" 4903 << "if(" << n << "_bounds_check_status!=0){\n" 4904 << "// physical bounds\n" 4905 << "tfel::raise_if<OutOfBoundsException>(" << n << "_bounds_check_status<0,\n" 4906 << "\"" << this->mb.getClassName() << ": a variable is out of its physical bounds \"\n" 4907 << "\"when calling the material property '" << n << "'\");\n" 4908 << "} else {\n" 4909 << "// standard bounds\n" 4910 << "if(this->policy==Strict){\n" 4911 << "tfel::raise<OutOfBoundsException>(\"" << this->mb.getClassName() << ": " 4912 << "a variable is out of its bounds \"\n" 4913 << "\"when calling the material property '" << n << "'\");\n" 4914 << "} else if(this->policy==Warning){\n" 4915 << "std::cerr << \"" << this->mb.getClassName() << ": " 4916 << "a variable is out of its bounds \"\n" 4917 << "\"when calling the material property '" << n << "'\\n\";\n" 4918 << "}\n" 4919 << "}\n" 4920 << "}\n"; 4921 } else if (!((m.is<BehaviourDescription::ConstantMaterialProperty>()) || 4922 (m.is<BehaviourDescription::AnalyticMaterialProperty>()))) { 4923 this->throwRuntimeError("BehaviourDSLCommon::writeMaterialPropertyEvaluation", 4924 "unsupported material property type"); 4925 } 4926 } // end of BehaviourDSLCommon::writeMaterialPropertyEvaluation 4927 writeMaterialPropertyEvaluation(std::ostream & out,const BehaviourDescription::MaterialProperty & m,std::function<std::string (const MaterialPropertyInput &)> & f) const4928 void BehaviourDSLCommon::writeMaterialPropertyEvaluation( 4929 std::ostream& out, 4930 const BehaviourDescription::MaterialProperty& m, 4931 std::function<std::string(const MaterialPropertyInput&)>& f) const { 4932 if (m.is<BehaviourDescription::ConstantMaterialProperty>()) { 4933 const auto& cmp = m.get<BehaviourDescription::ConstantMaterialProperty>(); 4934 if (!cmp.name.empty()) { 4935 out << "this->" << cmp.name; 4936 } else { 4937 out << cmp.value; 4938 } 4939 } else if (m.is<BehaviourDescription::ExternalMFrontMaterialProperty>()) { 4940 const auto& cmp = m.get<BehaviourDescription::ExternalMFrontMaterialProperty>(); 4941 const auto& mpd = *(cmp.mpd); 4942 out << MFrontMaterialPropertyInterface().getFunctionName(mpd); 4943 this->writeExternalMFrontMaterialPropertyArguments(out, cmp, f); 4944 } else if (m.is<BehaviourDescription::AnalyticMaterialProperty>()) { 4945 const auto& amp = m.get<BehaviourDescription::AnalyticMaterialProperty>(); 4946 tfel::math::Evaluator e(amp.f); 4947 auto mi = std::map<std::string, std::string>{}; 4948 for (const auto& i : this->mb.getMaterialPropertyInputs(e.getVariablesNames())) { 4949 mi[i.name] = f(i); 4950 } 4951 out << e.getCxxFormula(mi); 4952 } else if (m.empty()) { 4953 this->throwRuntimeError( 4954 "BehaviourDSLCommon::writeMaterialPropertyEvaluation", 4955 "empty material property"); 4956 } else { 4957 this->throwRuntimeError( 4958 "BehaviourDSLCommon::writeMaterialPropertyEvaluation", 4959 "unsupported material property type"); 4960 } 4961 } // end of BehaviourDSLCommon::writeMaterialPropertyEvaluation 4962 writeThermalExpansionCoefficientComputation(std::ostream & out,const BehaviourDescription::MaterialProperty & a,const std::string & T,const std::string & idx,const std::string & s) const4963 void BehaviourDSLCommon::writeThermalExpansionCoefficientComputation(std::ostream& out, 4964 const BehaviourDescription::MaterialProperty& a, 4965 const std::string& T, 4966 const std::string& idx, 4967 const std::string& s) const { 4968 auto throw_if = [this](const bool b, const std::string& m) { 4969 if (b) { 4970 this->throwRuntimeError( 4971 "BehaviourDSLCommon::" 4972 "writeThermalExpansionCoefficientComputation", 4973 m); 4974 } 4975 }; 4976 out << "const thermalexpansion alpha" << s; 4977 if (!idx.empty()) { 4978 out << "_" << idx; 4979 } 4980 out << " = "; 4981 if (a.is<BehaviourDescription::ConstantMaterialProperty>()) { 4982 const auto& cmp = a.get<BehaviourDescription::ConstantMaterialProperty>(); 4983 if (cmp.name.empty()) { 4984 out << cmp.value << ";\n"; 4985 } else { 4986 out << "this->" << cmp.name << ";\n"; 4987 } 4988 } else if (a.is<BehaviourDescription::ExternalMFrontMaterialProperty>()) { 4989 const auto& mpd = *(a.get<BehaviourDescription::ExternalMFrontMaterialProperty>().mpd); 4990 const auto inputs = this->mb.getMaterialPropertyInputs(mpd); 4991 out << MFrontMaterialPropertyInterface().getFunctionName(mpd) << '('; 4992 for (auto pi = inputs.begin(); pi != inputs.end();) { 4993 const auto c = pi->category; 4994 if (c == BehaviourDescription::MaterialPropertyInput::TEMPERATURE) { 4995 out << T; 4996 } else if ((c == BehaviourDescription::MaterialPropertyInput::MATERIALPROPERTY) || 4997 (c == BehaviourDescription::MaterialPropertyInput::PARAMETER)) { 4998 out << "this->" << pi->name; 4999 } else if (c == BehaviourDescription::MaterialPropertyInput::STATICVARIABLE) { 5000 out << this->mb.getClassName() << "::" << pi->name; 5001 } else { 5002 throw_if(true, 5003 "thermal expansion coefficients must depend " 5004 "on the temperature only"); 5005 } 5006 if (++pi != inputs.end()) { 5007 out << ","; 5008 } 5009 } 5010 out << ");\n"; 5011 } else if (a.is<BehaviourDescription::AnalyticMaterialProperty>()) { 5012 const auto& amp = a.get<BehaviourDescription::AnalyticMaterialProperty>(); 5013 auto m = std::map<std::string, std::string>{}; 5014 for (const auto& i : this->mb.getMaterialPropertyInputs(amp.getVariablesNames())) { 5015 const auto c = i.category; 5016 if (c == BehaviourDescription::MaterialPropertyInput::TEMPERATURE) { 5017 m.insert({"T", T}); 5018 } else if ((c == BehaviourDescription::MaterialPropertyInput::MATERIALPROPERTY) || 5019 (c == BehaviourDescription::MaterialPropertyInput::PARAMETER)) { 5020 m.insert({i.name, "this->" + i.name}); 5021 } else if (c == BehaviourDescription::MaterialPropertyInput::STATICVARIABLE) { 5022 m.insert({i.name, this->mb.getClassName() + "::" + i.name}); 5023 } else { 5024 throw_if(true, 5025 "thermal expansion coefficients must depend " 5026 "on the temperature only"); 5027 } 5028 } 5029 tfel::math::Evaluator ev(amp.f); 5030 out << ev.getCxxFormula(m) << ";\n"; 5031 } else { 5032 throw_if(true, "unsupported material property type"); 5033 } 5034 } // end of BehaviourDSLCommon::writeThermalExpansionCoefficientComputation 5035 writeThermalExpansionCoefficientsComputations(std::ostream & out,const BehaviourDescription::MaterialProperty & a,const std::string & suffix) const5036 void BehaviourDSLCommon::writeThermalExpansionCoefficientsComputations( 5037 std::ostream& out, const BehaviourDescription::MaterialProperty& a, const std::string& suffix) const { 5038 this->writeThermalExpansionCoefficientComputation(out, a, "this->initial_geometry_reference_temperature", "", 5039 suffix + "_Ti"); 5040 this->writeThermalExpansionCoefficientComputation(out, a, "this->T", "t", suffix + "_T"); 5041 this->writeThermalExpansionCoefficientComputation(out, a, "this->T+this->dT", "t_dt", suffix + "_T"); 5042 } // end of writeThermalExpansionCoefficientComputation 5043 writeThermalExpansionComputation(std::ostream & out,const std::string & t,const std::string & c,const std::string & suffix) const5044 void BehaviourDSLCommon::writeThermalExpansionComputation(std::ostream& out, 5045 const std::string& t, 5046 const std::string& c, 5047 const std::string& suffix) const { 5048 const auto Tref = "this->thermal_expansion_reference_temperature"; 5049 const auto T = (t == "t") ? "this->T" : "this->T+this->dT"; 5050 if (t == "t") { 5051 out << "dl0_l0"; 5052 } else { 5053 out << "dl1_l0"; 5054 } 5055 out << "[" << c << "] += 1/(1+alpha" << suffix << "_Ti * (this->initial_geometry_reference_temperature-" << Tref 5056 << "))*(" 5057 << "alpha" << suffix << "_T_" << t << " * (" << T << "-" << Tref << ")-" 5058 << "alpha" << suffix << "_Ti * (this->initial_geometry_reference_temperature-" << Tref << "));\n"; 5059 } // end of BehaviourDSLCommon::writeThermalExpansionComputation 5060 writeBehaviourComputeStressFreeExpansion(std::ostream & os,const Hypothesis h) const5061 void BehaviourDSLCommon::writeBehaviourComputeStressFreeExpansion(std::ostream& os, const Hypothesis h) const { 5062 auto tmpnames = std::vector<std::string>{}; 5063 auto throw_if = [this](const bool b, const std::string& m) { 5064 if (b) { 5065 this->throwRuntimeError("BehaviourDSLCommon::writeBehaviourComputeStressFreeExpansion", m); 5066 } 5067 }; 5068 auto eval = [](std::ostream& out, const BehaviourDescription::MaterialProperty& mp, const std::string& c, 5069 const bool b) { 5070 const auto& cmp = mp.get<BehaviourDescription::ConstantMaterialProperty>(); 5071 const auto Tref = "this->thermal_expansion_reference_temperature"; 5072 const auto i = b ? "1" : "0"; 5073 const auto T = b ? "this->T+this->dT" : "this->T"; 5074 if (cmp.name.empty()) { 5075 out << "dl" << i << "_l0" 5076 << "[" << c << "] += " << cmp.value << "/(1+" << cmp.value 5077 << "*(this->initial_geometry_reference_temperature-" << Tref << "))" 5078 << "*(" << T << "-this->initial_geometry_reference_temperature);\n"; 5079 } else { 5080 out << "dl" << i << "_l0" 5081 << "[" << c << "] += (this->" << cmp.name << ")/(1+(this->" << cmp.name 5082 << ")*(this->initial_geometry_reference_temperature-" << Tref << "))" 5083 << "*(" << T << "-this->initial_geometry_reference_temperature);\n"; 5084 } 5085 }; 5086 if (!this->mb.requiresStressFreeExpansionTreatment(h)) { 5087 return; 5088 } 5089 if (this->mb.areThermalExpansionCoefficientsDefined()) { 5090 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5091 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5092 "only finite strain or small strain behaviour are supported"); 5093 if (this->mb.getSymmetryType() == mfront::ORTHOTROPIC) { 5094 if ((this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::DEFAULT) && 5095 (this->mb.getThermalExpansionCoefficients().size() == 3u)) { 5096 // in this case, only tridimensional case is supported 5097 for (const auto mh : this->mb.getDistinctModellingHypotheses()) { 5098 throw_if(mh != ModellingHypothesis::TRIDIMENSIONAL, 5099 "an orthotropic axes convention must be choosen when " 5100 "using @ComputeThermalExpansion keyword in behaviours " 5101 "which shall be valid in other modelling hypothesis " 5102 "than 'Tridimensional'.\n" 5103 "Either restrict the validity of the behaviour to " 5104 "'Tridimensional' (see @ModellingHypothesis) or " 5105 "choose and orthotropic axes convention as on option " 5106 "to the @OrthotropicBehaviour keyword"); 5107 } 5108 } 5109 } 5110 } 5111 this->checkBehaviourFile(os); 5112 os << "void\n" 5113 << "computeStressFreeExpansion(std::pair<StressFreeExpansionType,StressFreeExpansionType>& dl01_l0)\n{\n"; 5114 os << "using namespace std;\n"; 5115 os << "using namespace tfel::math;\n"; 5116 os << "using std::vector;\n"; 5117 writeMaterialLaws(os, this->mb.getMaterialLaws()); 5118 os << "auto& dl0_l0 = dl01_l0.first;\n"; 5119 os << "auto& dl1_l0 = dl01_l0.second;\n"; 5120 os << "dl0_l0 = StressFreeExpansionType(typename StressFreeExpansionType::value_type(0));\n"; 5121 os << "dl1_l0 = StressFreeExpansionType(typename StressFreeExpansionType::value_type(0));\n"; 5122 if (this->mb.hasCode(h, BehaviourData::ComputeStressFreeExpansion)) { 5123 os << this->mb.getCode(h, BehaviourData::ComputeStressFreeExpansion) << '\n'; 5124 } 5125 if (this->mb.areThermalExpansionCoefficientsDefined()) { 5126 const auto& acs = this->mb.getThermalExpansionCoefficients(); 5127 if (acs.size() == 1u) { 5128 const auto& a = acs.front(); 5129 if (a.is<BehaviourDescription::ConstantMaterialProperty>()) { 5130 eval(os, a, "0", false); 5131 } else { 5132 this->writeThermalExpansionCoefficientsComputations(os, acs.front()); 5133 this->writeThermalExpansionComputation(os, "t", "0"); 5134 } 5135 os << "dl0_l0[1] += dl0_l0[0];\n" 5136 << "dl0_l0[2] += dl0_l0[0];\n"; 5137 if (a.is<BehaviourDescription::ConstantMaterialProperty>()) { 5138 eval(os, a, "0", true); 5139 } else { 5140 this->writeThermalExpansionComputation(os, "t_dt", "0"); 5141 } 5142 os << "dl1_l0[1] += dl1_l0[0];\n" 5143 << "dl1_l0[2] += dl1_l0[0];\n"; 5144 } else if (acs.size() == 3u) { 5145 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, "invalid number of thermal expansion coefficients"); 5146 for (size_t i = 0; i != 3; ++i) { 5147 if (!acs[i].is<BehaviourDescription::ConstantMaterialProperty>()) { 5148 this->writeThermalExpansionCoefficientsComputations(os, acs[i], std::to_string(i)); 5149 } 5150 } 5151 for (size_t i = 0; i != 3; ++i) { 5152 const auto idx = std::to_string(i); 5153 if (acs[i].is<BehaviourDescription::ConstantMaterialProperty>()) { 5154 eval(os, acs[i], idx, false); 5155 eval(os, acs[i], idx, true); 5156 } else { 5157 this->writeThermalExpansionComputation(os, "t", idx, idx); 5158 this->writeThermalExpansionComputation(os, "t_dt", idx, idx); 5159 } 5160 } 5161 } else { 5162 throw_if(true, "unsupported behaviour symmetry"); 5163 } 5164 } 5165 for (const auto& d : this->mb.getStressFreeExpansionDescriptions(h)) { 5166 if (d.is<BehaviourData::AxialGrowth>()) { 5167 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5168 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5169 "only finite strain or small strain behaviour are supported"); 5170 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, 5171 "axial growth is only supported for orthotropic behaviours"); 5172 const auto& s = d.get<BehaviourData::AxialGrowth>(); 5173 throw_if(s.sfe.is<BehaviourData::NullExpansion>(), "null swelling is not supported here"); 5174 // The z-axis is supposed to be aligned with the second 5175 // direction of orthotropy. 5176 if (s.sfe.is<BehaviourData::SFED_ESV>()) { 5177 const auto ev = s.sfe.get<BehaviourData::SFED_ESV>().vname; 5178 os << "dl0_l0[1]+=this->" << ev << ";\n" 5179 << "dl0_l0[0]+=real(1)/std::sqrt(1+this->" << ev << ")-real(1);\n" 5180 << "dl0_l0[2]+=real(1)/std::sqrt(1+this->" << ev << ")-real(1);\n" 5181 << "dl1_l0[1]+=this->" << ev << "+this->d" << ev << ";\n" 5182 << "dl1_l0[0]+=real(1)/std::sqrt(1+this->" << ev << "+this->d" << ev << ")-real(1);\n" 5183 << "dl1_l0[2]+=real(1)/std::sqrt(1+this->" << ev << "+this->d" << ev << ")-real(1);\n"; 5184 } else if (s.sfe.is<std::shared_ptr<ModelDescription>>()) { 5185 const auto& md = *(s.sfe.get<std::shared_ptr<ModelDescription>>()); 5186 throw_if(md.outputs.size() != 1u, "invalid number of outputs for model '" + md.className + "'"); 5187 const auto vs = md.className + "_" + md.outputs[0].name; 5188 os << "dl0_l0[1]+=this->" << vs << ";\n" 5189 << "dl0_l0[0]+=real(1)/std::sqrt(1+this->" << vs << ")-real(1);\n" 5190 << "dl0_l0[2]+=real(1)/std::sqrt(1+this->" << vs << ")-real(1);\n"; 5191 this->writeModelCall(os, tmpnames, h, md, vs, vs, "sfeh"); 5192 os << "dl1_l0[1]+=this->" << vs << ";\n" 5193 << "dl1_l0[0]+=real(1)/std::sqrt(1+this->" << vs << ")-real(1);\n" 5194 << "dl1_l0[2]+=real(1)/std::sqrt(1+this->" << vs << ")-real(1);\n"; 5195 } else { 5196 throw_if(true, "internal error, unsupported stress free expansion"); 5197 } 5198 } else if (d.is<BehaviourData::Relocation>()) { 5199 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5200 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5201 "only finite strain or small strain behaviour are supported"); 5202 const auto& s = d.get<BehaviourData::Relocation>(); 5203 throw_if(s.sfe.is<BehaviourData::NullExpansion>(), "null swelling is not supported here"); 5204 if (s.sfe.is<BehaviourData::SFED_ESV>()) { 5205 const auto ev = s.sfe.get<BehaviourData::SFED_ESV>().vname; 5206 if ((h == ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) || 5207 (h == ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRAIN)) { 5208 os << "dl0_l0[0]+=this->" << ev << "/2;\n" 5209 << "dl0_l0[2]+=this->" << ev << "/2;\n" 5210 << "dl1_l0[0]+=(this->" << ev << "+this->d" << ev << ")/2;\n" 5211 << "dl1_l0[2]+=(this->" << ev << "+this->d" << ev << ")/2;\n"; 5212 } 5213 if ((h == ModellingHypothesis::GENERALISEDPLANESTRAIN) || (h == ModellingHypothesis::PLANESTRAIN) || 5214 (h == ModellingHypothesis::PLANESTRESS)) { 5215 os << "dl0_l0[0]+=this->" << ev << "/2;\n" 5216 << "dl0_l0[1]+=this->" << ev << "/2;\n" 5217 << "dl1_l0[0]+=(this->" << ev << "+this->d" << ev << ")/2;\n" 5218 << "dl1_l0[1]+=(this->" << ev << "+this->d" << ev << ")/2;\n"; 5219 } 5220 } else if (s.sfe.is<std::shared_ptr<ModelDescription>>()) { 5221 const auto& md = *(s.sfe.get<std::shared_ptr<ModelDescription>>()); 5222 throw_if(md.outputs.size() != 1u, "invalid number of outputs for model '" + md.className + "'"); 5223 const auto vs = md.className + "_" + md.outputs[0].name; 5224 if ((h == ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) || 5225 (h == ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRAIN)) { 5226 os << "dl0_l0[0]+=(this->" << vs << ")/2;\n" 5227 << "dl0_l0[2]+=(this->" << vs << ")/2;\n"; 5228 } 5229 this->writeModelCall(os, tmpnames, h, md, vs, vs, "sfeh"); 5230 if ((h == ModellingHypothesis::GENERALISEDPLANESTRAIN) || (h == ModellingHypothesis::PLANESTRAIN) || 5231 (h == ModellingHypothesis::PLANESTRESS)) { 5232 os << "dl0_l0[0]+=(this->" << vs << ")/2;\n" 5233 << "dl0_l0[1]+=(this->" << vs << ")/2;\n"; 5234 } 5235 } else { 5236 throw_if(true, "internal error, unsupported stress free expansion"); 5237 } 5238 } else if (d.is<BehaviourData::OrthotropicStressFreeExpansion>()) { 5239 using StressFreeExpansionHandler = BehaviourData::StressFreeExpansionHandler; 5240 const auto& s = d.get<BehaviourData::OrthotropicStressFreeExpansion>(); 5241 auto write = [this, &os, &tmpnames, throw_if, h](const StressFreeExpansionHandler& sfe, const char* const c) { 5242 if (sfe.is<BehaviourData::SFED_ESV>()) { 5243 const auto& ev = sfe.get<BehaviourData::SFED_ESV>().vname; 5244 os << "dl0_l0[" << c << "]+=this->" << ev << ";\n"; 5245 os << "dl1_l0[" << c << "]+=this->" << ev << "+this->d" << ev << ";\n"; 5246 } else if (sfe.is<std::shared_ptr<ModelDescription>>()) { 5247 const auto& md = *(sfe.get<std::shared_ptr<ModelDescription>>()); 5248 throw_if(md.outputs.size() != 1u, "invalid number of outputs for model '" + md.className + "'"); 5249 const auto vs = md.className + "_" + md.outputs[0].name; 5250 os << "dl0_l0[" << c << "]+=this->" << vs << ";\n"; 5251 this->writeModelCall(os, tmpnames, h, md, vs, vs, "sfeh"); 5252 os << "dl1_l0[" << c << "]+=this->" << vs << ";\n"; 5253 } else if (!sfe.is<BehaviourData::NullExpansion>()) { 5254 throw_if(true, "internal error, unsupported stress free expansion"); 5255 } 5256 }; 5257 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5258 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5259 "only finite strain or small strain behaviour are supported"); 5260 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, 5261 "orthotropic stress free expansion is only supported " 5262 "for orthotropic behaviours"); 5263 throw_if(s.sfe0.is<BehaviourData::NullExpansion>() && s.sfe1.is<BehaviourData::NullExpansion>() && 5264 s.sfe2.is<BehaviourData::NullExpansion>(), 5265 "null swelling is not supported here"); 5266 write(s.sfe0, "0"); 5267 write(s.sfe1, "1"); 5268 write(s.sfe2, "2"); 5269 } else if (d.is<BehaviourData::OrthotropicStressFreeExpansionII>()) { 5270 const auto& s = d.get<BehaviourData::OrthotropicStressFreeExpansionII>(); 5271 const auto& ev = s.esv.vname; 5272 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5273 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5274 "only finite strain or small strain behaviour are supported"); 5275 throw_if(this->mb.getSymmetryType() != mfront::ORTHOTROPIC, 5276 "orthotropic stress free expansion is only supported " 5277 "for orthotropic behaviours"); 5278 os << "dl0_l0[0]+=this->" << ev << "[0];\n" 5279 << "dl0_l0[1]+=this->" << ev << "[1];\n" 5280 << "dl0_l0[2]+=this->" << ev << "[2];\n" 5281 << "dl1_l0[0]+=this->" << ev << "[0]+this->d" << ev << "[0];\n" 5282 << "dl1_l0[1]+=this->" << ev << "[1]+this->d" << ev << "[1];\n" 5283 << "dl1_l0[2]+=this->" << ev << "[2]+this->d" << ev << "[2];\n"; 5284 } else if (d.is<BehaviourData::IsotropicStressFreeExpansion>()) { 5285 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5286 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5287 "only finite strain or small strain behaviour are supported"); 5288 const auto& s = d.get<BehaviourData::IsotropicStressFreeExpansion>(); 5289 throw_if(s.sfe.is<BehaviourData::NullExpansion>(), "null swelling is not supported here"); 5290 if (s.sfe.is<BehaviourData::SFED_ESV>()) { 5291 const auto ev = s.sfe.get<BehaviourData::SFED_ESV>().vname; 5292 os << "dl0_l0[0]+=this->" << ev << ";\n" 5293 << "dl0_l0[1]+=this->" << ev << ";\n" 5294 << "dl0_l0[2]+=this->" << ev << ";\n" 5295 << "dl1_l0[0]+=this->" << ev << "+this->d" << ev << ";\n" 5296 << "dl1_l0[1]+=this->" << ev << "+this->d" << ev << ";\n" 5297 << "dl1_l0[2]+=this->" << ev << "+this->d" << ev << ";\n"; 5298 } else if (s.sfe.is<std::shared_ptr<ModelDescription>>()) { 5299 const auto& md = *(s.sfe.get<std::shared_ptr<ModelDescription>>()); 5300 throw_if(md.outputs.size() != 1u, "invalid number of outputs for model '" + md.className + "'"); 5301 const auto vs = md.className + "_" + md.outputs[0].name; 5302 os << "dl0_l0[0]+=this->" << vs << ";\n" 5303 << "dl0_l0[1]+=this->" << vs << ";\n" 5304 << "dl0_l0[2]+=this->" << vs << ";\n"; 5305 this->writeModelCall(os, tmpnames, h, md, vs, vs, "sfeh"); 5306 os << "dl1_l0[0]+=this->" << vs << ";\n" 5307 << "dl1_l0[1]+=this->" << vs << ";\n" 5308 << "dl1_l0[2]+=this->" << vs << ";\n"; 5309 } else { 5310 throw_if(true, "internal error, unsupported stress free expansion"); 5311 } 5312 } else if (d.is<BehaviourData::VolumeSwellingStressFreeExpansion>()) { 5313 throw_if((this->mb.getBehaviourType() != BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) && 5314 (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR), 5315 "only finite strain or small strain behaviour are supported"); 5316 const auto& s = d.get<BehaviourData::VolumeSwellingStressFreeExpansion>(); 5317 throw_if(s.sfe.is<BehaviourData::NullExpansion>(), "null swelling is not supported here"); 5318 if (s.sfe.is<BehaviourData::SFED_ESV>()) { 5319 const auto ev = s.sfe.get<BehaviourData::SFED_ESV>().vname; 5320 os << "dl0_l0[0]+=this->" << ev << "/3;\n" 5321 << "dl0_l0[1]+=this->" << ev << "/3;\n" 5322 << "dl0_l0[2]+=this->" << ev << "/3;\n" 5323 << "dl1_l0[0]+=(this->" << ev << "+this->d" << ev << ")/3;\n" 5324 << "dl1_l0[1]+=(this->" << ev << "+this->d" << ev << ")/3;\n" 5325 << "dl1_l0[2]+=(this->" << ev << "+this->d" << ev << ")/3;\n"; 5326 } else if (s.sfe.is<std::shared_ptr<ModelDescription>>()) { 5327 const auto& md = *(s.sfe.get<std::shared_ptr<ModelDescription>>()); 5328 throw_if(md.outputs.size() != 1u, "invalid number of outputs for model '" + md.className + "'"); 5329 const auto vs = md.className + "_" + md.outputs[0].name; 5330 os << "dl0_l0[0]+=this->" << vs << "/3;\n" 5331 << "dl0_l0[1]+=this->" << vs << "/3;\n" 5332 << "dl0_l0[2]+=this->" << vs << "/3;\n"; 5333 this->writeModelCall(os, tmpnames, h, md, vs, vs, "sfeh"); 5334 os << "dl1_l0[0]+=this->" << vs << "/3;\n" 5335 << "dl1_l0[1]+=this->" << vs << "/3;\n" 5336 << "dl1_l0[2]+=this->" << vs << "/3;\n"; 5337 } else { 5338 throw_if(true, "internal error, unsupported stress free expansion"); 5339 } 5340 } else { 5341 throw_if(true, 5342 "internal error, unsupported stress " 5343 "free expansion description"); 5344 } 5345 } 5346 if (this->mb.getSymmetryType() == mfront::ORTHOTROPIC) { 5347 if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PIPE) { 5348 os << "tfel::material::convertStressFreeExpansionStrain<hypothesis,tfel::material::OrthotropicAxesConvention::" 5349 "PIPE>(dl0_l0);\n" 5350 << "tfel::material::convertStressFreeExpansionStrain<hypothesis,tfel::material::OrthotropicAxesConvention::" 5351 "PIPE>(dl1_l0);\n"; 5352 } else if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PLATE) { 5353 os << "tfel::material::convertStressFreeExpansionStrain<hypothesis,tfel::material::OrthotropicAxesConvention::" 5354 "PLATE>(dl0_l0);\n" 5355 << "tfel::material::convertStressFreeExpansionStrain<hypothesis,tfel::material::OrthotropicAxesConvention::" 5356 "PLATE>(dl1_l0);\n"; 5357 } else { 5358 throw_if(this->mb.getOrthotropicAxesConvention() != OrthotropicAxesConvention::DEFAULT, 5359 "internal error, unsupported orthotropic axes convention"); 5360 for (const auto mh : this->mb.getDistinctModellingHypotheses()) { 5361 throw_if(mh != ModellingHypothesis::TRIDIMENSIONAL, 5362 "an orthotropic axes convention must be choosen when " 5363 "defining a stress free expansion in behaviours " 5364 "which shall be valid in other modelling hypothesis " 5365 "than 'Tridimensional'.\n" 5366 "Either restrict the validity of the behaviour to " 5367 "'Tridimensional' (see @ModellingHypothesis) or " 5368 "choose and orthotropic axes convention as on option " 5369 "to the @OrthotropicBehaviour keyword"); 5370 } 5371 } 5372 } 5373 os << "}\n\n"; 5374 } // end of BehaviourDSLCommon::writeBehaviourComputeStressFreeExpansion 5375 writeBehaviourInitializeMethod(std::ostream & os,const Hypothesis h) const5376 void BehaviourDSLCommon::writeBehaviourInitializeMethod(std::ostream& os, const Hypothesis h) const { 5377 this->checkBehaviourFile(os); 5378 os << "/*!\n" 5379 << " * \\ brief initialize the behaviour with user code\n" 5380 << " */\n" 5381 << "void initialize(){\n" 5382 << "using namespace std;\n" 5383 << "using namespace tfel::math;\n" 5384 << "using std::vector;\n"; 5385 writeMaterialLaws(os, this->mb.getMaterialLaws()); 5386 if (this->mb.hasCode(h, BehaviourData::BeforeInitializeLocalVariables)) { 5387 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 5388 writeStandardPerformanceProfilingBegin(os, this->mb.getClassName(), 5389 BehaviourData::BeforeInitializeLocalVariables, "binit"); 5390 } 5391 os << this->mb.getCodeBlock(h, BehaviourData::BeforeInitializeLocalVariables).code << '\n'; 5392 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 5393 writeStandardPerformanceProfilingEnd(os); 5394 } 5395 } 5396 if (this->mb.hasCode(h, BehaviourData::InitializeLocalVariables)) { 5397 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 5398 writeStandardPerformanceProfilingBegin(os, this->mb.getClassName(), BehaviourData::InitializeLocalVariables, 5399 "init"); 5400 } 5401 os << this->mb.getCodeBlock(h, BehaviourData::InitializeLocalVariables).code << '\n'; 5402 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 5403 writeStandardPerformanceProfilingEnd(os); 5404 } 5405 } 5406 if (this->mb.hasCode(h, BehaviourData::AfterInitializeLocalVariables)) { 5407 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 5408 writeStandardPerformanceProfilingBegin(os, this->mb.getClassName(), 5409 BehaviourData::AfterInitializeLocalVariables, "ainit"); 5410 } 5411 os << this->mb.getCodeBlock(h, BehaviourData::AfterInitializeLocalVariables).code << '\n'; 5412 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 5413 writeStandardPerformanceProfilingEnd(os); 5414 } 5415 } 5416 this->writeBehaviourParserSpecificInitializeMethodPart(os, h); 5417 os << "}\n\n"; 5418 } // end of void BehaviourDSLCommon::writeBehaviourInitializeMethod 5419 writeBehaviourLocalVariablesInitialisation(std::ostream & os,const Hypothesis h) const5420 void BehaviourDSLCommon::writeBehaviourLocalVariablesInitialisation(std::ostream& os, const Hypothesis h) const { 5421 const auto& md = this->mb.getBehaviourData(h); 5422 this->checkBehaviourFile(os); 5423 for (const auto& v : md.getLocalVariables()) { 5424 if (this->mb.useDynamicallyAllocatedVector(v.arraySize)) { 5425 os << "this->" << v.name << ".resize(" << v.arraySize << ");\n"; 5426 } 5427 } 5428 } 5429 writeBehaviourParameterInitialisation(std::ostream & os,const Hypothesis h) const5430 void BehaviourDSLCommon::writeBehaviourParameterInitialisation( 5431 std::ostream& os, const Hypothesis h) const { 5432 constexpr const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 5433 this->checkBehaviourFile(os); 5434 const auto& d = this->mb.getBehaviourData(h); 5435 for (const auto& p : d.getParameters()) { 5436 if ((h == uh) || (this->mb.hasParameter(uh, p.name))) { 5437 if (p.arraySize == 1u) { 5438 os << "this->" << p.name << " = " << this->mb.getClassName() 5439 << "ParametersInitializer::get()." << p.name << ";\n"; 5440 } else { 5441 os << "tfel::fsalgo::copy<" << p.arraySize << ">::exe(" 5442 << this->mb.getClassName() << "ParametersInitializer::get()." 5443 << p.name << ".begin(),this->" << p.name << ".begin());\n"; 5444 } 5445 } else { 5446 if (p.arraySize == 1u) { 5447 os << "this->" << p.name << " = " << this->mb.getClassName() 5448 << ModellingHypothesis::toString(h) 5449 << "ParametersInitializer::get()." << p.name << ";\n"; 5450 } else { 5451 os << "tfel::fsalgo::copy<" << p.arraySize << ">::exe(" 5452 << this->mb.getClassName() << ModellingHypothesis::toString(h) 5453 << "ParametersInitializer::get()." << p.name << ".begin(),this->" 5454 << p.name << ".begin());\n"; 5455 } 5456 } 5457 } 5458 } // end of BehaviourDSLCommon::writeBehaviourParameterInitialisation 5459 writeBehaviourDataMainVariablesSetters(std::ostream & os) const5460 void BehaviourDSLCommon::writeBehaviourDataMainVariablesSetters(std::ostream& os) const { 5461 this->checkBehaviourDataFile(os); 5462 for (const auto& i : this->interfaces) { 5463 i.second->writeBehaviourDataMainVariablesSetters(os, this->mb); 5464 os << '\n'; 5465 } 5466 } // end of BehaviourDSLCommon::writeBehaviourDataMainVariablesSetters 5467 writeIntegrationDataMainVariablesSetters(std::ostream & os) const5468 void BehaviourDSLCommon::writeIntegrationDataMainVariablesSetters(std::ostream& os) const { 5469 this->checkIntegrationDataFile(os); 5470 for (const auto& i : this->interfaces) { 5471 i.second->writeIntegrationDataMainVariablesSetters(os, this->mb); 5472 os << '\n'; 5473 } 5474 } // end of BehaviourDSLCommon::writeIntegrationDataMainVariablesSetters 5475 writeBehaviourGetModellingHypothesis(std::ostream & os) const5476 void BehaviourDSLCommon::writeBehaviourGetModellingHypothesis(std::ostream& os) const { 5477 this->checkBehaviourFile(os); 5478 os << "/*!\n" 5479 << "* \\return the modelling hypothesis\n" 5480 << "*/\n" 5481 << "constexpr ModellingHypothesis::Hypothesis\ngetModellingHypothesis() const{\n" 5482 << "return hypothesis;\n" 5483 << "} // end of getModellingHypothesis\n\n"; 5484 } // end of BehaviourDSLCommon::writeBehaviourGetModellingHypothesis(); 5485 writeBehaviourLocalVariables(std::ostream & os,const Hypothesis h) const5486 void BehaviourDSLCommon::writeBehaviourLocalVariables(std::ostream& os, const Hypothesis h) const { 5487 this->checkBehaviourFile(os); 5488 const auto& md = this->mb.getBehaviourData(h); 5489 this->writeVariablesDeclarations(os, md.getLocalVariables(), "", "", this->fd.fileName, false); 5490 os << '\n'; 5491 } 5492 writeBehaviourIntegrationVariables(std::ostream & os,const Hypothesis h) const5493 void BehaviourDSLCommon::writeBehaviourIntegrationVariables(std::ostream& os, const Hypothesis h) const { 5494 this->checkBehaviourFile(os); 5495 const auto& md = this->mb.getBehaviourData(h); 5496 for (const auto& v : md.getIntegrationVariables()) { 5497 if (!md.isStateVariableName(v.name)) { 5498 if (md.isMemberUsedInCodeBlocks(v.name)) { 5499 this->writeVariableDeclaration(os, v, "", "", this->fd.fileName, false); 5500 } 5501 } 5502 } 5503 os << '\n'; 5504 } // end od BehaviourDSLCommon::writeBehaviourIntegrationVariables 5505 writeBehaviourParameters(std::ostream & os,const Hypothesis h) const5506 void BehaviourDSLCommon::writeBehaviourParameters(std::ostream& os, const Hypothesis h) const { 5507 this->checkBehaviourFile(os); 5508 const auto& d = this->mb.getBehaviourData(h); 5509 for (const auto& v : d.getParameters()) { 5510 if (!getDebugMode()) { 5511 if (v.lineNumber != 0u) { 5512 os << "#line " << v.lineNumber << " \"" << this->fd.fileName << "\"\n"; 5513 } 5514 } 5515 if (v.arraySize == 1) { 5516 os << v.type << " " << v.name << ";\n"; 5517 } else { 5518 os << "tfel::math::tvector<" << v.arraySize << "," << v.type << "> " << v.name << ";\n"; 5519 } 5520 } 5521 os << '\n'; 5522 } 5523 writeBehaviourPolicyVariable(std::ostream & os) const5524 void BehaviourDSLCommon::writeBehaviourPolicyVariable(std::ostream& os) const { 5525 this->checkBehaviourFile(os); 5526 os << "//! policy for treating out of bounds conditions\n" 5527 << "OutOfBoundsPolicy policy = None;\n"; 5528 } // end of BehaviourDSLCommon::writeBehaviourPolicyVariable 5529 writeBehaviourStaticVariables(std::ostream & os,const Hypothesis h) const5530 void BehaviourDSLCommon::writeBehaviourStaticVariables(std::ostream& os, const Hypothesis h) const { 5531 const auto& md = this->mb.getBehaviourData(h); 5532 this->checkBehaviourFile(os); 5533 for (const auto& v : md.getStaticVariables()) { 5534 if (!getDebugMode()) { 5535 if (v.lineNumber != 0u) { 5536 os << "#line " << v.lineNumber << " \"" << this->fd.fileName << "\"\n"; 5537 } 5538 } 5539 if (v.type == "int") { 5540 os << "static constexpr " << v.type << " " << v.name << " = " << v.value << ";\n"; 5541 } else { 5542 os << "static const " << v.type << " " << v.name << ";\n"; 5543 } 5544 } 5545 os << '\n'; 5546 } 5547 writeBehaviourIntegrationVariablesIncrements(std::ostream & os,const Hypothesis h) const5548 void BehaviourDSLCommon::writeBehaviourIntegrationVariablesIncrements(std::ostream& os, const Hypothesis h) const { 5549 const auto& md = this->mb.getBehaviourData(h); 5550 this->checkBehaviourFile(os); 5551 this->writeVariablesDeclarations(os, md.getIntegrationVariables(), "d", "", this->fd.fileName, 5552 this->useStateVarTimeDerivative); 5553 os << '\n'; 5554 } 5555 writeBehaviourOutputOperator(std::ostream & os,const Hypothesis h) const5556 void BehaviourDSLCommon::writeBehaviourOutputOperator(std::ostream& os, const Hypothesis h) const { 5557 const auto& md = this->mb.getBehaviourData(h); 5558 this->checkBehaviourFile(os); 5559 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 5560 if (this->mb.useQt()) { 5561 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n" 5562 << "std::ostream&\n" 5563 << "operator <<(std::ostream& os," 5564 << "const " << this->mb.getClassName() << "<hypothesis,Type,use_qt>& b)\n"; 5565 } else { 5566 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n" 5567 << "std::ostream&\n" 5568 << "operator <<(std::ostream& os," 5569 << "const " << this->mb.getClassName() << "<hypothesis,Type,false>& b)\n"; 5570 } 5571 } else { 5572 if (this->mb.useQt()) { 5573 os << "template<typename Type,bool use_qt>\n" 5574 << "std::ostream&\n" 5575 << "operator <<(std::ostream& os," 5576 << "const " << this->mb.getClassName() 5577 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>& b)\n"; 5578 } else { 5579 os << "template<typename Type>\n" 5580 << "std::ostream&\n" 5581 << "operator <<(std::ostream& os," 5582 << "const " << this->mb.getClassName() 5583 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>& b)\n"; 5584 } 5585 } 5586 os << "{\n"; 5587 for (const auto& v : this->mb.getMainVariables()) { 5588 if (Gradient::isIncrementKnown(v.first)) { 5589 os << "os << \"" << displayName(v.first) << " : \" << b." 5590 << v.first.name << " << '\\n';\n"; 5591 if (getUnicodeOutputOption()) { 5592 os << "os << \"\u0394" << displayName(v.first) << " : \" << b.d" 5593 << v.first.name << " << '\\n';\n"; 5594 } else { 5595 os << "os << \"d" << displayName(v.first) << " : \" << b.d" 5596 << v.first.name << " << '\\n';\n"; 5597 } 5598 } else { 5599 if (getUnicodeOutputOption()) { 5600 os << "os << \"" << displayName(v.first) << "\u2080 : \" << b." 5601 << v.first.name << "0 << '\\n';\n" 5602 << "os << \"" << displayName(v.first) << "\u2081 : \" << b." 5603 << v.first.name << "1 << '\\n';\n"; 5604 } else { 5605 os << "os << \"" << displayName(v.first) << "0 : \" << b." 5606 << v.first.name << "0 << '\\n';\n" 5607 << "os << \"" << displayName(v.first) << "1 : \" << b." 5608 << v.first.name << "1 << '\\n';\n"; 5609 } 5610 } 5611 os << "os << \"" << displayName(v.second) << " : \" << b." 5612 << v.second.name << " << '\\n';\n"; 5613 } 5614 if (getUnicodeOutputOption()) { 5615 os << "os << \"\u0394t : \" << b.dt << '\\n';\n"; 5616 } else { 5617 os << "os << \"dt : \" << b.dt << '\\n';\n"; 5618 } 5619 for (const auto& v : md.getMaterialProperties()) { 5620 os << "os << \"" << displayName(v) << " : \" << b." << v.name 5621 << " << '\\n';\n"; 5622 } 5623 for (const auto& v : md.getStateVariables()) { 5624 os << "os << \"" << displayName(v) << " : \" << b." << v.name 5625 << " << '\\n';\n"; 5626 if (getUnicodeOutputOption()) { 5627 os << "os << \"\u0394" << displayName(v) << " : \" << b.d" << v.name 5628 << " << '\\n';\n"; 5629 } else { 5630 os << "os << \"d" << displayName(v) << " : \" << b.d" << v.name 5631 << " << '\\n';\n"; 5632 } 5633 } 5634 for (const auto& v : md.getAuxiliaryStateVariables()) { 5635 os << "os << \"" << displayName(v) << " : \" << b." << v.name 5636 << " << '\\n';\n"; 5637 } 5638 for (const auto& v : md.getExternalStateVariables()) { 5639 os << "os << \"" << displayName(v) << " : \" << b." << v.name 5640 << " << '\\n';\n"; 5641 if (getUnicodeOutputOption()) { 5642 os << "os << \"\u0394" << displayName(v) << " : \" << b.d" << v.name 5643 << " << '\\n';\n"; 5644 } else { 5645 os << "os << \"d" << displayName(v) << " : \" << b.d" << v.name 5646 << " << '\\n';\n"; 5647 } 5648 } 5649 for (const auto& v : md.getLocalVariables()) { 5650 #pragma message("BehaviourDSLCommon: handle LocalDataStructure properly") 5651 if ((v.type.size() >= 7) && (v.type.substr(0, 7) != "struct{")) { 5652 os << "os << \"" << displayName(v) << " : \" << b." << v.name 5653 << " << '\\n';\n"; 5654 } 5655 } 5656 for (const auto& v : md.getParameters()) { 5657 os << "os << \"" << displayName(v) << " : \" << b." << v.name 5658 << " << '\\n';\n"; 5659 } 5660 os << "return os;\n" 5661 << "}\n\n"; 5662 } 5663 writeBehaviourDestructor(std::ostream & os) const5664 void BehaviourDSLCommon::writeBehaviourDestructor(std::ostream& os) const { 5665 this->checkBehaviourFile(os); 5666 os << "//!\n" 5667 << "~" << this->mb.getClassName() << "()\n" 5668 << " override = default;\n\n"; 5669 } 5670 writeBehaviourUpdateExternalStateVariables(std::ostream & os,const Hypothesis h) const5671 void BehaviourDSLCommon::writeBehaviourUpdateExternalStateVariables(std::ostream& os, const Hypothesis h) const { 5672 const auto& md = this->mb.getBehaviourData(h); 5673 this->checkBehaviourFile(os); 5674 os << "void updateExternalStateVariables(){\n"; 5675 for (const auto& v : this->mb.getMainVariables()) { 5676 if (Gradient::isIncrementKnown(v.first)) { 5677 os << "this->" << v.first.name << " += this->d" << v.first.name << ";\n"; 5678 } else { 5679 os << "this->" << v.first.name << "0 = this->" << v.first.name << "1;\n"; 5680 } 5681 } 5682 for (const auto& v : md.getExternalStateVariables()) { 5683 os << "this->" << v.name << " += this->d" << v.name << ";\n"; 5684 } 5685 os << "}\n\n"; 5686 } 5687 writeBehaviourIncludes(std::ostream & os) const5688 void BehaviourDSLCommon::writeBehaviourIncludes(std::ostream& os) const { 5689 this->checkBehaviourFile(os); 5690 os << "#include<string>\n" 5691 << "#include<iostream>\n" 5692 << "#include<limits>\n" 5693 << "#include<stdexcept>\n" 5694 << "#include<algorithm>\n\n" 5695 << "#include\"TFEL/Raise.hxx\"\n" 5696 << "#include\"TFEL/PhysicalConstants.hxx\"\n" 5697 << "#include\"TFEL/Config/TFELConfig.hxx\"\n" 5698 << "#include\"TFEL/Config/TFELTypes.hxx\"\n" 5699 << "#include\"TFEL/Metaprogramming/StaticAssert.hxx\"\n" 5700 << "#include\"TFEL/TypeTraits/IsFundamentalNumericType.hxx\"\n" 5701 << "#include\"TFEL/TypeTraits/IsReal.hxx\"\n" 5702 << "#include\"TFEL/Math/General/IEEE754.hxx\"\n"; 5703 if(!this->mb.hasTrivialTangentOperatorStructure()){ 5704 os << "#include\"TFEL/Math/Vector/TVectorView.hxx\"\n" 5705 << "#include\"TFEL/Math/Matrix/TMatrixView.hxx\"\n"; 5706 } 5707 os << "#include\"TFEL/Material/MaterialException.hxx\"\n" 5708 << "#include\"TFEL/Material/MechanicalBehaviour.hxx\"\n" 5709 << "#include\"TFEL/Material/MechanicalBehaviourTraits.hxx\"\n" 5710 << "#include\"TFEL/Material/OutOfBoundsPolicy.hxx\"\n" 5711 << "#include\"TFEL/Material/BoundsCheck.hxx\"\n" 5712 << "#include\"TFEL/Material/IsotropicPlasticity.hxx\"\n" 5713 << "#include\"TFEL/Material/Lame.hxx\"\n" 5714 << "#include\"TFEL/Material/Hosford1972YieldCriterion.hxx\"\n"; 5715 if (this->mb.getSymmetryType() == ORTHOTROPIC) { 5716 os << "#include\"TFEL/Material/OrthotropicPlasticity.hxx\"\n" 5717 << "#include\"TFEL/Material/OrthotropicStressLinearTransformation.hxx\"\n" 5718 << "#include\"TFEL/Material/Hill.hxx\"\n" 5719 << "#include\"TFEL/Material/Barlat2004YieldCriterion.hxx\"\n" 5720 << "#include\"TFEL/Material/OrthotropicAxesConvention.hxx\"\n"; 5721 } 5722 if (this->mb.getAttribute(BehaviourDescription::computesStiffnessTensor, false)) { 5723 os << "#include\"TFEL/Material/StiffnessTensor.hxx\"\n"; 5724 } 5725 if ((this->mb.isStrainMeasureDefined()) && 5726 (this->mb.getStrainMeasure() == BehaviourDescription::HENCKY)) { 5727 os << "#include\"TFEL/Material/LogarithmicStrainComputeAxialStrainIncrementElasticPrediction.hxx\"\n"; 5728 } 5729 if (this->mb.getAttribute<bool>(BehaviourData::profiling, false)) { 5730 os << "#include\"MFront/BehaviourProfiler.hxx\"\n"; 5731 } 5732 os << "#include\"" << this->getBehaviourDataFileName() << "\"\n" 5733 << "#include\"" << this->getIntegrationDataFileName() << "\"\n"; 5734 os << '\n'; 5735 } 5736 writeBehaviourAdditionalMembers(std::ostream & os,const Hypothesis h) const5737 void BehaviourDSLCommon::writeBehaviourAdditionalMembers(std::ostream& os, const Hypothesis h) const { 5738 this->checkBehaviourFile(os); 5739 const auto& m = this->mb.getMembers(h); 5740 if (!m.empty()) { 5741 os << m << "\n\n"; 5742 } 5743 } 5744 writeBehaviourPrivate(std::ostream & os,const Hypothesis h) const5745 void BehaviourDSLCommon::writeBehaviourPrivate(std::ostream& os, const Hypothesis h) const { 5746 this->checkBehaviourFile(os); 5747 const auto& c = this->mb.getPrivateCode(h); 5748 if (!c.empty()) { 5749 os << c << "\n\n"; 5750 } 5751 } // end of void BehaviourDSLCommon::writeBehaviourPrivate 5752 writeBehaviourStandardTFELTypedefs(std::ostream & os) const5753 void BehaviourDSLCommon::writeBehaviourStandardTFELTypedefs(std::ostream& os) const { 5754 using namespace tfel::material; 5755 this->checkBehaviourFile(os); 5756 const auto btype = this->mb.getBehaviourTypeFlag(); 5757 os << "static " << constexpr_c << " unsigned short TVectorSize = N;\n" 5758 << "typedef tfel::math::StensorDimeToSize<N> StensorDimeToSize;\n" 5759 << "static " << constexpr_c << " unsigned short StensorSize = " 5760 << "StensorDimeToSize::value;\n" 5761 << "typedef tfel::math::TensorDimeToSize<N> TensorDimeToSize;\n" 5762 << "static " << constexpr_c << " unsigned short TensorSize = " 5763 << "TensorDimeToSize::value;\n\n"; 5764 this->writeStandardTFELTypedefs(os); 5765 os << '\n' << "public :\n\n"; 5766 const auto qt = this->mb.useQt() ? "use_qt" : "false"; 5767 os << "typedef " << this->mb.getClassName() << "BehaviourData<hypothesis,Type," << qt << "> BehaviourData;\n" 5768 << "typedef " << this->mb.getClassName() << "IntegrationData<hypothesis,Type," << qt << "> IntegrationData;\n" 5769 << "typedef typename MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::SMFlag SMFlag;\n" 5770 << "typedef typename MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::SMType SMType;\n" 5771 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::ELASTIC;\n" 5772 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::SECANTOPERATOR;\n" 5773 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::TANGENTOPERATOR;\n" 5774 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::CONSISTENTTANGENTOPERATOR;\n" 5775 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::NOSTIFFNESSREQUESTED;\n"; 5776 if ((this->mb.getBehaviourType() == BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) || 5777 (this->mb.getBehaviourType() == BehaviourDescription::COHESIVEZONEMODEL)) { 5778 os << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::STANDARDTANGENTOPERATOR;\n"; 5779 } else if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 5780 for (const auto& toflag : getFiniteStrainBehaviourTangentOperatorFlags()) { 5781 os << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt 5782 << ">::" << convertFiniteStrainBehaviourTangentOperatorFlagToString(toflag) << ";\n"; 5783 } 5784 } 5785 os << "using IntegrationResult = typename MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt 5786 << ">::IntegrationResult;\n\n" 5787 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::SUCCESS;\n" 5788 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::FAILURE;\n" 5789 << "using MechanicalBehaviour<" << btype << ",hypothesis,Type," << qt << ">::UNRELIABLE_RESULTS;\n\n"; 5790 if ((this->mb.getBehaviourType() == BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) || 5791 (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR)) { 5792 os << "using StressFreeExpansionType = " << this->mb.getStressFreeExpansionType() << ";\n\n"; 5793 } 5794 } // end of BehaviourDSLCommon::writeBehaviourStandardTFELTypedefs 5795 writeBehaviourTraits(std::ostream & os) const5796 void BehaviourDSLCommon::writeBehaviourTraits(std::ostream& os) const { 5797 constexpr const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 5798 this->checkBehaviourFile(os); 5799 const auto& ah = ModellingHypothesis::getModellingHypotheses(); 5800 // writing partial specialisations 5801 if (this->mb.getModellingHypotheses().size() >= 4u) { 5802 // on définit toutes les hypothèses par défaut 5803 this->writeBehaviourTraitsSpecialisation(os, uh, true); 5804 // unsupported hypothesis 5805 for (const auto h : ah) { 5806 if (this->mb.isModellingHypothesisSupported(h)) { 5807 if (this->mb.hasSpecialisedMechanicalData(h)) { 5808 this->writeBehaviourTraitsSpecialisation(os, h, true); 5809 } 5810 } else { 5811 this->writeBehaviourTraitsSpecialisation(os, h, false); 5812 } 5813 } 5814 } else { 5815 // on exclut toutes les hypothèses par défaut 5816 this->writeBehaviourTraitsSpecialisation(os, uh, false); 5817 // unsupported hypothesis 5818 for (const auto h : this->mb.getModellingHypotheses()) { 5819 this->writeBehaviourTraitsSpecialisation(os, h, true); 5820 } 5821 } 5822 } 5823 writeBehaviourTraitsSpecialisation(std::ostream & os,const Hypothesis h,const bool b) const5824 void BehaviourDSLCommon::writeBehaviourTraitsSpecialisation(std::ostream& os, 5825 const Hypothesis h, 5826 const bool b) const { 5827 SupportedTypes::TypeSize coefSize; 5828 SupportedTypes::TypeSize stateVarsSize; 5829 SupportedTypes::TypeSize externalStateVarsSize; 5830 SupportedTypes::TypeSize externalStateVarsSize2; 5831 if (b) { 5832 const auto& d = this->mb.getBehaviourData(h); 5833 for (const auto& m : d.getMaterialProperties()) { 5834 coefSize += this->getTypeSize(m.type, m.arraySize); 5835 } 5836 for (const auto& v : d.getPersistentVariables()) { 5837 stateVarsSize += this->getTypeSize(v.type, v.arraySize); 5838 } 5839 for (const auto& v : d.getExternalStateVariables()) { 5840 externalStateVarsSize += this->getTypeSize(v.type, v.arraySize); 5841 } 5842 externalStateVarsSize2 = externalStateVarsSize; 5843 externalStateVarsSize2 -= SupportedTypes::TypeSize(1, 0, 0, 0); 5844 } 5845 os << "/*!\n" 5846 << "* Partial specialisation for " << this->mb.getClassName() << ".\n" 5847 << "*/\n"; 5848 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 5849 if (this->mb.useQt()) { 5850 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n" 5851 << "class MechanicalBehaviourTraits<" << this->mb.getClassName() << "<hypothesis,Type,use_qt> >\n"; 5852 } else { 5853 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n" 5854 << "class MechanicalBehaviourTraits<" << this->mb.getClassName() << "<hypothesis,Type,false> >\n"; 5855 } 5856 } else { 5857 if (this->mb.useQt()) { 5858 os << "template<typename Type,bool use_qt>\n" 5859 << "class MechanicalBehaviourTraits<" << this->mb.getClassName() 5860 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt> >\n"; 5861 } else { 5862 os << "template<typename Type>\n" 5863 << "class MechanicalBehaviourTraits<" << this->mb.getClassName() 5864 << "<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false> >\n"; 5865 } 5866 } 5867 os << "{\n"; 5868 if (b) { 5869 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 5870 os << "static " << constexpr_c << " unsigned short N = " 5871 << "ModellingHypothesisToSpaceDimension<hypothesis>::value;\n"; 5872 } else { 5873 os << "static " << constexpr_c << " unsigned short N = ModellingHypothesisToSpaceDimension<" 5874 << "ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ">::value;\n"; 5875 } 5876 os << "static " << constexpr_c << " unsigned short TVectorSize = N;\n" 5877 << "typedef tfel::math::StensorDimeToSize<N> StensorDimeToSize;\n" 5878 << "static " << constexpr_c << " unsigned short StensorSize = " 5879 << "StensorDimeToSize::value;\n" 5880 << "typedef tfel::math::TensorDimeToSize<N> TensorDimeToSize;\n" 5881 << "static " << constexpr_c << " unsigned short TensorSize = " 5882 << "TensorDimeToSize::value;\n"; 5883 } 5884 os << "public:\n"; 5885 if (b) { 5886 os << "static " << constexpr_c << " bool is_defined = true;\n"; 5887 } else { 5888 os << "static " << constexpr_c << " bool is_defined = false;\n"; 5889 } 5890 if (this->mb.useQt()) { 5891 os << "static " << constexpr_c << " bool use_quantities = use_qt;\n"; 5892 } else { 5893 os << "static " << constexpr_c << " bool use_quantities = false;\n"; 5894 } 5895 if (this->mb.getSymmetryType() == mfront::ORTHOTROPIC) { 5896 os << "//! orthotropic axes convention\n"; 5897 if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::DEFAULT) { 5898 os << "static " << constexpr_c << " OrthotropicAxesConvention oac = OrthotropicAxesConvention::DEFAULT;\n"; 5899 } else if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PIPE) { 5900 os << "static " << constexpr_c << " OrthotropicAxesConvention oac = OrthotropicAxesConvention::PIPE;\n"; 5901 } else if (this->mb.getOrthotropicAxesConvention() == OrthotropicAxesConvention::PLATE) { 5902 os << "static " << constexpr_c << " OrthotropicAxesConvention oac = OrthotropicAxesConvention::PLATE;\n"; 5903 } else { 5904 this->throwRuntimeError("BehaviourDSLCommon::writeBehaviourTraitsSpecialisation", 5905 "internal error : unsupported orthotropic axes convention"); 5906 } 5907 } 5908 if ((b) && (this->mb.requiresStressFreeExpansionTreatment(h))) { 5909 os << "static " << constexpr_c << " bool hasStressFreeExpansion = true;\n"; 5910 } else { 5911 os << "static " << constexpr_c << " bool hasStressFreeExpansion = false;\n"; 5912 } 5913 if (this->mb.areThermalExpansionCoefficientsDefined()) { 5914 os << "static " << constexpr_c << " bool handlesThermalExpansion = true;\n"; 5915 } else { 5916 os << "static " << constexpr_c << " bool handlesThermalExpansion = false;\n"; 5917 } 5918 if (b) { 5919 os << "static " << constexpr_c << " unsigned short dimension = N;\n"; 5920 } else { 5921 os << "static " << constexpr_c << " unsigned short dimension = 0u;\n"; 5922 } 5923 os << "typedef Type NumType;\n" 5924 << "static " << constexpr_c << " unsigned short material_properties_nb = " << coefSize << ";\n" 5925 << "static " << constexpr_c << " unsigned short internal_variables_nb = " << stateVarsSize << ";\n" 5926 << "static " << constexpr_c << " unsigned short external_variables_nb = " << externalStateVarsSize << ";\n" 5927 << "static " << constexpr_c << " unsigned short external_variables_nb2 = " << externalStateVarsSize2 << ";\n" 5928 << "static " << constexpr_c << " bool hasConsistentTangentOperator = "; 5929 if (b) { 5930 if (this->mb.getAttribute<bool>(h, BehaviourData::hasConsistentTangentOperator, false)) { 5931 os << "true;\n"; 5932 } else { 5933 os << "false;\n"; 5934 } 5935 } else { 5936 os << "false;\n"; 5937 } 5938 os << "static " << constexpr_c << " bool isConsistentTangentOperatorSymmetric = "; 5939 if (b) { 5940 if (this->mb.getAttribute<bool>(h, BehaviourData::isConsistentTangentOperatorSymmetric, false)) { 5941 os << "true;\n"; 5942 } else { 5943 os << "false;\n"; 5944 } 5945 } else { 5946 os << "false;\n"; 5947 } 5948 os << "static " << constexpr_c << " bool hasPredictionOperator = "; 5949 if (b) { 5950 if (this->mb.getAttribute<bool>(h, BehaviourData::hasPredictionOperator, false)) { 5951 os << "true;\n"; 5952 } else { 5953 os << "false;\n"; 5954 } 5955 } else { 5956 os << "false;\n"; 5957 } 5958 os << "static " << constexpr_c << " bool hasAPrioriTimeStepScalingFactor = "; 5959 if (b) { 5960 if (this->mb.getAttribute<bool>(h, BehaviourData::hasAPrioriTimeStepScalingFactor, false)) { 5961 os << "true;\n"; 5962 } else { 5963 os << "false;\n"; 5964 } 5965 } else { 5966 os << "false;\n"; 5967 } 5968 // internal enery 5969 os << "static " << constexpr_c << " bool hasComputeInternalEnergy = "; 5970 if (b) { 5971 if (this->mb.hasCode(h, BehaviourData::ComputeInternalEnergy)) { 5972 os << "true;\n"; 5973 } else { 5974 os << "false;\n"; 5975 } 5976 } else { 5977 os << "false;\n"; 5978 } 5979 // dissipated energy 5980 os << "static " << constexpr_c << " bool hasComputeDissipatedEnergy = "; 5981 if (b) { 5982 if (this->mb.hasCode(h, BehaviourData::ComputeDissipatedEnergy)) { 5983 os << "true;\n"; 5984 } else { 5985 os << "false;\n"; 5986 } 5987 } else { 5988 os << "false;\n"; 5989 } 5990 // name of the class 5991 os << "/*!\n" 5992 << "* \\return the name of the class.\n" 5993 << "*/\n" 5994 << "static const char* getName(){\n" 5995 << "return \"" << this->mb.getClassName() << "\";\n" 5996 << "}\n\n" 5997 << "};\n\n"; 5998 } 5999 writeBehaviourParserSpecificInheritanceRelationship(std::ostream & os) const6000 void BehaviourDSLCommon::writeBehaviourParserSpecificInheritanceRelationship(std::ostream& os) const { os << '\n'; } 6001 writeBehaviourParserSpecificTypedefs(std::ostream &) const6002 void BehaviourDSLCommon::writeBehaviourParserSpecificTypedefs(std::ostream&) const { 6003 // Empty member meant to be overriden in Child if necessary 6004 } 6005 writeBehaviourParserSpecificMembers(std::ostream &,const Hypothesis) const6006 void BehaviourDSLCommon::writeBehaviourParserSpecificMembers(std::ostream&, const Hypothesis) const { 6007 // Empty member meant to be overriden in Child if necessary 6008 } 6009 writeBehaviourParserSpecificIncludes(std::ostream &) const6010 void BehaviourDSLCommon::writeBehaviourParserSpecificIncludes(std::ostream&) const { 6011 // Empty member meant to be overriden in Child if necessary 6012 } 6013 writeBehaviourParametersInitializers(std::ostream & os) const6014 void BehaviourDSLCommon::writeBehaviourParametersInitializers(std::ostream& os) const { 6015 if (!this->mb.hasParameters()) { 6016 return; 6017 } 6018 auto mh = this->mb.getDistinctModellingHypotheses(); 6019 mh.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 6020 for (const auto h : mh) { 6021 if (this->mb.hasParameters(h)) { 6022 this->writeBehaviourParametersInitializer(os, h); 6023 } 6024 } 6025 } // end of BehaviourDSLCommon::writeBehaviourParametersInitializers 6026 writeBehaviourParametersInitializer(std::ostream & os,const Hypothesis h) const6027 void BehaviourDSLCommon::writeBehaviourParametersInitializer(std::ostream& os, const Hypothesis h) const { 6028 const auto& md = this->mb.getBehaviourData(h); 6029 const auto& params = md.getParameters(); 6030 std::string cname(this->mb.getClassName()); 6031 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 6032 cname += ModellingHypothesis::toString(h); 6033 } 6034 cname += "ParametersInitializer"; 6035 bool rp = false; 6036 bool ip = false; 6037 bool up = false; 6038 bool rp2 = false; 6039 bool ip2 = false; 6040 bool up2 = false; 6041 this->checkBehaviourFile(os); 6042 os << "struct " << cname << '\n' 6043 << "{\n" 6044 << "static " << cname << "&\n" 6045 << "get();\n\n"; 6046 for (const auto& p : params) { 6047 if (p.type == "int") { 6048 ip = true; 6049 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 6050 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 6051 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 6052 ip2 = true; 6053 os << "int " << p.name << ";\n"; 6054 } 6055 } else if (p.type == "ushort") { 6056 up = true; 6057 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 6058 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 6059 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 6060 up2 = true; 6061 os << "unsigned short " << p.name << ";\n"; 6062 } 6063 } else { 6064 const auto f = SupportedTypes::getTypeFlag(p.type); 6065 if (f != SupportedTypes::SCALAR) { 6066 this->throwRuntimeError("BehaviourDSLCommon::writeBehaviourParametersInitializer", 6067 "invalid type for parameter '" + p.name + "' ('" + p.type + "')"); 6068 } 6069 rp = true; 6070 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 6071 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 6072 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 6073 rp2 = true; 6074 if (p.arraySize == 1) { 6075 os << "double " << p.name << ";\n"; 6076 } else { 6077 os << "tfel::math::tvector<" << p.arraySize << ",double> " << p.name << ";\n"; 6078 } 6079 } 6080 } 6081 } 6082 if (!params.empty()) { 6083 os << '\n'; 6084 } 6085 if (rp) { 6086 os << "void set(const char* const,const double);\n\n"; 6087 } 6088 if (ip) { 6089 os << "void set(const char* const,const int);\n\n"; 6090 } 6091 if (up) { 6092 os << "void set(const char* const,const unsigned short);\n\n"; 6093 } 6094 if (rp2) { 6095 os << "/*!\n" 6096 << " * \\brief convert a string to double\n" 6097 << " * \\param[in] p : parameter\n" 6098 << " * \\param[in] v : value\n" 6099 << " */\n" 6100 << "static double getDouble(const std::string&,const std::string&);\n"; 6101 } 6102 if (ip2) { 6103 os << "/*!\n" 6104 << " * \\brief convert a string to int\n" 6105 << " * \\param[in] p : parameter\n" 6106 << " * \\param[in] v : value\n" 6107 << " */\n" 6108 << "static int getInt(const std::string&,const std::string&);\n"; 6109 } 6110 if (up2) { 6111 os << "/*!\n" 6112 << " * \\brief convert a string to unsigned short\n" 6113 << " * \\param[in] p : parameter\n" 6114 << " * \\param[in] v : value\n" 6115 << " */\n" 6116 << "static unsigned short getUnsignedShort(const std::string&,const std::string&);\n"; 6117 } 6118 os << "private :\n\n" 6119 << cname << "();\n\n" 6120 << cname << "(const " << cname << "&);\n\n" 6121 << cname << "&\n" 6122 << "operator=(const " << cname << "&);\n" 6123 << "/*!\n" 6124 << " * \\brief read the parameters from the given file\n" 6125 << " * \\param[out] pi : parameters initializer\n" 6126 << " * \\param[in] fn : file name\n" 6127 << " */\n" 6128 << "static void readParameters(" << cname << "&,const char* const);\n" 6129 << "};\n\n"; 6130 } // end of BehaviourDSLCommon::writeBehaviourParametersInitializer 6131 writeBehaviourParserSpecificInitializeMethodPart(std::ostream &,const Hypothesis) const6132 void BehaviourDSLCommon::writeBehaviourParserSpecificInitializeMethodPart(std::ostream&, const Hypothesis) const { 6133 // Empty member meant to be overriden in Child if necessary 6134 } 6135 writeBehaviourFileBegin(std::ostream & os) const6136 void BehaviourDSLCommon::writeBehaviourFileBegin(std::ostream& os) const { 6137 this->checkBehaviourFile(os); 6138 this->writeBehaviourFileHeader(os); 6139 this->writeBehaviourFileHeaderBegin(os); 6140 this->writeBehaviourIncludes(os); 6141 this->writeBehaviourParserSpecificIncludes(os); 6142 this->writeIncludes(os); 6143 // includes specific to interfaces 6144 for (const auto& i : this->interfaces) { 6145 i.second->writeInterfaceSpecificIncludes(os, this->mb); 6146 } 6147 this->writeNamespaceBegin(os); 6148 this->writeBehaviourParametersInitializers(os); 6149 this->writeBehaviourForwardDeclarations(os); 6150 this->writeBehaviourProfiler(os); 6151 } // end of BehaviourDSLCommon::writeBehaviourFileBegin 6152 writeBehaviourProfiler(std::ostream & os) const6153 void BehaviourDSLCommon::writeBehaviourProfiler(std::ostream& os) const { 6154 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 6155 this->checkBehaviourFile(os); 6156 os << "/*!\n" 6157 << " * " << this->mb.getClassName() << " profiler\n" 6158 << " */\n" 6159 << "struct " << this->mb.getClassName() << "Profiler\n" 6160 << "{\n" 6161 << "//! return the profiler associated with the behaviour\n" 6162 << "static mfront::BehaviourProfiler& getProfiler();\n" 6163 << "}; // end of struct " << this->mb.getClassName() << "Profiler\n\n"; 6164 } 6165 } // end of BehaviourDSLCommon::writeBehaviourProfiler 6166 writeBehaviourClass(std::ostream & os,const Hypothesis h) const6167 void BehaviourDSLCommon::writeBehaviourClass(std::ostream& os, const Hypothesis h) const { 6168 this->checkBehaviourFile(os); 6169 this->writeBehaviourClassBegin(os, h); 6170 this->writeBehaviourStandardTFELTypedefs(os); 6171 os << "private :\n\n"; 6172 this->writeBehaviourParserSpecificTypedefs(os); 6173 this->writeBehaviourStaticVariables(os, h); 6174 this->writeBehaviourIntegrationVariables(os, h); 6175 this->writeBehaviourIntegrationVariablesIncrements(os, h); 6176 this->writeBehaviourLocalVariables(os, h); 6177 this->writeBehaviourParameters(os, h); 6178 this->writeBehaviourTangentOperator(os); 6179 this->writeBehaviourParserSpecificMembers(os, h); 6180 this->writeBehaviourUpdateIntegrationVariables(os, h); 6181 this->writeBehaviourUpdateStateVariables(os, h); 6182 this->writeBehaviourUpdateAuxiliaryStateVariables(os, h); 6183 this->writeBehaviourAdditionalMembers(os, h); 6184 this->writeBehaviourPrivate(os, h); 6185 this->writeBehaviourDisabledConstructors(os); 6186 // from this point, all is public 6187 os << "public:\n\n"; 6188 this->writeBehaviourConstructors(os, h); 6189 this->writeBehaviourComputeStressFreeExpansion(os, h); 6190 this->writeBehaviourInitializeMethod(os, h); 6191 this->writeBehaviourSetOutOfBoundsPolicy(os); 6192 this->writeBehaviourGetModellingHypothesis(os); 6193 this->writeBehaviourCheckBounds(os, h); 6194 this->writeBehaviourComputePredictionOperator(os, h); 6195 this->writeBehaviourGetTimeStepScalingFactor(os); 6196 this->writeBehaviourComputeAPrioriTimeStepScalingFactor(os); 6197 this->writeBehaviourIntegrator(os, h); 6198 this->writeBehaviourComputeAPosterioriTimeStepScalingFactor(os); 6199 this->writeBehaviourComputeInternalEnergy(os, h); 6200 this->writeBehaviourComputeDissipatedEnergy(os, h); 6201 this->writeBehaviourComputeTangentOperator(os, h); 6202 this->writeBehaviourGetTangentOperator(os); 6203 this->writeBehaviourUpdateExternalStateVariables(os, h); 6204 this->writeBehaviourDestructor(os); 6205 this->checkBehaviourFile(os); 6206 os << "private:\n\n"; 6207 this->writeBehaviourComputeAPrioriTimeStepScalingFactorII(os, h); 6208 this->writeBehaviourComputeAPosterioriTimeStepScalingFactorII(os, h); 6209 this->writeBehaviourPolicyVariable(os); 6210 this->writeBehaviourClassEnd(os); 6211 this->writeBehaviourOutputOperator(os, h); 6212 } 6213 writeBehaviourFileEnd(std::ostream & os) const6214 void BehaviourDSLCommon::writeBehaviourFileEnd(std::ostream& os) const { 6215 this->checkBehaviourFile(os); 6216 this->writeBehaviourTraits(os); 6217 this->writeNamespaceEnd(os); 6218 this->writeBehaviourFileHeaderEnd(os); 6219 } // end of BehaviourDSLCommon::writeBehaviourFileBegin 6220 hasUserDefinedPredictionOperatorCode(const BehaviourDescription & mb,const tfel::material::ModellingHypothesis::Hypothesis h)6221 static bool hasUserDefinedPredictionOperatorCode(const BehaviourDescription& mb, 6222 const tfel::material::ModellingHypothesis::Hypothesis h) { 6223 using tfel::material::getFiniteStrainBehaviourTangentOperatorFlags; 6224 if (mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 6225 // all available tangent operators for finite strain behaviours 6226 const auto tos = getFiniteStrainBehaviourTangentOperatorFlags(); 6227 // search tangent operators defined by the user 6228 for (const auto& t : tos) { 6229 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6230 if (mb.hasCode(h, std::string(BehaviourData::ComputePredictionOperator) + '-' + ktype)) { 6231 return true; 6232 } 6233 } 6234 } else { 6235 if (mb.hasCode(h, BehaviourData::ComputePredictionOperator)) { 6236 return true; 6237 } 6238 } 6239 return false; 6240 } // end of BehaviourDSLCommon::hasUserDefinedTangentOperatorCode 6241 writeBehaviourComputePredictionOperator(std::ostream & os,const Hypothesis h) const6242 void BehaviourDSLCommon::writeBehaviourComputePredictionOperator(std::ostream& os, const Hypothesis h) const { 6243 using namespace std; 6244 using namespace tfel::material; 6245 const auto btype = this->mb.getBehaviourTypeFlag(); 6246 if ((!this->mb.getAttribute<bool>(h, BehaviourData::hasPredictionOperator, false)) && 6247 (this->mb.hasCode(h, BehaviourData::ComputePredictionOperator))) { 6248 this->throwRuntimeError("BehaviourDSLCommon::writeBehaviourComputePredictionOperator : ", 6249 "attribute 'hasPredictionOperator' is set but no associated code defined"); 6250 } 6251 if (!hasUserDefinedPredictionOperatorCode(this->mb, h)) { 6252 os << "IntegrationResult computePredictionOperator(const SMFlag,const SMType) override{\n" 6253 << "tfel::raise(\"" << this->mb.getClassName() << "::computePredictionOperator: \"\n" 6254 << "\"unsupported prediction operator flag\");\n" 6255 << "}\n\n"; 6256 return; 6257 } 6258 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 6259 // all available tangent operators for finite strain behaviours 6260 const auto tos(getFiniteStrainBehaviourTangentOperatorFlags()); 6261 // all known converters 6262 const auto converters = 6263 FiniteStrainBehaviourTangentOperatorConversion::getAvailableFiniteStrainBehaviourTangentOperatorConversions(); 6264 // tangent operators defined by the user 6265 vector<FiniteStrainBehaviourTangentOperatorBase::Flag> ktos; 6266 for (const auto& t : tos) { 6267 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6268 if (this->mb.hasCode(h, std::string(BehaviourData::ComputePredictionOperator) + '-' + ktype)) { 6269 ktos.push_back(t); 6270 } 6271 } 6272 if (!ktos.empty()) { 6273 // computing all the conversion paths starting from user defined ones 6274 vector<FiniteStrainBehaviourTangentOperatorConversionPath> paths; 6275 for (const auto& k : ktos) { 6276 const auto kpaths = 6277 FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath(k, ktos, converters); 6278 paths.insert(paths.end(), kpaths.begin(), kpaths.end()); 6279 } 6280 for (const auto& t : tos) { 6281 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6282 if (std::find(ktos.begin(), ktos.end(), t) != ktos.end()) { 6283 os << "IntegrationResult\ncomputePredictionOperator_" << ktype << "(const SMType smt){\n" 6284 << "using namespace std;\n" 6285 << "using namespace tfel::math;\n" 6286 << "using std::vector;\n"; 6287 writeMaterialLaws(os, this->mb.getMaterialLaws()); 6288 os << this->mb.getCode(h, std::string(BehaviourData::ComputePredictionOperator) + "-" + ktype) << '\n' 6289 << "return SUCCESS;\n" 6290 << "}\n\n"; 6291 } else { 6292 if ((h == 6293 ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) || 6294 (h == ModellingHypothesis::PLANESTRESS)) { 6295 os << "IntegrationResult computePredictionOperator_" << ktype << "(const SMType){\n" 6296 << "tfel::raise(\"" << this->mb.getClassName() << "::computePredictionOperator_" << ktype << ": \"\n" 6297 << "\"computing the prediction operator '" << ktype << "' is not supported\");\n" 6298 << "}\n\n"; 6299 } else { 6300 const auto path = 6301 FiniteStrainBehaviourTangentOperatorConversionPath:: 6302 getShortestPath(paths, t); 6303 if (path.empty()) { 6304 os << "IntegrationResult computePredictionOperator_" << ktype 6305 << "(const SMType){\n" 6306 << "tfel::raise(\"" << this->mb.getClassName() 6307 << "::computePredictionOperator_" << ktype << ": \"\n" 6308 << "\"computing the prediction operator '" << ktype 6309 << "' is not supported\");\n" 6310 << "}\n\n"; 6311 } else { 6312 os << "IntegrationResult computePredictionOperator_" << ktype 6313 << "(const SMType smt){\n"; 6314 auto pc = path.begin(); 6315 os << "using namespace tfel::math;\n"; 6316 os << "// computing " 6317 << convertFiniteStrainBehaviourTangentOperatorFlagToString( 6318 pc->from()) 6319 << '\n'; 6320 const auto k = 6321 convertFiniteStrainBehaviourTangentOperatorFlagToString( 6322 pc->from()); 6323 os << "this->computePredictionOperator_" << k << "(smt);\n" 6324 << "const " 6325 << getFiniteStrainBehaviourTangentOperatorFlagType( 6326 pc->from()) 6327 << "<N,stress>" 6328 << " tangentOperator_" 6329 << convertFiniteStrainBehaviourTangentOperatorFlagToString( 6330 pc->from()) 6331 << " = this->Dt.template get<" 6332 << getFiniteStrainBehaviourTangentOperatorFlagType( 6333 pc->from()) 6334 << "<N,stress> >();\n"; 6335 for (; pc != path.end();) { 6336 const auto converter = *pc; 6337 if (++pc == path.end()) { 6338 os << converter.getFinalConversion() << '\n'; 6339 } else { 6340 os << converter.getIntermediateConversion() << '\n'; 6341 } 6342 } 6343 os << "return SUCCESS;\n" 6344 << "}\n\n"; 6345 } 6346 } 6347 } 6348 } 6349 os << "IntegrationResult computePredictionOperator(const SMFlag smflag,const SMType smt) override{\n" 6350 << "using namespace std;\n" 6351 << "switch(smflag){\n"; 6352 for (const auto& t : tos) { 6353 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6354 os << "case " << ktype << ":\n" 6355 << "return this->computePredictionOperator_" << ktype << "(smt);\n"; 6356 } 6357 os << "}\n" 6358 << "tfel::raise(\"" << this->mb.getClassName() << "::computePredictionOperator: \"\n" 6359 << "\"unsupported prediction operator flag\");\n" 6360 << "}\n\n"; 6361 } 6362 } else { 6363 os << "IntegrationResult\n" 6364 << "computePredictionOperator(const SMFlag smflag,const SMType smt) override{\n" 6365 << "using namespace std;\n" 6366 << "using namespace tfel::math;\n" 6367 << "using std::vector;\n"; 6368 writeMaterialLaws(os, this->mb.getMaterialLaws()); 6369 if ((this->mb.getBehaviourType() == BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) || 6370 (this->mb.getBehaviourType() == BehaviourDescription::COHESIVEZONEMODEL)|| 6371 (this->mb.getBehaviourType() == BehaviourDescription::GENERALBEHAVIOUR)) { 6372 if (mb.useQt()) { 6373 os << "tfel::raise_if(smflag!=MechanicalBehaviour<" << btype 6374 << ",hypothesis,Type,use_qt>::STANDARDTANGENTOPERATOR,\n" 6375 << "\"invalid prediction operator flag\");\n"; 6376 } else { 6377 os << "tfel::raise_if(smflag!=MechanicalBehaviour<" << btype 6378 << ",hypothesis,Type,false>::STANDARDTANGENTOPERATOR,\n" 6379 << "\"invalid prediction operator flag\");\n"; 6380 } 6381 } 6382 os << this->mb.getCode(h, BehaviourData::ComputePredictionOperator) 6383 << "return SUCCESS;\n" 6384 << "}\n\n"; 6385 } 6386 } // end of BehaviourDSLCommon::writeBehaviourComputePredictionOperator 6387 writeBehaviourComputeTangentOperator(std::ostream & os,const Hypothesis h) const6388 void BehaviourDSLCommon::writeBehaviourComputeTangentOperator(std::ostream& os, const Hypothesis h) const { 6389 using namespace tfel::material; 6390 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 6391 // all available tangent operators for finite strain behaviours 6392 const auto tos(getFiniteStrainBehaviourTangentOperatorFlags()); 6393 // all known converters 6394 const auto converters = 6395 FiniteStrainBehaviourTangentOperatorConversion::getAvailableFiniteStrainBehaviourTangentOperatorConversions(); 6396 // tangent operators defined by the user 6397 std::vector<FiniteStrainBehaviourTangentOperatorBase::Flag> ktos; 6398 for (const auto& t : tos) { 6399 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6400 if (this->mb.hasCode(h, std::string(BehaviourData::ComputeTangentOperator) + '-' + ktype)) { 6401 ktos.push_back(t); 6402 } 6403 } 6404 if (!ktos.empty()) { 6405 // computing all the conversion paths starting from user defined ones 6406 std::vector<FiniteStrainBehaviourTangentOperatorConversionPath> paths; 6407 for (const auto& k : ktos) { 6408 const auto kpaths = 6409 FiniteStrainBehaviourTangentOperatorConversionPath::getConversionsPath(k, ktos, converters); 6410 paths.insert(paths.end(), kpaths.begin(), kpaths.end()); 6411 } 6412 for (const auto& t : tos) { 6413 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6414 if (find(ktos.begin(), ktos.end(), t) != ktos.end()) { 6415 os << "bool computeConsistentTangentOperator_" << ktype << "(const SMType smt){\n" 6416 << "using namespace std;\n" 6417 << "using namespace tfel::math;\n" 6418 << "using std::vector;\n"; 6419 writeMaterialLaws(os, this->mb.getMaterialLaws()); 6420 this->writeBehaviourComputeTangentOperatorBody( 6421 os, h, std::string(BehaviourData::ComputeTangentOperator) + 6422 "-" + ktype); 6423 os << "}\n\n"; 6424 } else { 6425 if ((h == 6426 ModellingHypothesis::AXISYMMETRICALGENERALISEDPLANESTRESS) || 6427 (h == ModellingHypothesis::PLANESTRESS)) { 6428 os << "bool computeConsistentTangentOperator_" << ktype 6429 << "(const SMType){\n" 6430 << "tfel::raise(\"" << this->mb.getClassName() 6431 << "::computeConsistentTangentOperator_" << ktype << ": \"\n" 6432 << "\"computing the tangent operator '" << ktype 6433 << "' is not supported\");\n" 6434 << "}\n\n"; 6435 } else { 6436 const auto path = 6437 FiniteStrainBehaviourTangentOperatorConversionPath:: 6438 getShortestPath(paths, t); 6439 if (path.empty()) { 6440 os << "bool computeConsistentTangentOperator_" << ktype 6441 << "(const SMType){\n" 6442 << "tfel::raise(\"" << this->mb.getClassName() 6443 << "::computeConsistentTangentOperator_" << ktype << ": \"\n" 6444 << "\"computing the tangent operator '" << ktype 6445 << "' is not supported\");\n" 6446 << "}\n\n"; 6447 } else { 6448 os << "bool computeConsistentTangentOperator_" << ktype 6449 << "(const SMType smt){\n"; 6450 auto pc = path.begin(); 6451 os << "using namespace tfel::math;\n"; 6452 os << "// computing " 6453 << convertFiniteStrainBehaviourTangentOperatorFlagToString( 6454 pc->from()) 6455 << '\n'; 6456 const auto k = 6457 convertFiniteStrainBehaviourTangentOperatorFlagToString( 6458 pc->from()); 6459 os << "this->computeConsistentTangentOperator_" << k 6460 << "(smt);\n" 6461 << "const " 6462 << getFiniteStrainBehaviourTangentOperatorFlagType( 6463 pc->from()) 6464 << "<N,stress>" 6465 << " tangentOperator_" 6466 << convertFiniteStrainBehaviourTangentOperatorFlagToString( 6467 pc->from()) 6468 << " = this->Dt.template get<" 6469 << getFiniteStrainBehaviourTangentOperatorFlagType( 6470 pc->from()) 6471 << "<N,stress> >();\n"; 6472 for (; pc != path.end();) { 6473 const auto converter = *pc; 6474 if (++pc == path.end()) { 6475 os << converter.getFinalConversion() << '\n'; 6476 } else { 6477 os << converter.getIntermediateConversion() << '\n'; 6478 } 6479 } 6480 os << "return true;\n" 6481 << "}\n\n"; 6482 } 6483 } 6484 } 6485 } 6486 os << "bool computeConsistentTangentOperator(const SMFlag smflag,const SMType smt){\n" 6487 << "switch(smflag){\n"; 6488 for (const auto& t : tos) { 6489 const auto ktype = convertFiniteStrainBehaviourTangentOperatorFlagToString(t); 6490 os << "case " << ktype << ":\n" 6491 << "return this->computeConsistentTangentOperator_" << ktype << "(smt);\n"; 6492 } 6493 os << "}\n" 6494 << "tfel::raise(\"" << this->mb.getClassName() << "::computeConsistentTangentOperator: \"\n" 6495 << "\"unsupported tangent operator flag\");\n" 6496 << "}\n\n"; 6497 } 6498 } else { 6499 if (this->mb.hasCode(h, BehaviourData::ComputeTangentOperator)) { 6500 os << "bool computeConsistentTangentOperator(const SMType smt){\n" 6501 << "using namespace std;\n" 6502 << "using namespace tfel::math;\n" 6503 << "using std::vector;\n"; 6504 writeMaterialLaws(os, this->mb.getMaterialLaws()); 6505 this->writeBehaviourComputeTangentOperatorBody( 6506 os, h, BehaviourData::ComputeTangentOperator); 6507 os << "}\n\n"; 6508 } 6509 } 6510 } // end of BehaviourDSLCommon::writeBehaviourComputeTangentOperator 6511 writeBehaviourComputeTangentOperatorBody(std::ostream & os,const Hypothesis h,const std::string & n) const6512 void BehaviourDSLCommon::writeBehaviourComputeTangentOperatorBody( 6513 std::ostream& os, const Hypothesis h, const std::string& n) const { 6514 os << this->mb.getCode(h, n) << '\n' << "return true;\n"; 6515 } // end of BehaviourDSLCommon::writeBehaviourComputeTangentOperatorBody 6516 writeBehaviourGetTangentOperator(std::ostream & os) const6517 void BehaviourDSLCommon::writeBehaviourGetTangentOperator(std::ostream& os) const { 6518 this->checkBehaviourFile(os); 6519 os << "const TangentOperator& getTangentOperator() const{\n" 6520 << "return this->Dt;\n" 6521 << "}\n\n"; 6522 } // end of BehaviourDSLCommon::writeBehaviourComputeTangentOperator() 6523 writeBehaviourGetTimeStepScalingFactor(std::ostream & os) const6524 void BehaviourDSLCommon::writeBehaviourGetTimeStepScalingFactor(std::ostream& os) const { 6525 this->checkBehaviourFile(os); 6526 os << "real getMinimalTimeStepScalingFactor() const override{\n" 6527 " return this->minimal_time_step_scaling_factor;\n" 6528 "}\n\n"; 6529 } 6530 writeBehaviourComputeAPrioriTimeStepScalingFactor(std::ostream & os) const6531 void BehaviourDSLCommon::writeBehaviourComputeAPrioriTimeStepScalingFactor(std::ostream& os) const { 6532 this->checkBehaviourFile(os); 6533 os << "std::pair<bool,real>\n" 6534 "computeAPrioriTimeStepScalingFactor(const real current_time_step_scaling_factor) const override{\n" 6535 "const auto time_scaling_factor = this->computeAPrioriTimeStepScalingFactorII();\n" 6536 "return {time_scaling_factor.first,\n" 6537 " std::min(std::min(std::max(time_scaling_factor.second,\n" 6538 " this->minimal_time_step_scaling_factor),\n" 6539 " this->maximal_time_step_scaling_factor),\n" 6540 " current_time_step_scaling_factor)};\n" 6541 "}\n\n"; 6542 } // end of BehaviourDSLCommon::writeBehaviourComputeAPrioriTimeStepScalingFactor 6543 writeBehaviourComputeAPrioriTimeStepScalingFactorII(std::ostream & os,const Hypothesis h) const6544 void BehaviourDSLCommon::writeBehaviourComputeAPrioriTimeStepScalingFactorII(std::ostream& os, 6545 const Hypothesis h) const { 6546 this->checkBehaviourFile(os); 6547 os << "std::pair<bool,real> computeAPrioriTimeStepScalingFactorII() const{\n"; 6548 if (this->mb.hasCode(h, BehaviourData::APrioriTimeStepScalingFactor)) { 6549 os << "using namespace std;\n" 6550 << "using namespace tfel::math;\n" 6551 << "using std::vector;\n"; 6552 writeMaterialLaws(os, this->mb.getMaterialLaws()); 6553 os << this->mb.getCode(h, BehaviourData::APrioriTimeStepScalingFactor) << '\n'; 6554 } 6555 os << "return {true,this->maximal_time_step_scaling_factor};\n" 6556 << "}\n\n"; 6557 } 6558 writeBehaviourComputeAPosterioriTimeStepScalingFactor(std::ostream & os) const6559 void BehaviourDSLCommon::writeBehaviourComputeAPosterioriTimeStepScalingFactor(std::ostream& os) const { 6560 this->checkBehaviourFile(os); 6561 os << "std::pair<bool,real>\n" 6562 "computeAPosterioriTimeStepScalingFactor(const real current_time_step_scaling_factor) const override{\n" 6563 "const auto time_scaling_factor = this->computeAPosterioriTimeStepScalingFactorII();\n" 6564 "return {time_scaling_factor.first,\n" 6565 " std::min(std::min(std::max(time_scaling_factor.second,\n" 6566 " this->minimal_time_step_scaling_factor),\n" 6567 " this->maximal_time_step_scaling_factor),\n" 6568 " current_time_step_scaling_factor)};\n" 6569 "}\n\n"; 6570 } // end of BehaviourDSLCommon::writeBehaviourComputeAPosterioriTimeStepScalingFactor 6571 writeBehaviourComputeAPosterioriTimeStepScalingFactorII(std::ostream & os,const Hypothesis h) const6572 void BehaviourDSLCommon::writeBehaviourComputeAPosterioriTimeStepScalingFactorII(std::ostream& os, 6573 const Hypothesis h) const { 6574 this->checkBehaviourFile(os); 6575 os << "std::pair<bool,real> computeAPosterioriTimeStepScalingFactorII() const{\n"; 6576 if (this->mb.hasCode(h, BehaviourData::APosterioriTimeStepScalingFactor)) { 6577 os << "using namespace std;\n" 6578 << "using namespace tfel::math;\n" 6579 << "using std::vector;\n"; 6580 writeMaterialLaws(os, this->mb.getMaterialLaws()); 6581 os << this->mb.getCode(h, BehaviourData::APosterioriTimeStepScalingFactor) << '\n'; 6582 } 6583 os << "return {true,this->maximal_time_step_scaling_factor};\n" 6584 << "}\n\n"; 6585 } // end of BehaviourDSLCommon::writeBehaviourComputeAPosterioriTimeStepScalingFactor 6586 writeBehaviourTangentOperator(std::ostream & os) const6587 void BehaviourDSLCommon::writeBehaviourTangentOperator( 6588 std::ostream& os) const { 6589 this->checkBehaviourFile(os); 6590 if (!this->mb.hasTangentOperator()) { 6591 return; 6592 } 6593 const auto& blocks = this->mb.getTangentOperatorBlocks(); 6594 os << "//! Tangent operator;\n" 6595 << "TangentOperator Dt;\n"; 6596 if (this->mb.hasTrivialTangentOperatorStructure()) { 6597 tfel::raise_if( 6598 ((blocks.size() != 1u) || (blocks.front().first.arraySize != 1u) || 6599 (blocks.front().second.arraySize != 1u)), 6600 "BehaviourDSLCommon::writeBehaviourTangentOperator: internal error"); 6601 if (this->mb.getBehaviourType() != 6602 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 6603 os << "//! alias to the tangent operator;\n" 6604 << "TangentOperator& " 6605 << this->mb.getTangentOperatorBlockName(blocks.front()) << ";\n"; 6606 } 6607 return; 6608 } 6609 // write blocks 6610 for (const auto& b : blocks) { 6611 const auto& v1 = b.first; 6612 const auto& v2 = b.second; 6613 if ((v1.arraySize != 1u) || (v2.arraySize != 1u)) { 6614 break; 6615 } 6616 auto throw_unsupported_block = [&v1, &v2] { 6617 tfel::raise( 6618 "BehaviourDSLCommon::writeBehaviourTangentOperator:" 6619 "tangent operator blocks associated with " 6620 "the derivative of '" + // 6621 displayName(v1) + "' (of type '" + v1.type + "') with respect to '" + // 6622 displayName(v2) + "' (of type '" + v2.type + "') is not supported"); 6623 }; 6624 const auto bn = this->mb.getTangentOperatorBlockName(b); 6625 if (v1.getTypeFlag() == SupportedTypes::SCALAR) { 6626 if (v2.getTypeFlag() == SupportedTypes::SCALAR) { 6627 os << "real& " << bn << ";\n"; 6628 } else if (v2.getTypeFlag() == SupportedTypes::STENSOR) { 6629 os << "tfel::math::StensorView<N,real> " << bn << ";\n"; 6630 } else if (v2.getTypeFlag() == SupportedTypes::TENSOR) { 6631 os << "tfel::math::TensorView<N,real> " << bn << ";\n"; 6632 } else { 6633 throw_unsupported_block(); 6634 } 6635 } else if (v1.getTypeFlag() == SupportedTypes::TVECTOR) { 6636 if (v2.getTypeFlag() == SupportedTypes::SCALAR) { 6637 os << "tfel::math::TVectorView<N,real> " << bn << ";\n"; 6638 } else if (v2.getTypeFlag() == SupportedTypes::TVECTOR) { 6639 os << "tfel::math::TMatrixView<N,N,real> " << bn << ";\n"; 6640 } else { 6641 throw_unsupported_block(); 6642 } 6643 } else if (v1.getTypeFlag() == SupportedTypes::STENSOR) { 6644 if (v2.getTypeFlag() == SupportedTypes::SCALAR) { 6645 os << "tfel::math::StensorView<N,real> " << bn << ";\n"; 6646 } else if (v2.getTypeFlag() == SupportedTypes::STENSOR) { 6647 os << "tfel::math::ST2toST2View<N,real> " << bn << ";\n"; 6648 } else if (v2.getTypeFlag() == SupportedTypes::TENSOR) { 6649 os << "tfel::math::ST2toT2View<N,real> " << bn << ";\n"; 6650 } else { 6651 throw_unsupported_block(); 6652 } 6653 } else if (v1.getTypeFlag() == SupportedTypes::TENSOR) { 6654 if (v2.getTypeFlag() == SupportedTypes::SCALAR) { 6655 os << "tfel::math::TensorView<N,real> " << bn << ";\n"; 6656 } else if (v2.getTypeFlag() == SupportedTypes::STENSOR) { 6657 os << "tfel::math::T2toST2View<N,real> " << bn << ";\n"; 6658 } else if (v2.getTypeFlag() == SupportedTypes::TENSOR) { 6659 os << "tfel::math::T2toT2View<N,real> " << bn << ";\n"; 6660 } else { 6661 throw_unsupported_block(); 6662 } 6663 } else { 6664 throw_unsupported_block(); 6665 } 6666 } 6667 } // end of BehaviourDSLCommon::writeBehaviourTangentOperator() 6668 checkIntegrationDataFile(std::ostream & os) const6669 void BehaviourDSLCommon::checkIntegrationDataFile(std::ostream& os) const { 6670 if ((!os) || (!os.good())) { 6671 this->throwRuntimeError( 6672 "BehaviourDSLCommon::checkIntegrationDataOutputFile", 6673 "output file is not valid"); 6674 } 6675 } 6676 writeIntegrationDataFileHeader(std::ostream & os) const6677 void BehaviourDSLCommon::writeIntegrationDataFileHeader(std::ostream& os) const { 6678 this->checkIntegrationDataFile(os); 6679 os << "/*!\n"; 6680 os << "* \\file " << this->getIntegrationDataFileName() << '\n'; 6681 os << "* \\brief " 6682 << "this file implements the " << this->mb.getClassName() << "IntegrationData" 6683 << " class.\n"; 6684 os << "* File generated by "; 6685 os << MFrontHeader::getVersionName() << " "; 6686 os << "version " << MFrontHeader::getVersionNumber(); 6687 os << '\n'; 6688 if (!this->fd.authorName.empty()) { 6689 os << "* \\author " << this->fd.authorName << '\n'; 6690 } 6691 if (!this->fd.date.empty()) { 6692 os << "* \\date " << this->fd.date << '\n'; 6693 } 6694 os << " */\n\n"; 6695 } 6696 writeIntegrationDataFileHeaderBegin(std::ostream & os) const6697 void BehaviourDSLCommon::writeIntegrationDataFileHeaderBegin(std::ostream& os) const { 6698 this->checkIntegrationDataFile(os); 6699 os << "#ifndef LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_INTEGRATION_DATA_HXX\n" 6700 << "#define LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_INTEGRATION_DATA_HXX\n\n"; 6701 } 6702 writeIntegrationDataFileHeaderEnd(std::ostream & os) const6703 void BehaviourDSLCommon::writeIntegrationDataFileHeaderEnd(std::ostream& os) const { 6704 this->checkIntegrationDataFile(os); 6705 os << "#endif /* LIB_TFELMATERIAL_" << makeUpperCase(this->mb.getClassName()) << "_INTEGRATION_DATA_HXX */\n"; 6706 } 6707 writeIntegrationDataStandardTFELIncludes(std::ostream & os) const6708 void BehaviourDSLCommon::writeIntegrationDataStandardTFELIncludes(std::ostream& os) const { 6709 bool b1 = false; 6710 bool b2 = false; 6711 this->checkIntegrationDataFile(os); 6712 os << "#include<string>\n" 6713 << "#include<iostream>\n" 6714 << "#include<limits>\n" 6715 << "#include<stdexcept>\n" 6716 << "#include<algorithm>\n\n" 6717 << "#include\"TFEL/Raise.hxx\"\n" 6718 << "#include\"TFEL/PhysicalConstants.hxx\"\n" 6719 << "#include\"TFEL/Config/TFELConfig.hxx\"\n" 6720 << "#include\"TFEL/Config/TFELTypes.hxx\"\n" 6721 << "#include\"TFEL/Metaprogramming/StaticAssert.hxx\"\n" 6722 << "#include\"TFEL/TypeTraits/IsFundamentalNumericType.hxx\"\n" 6723 << "#include\"TFEL/TypeTraits/IsScalar.hxx\"\n" 6724 << "#include\"TFEL/TypeTraits/IsReal.hxx\"\n" 6725 << "#include\"TFEL/TypeTraits/Promote.hxx\"\n" 6726 << "#include\"TFEL/Math/General/IEEE754.hxx\"\n"; 6727 this->mb.requiresTVectorOrVectorIncludes(b1, b2); 6728 if (b1) { 6729 os << "#include\"TFEL/Math/tvector.hxx\"\n" 6730 << "#include\"TFEL/Math/Vector/tvectorIO.hxx\"\n"; 6731 } 6732 if (b2) { 6733 os << "#include\"TFEL/Math/vector.hxx\"\n"; 6734 } 6735 os << "#include\"TFEL/Math/stensor.hxx\"\n" 6736 << "#include\"TFEL/Math/st2tost2.hxx\"\n"; 6737 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 6738 os << "#include\"TFEL/Math/tensor.hxx\"\n" 6739 << "#include\"TFEL/Math/t2tot2.hxx\"\n" 6740 << "#include\"TFEL/Math/t2tost2.hxx\"\n" 6741 << "#include\"TFEL/Math/st2tot2.hxx\"\n"; 6742 } 6743 } 6744 writeIntegrationDataDefaultMembers(std::ostream & os) const6745 void BehaviourDSLCommon::writeIntegrationDataDefaultMembers(std::ostream& os) const { 6746 this->checkIntegrationDataFile(os); 6747 os << "protected: \n\n"; 6748 for (const auto& v : this->mb.getMainVariables()) { 6749 if (Gradient::isIncrementKnown(v.first)) { 6750 os << "/*!\n" 6751 << " * \\brief " << v.first.name << " increment\n" 6752 << " */\n" 6753 << v.first.type << " d" << v.first.name << ";\n\n"; 6754 } else { 6755 os << "/*!\n" 6756 << " * \\brief " << v.first.name << " at the end of the time step\n" 6757 << " */\n" 6758 << v.first.type << " " << v.first.name << "1;\n\n"; 6759 } 6760 } 6761 os << "/*!\n" 6762 << " * \\brief time increment\n" 6763 << " */\n" 6764 << "time dt;\n\n"; 6765 } 6766 writeIntegrationDataStandardTFELTypedefs(std::ostream & os) const6767 void BehaviourDSLCommon::writeIntegrationDataStandardTFELTypedefs(std::ostream& os) const { 6768 this->checkIntegrationDataFile(os); 6769 os << "static " << constexpr_c << " unsigned short TVectorSize = N;\n" 6770 << "typedef tfel::math::StensorDimeToSize<N> StensorDimeToSize;\n" 6771 << "static " << constexpr_c << " unsigned short StensorSize = " 6772 << "StensorDimeToSize::value;\n" 6773 << "typedef tfel::math::TensorDimeToSize<N> TensorDimeToSize;\n" 6774 << "static " << constexpr_c << " unsigned short TensorSize = " 6775 << "TensorDimeToSize::value;\n\n"; 6776 this->writeStandardTFELTypedefs(os); 6777 os << '\n'; 6778 } 6779 writeIntegrationDataDisabledConstructors(std::ostream & os) const6780 void BehaviourDSLCommon::writeIntegrationDataDisabledConstructors(std::ostream& os) const { 6781 this->checkIntegrationDataFile(os); 6782 } 6783 writeIntegrationDataConstructors(std::ostream & os,const Hypothesis h) const6784 void BehaviourDSLCommon::writeIntegrationDataConstructors(std::ostream& os, const Hypothesis h) const { 6785 const auto& md = this->mb.getBehaviourData(h); 6786 this->checkIntegrationDataFile(os); 6787 os << "/*!\n" 6788 << "* \\brief Default constructor\n" 6789 << "*/\n" 6790 << this->mb.getClassName() << "IntegrationData()\n" 6791 << "{}\n\n" 6792 << "/*!\n" 6793 << "* \\brief Copy constructor\n" 6794 << "*/\n" 6795 << this->mb.getClassName() << "IntegrationData(const " << this->mb.getClassName() << "IntegrationData& src)\n" 6796 << ": "; 6797 for (const auto& v : this->mb.getMainVariables()) { 6798 if (Gradient::isIncrementKnown(v.first)) { 6799 os << "d" << v.first.name << "(src.d" << v.first.name << "),\n"; 6800 } else { 6801 os << v.first.name << "1(src." << v.first.name << "1),\n"; 6802 } 6803 } 6804 os << "dt(src.dt)"; 6805 for (const auto& v : md.getExternalStateVariables()) { 6806 os << ",\nd" << v.name << "(src.d" << v.name << ")"; 6807 } 6808 os << "\n{}\n\n"; 6809 // Creating constructor for external interfaces 6810 for (const auto& i : this->interfaces) { 6811 if (i.second->isBehaviourConstructorRequired(h, this->mb)) { 6812 i.second->writeIntegrationDataConstructor(os, h, this->mb); 6813 } 6814 } 6815 } 6816 writeIntegrationDataScaleOperators(std::ostream & os,const Hypothesis h) const6817 void BehaviourDSLCommon::writeIntegrationDataScaleOperators(std::ostream& os, const Hypothesis h) const { 6818 const auto& md = this->mb.getBehaviourData(h); 6819 bool iknown = true; 6820 for (const auto& v : this->mb.getMainVariables()) { 6821 iknown = Gradient::isIncrementKnown(v.first); 6822 } 6823 this->checkIntegrationDataFile(os); 6824 os << "/*\n" 6825 << "* \\brief scale the integration data by a scalar.\n" 6826 << "*/\n" 6827 << "template<typename Scal>\n" 6828 << "typename std::enable_if<\n" 6829 << "tfel::typetraits::IsFundamentalNumericType<Scal>::cond&&\n" 6830 << "tfel::typetraits::IsScalar<Scal>::cond&&\n" 6831 << "tfel::typetraits::IsReal<Scal>::cond&&\n" 6832 << "std::is_same<Type," 6833 << "typename tfel::typetraits::Promote" 6834 << "<Type,Scal>::type>::value,\n" 6835 << this->mb.getClassName() << "IntegrationData&\n" 6836 << ">::type\n"; 6837 if (!iknown) { 6838 if (this->mb.useQt()) { 6839 os << "scale(const " << this->mb.getClassName() 6840 << "BehaviourData<hypothesis,Type,use_qt>& behaviourData, const Scal time_scaling_factor){\n"; 6841 } else { 6842 os << "scale(const " << this->mb.getClassName() 6843 << "BehaviourData<hypothesis,Type,false>& behaviourData, const Scal time_scaling_factor){\n"; 6844 } 6845 } else { 6846 if (this->mb.useQt()) { 6847 os << "scale(const " << this->mb.getClassName() 6848 << "BehaviourData<hypothesis,Type,use_qt>&, const Scal time_scaling_factor){\n"; 6849 } else { 6850 os << "scale(const " << this->mb.getClassName() 6851 << "BehaviourData<hypothesis,Type,false>&, const Scal time_scaling_factor){\n"; 6852 } 6853 } 6854 os << "this->dt *= time_scaling_factor;\n"; 6855 for (const auto& v : this->mb.getMainVariables()) { 6856 if (Gradient::isIncrementKnown(v.first)) { 6857 os << "this->d" << v.first.name << " *= time_scaling_factor;\n"; 6858 } else { 6859 os << "this->" << v.first.name << "1 = (1-time_scaling_factor)*(behaviourData." << v.first.name 6860 << "0)+time_scaling_factor*(this->" << v.first.name << "1);\n"; 6861 } 6862 } 6863 for (const auto& v : md.getExternalStateVariables()) { 6864 os << "this->d" << v.name << " *= time_scaling_factor;\n"; 6865 } 6866 os << "return *this;\n" 6867 << "}\n\n"; 6868 } // end of BehaviourDSLCommon::writeIntegrationDataScaleOpeartors 6869 writeIntegrationDataUpdateDrivingVariablesMethod(std::ostream & os) const6870 void BehaviourDSLCommon::writeIntegrationDataUpdateDrivingVariablesMethod(std::ostream& os) const { 6871 bool iknown = true; 6872 for (const auto& v : this->mb.getMainVariables()) { 6873 iknown = Gradient::isIncrementKnown(v.first); 6874 } 6875 this->checkIntegrationDataFile(os); 6876 os << "/*!\n" 6877 << "* \\brief update the driving variable in case of substepping.\n" 6878 << "*/\n" 6879 << this->mb.getClassName() << "IntegrationData&\n"; 6880 if (!iknown) { 6881 if (this->mb.useQt()) { 6882 os << "updateDrivingVariables(const " << this->mb.getClassName() 6883 << "BehaviourData<hypothesis,Type,use_qt>& behaviourData){\n"; 6884 } else { 6885 os << "updateDrivingVariables(const " << this->mb.getClassName() 6886 << "BehaviourData<hypothesis,Type,false>& behaviourData){\n"; 6887 } 6888 } else { 6889 if (this->mb.useQt()) { 6890 os << "updateDrivingVariables(const " << this->mb.getClassName() 6891 << "BehaviourData<hypothesis,Type,use_qt>&){\n"; 6892 } else { 6893 os << "updateDrivingVariables(const " << this->mb.getClassName() 6894 << "BehaviourData<hypothesis,Type,false>&){\n"; 6895 } 6896 } 6897 for (const auto& v : this->mb.getMainVariables()) { 6898 if (!Gradient::isIncrementKnown(v.first)) { 6899 os << "this->" << v.first.name << "1 += " 6900 << "this->" << v.first.name << "1 - (behaviourData." 6901 << v.first.name << "0);\n"; 6902 } 6903 } 6904 os << "return *this;\n" 6905 << "}\n\n"; 6906 } // end of BehaviourDSLCommon::writeIntegrationUpdateDrivingVariablesMethod 6907 writeIntegrationDataClassHeader(std::ostream & os) const6908 void BehaviourDSLCommon::writeIntegrationDataClassHeader(std::ostream& os) const { 6909 this->checkIntegrationDataFile(os); 6910 os << "/*!\n" 6911 << "* \\class " << this->mb.getClassName() << "IntegrationData\n" 6912 << "* \\brief This class implements the " << this->mb.getClassName() << "IntegrationData" 6913 << " behaviour.\n" 6914 << "* \\param unsigned short N, space dimension.\n" 6915 << "* \\param typename Type, numerical type.\n" 6916 << "* \\param bool use_qt, conditional saying if quantities are use.\n"; 6917 if (!this->fd.authorName.empty()) { 6918 os << "* \\author " << this->fd.authorName << '\n'; 6919 } 6920 if (!this->fd.date.empty()) { 6921 os << "* \\date " << this->fd.date << '\n'; 6922 } 6923 os << "*/\n"; 6924 } 6925 writeIntegrationDataForwardDeclarations(std::ostream & os) const6926 void BehaviourDSLCommon::writeIntegrationDataForwardDeclarations(std::ostream& os) const { 6927 this->checkIntegrationDataFile(os); 6928 os << "//! \\brief forward declaration\n" 6929 << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n" 6930 << "class " << this->mb.getClassName() << "IntegrationData;\n\n"; 6931 if (this->mb.useQt()) { 6932 os << "//! \\brief forward declaration\n" 6933 << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n" 6934 << "std::ostream&\n operator <<(std::ostream&," 6935 << "const " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,use_qt>&);\n\n"; 6936 } else { 6937 os << "//! \\brief forward declaration\n" 6938 << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n" 6939 << "std::ostream&\n operator <<(std::ostream&," 6940 << "const " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>&);\n\n"; 6941 } 6942 // maintenant, il faut déclarer toutes les spécialisations partielles... 6943 const auto& mh = this->mb.getModellingHypotheses(); 6944 for (const auto& h : mh) { 6945 if (this->mb.hasSpecialisedMechanicalData(h)) { 6946 if (this->mb.useQt()) { 6947 os << "//! \\brief forward declaration\n" 6948 << "template<typename Type,bool use_qt>\n" 6949 << "std::ostream&\n operator <<(std::ostream&," 6950 << "const " << this->mb.getClassName() 6951 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 6952 << ",Type,use_qt>&);\n\n"; 6953 } else { 6954 os << "//! \\brief forward declaration\n" 6955 << "template<typename Type>\n" 6956 << "std::ostream&\n operator <<(std::ostream&," 6957 << "const " << this->mb.getClassName() 6958 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 6959 << ",Type,false>&);\n\n"; 6960 } 6961 } 6962 } 6963 } 6964 writeIntegrationDataClassBegin(std::ostream & os,const Hypothesis h) const6965 void BehaviourDSLCommon::writeIntegrationDataClassBegin(std::ostream& os, const Hypothesis h) const { 6966 this->checkIntegrationDataFile(os); 6967 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 6968 if (this->mb.useQt()) { 6969 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n"; 6970 os << "class " << this->mb.getClassName() << "IntegrationData\n"; 6971 } else { 6972 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n"; 6973 os << "class " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>\n"; 6974 } 6975 } else { 6976 if (this->mb.useQt()) { 6977 os << "template<typename Type,bool use_qt>\n"; 6978 os << "class " << this->mb.getClassName() 6979 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,use_qt>\n"; 6980 } else { 6981 os << "template<typename Type>\n"; 6982 os << "class " << this->mb.getClassName() 6983 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ",Type,false>\n"; 6984 } 6985 } 6986 os << "{\n\n"; 6987 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 6988 os << "static " << constexpr_c << " ModellingHypothesis::Hypothesis hypothesis = " 6989 << "ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) << ";\n"; 6990 } 6991 os << "static " << constexpr_c << " unsigned short N = ModellingHypothesisToSpaceDimension<hypothesis>::value;\n"; 6992 os << "TFEL_STATIC_ASSERT(N==1||N==2||N==3);\n"; 6993 os << "TFEL_STATIC_ASSERT(tfel::typetraits::" 6994 << "IsFundamentalNumericType<Type>::cond);\n"; 6995 os << "TFEL_STATIC_ASSERT(tfel::typetraits::IsReal<Type>::cond);\n\n"; 6996 os << "friend std::ostream& operator<< <>(std::ostream&,const "; 6997 os << this->mb.getClassName() << "IntegrationData&);\n\n"; 6998 } 6999 writeIntegrationDataOutputOperator(std::ostream & os,const Hypothesis h) const7000 void BehaviourDSLCommon::writeIntegrationDataOutputOperator(std::ostream& os, const Hypothesis h) const { 7001 const auto& md = this->mb.getBehaviourData(h); 7002 this->checkBehaviourFile(os); 7003 if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 7004 if (this->mb.useQt()) { 7005 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type,bool use_qt>\n"; 7006 os << "std::ostream&\n"; 7007 os << "operator <<(std::ostream& os,"; 7008 os << "const " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,use_qt>& b)\n"; 7009 } else { 7010 os << "template<ModellingHypothesis::Hypothesis hypothesis,typename Type>\n"; 7011 os << "std::ostream&\n"; 7012 os << "operator <<(std::ostream& os,"; 7013 os << "const " << this->mb.getClassName() << "IntegrationData<hypothesis,Type,false>& b)\n"; 7014 } 7015 } else { 7016 if (this->mb.useQt()) { 7017 os << "template<typename Type,bool use_qt>\n"; 7018 os << "std::ostream&\n"; 7019 os << "operator <<(std::ostream& os,"; 7020 os << "const " << this->mb.getClassName() 7021 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 7022 << ",Type,use_qt>& b)\n"; 7023 } else { 7024 os << "template<typename Type>\n"; 7025 os << "std::ostream&\n"; 7026 os << "operator <<(std::ostream& os,"; 7027 os << "const " << this->mb.getClassName() 7028 << "IntegrationData<ModellingHypothesis::" << ModellingHypothesis::toUpperCaseString(h) 7029 << ",Type,false>& b)\n"; 7030 } 7031 } 7032 os << "{\n"; 7033 for (const auto& v : this->mb.getMainVariables()) { 7034 if (Gradient::isIncrementKnown(v.first)) { 7035 if (getUnicodeOutputOption()) { 7036 os << "os << \"\u0394" << displayName(v.first) << " : \" << b.d" 7037 << v.first.name << " << '\\n';\n"; 7038 } else { 7039 os << "os << \"d" << displayName(v.first) << " : \" << b.d" 7040 << v.first.name << " << '\\n';\n"; 7041 } 7042 } else { 7043 if (getUnicodeOutputOption()) { 7044 os << "os << \"" << displayName(v.first) << "\u2081 : \" << b." 7045 << v.first.name << "1 << '\\n';\n"; 7046 } else { 7047 os << "os << \"" << displayName(v.first) << "1 : \" << b." 7048 << v.first.name << "1 << '\\n';\n"; 7049 } 7050 } 7051 os << "os << \"" << displayName(v.second) << " : \" << b." 7052 << v.second.name << " << '\\n';\n"; 7053 } 7054 if (getUnicodeOutputOption()) { 7055 os << "os << \"\u0394t : \" << b.dt << '\\n';\n"; 7056 } else { 7057 os << "os << \"dt : \" << b.dt << '\\n';\n"; 7058 } 7059 for (const auto& ev : md.getExternalStateVariables()) { 7060 if (getUnicodeOutputOption()) { 7061 os << "os << \"\u0394" << displayName(ev) << " : \" << b.d" << ev.name 7062 << " << '\\n';\n"; 7063 } else { 7064 os << "os << \"d" << displayName(ev) << " : \" << b.d" << ev.name 7065 << " << '\\n';\n"; 7066 } 7067 } 7068 os << "return os;\n"; 7069 os << "}\n\n"; 7070 } // end of BehaviourDSLCommon::writeIntegrationDataOutputOperator 7071 writeIntegrationDataClassEnd(std::ostream & os) const7072 void BehaviourDSLCommon::writeIntegrationDataClassEnd(std::ostream& os) const { 7073 this->checkIntegrationDataFile(os); 7074 os << "}; // end of " << this->mb.getClassName() << "IntegrationData" 7075 << "class\n\n"; 7076 } 7077 writeIntegrationDataExternalStateVariables(std::ostream & os,const Hypothesis h) const7078 void BehaviourDSLCommon::writeIntegrationDataExternalStateVariables(std::ostream& os, const Hypothesis h) const { 7079 const auto& md = this->mb.getBehaviourData(h); 7080 this->checkIntegrationDataFile(os); 7081 this->writeVariablesDeclarations(os, md.getExternalStateVariables(), "d", "", this->fd.fileName, false); 7082 } 7083 writeIntegrationDataFileBegin(std::ostream & os) const7084 void BehaviourDSLCommon::writeIntegrationDataFileBegin(std::ostream& os) const { 7085 this->checkIntegrationDataFile(os); 7086 this->writeIntegrationDataFileHeader(os); 7087 this->writeIntegrationDataFileHeaderBegin(os); 7088 this->writeIntegrationDataStandardTFELIncludes(os); 7089 this->writeIncludes(os); 7090 // includes specific to interfaces 7091 for (const auto& i : this->interfaces) { 7092 i.second->writeInterfaceSpecificIncludes(os, this->mb); 7093 } 7094 this->writeNamespaceBegin(os); 7095 this->writeIntegrationDataForwardDeclarations(os); 7096 } // end of BehaviourDSLCommon::writeIntegrationDataFile 7097 writeIntegrationDataClass(std::ostream & os,const Hypothesis h) const7098 void BehaviourDSLCommon::writeIntegrationDataClass(std::ostream& os, const Hypothesis h) const { 7099 this->checkIntegrationDataFile(os); 7100 this->writeIntegrationDataClassBegin(os, h); 7101 this->writeIntegrationDataStandardTFELTypedefs(os); 7102 this->writeIntegrationDataDefaultMembers(os); 7103 this->writeIntegrationDataExternalStateVariables(os, h); 7104 this->writeIntegrationDataDisabledConstructors(os); 7105 os << "public:\n\n"; 7106 this->writeIntegrationDataConstructors(os, h); 7107 this->writeIntegrationDataMainVariablesSetters(os); 7108 this->writeIntegrationDataScaleOperators(os, h); 7109 this->writeIntegrationDataUpdateDrivingVariablesMethod(os); 7110 this->writeIntegrationDataClassEnd(os); 7111 this->writeIntegrationDataOutputOperator(os, h); 7112 } 7113 writeIntegrationDataFileEnd(std::ostream & os) const7114 void BehaviourDSLCommon::writeIntegrationDataFileEnd(std::ostream& os) const { 7115 this->checkIntegrationDataFile(os); 7116 this->writeNamespaceEnd(os); 7117 this->writeIntegrationDataFileHeaderEnd(os); 7118 } // end of BehaviourDSLCommon::writeIntegrationDataFileEnd 7119 checkSrcFile(std::ostream & os) const7120 void BehaviourDSLCommon::checkSrcFile(std::ostream& os) const { 7121 if ((!os) || (!os.good())) { 7122 this->throwRuntimeError("BehaviourDSLCommon::checkSrcFile", "output file is not valid"); 7123 } 7124 } 7125 writeSrcFileHeader(std::ostream & os) const7126 void BehaviourDSLCommon::writeSrcFileHeader(std::ostream& os) const { 7127 this->checkSrcFile(os); 7128 os << "/*!\n" 7129 << "* \\file " << this->getSrcFileName() << '\n' 7130 << "* \\brief " 7131 << "this file implements the " << this->mb.getClassName() << " Behaviour.\n" 7132 << "* File generated by " << MFrontHeader::getVersionName() << " " 7133 << "version " << MFrontHeader::getVersionNumber() << '\n'; 7134 if (!this->fd.authorName.empty()) { 7135 os << "* \\author " << this->fd.authorName << '\n'; 7136 } 7137 if (!this->fd.date.empty()) { 7138 os << "* \\date " << this->fd.date << '\n'; 7139 } 7140 os << " */\n\n"; 7141 if (this->mb.hasParameters()) { 7142 os << "#include<string>\n" 7143 << "#include<cstring>\n" 7144 << "#include<sstream>\n" 7145 << "#include<fstream>\n" 7146 << "#include<stdexcept>\n\n"; 7147 } 7148 os << "#include\"TFEL/Raise.hxx\"\n" 7149 << "#include\"" << this->getBehaviourDataFileName() << "\"\n" 7150 << "#include\"" << this->getIntegrationDataFileName() << "\"\n" 7151 << "#include\"" << this->getBehaviourFileName() << "\"\n\n"; 7152 } // end of BehaviourDSLCommon::writeSrcFileHeader() 7153 writeSrcFileStaticVariables(std::ostream & os,const Hypothesis h) const7154 void BehaviourDSLCommon::writeSrcFileStaticVariables(std::ostream& os, const Hypothesis h) const { 7155 const auto& md = this->mb.getBehaviourData(h); 7156 const auto m = "tfel::material::ModellingHypothesis::" + ModellingHypothesis::toUpperCaseString(h); 7157 this->checkSrcFile(os); 7158 for (const auto& v : md.getStaticVariables()) { 7159 if (v.type == "int") { 7160 continue; 7161 } 7162 if (this->mb.useQt()) { 7163 os << "template<>\n"; 7164 os << "const " << this->mb.getClassName() << "<" << m << ",float,true>::" << v.type << '\n' 7165 << this->mb.getClassName() << "<" << m << ",float,true>::" << v.name << " = " << this->mb.getClassName() 7166 << "<" << m << ",float,true>::" << v.type << "(static_cast<float>(" << v.value << "));\n\n"; 7167 } 7168 os << "template<>\n"; 7169 os << "const " << this->mb.getClassName() << "<" << m << ",float,false>::" << v.type << '\n' 7170 << this->mb.getClassName() << "<" << m << ",float,false>::" << v.name << " = " << this->mb.getClassName() 7171 << "<" << m << ",float,false>::" << v.type << "(static_cast<float>(" << v.value << "));\n\n"; 7172 if (this->mb.useQt()) { 7173 os << "template<>\n"; 7174 os << "const " << this->mb.getClassName() << "<" << m << ",double,true>::" << v.type << '\n' 7175 << this->mb.getClassName() << "<" << m << ",double,true>::" << v.name << " = " << this->mb.getClassName() 7176 << "<" << m << ",double,true>::" << v.type << "(static_cast<double>(" << v.value << "));\n\n"; 7177 } 7178 os << "template<>\n"; 7179 os << "const " << this->mb.getClassName() << "<" << m << ",double,false>::" << v.type << '\n' 7180 << this->mb.getClassName() << "<" << m << ",double,false>::" << v.name << " = " << this->mb.getClassName() 7181 << "<" << m << ",double,false>::" << v.type << "(static_cast<double>(" << v.value << "));\n\n"; 7182 if (this->mb.useQt()) { 7183 os << "template<>\n"; 7184 os << "const " << this->mb.getClassName() << "<" << m << ",long double,true>::" << v.type << '\n' 7185 << this->mb.getClassName() << "<" << m << ",long double,true>::" << v.name << " = " 7186 << this->mb.getClassName() << "<" << m << ",long double,true>::" << v.type << "(static_cast<long double>(" 7187 << v.value << "));\n\n"; 7188 } 7189 os << "template<>\n"; 7190 os << "const " << this->mb.getClassName() << "<" << m << ",long double,false>::" << v.type << '\n' 7191 << this->mb.getClassName() << "<" << m << ",long double,false>::" << v.name << " = " << this->mb.getClassName() 7192 << "<" << m << ",long double,false>::" << v.type << "(static_cast<long double>(" << v.value << "));\n\n"; 7193 } 7194 } // end of BehaviourDSLCommon::writeSrcFileStaticVariables 7195 writeSrcFileUserDefinedCode(std::ostream & os) const7196 void BehaviourDSLCommon::writeSrcFileUserDefinedCode(std::ostream& os) const { 7197 this->checkSrcFile(os); 7198 const auto& s = this->mb.getSources(); 7199 if (!s.empty()) { 7200 os << s << "\n\n"; 7201 } 7202 } // end of BehaviourDSLCommon::writeSrcFileUserDefinedCode 7203 writeSrcFileParametersInitializers(std::ostream & os) const7204 void BehaviourDSLCommon::writeSrcFileParametersInitializers(std::ostream& os) const { 7205 if (!this->mb.hasParameters()) { 7206 return; 7207 } 7208 auto hs = this->mb.getDistinctModellingHypotheses(); 7209 hs.insert(ModellingHypothesis::UNDEFINEDHYPOTHESIS); 7210 for (const auto& h : hs) { 7211 if (this->mb.hasParameters(h)) { 7212 this->writeSrcFileParametersInitializer(os, h); 7213 } 7214 } 7215 } // end of BehaviourDSLCommon::writeSrcFileParametersInitializer 7216 BehaviourDSLCommon_writeConverter(std::ostream & f,const std::string & cname,const std::string & type,const std::string & type2)7217 static void BehaviourDSLCommon_writeConverter(std::ostream& f, 7218 const std::string& cname, 7219 const std::string& type, 7220 const std::string& type2) { 7221 f << type << '\n' 7222 << cname << "::get" << type2 << "(const std::string& n,\n" 7223 << "const std::string& v)\n" 7224 << "{\n" 7225 << type << " value;\n" 7226 << "std::istringstream converter(v);\n" 7227 << "converter >> value;\n" 7228 << "tfel::raise_if(!converter||(!converter.eof()),\n" 7229 << "\"" << cname << "::get" << type2 << ": \"\n" 7230 << "\"can't convert '\"+v+\"' to " << type << " " 7231 << "for parameter '\"+ n+\"'\");\n" 7232 << "return value;\n" 7233 << "}\n\n"; 7234 } 7235 writeSrcFileParametersInitializer(std::ostream & os,const Hypothesis h) const7236 void BehaviourDSLCommon::writeSrcFileParametersInitializer(std::ostream& os, const Hypothesis h) const { 7237 this->checkBehaviourFile(os); 7238 // treating the default case 7239 bool rp = false; // real parameter found 7240 bool ip = false; // integer parameter found 7241 bool up = false; // unsigned short parameter found 7242 bool rp2 = false; // real parameter found 7243 bool ip2 = false; // integer parameter found 7244 bool up2 = false; // unsigned short parameter found 7245 std::string cname(this->mb.getClassName()); 7246 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 7247 cname += ModellingHypothesis::toString(h); 7248 } 7249 cname += "ParametersInitializer"; 7250 std::string dcname(this->mb.getClassName() + "ParametersInitializer"); 7251 os << cname << "&\n" 7252 << cname << "::get()\n" 7253 << "{\n" 7254 << "static " << cname << " i;\n" 7255 << "return i;\n" 7256 << "}\n\n"; 7257 os << cname << "::" << cname << "()\n" 7258 << "{\n"; 7259 for (const auto& p : this->mb.getBehaviourData(h).getParameters()) { 7260 if (p.type == "int") { 7261 ip = true; 7262 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7263 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7264 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7265 ip2 = true; 7266 os << "this->" << p.name << " = " << this->mb.getIntegerParameterDefaultValue(h, p.name) << ";\n"; 7267 } 7268 } else if (p.type == "ushort") { 7269 up = true; 7270 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7271 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7272 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7273 up2 = true; 7274 os << "this->" << p.name << " = " << this->mb.getUnsignedShortParameterDefaultValue(h, p.name) << ";\n"; 7275 } 7276 } else { 7277 const auto f = SupportedTypes::getTypeFlag(p.type); 7278 if (f != SupportedTypes::SCALAR) { 7279 this->throwRuntimeError("BehaviourDSLCommon::writeSrcFileParametersInitializer", 7280 "unsupported parameter type '" + p.type + 7281 "' " 7282 "for parameter '" + 7283 p.name + "'"); 7284 } 7285 rp = true; 7286 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7287 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7288 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7289 rp2 = true; 7290 if (p.arraySize == 1u) { 7291 os << "this->" << p.name << " = " << this->mb.getFloattingPointParameterDefaultValue(h, p.name) << ";\n"; 7292 } else { 7293 for (unsigned short i = 0; i != p.arraySize; ++i) { 7294 os << "this->" << p.name << "[" << i 7295 << "] = " << this->mb.getFloattingPointParameterDefaultValue(h, p.name, i) << ";\n"; 7296 } 7297 } 7298 } 7299 } 7300 } 7301 os << "// Reading parameters from a file\n"; 7302 os << cname << "::readParameters(*this,\"" << getParametersFileName(this->mb) 7303 << "\");\n"; 7304 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 7305 os << cname << "::readParameters(*this,\"" 7306 << getParametersFileName(this->mb, h) << "\");\n"; 7307 } 7308 os << "}\n\n"; 7309 auto write_if = [&os](bool& b) { 7310 if (b) { 7311 os << "if("; 7312 b = false; 7313 } else { 7314 os << "} else if("; 7315 } 7316 }; 7317 if (rp) { 7318 os << "void\n" 7319 << cname << "::set(const char* const key,\nconst double v)" 7320 << "{\n" 7321 << "using namespace std;\n"; 7322 bool first = true; 7323 for (const auto& p : this->mb.getBehaviourData(h).getParameters()) { 7324 if ((p.type == "int") || (p.type == "ushort")) { 7325 continue; 7326 } 7327 const auto f = SupportedTypes::getTypeFlag(p.type); 7328 if (f != SupportedTypes::SCALAR) { 7329 this->throwRuntimeError("BehaviourDSLCommon::writeSrcFileParametersInitializer", 7330 "unsupported parameter type '" + p.type + 7331 "' " 7332 "for parameter '" + 7333 p.name + "'"); 7334 } 7335 if (p.arraySize == 1u) { 7336 write_if(first); 7337 os << "::strcmp(\"" + this->mb.getExternalName(h, p.name) + "\",key)==0){\n"; 7338 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7339 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7340 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7341 os << "this->" << p.name << " = v;\n"; 7342 } else { 7343 os << dcname << "::get().set(\"" << this->mb.getExternalName(h, p.name) << "\",v);\n"; 7344 } 7345 } else { 7346 for (unsigned short i = 0; i != p.arraySize; ++i) { 7347 write_if(first); 7348 const auto vn = p.name + '[' + std::to_string(i) + ']'; 7349 const auto en = this->mb.getExternalName(h, p.name) + '[' + std::to_string(i) + ']'; 7350 os << "::strcmp(\"" + en + "\",key)==0){\n"; 7351 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7352 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7353 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7354 os << "this->" << vn << " = v;\n"; 7355 } else { 7356 os << dcname << "::get().set(\"" << en << "\",v);\n"; 7357 } 7358 } 7359 } 7360 } 7361 os << "} else {\n"; 7362 os << "tfel::raise(\"" << cname << "::set: \"\n" 7363 << "\" no parameter named " 7364 << "'\"+std::string(key)+\"'\");\n" 7365 << "}\n" 7366 << "}\n\n"; 7367 } 7368 if (ip) { 7369 os << "void\n" 7370 << cname << "::set(const char* const key,\nconst int v)" 7371 << "{\n" 7372 << "using namespace std;\n"; 7373 bool first = true; 7374 for (const auto& p : this->mb.getBehaviourData(h).getParameters()) { 7375 if (p.type == "int") { 7376 write_if(first); 7377 os << "::strcmp(\"" + this->mb.getExternalName(h, p.name) + "\",key)==0){\n"; 7378 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7379 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7380 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7381 os << "this->" << p.name << " = v;\n"; 7382 } else { 7383 os << dcname << "::get().set(\"" << this->mb.getExternalName(h, p.name) << "\",v);\n"; 7384 } 7385 } 7386 } 7387 os << "} else {\n"; 7388 os << "tfel::raise(\"" << cname << "::set: \"\n" 7389 << "\"no parameter named " 7390 << "'\"+std::string(key)+\"'\");\n" 7391 << "}\n" 7392 << "}\n\n"; 7393 } 7394 if (up) { 7395 os << "void\n" 7396 << cname << "::set(const char* const key,\nconst unsigned short v)" 7397 << "{\n" 7398 << "using namespace std;\n"; 7399 bool first = true; 7400 for (const auto& p : this->mb.getBehaviourData(h).getParameters()) { 7401 if (p.type == "ushort") { 7402 write_if(first); 7403 os << "::strcmp(\"" + this->mb.getExternalName(h, p.name) + "\",key)==0){\n"; 7404 if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7405 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7406 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))) { 7407 os << "this->" << p.name << " = v;\n"; 7408 } else { 7409 os << dcname << "::get().set(\"" << this->mb.getExternalName(h, p.name) << "\",v);\n"; 7410 } 7411 } 7412 } 7413 os << "} else {\n"; 7414 os << "tfel::raise(\"" << cname << "::set: \"\n" 7415 << "\"no parameter named '\"+std::string(key)+\"'\");\n" 7416 << "}\n" 7417 << "}\n\n"; 7418 } 7419 if (rp2) { 7420 BehaviourDSLCommon_writeConverter(os, cname, "double", "Double"); 7421 } 7422 if (ip2) { 7423 BehaviourDSLCommon_writeConverter(os, cname, "int", "Int"); 7424 } 7425 if (up2) { 7426 BehaviourDSLCommon_writeConverter(os, cname, "unsigned short", "UnsignedShort"); 7427 } 7428 os << "void\n" << cname << "::readParameters(" << cname << "&"; 7429 if (rp2 || ip2 || up2) { 7430 os << " pi"; 7431 } 7432 os << ",const char* const fn)" 7433 << "{\n" 7434 << "auto tokenize = [](const std::string& line){\n" 7435 << "std::istringstream tokenizer(line);\n" 7436 << "std::vector<std::string> tokens;\n" 7437 << "std::copy(std::istream_iterator<std::string>(tokenizer),\n" 7438 << "std::istream_iterator<std::string>(),\n" 7439 << "std::back_inserter(tokens));\n" 7440 << "return tokens;\n" 7441 << "};\n" 7442 << "std::ifstream f(fn);\n" 7443 << "if(!f){\n" 7444 << "return;\n" 7445 << "}\n" 7446 << "size_t ln = 1u;\n" 7447 << "while(!f.eof()){\n" 7448 << "auto line = std::string{};\n" 7449 << "std::getline(f,line);\n" 7450 << "auto tokens = tokenize(line);\n" 7451 << "auto throw_if = [ln,line,fn](const bool c,const std::string& m){\n" 7452 << "tfel::raise_if(c,\"" << cname << "::readParameters: \"\n" 7453 << "\"error at line '\"+std::to_string(ln)+\"' \"\n" 7454 << "\"while reading parameter file '\"+std::string(fn)+\"'\"\n" 7455 << "\"(\"+m+\")\");\n" 7456 << "};\n" 7457 << "if(tokens.empty()){\n" 7458 << "continue;\n" 7459 << "}\n" 7460 << "if(tokens[0][0]=='#'){\n" 7461 << "continue;\n" 7462 << "}\n" 7463 << "throw_if(tokens.size()!=2u,\"invalid number of tokens\");\n"; 7464 bool first = true; 7465 for (const auto& p : this->mb.getBehaviourData(h).getParameters()) { 7466 const auto b = ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) || 7467 ((h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) && 7468 (!this->mb.hasParameter(ModellingHypothesis::UNDEFINEDHYPOTHESIS, p.name)))); 7469 auto write = [this, &os, &p, &b, &dcname, &cname](const std::string& vn, const std::string& en) { 7470 os << "\"" << en << "\"==tokens[0]){\n"; 7471 if (b) { 7472 os << "pi." << vn << " = "; 7473 if (p.type == "int") { 7474 os << cname << "::getInt(tokens[0],tokens[1]);\n"; 7475 } else if (p.type == "ushort") { 7476 os << cname << "::getUnsignedShort(tokens[0],tokens[1]);\n"; 7477 } else { 7478 const auto f = SupportedTypes::getTypeFlag(p.type); 7479 if (f != SupportedTypes::SCALAR) { 7480 this->throwRuntimeError("BehaviourDSLCommon::writeSrcFileParametersInitializer", 7481 "invalid parameter type '" + p.type + "'"); 7482 } 7483 os << cname << "::getDouble(tokens[0],tokens[1]);\n"; 7484 } 7485 } else { 7486 os << dcname << "::get().set(\"" << en << "\",\n"; 7487 if (p.type == "int") { 7488 os << dcname << "::getInt(tokens[0],tokens[1])"; 7489 } else if (p.type == "ushort") { 7490 os << dcname << "::getUnsignedShort(tokens[0],tokens[1])"; 7491 } else { 7492 const auto f = SupportedTypes::getTypeFlag(p.type); 7493 if (f != SupportedTypes::SCALAR) { 7494 this->throwRuntimeError("BehaviourDSLCommon::writeSrcFileParametersInitializer", 7495 "invalid parameter type '" + p.type + "'"); 7496 } 7497 os << dcname << "::getDouble(tokens[0],tokens[1])"; 7498 } 7499 os << ");\n"; 7500 } 7501 }; 7502 if (p.arraySize == 1u) { 7503 write_if(first); 7504 write(p.name, this->mb.getExternalName(h, p.name)); 7505 } else { 7506 for (unsigned short i = 0; i != p.arraySize; ++i) { 7507 const auto vn = p.name + '[' + std::to_string(i) + ']'; 7508 const auto en = this->mb.getExternalName(h, p.name) + '[' + std::to_string(i) + ']'; 7509 write_if(first); 7510 write(vn, en); 7511 } 7512 } 7513 } 7514 os << "} else {\n" 7515 << "throw_if(true,\"invalid parameter '\"+tokens[0]+\"'\");\n" 7516 << "}\n" 7517 << "}\n" 7518 << "}\n\n"; 7519 } // end of BehaviourDSLCommon::writeSrcFileParametersInitializer 7520 writeSrcFileBehaviourProfiler(std::ostream & os) const7521 void BehaviourDSLCommon::writeSrcFileBehaviourProfiler(std::ostream& os) const { 7522 if (this->mb.getAttribute(BehaviourData::profiling, false)) { 7523 this->checkSrcFile(os); 7524 os << "mfront::BehaviourProfiler&\n" 7525 << this->mb.getClassName() << "Profiler::getProfiler()\n" 7526 << "{\n" 7527 << "static mfront::BehaviourProfiler profiler(\"" << this->mb.getClassName() << "\");\n;" 7528 << "return profiler;\n" 7529 << "}\n\n"; 7530 } 7531 } // end of BehaviourDSLCommon::writeSrcFileBehaviourProfiler 7532 writeSrcFile(std::ostream & os) const7533 void BehaviourDSLCommon::writeSrcFile(std::ostream& os) const { 7534 this->writeSrcFileHeader(os); 7535 this->writeSrcFileUserDefinedCode(os); 7536 this->writeNamespaceBegin(os); 7537 this->writeSrcFileBehaviourProfiler(os); 7538 this->writeSrcFileParametersInitializers(os); 7539 // modelling hypotheses handled by the behaviour 7540 const auto& mh = this->mb.getModellingHypotheses(); 7541 for (const auto& h : mh) { 7542 this->writeSrcFileStaticVariables(os, h); 7543 } 7544 this->writeNamespaceEnd(os); 7545 } // end of BehaviourDSLCommon::writeSrcFile 7546 predictionOperatorVariableModifier(const Hypothesis h,const std::string & var,const bool addThisPtr)7547 std::string BehaviourDSLCommon::predictionOperatorVariableModifier(const Hypothesis h, 7548 const std::string& var, 7549 const bool addThisPtr) { 7550 if (this->mb.isIntegrationVariableIncrementName(h, var)) { 7551 this->throwRuntimeError("BehaviourDSLCommon::predictionOperatorVariableModifier : ", 7552 "integration variable '" + var + "' can't be used in @PredictionOperator"); 7553 } 7554 if (addThisPtr) { 7555 return "(this->" + var + ")"; 7556 } 7557 return var; 7558 } // end of BehaviourDSLCommon::predictionOperatorVariableModifier 7559 treatProfiling()7560 void BehaviourDSLCommon::treatProfiling() { 7561 const auto b = this->readBooleanValue("BehaviourDSLCommon::treatProfiling"); 7562 this->readSpecifiedToken("BehaviourDSLCommon::treatProfiling", ";"); 7563 this->mb.setAttribute(BehaviourData::profiling, b, false); 7564 } // end of BehaviourDSLCommon::treatProfiling 7565 treatPredictionOperator()7566 void BehaviourDSLCommon::treatPredictionOperator() { 7567 using namespace std; 7568 using namespace tfel::material; 7569 using namespace tfel::utilities; 7570 CodeBlockOptions o; 7571 this->readCodeBlockOptions(o, true); 7572 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 7573 bool found = false; 7574 if (o.untreated.size() != 1u) { 7575 ostringstream msg; 7576 msg << "tangent operator type is undefined. Valid tanget operator type are :\n"; 7577 for (const auto& to : getFiniteStrainBehaviourTangentOperatorFlags()) { 7578 msg << "- " << convertFiniteStrainBehaviourTangentOperatorFlagToString(to) << " : " 7579 << getFiniteStrainBehaviourTangentOperatorDescription(to) << '\n'; 7580 } 7581 this->throwRuntimeError("BehaviourDSLCommon::treatPredictionOperator", msg.str()); 7582 } 7583 if (o.untreated[0].flag != Token::Standard) { 7584 this->throwRuntimeError("BehaviourDSLCommon::treatPredictionOperator", 7585 "invalid option '" + o.untreated[0].value + "'"); 7586 } 7587 const auto& ktype = o.untreated[0].value; 7588 for (const auto& to : getFiniteStrainBehaviourTangentOperatorFlags()) { 7589 if (ktype == convertFiniteStrainBehaviourTangentOperatorFlagToString(to)) { 7590 found = true; 7591 break; 7592 } 7593 } 7594 if (!found) { 7595 ostringstream msg; 7596 msg << "invalid tangent operator type '" + ktype + "'. Valid tanget operator type are :\n"; 7597 for (const auto& to : getFiniteStrainBehaviourTangentOperatorFlags()) { 7598 msg << "- " << convertFiniteStrainBehaviourTangentOperatorFlagToString(to) << " : " 7599 << getFiniteStrainBehaviourTangentOperatorDescription(to) << '\n'; 7600 } 7601 this->throwRuntimeError("BehaviourDSLCommon::treatPredictionOperator", msg.str()); 7602 } 7603 const auto po = std::string(BehaviourData::ComputePredictionOperator) + "-" + ktype; 7604 this->readCodeBlock(*this, o, po, &BehaviourDSLCommon::predictionOperatorVariableModifier, true); 7605 for (const auto& h : o.hypotheses) { 7606 if (!this->mb.hasAttribute(h, BehaviourData::hasPredictionOperator)) { 7607 this->mb.setAttribute(h, BehaviourData::hasPredictionOperator, true); 7608 } 7609 } 7610 } else { 7611 this->treatUnsupportedCodeBlockOptions(o); 7612 this->readCodeBlock(*this, o, BehaviourData::ComputePredictionOperator, 7613 &BehaviourDSLCommon::predictionOperatorVariableModifier, true); 7614 for (const auto& h : o.hypotheses) { 7615 this->mb.setAttribute(h, BehaviourData::hasPredictionOperator, true); 7616 } 7617 } 7618 } // end of BehaviourDSLCommon::treatPredictionOperator 7619 treatParameter()7620 void BehaviourDSLCommon::treatParameter() { 7621 auto throw_if = [this](const bool b, const std::string& m) { 7622 if (b) { 7623 this->throwRuntimeError("BehaviourDSLCommon::treatParameter", m); 7624 } 7625 }; 7626 std::set<Hypothesis> mh; 7627 this->readHypothesesList(mh); 7628 auto endOfTreatment = false; 7629 while ((this->current != this->tokens.end()) && (!endOfTreatment)) { 7630 const auto vtype = [this, throw_if]() -> std::string { 7631 const auto v = this->current->value; 7632 if (SupportedTypes::isSupportedType(v)) { 7633 throw_if(SupportedTypes::getTypeFlag(v) != SupportedTypes::SCALAR, 7634 "invalid parameter type"); 7635 ++(this->current); 7636 return v; 7637 } 7638 return "real"; 7639 }(); 7640 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameter"); 7641 const auto sname = this->current->value; 7642 const auto vname = tfel::unicode::getMangledString(sname); 7643 throw_if(!isValidIdentifier(vname), 7644 "variable given is not valid (read " 7645 "'" + 7646 sname + "')."); 7647 const auto lineNumber = this->current->line; 7648 ++(this->current); 7649 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameter"); 7650 const auto arraySize = this->readArrayOfVariablesSize(sname, true); 7651 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameter"); 7652 if ((this->current->value == "=") || (this->current->value == "{") || 7653 (this->current->value == "(")) { 7654 std::string ci; // closing initializer 7655 if (this->current->value == "{") { 7656 ci = "}"; 7657 } 7658 if (this->current->value == "(") { 7659 throw_if(arraySize != 1u, 7660 "invalid initalisation syntax for " 7661 "the default values of an array of parameters.\n" 7662 "Unexpected token '" + 7663 current->value + "'"); 7664 ci = ")"; 7665 } 7666 ++(this->current); 7667 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameter"); 7668 if (arraySize != 1u) { 7669 if (ci != "}") { 7670 this->readSpecifiedToken("BehaviourDSLCommon::treatParameter", "{"); 7671 } 7672 --(this->current); 7673 const auto r = this->readArrayOfDouble("BehaviourDSLCommon::treatParameter"); 7674 throw_if( 7675 r.size() != arraySize, 7676 "number of values given does not match the numberf of parameters " 7677 "(" + 7678 std::to_string(r.size()) + " vs +" + 7679 std::to_string(arraySize) + ").\n"); 7680 for (const auto& h : mh) { 7681 VariableDescription p; 7682 if (vname == sname) { 7683 p = VariableDescription(vtype, vname, arraySize, lineNumber); 7684 } else { 7685 p = VariableDescription(vtype, sname, vname, arraySize, 7686 lineNumber); 7687 } 7688 p.description = this->currentComment; 7689 this->mb.addParameter(h, p); 7690 for (decltype(r.size()) i = 0; i != r.size(); ++i) { 7691 this->mb.setParameterDefaultValue(h, vname, i, r[i]); 7692 } 7693 } 7694 } else { 7695 double value; 7696 std::istringstream converter(this->current->value); 7697 converter >> value; 7698 if (!converter || (!converter.eof())) { 7699 this->throwRuntimeError( 7700 "BehaviourDSLCommon::treatParameter", 7701 "could not read default value for parameter '" + sname + "'"); 7702 } 7703 ++(this->current); 7704 this->checkNotEndOfFile("BehaviourDSLCommon::treatParameter"); 7705 if (!ci.empty()) { 7706 this->readSpecifiedToken("BehaviourDSLCommon::treatParameter", ci); 7707 } 7708 for (const auto& h : mh) { 7709 VariableDescription p; 7710 if (vname == sname) { 7711 p = VariableDescription(vtype, vname, 1u, lineNumber); 7712 } else { 7713 p = VariableDescription(vtype, sname, vname, 1u, lineNumber); 7714 } 7715 p.description = this->currentComment; 7716 this->mb.addParameter(h, p); 7717 this->mb.setParameterDefaultValue(h, vname, value); 7718 } 7719 } 7720 } else { 7721 throw_if(arraySize != 1, 7722 "default values of parameters array " 7723 "must be defined with the array. " 7724 "Unexpected token '" + 7725 current->value + "'"); 7726 for (const auto& h : mh) { 7727 VariableDescription p; 7728 if (vname == sname) { 7729 p = VariableDescription(vtype, vname, 1u, lineNumber); 7730 } else { 7731 p = VariableDescription(vtype, sname, vname, 1u, lineNumber); 7732 } 7733 p.description = this->currentComment; 7734 this->mb.addParameter(h, p); 7735 } 7736 } 7737 if (this->current->value == ",") { 7738 ++(this->current); 7739 } else if (this->current->value == ";") { 7740 endOfTreatment = true; 7741 ++(this->current); 7742 } else { 7743 throw_if(true, "',' or ';' expected after '" + sname + "', read '" + 7744 this->current->value + "'"); 7745 } 7746 } 7747 if (!endOfTreatment) { 7748 --(this->current); 7749 throw_if(true, "expected ';' before end of file"); 7750 } 7751 } // end of BehaviourDSLCommon::treatParameter 7752 treatInitLocalVariables()7753 void BehaviourDSLCommon::treatInitLocalVariables() { 7754 this->readCodeBlock(*this, BehaviourData::InitializeLocalVariables, 7755 &BehaviourDSLCommon::standardModifier, true, true); 7756 } // end of BehaviourDSLCommon:treatInitLocalVariables 7757 treatMinimalTimeStepScalingFactor()7758 void BehaviourDSLCommon::treatMinimalTimeStepScalingFactor() { 7759 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 7760 double r_dt; 7761 this->checkNotEndOfFile("BehaviourDSLCommon::treatMinimalTimeStepScalingFactor", "Cannot read value."); 7762 std::istringstream flux(current->value); 7763 flux >> r_dt; 7764 if ((flux.fail()) || (!flux.eof())) { 7765 this->throwRuntimeError("BehaviourDSLCommon::treatMinimalTimeStepScalingFactor", "Failed to read value."); 7766 } 7767 if (r_dt < 10 * std::numeric_limits<double>::min()) { 7768 this->throwRuntimeError("BehaviourDSLCommon::treatMinimalTimeStepScalingFactor", 7769 "minimal time step scaling factor either too " 7770 "low value or negative."); 7771 } 7772 ++(this->current); 7773 this->readSpecifiedToken("BehaviourDSLCommon::treatMinimalTimeStepScalingFactor", ";"); 7774 VariableDescription e("real", "minimal_time_step_scaling_factor", 1u, 0u); 7775 e.description = "minimal value for the time step scaling factor"; 7776 this->mb.addParameter(h, e, BehaviourData::ALREADYREGISTRED); 7777 this->mb.setParameterDefaultValue(h, "minimal_time_step_scaling_factor", r_dt); 7778 this->mb.setEntryName(h, "minimal_time_step_scaling_factor", "minimal_time_step_scaling_factor"); 7779 } // end of BehaviourDSLCommon::treatMinimalTimeStepScalingFactor 7780 treatMaximalTimeStepScalingFactor()7781 void BehaviourDSLCommon::treatMaximalTimeStepScalingFactor() { 7782 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 7783 double r_dt; 7784 this->checkNotEndOfFile("BehaviourDSLCommon::treatMaximalTimeStepScalingFactor", "Cannot read value."); 7785 std::istringstream flux(current->value); 7786 flux >> r_dt; 7787 if ((flux.fail()) || (!flux.eof())) { 7788 this->throwRuntimeError("BehaviourDSLCommon::treatMaximalTimeStepScalingFactor", "Failed to read value."); 7789 } 7790 if (r_dt < 1) { 7791 this->throwRuntimeError("BehaviourDSLCommon::treatMaximalTimeStepScalingFactor", 7792 "maximal time step scaling factor value either too " 7793 "low or negative."); 7794 } 7795 ++(this->current); 7796 this->readSpecifiedToken("BehaviourDSLCommon::treatMaximalTimeStepScalingFactor", ";"); 7797 VariableDescription e("real", "maximal_time_step_scaling_factor", 1u, 0u); 7798 e.description = "maximal value for the time step scaling factor"; 7799 this->mb.addParameter(h, e, BehaviourData::ALREADYREGISTRED); 7800 this->mb.setParameterDefaultValue(h, "maximal_time_step_scaling_factor", r_dt); 7801 this->mb.setEntryName(h, "maximal_time_step_scaling_factor", "maximal_time_step_scaling_factor"); 7802 } // end of BehaviourDSLCommon::treatMaximalTimeStepScalingFactor 7803 setMinimalTangentOperator()7804 void BehaviourDSLCommon::setMinimalTangentOperator() { 7805 if (this->mb.getBehaviourType() != BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 7806 for (const auto& h : this->mb.getDistinctModellingHypotheses()) { 7807 // basic check 7808 if (this->mb.hasAttribute(h, BehaviourData::hasConsistentTangentOperator)) { 7809 if (!this->mb.hasCode(h, BehaviourData::ComputeTangentOperator)) { 7810 this->throwRuntimeError("BehaviourDSLCommon::setMinimalTangentOperator", 7811 "behaviour has attribute 'hasConsistentTangentOperator' but " 7812 "no associated code"); 7813 } 7814 } 7815 } 7816 if (this->mb.getAttribute(BehaviourDescription::requiresStiffnessTensor, false)) { 7817 if (this->mb.getBehaviourType() == BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) { 7818 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 7819 // if the user provided a tangent operator, it won't be 7820 // overriden 7821 7822 CodeBlock tangentOperator; 7823 std::ostringstream code; 7824 code << "if(smt==ELASTIC){\n" 7825 << "this->Dt = this->D;\n" 7826 << "} else {\n" 7827 << "return false;\n" 7828 << "}\n"; 7829 tangentOperator.code = code.str(); 7830 this->mb.setCode(h, BehaviourData::ComputeTangentOperator, tangentOperator, 7831 BehaviourData::CREATEBUTDONTREPLACE, BehaviourData::BODY); 7832 this->mb.setAttribute(h, BehaviourData::hasConsistentTangentOperator, true, true); 7833 } 7834 } 7835 } 7836 } // end of BehaviourDSLCommon::setMinimalTangentOperator 7837 treatInternalEnergy()7838 void BehaviourDSLCommon::treatInternalEnergy() { 7839 this->readCodeBlock(*this, BehaviourData::ComputeInternalEnergy, &BehaviourDSLCommon::standardModifier, true, true); 7840 } // end of BehaviourDSLCommon::treatInternalEnergy 7841 treatDissipatedEnergy()7842 void BehaviourDSLCommon::treatDissipatedEnergy() { 7843 this->readCodeBlock(*this, BehaviourData::ComputeDissipatedEnergy, &BehaviourDSLCommon::standardModifier, true, 7844 true); 7845 } // end of BehaviourDSLCommon::treatDissipatedEnergy 7846 readSlipSystem(BehaviourDSLCommon::CxxTokenizer::const_iterator & p,const BehaviourDSLCommon::CxxTokenizer::const_iterator pe)7847 static BehaviourDescription::SlipSystem readSlipSystem(BehaviourDSLCommon::CxxTokenizer::const_iterator& p, 7848 const BehaviourDSLCommon::CxxTokenizer::const_iterator pe) { 7849 using tfel::utilities::CxxTokenizer; 7850 using tfel::material::SlipSystemsDescription; 7851 auto throw_if = [](const bool c, const std::string& msg) { tfel::raise_if(c, "readSlipSystem: " + msg); }; 7852 const auto direction = CxxTokenizer::readList("readSlipSystem", "<", ">", p, pe); 7853 const auto plane = CxxTokenizer::readList("readSlipSystem", "{", "}", p, pe); 7854 throw_if(plane.size() != direction.size(), "plane and direction don't match in size"); 7855 throw_if((plane.size() != 3u) && (plane.size() != 4u), 7856 "invalid definition of a plane " 7857 "(must be an array of 3 or 4 integers, read '" + 7858 std::to_string(plane.size()) + "' values)"); 7859 if (plane.size() == 3u) { 7860 SlipSystemsDescription::system3d s3d; 7861 for (tfel::math::tvector<3u, int>::size_type i = 0; i != 3; ++i) { 7862 s3d.plane[i] = std::stoi(plane[i].value); 7863 s3d.burgers[i] = std::stoi(direction[i].value); 7864 } 7865 return {s3d}; 7866 } 7867 SlipSystemsDescription::system4d s4d; 7868 for (tfel::math::tvector<4u, int>::size_type i = 0; i != 4; ++i) { 7869 s4d.plane[i] = std::stoi(plane[i].value); 7870 s4d.burgers[i] = std::stoi(direction[i].value); 7871 } 7872 return {s4d}; 7873 } 7874 treatSlipSystem()7875 void BehaviourDSLCommon::treatSlipSystem() { 7876 const auto s = readSlipSystem(this->current, this->tokens.end()); 7877 this->mb.setSlipSystems({1u, s}); 7878 this->readSpecifiedToken("BehaviourDSLCommon::treatSlipSystem", ";"); 7879 } // end of BehaviourDescription::treatSlipSystem() 7880 treatSlipSystems()7881 void BehaviourDSLCommon::treatSlipSystems() { 7882 const std::string m = "BehaviourDSLCommon::treatSlipSystems"; 7883 std::vector<BehaviourDescription::SlipSystem> ss; 7884 this->readSpecifiedToken(m, "{"); 7885 this->checkNotEndOfFile(m, "expected token"); 7886 while (this->current->value != "}") { 7887 this->checkNotEndOfFile(m, "expected slip system"); 7888 ss.push_back(readSlipSystem(this->current, this->tokens.end())); 7889 this->checkNotEndOfFile(m, "expected ',' or '}'"); 7890 if (this->current->value != "}") { 7891 this->readSpecifiedToken(m, ","); 7892 this->checkNotEndOfFile(m, "expected slip system"); 7893 if (this->current->value == "}") { 7894 this->throwRuntimeError(m, "unexpected token '}'"); 7895 } 7896 } 7897 } 7898 this->readSpecifiedToken(m, "}"); 7899 this->readSpecifiedToken(m, ";"); 7900 this->mb.setSlipSystems(ss); 7901 } // end of BehaviourDSLCommon::treatSlipSystems 7902 treatCrystalStructure()7903 void BehaviourDSLCommon::treatCrystalStructure() { 7904 using tfel::material::CrystalStructure; 7905 this->checkNotEndOfFile("BehaviourDSLCommon::treatCrystalStructure", "expected crystal structure"); 7906 if (this->current->value == "Cubic") { 7907 this->mb.setCrystalStructure(CrystalStructure::Cubic); 7908 } else if (this->current->value == "FCC") { 7909 this->mb.setCrystalStructure(CrystalStructure::FCC); 7910 } else if (this->current->value == "BCC") { 7911 this->mb.setCrystalStructure(CrystalStructure::BCC); 7912 } else if (this->current->value == "HCP") { 7913 this->mb.setCrystalStructure(CrystalStructure::HCP); 7914 } else { 7915 this->throwRuntimeError("BehaviourDSLCommon::treatCrystalStructure", 7916 "unsupported crystal structure " 7917 "'" + 7918 this->current->value + "'"); 7919 } 7920 ++(this->current); 7921 this->readSpecifiedToken("BehaviourDSLCommon::treatCrystalStructure", ";"); 7922 } // end of BehaviourDSLCommon::treatCrystalStructure 7923 treatInteractionMatrix()7924 void BehaviourDSLCommon::treatInteractionMatrix() { 7925 auto throw_if = [this](const bool b, const std::string& m) { 7926 if (b) { 7927 this->throwRuntimeError("BehaviourDSLCommon::treatInteractionMatrix", m); 7928 } 7929 }; 7930 throw_if(!this->mb.areSlipSystemsDefined(), "slip systems have not been defined"); 7931 const auto& im = this->mb.getInteractionMatrixStructure(); 7932 const auto r = im.rank(); 7933 const auto mv = 7934 CxxTokenizer::readArray("BehaviourDSLCommon::treatInteractionMatrix", this->current, this->tokens.end()); 7935 this->readSpecifiedToken("BehaviourDSLCommon::treatInteractionMatrix", ";"); 7936 throw_if(mv.size() != r, 7937 "the number of values does " 7938 "not match the number of independent coefficients " 7939 "in the interaction matrix"); 7940 auto imv = std::vector<long double>{}; 7941 imv.reserve((mv.size())); 7942 for (const auto& v : mv) { 7943 imv.push_back(tfel::utilities::convert<long double>(v)); 7944 } 7945 this->mb.setInteractionMatrix(imv); 7946 } // end of BehaviourDSLCommon::treatInteractionMatrix 7947 treatDislocationsMeanFreePathInteractionMatrix()7948 void BehaviourDSLCommon::treatDislocationsMeanFreePathInteractionMatrix() { 7949 auto throw_if = [this](const bool b, const std::string& m) { 7950 if (b) { 7951 this->throwRuntimeError( 7952 "BehaviourDSLCommon::" 7953 "treatDislocationsMeanFreePathInteractionMatrix", 7954 m); 7955 } 7956 }; 7957 throw_if(!this->mb.areSlipSystemsDefined(), "slip systems have not been defined"); 7958 const auto& im = this->mb.getInteractionMatrixStructure(); 7959 const auto r = im.rank(); 7960 const auto mv = CxxTokenizer::readArray( 7961 "BehaviourDSLCommon::" 7962 "treatDislocationsMeanFreePathInteractionMatrix", 7963 this->current, this->tokens.end()); 7964 this->readSpecifiedToken( 7965 "BehaviourDSLCommon::" 7966 "treatDislocationsMeanFreePathInteractionMatrix", 7967 ";"); 7968 throw_if(mv.size() != r, 7969 "the number of values does " 7970 "not match the number of independent coefficients " 7971 "in the interaction matrix"); 7972 auto imv = std::vector<long double>{}; 7973 imv.reserve((mv.size())); 7974 for (const auto& v : mv) { 7975 imv.push_back(tfel::utilities::convert<long double>(v)); 7976 } 7977 this->mb.setDislocationsMeanFreePathInteractionMatrix(imv); 7978 } // end of BehaviourDSLCommon::treatDislocationsMeanFreePathInteractionMatrix 7979 7980 void BehaviourDSLCommon:: setComputeFinalThermodynamicForcesFromComputeFinalThermodynamicForcesCandidateIfNecessary()7981 setComputeFinalThermodynamicForcesFromComputeFinalThermodynamicForcesCandidateIfNecessary() { 7982 // first treating specialised mechanical data 7983 for (const auto& h : this->mb.getDistinctModellingHypotheses()) { 7984 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 7985 if (!this->mb.hasCode(h, BehaviourData::ComputeFinalThermodynamicForces)) { 7986 if (this->mb.hasCode(h, BehaviourData::ComputeFinalThermodynamicForcesCandidate)) { 7987 this->mb.setCode(h, BehaviourData::ComputeFinalThermodynamicForces, 7988 this->mb.getCodeBlock(h, BehaviourData::ComputeFinalThermodynamicForcesCandidate), 7989 BehaviourData::CREATE, BehaviourData::BODY); 7990 } 7991 } 7992 } 7993 } 7994 // now treating the default hypothesis case 7995 if (!this->mb.areAllMechanicalDataSpecialised()) { 7996 const auto h = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 7997 if (!this->mb.hasCode(h, BehaviourData::ComputeFinalThermodynamicForces)) { 7998 if (this->mb.hasCode(h, BehaviourData::ComputeFinalThermodynamicForcesCandidate)) { 7999 this->mb.setCode(h, BehaviourData::ComputeFinalThermodynamicForces, 8000 this->mb.getCodeBlock(h, BehaviourData::ComputeFinalThermodynamicForcesCandidate), 8001 BehaviourData::CREATEBUTDONTREPLACE, BehaviourData::BODY); 8002 } 8003 } 8004 } 8005 } // end of 8006 // BehaviourDSLCommon::setComputeFinalThermodynamicForcesFromComputeFinalThermodynamicForcesCandidateIfNecessary 8007 getOverridableVariableNameByExternalName(const std::string & en) const8008 std::string BehaviourDSLCommon::getOverridableVariableNameByExternalName( 8009 const std::string& en) const { 8010 constexpr const auto uh = ModellingHypothesis::UNDEFINEDHYPOTHESIS; 8011 const auto& d = this->mb.getBehaviourData(uh); 8012 const auto pp = findByExternalName(d.getParameters(), en); 8013 if (pp != d.getParameters().end()) { 8014 return pp->name; 8015 } 8016 const auto pmp = findByExternalName(d.getMaterialProperties(), en); 8017 if (pmp == d.getMaterialProperties().end()) { 8018 tfel::raise( 8019 "BehaviourDSLCommon::getOverridableVariableNameByExternalName: " 8020 "no overridable variable associated with external name '" + 8021 en + "'"); 8022 } 8023 return pmp->name; 8024 } // end of BehaviourDSLCommon::getOverridableVariableNameByExternalName 8025 overrideByAParameter(const std::string & n,const double v)8026 void BehaviourDSLCommon::overrideByAParameter(const std::string& n, 8027 const double v) { 8028 this->mb.overrideByAParameter(n, v); 8029 } // end of BehaviourDSLCommon::overrideByAParameter 8030 8031 BehaviourDSLCommon::~BehaviourDSLCommon() = default; 8032 8033 } // end of namespace mfront 8034