1 /*! 2 * \file mfront/src/SymbolsGenerator.cxx 3 * \brief 4 * \author Thomas Helfer 5 * \date 08/07/2018 6 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 7 * reserved. 8 * This project is publicly released under either the GNU GPL Licence 9 * or the CECILL-A licence. A copy of thoses licences are delivered 10 * with the sources of TFEL. CEA or EDF may also distribute this 11 * project under specific licensing conditions. 12 */ 13 14 #include <iostream> 15 16 #include <sstream> 17 #include "TFEL/Raise.hxx" 18 #include "TFEL/Config/GetTFELVersion.h" 19 #include "TFEL/Utilities/StringAlgorithms.hxx" 20 #include "TFEL/System/System.hxx" 21 #include "MFront/DSLUtilities.hxx" 22 #include "MFront/FileDescription.hxx" 23 #include "MFront/BehaviourDescription.hxx" 24 #include "MFront/BehaviourMaterialProperty.hxx" 25 #include "MFront/StandardBehaviourInterface.hxx" 26 #include "MFront/SymbolsGenerator.hxx" 27 28 namespace mfront { 29 getVariableTypeId(const VariableDescription & v)30 static int getVariableTypeId(const VariableDescription& v) { 31 switch (SupportedTypes::getTypeFlag(v.type)) { 32 case SupportedTypes::SCALAR: 33 return 0; 34 break; 35 case SupportedTypes::STENSOR: 36 return 1; 37 break; 38 case SupportedTypes::TVECTOR: 39 return 2; 40 break; 41 case SupportedTypes::TENSOR: 42 return 3; 43 break; 44 default: 45 tfel::raise( 46 "getVariableTypeId: " 47 "internal error, tag unsupported for " 48 "variable '" + 49 v.name + "'"); 50 } 51 } // end of getVariableTypeId 52 getSymbolName(const StandardBehaviourInterface & i,const std::string & n,const Hypothesis h) const53 std::string SymbolsGenerator::getSymbolName( 54 const StandardBehaviourInterface& i, 55 const std::string& n, 56 const Hypothesis h) const { 57 if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) { 58 return i.getFunctionNameBasis(n) + "_" + ModellingHypothesis::toString(h); 59 } 60 return i.getFunctionNameBasis(n); 61 } // end of SymbolsGenerator::getSymbolName 62 generateGeneralSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & bd,const FileDescription & fd,const std::set<Hypothesis> & mhs,const std::string & name) const63 void SymbolsGenerator::generateGeneralSymbols( 64 std::ostream& out, 65 const StandardBehaviourInterface& i, 66 const BehaviourDescription& bd, 67 const FileDescription& fd, 68 const std::set<Hypothesis>& mhs, 69 const std::string& name) const { 70 this->writeEntryPointSymbol(out, i, name); 71 this->writeTFELVersionSymbol(out, i, name); 72 this->writeMaterialSymbol(out, i, bd, name); 73 this->writeMaterialKnowledgeTypeSymbol(out, i, name); 74 this->writeInterfaceNameSymbols(out, i, bd, fd, name); 75 this->writeSourceFileSymbols(out, i, bd, fd, name); 76 this->writeSupportedModellingHypothesis(out, i, bd, mhs, name); 77 this->writeMainVariablesSymbols(out, i, bd, name); 78 this->writeTangentOperatorSymbols(out, i, bd, name); 79 this->writeBehaviourTypeSymbols(out, i, bd, name); 80 this->writeBehaviourKinematicSymbols(out, i, bd, name); 81 this->writeSymmetryTypeSymbols(out, i, bd, name); 82 this->writeElasticSymmetryTypeSymbols(out, i, bd, name); 83 this->writeSpecificSymbols(out, i, bd, fd, name); 84 } 85 writeEntryPointSymbol(std::ostream & out,const StandardBehaviourInterface & i,const std::string & n) const86 void SymbolsGenerator::writeEntryPointSymbol( 87 std::ostream& out, 88 const StandardBehaviourInterface& i, 89 const std::string& n) const { 90 mfront::writeEntryPointSymbol(out, i.getFunctionNameBasis(n)); 91 } // end of SymbolsGenerator::writeEntryPointSymbol 92 writeTFELVersionSymbol(std::ostream & out,const StandardBehaviourInterface & i,const std::string & n) const93 void SymbolsGenerator::writeTFELVersionSymbol( 94 std::ostream& out, 95 const StandardBehaviourInterface& i, 96 const std::string& n) const { 97 mfront::writeTFELVersionSymbol(out, i.getFunctionNameBasis(n)); 98 } // end of SymbolsGenerator::writeTFELVersionSymbol 99 writeMaterialSymbol(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & n) const100 void SymbolsGenerator::writeMaterialSymbol( 101 std::ostream& out, 102 const StandardBehaviourInterface& i, 103 const BehaviourDescription& mb, 104 const std::string& n) const { 105 mfront::writeMaterialSymbol(out, i.getFunctionNameBasis(n), 106 mb.getMaterialName()); 107 } // end of SymbolsGenerator::writeEntryPointSymbol 108 writeMainVariablesSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & bd,const std::string & name) const109 void SymbolsGenerator::writeMainVariablesSymbols( 110 std::ostream& out, 111 const StandardBehaviourInterface& i, 112 const BehaviourDescription& bd, 113 const std::string& name) const { 114 const auto& mvs = bd.getMainVariables(); 115 std::vector<std::string> dvnames; 116 std::vector<int> dvtypes; 117 std::vector<std::string> thnames; 118 std::vector<int> thtypes; 119 auto nmvs = decltype(mvs.size()){}; 120 for (const auto& mv : mvs) { 121 const auto& dv = mv.first; 122 const auto& th = mv.second; 123 if (dv.arraySize != th.arraySize) { 124 tfel::raise( 125 "SymbolsGenerator::writeMainVariablesSymbols: " 126 "array size for driving variable '" + 127 dv.name + 128 "' " 129 "does not match the array size of the associated " 130 "thermodynamic forces '" + 131 th.name + "'"); 132 } 133 const auto dvname = dv.getExternalName(); 134 const auto dvtype = getVariableTypeId(dv); 135 const auto thname = th.getExternalName(); 136 const auto thtype = getVariableTypeId(th); 137 if (dvname == "Strain") { 138 if (thname != "Stress") { 139 tfel::raise( 140 "SymbolsGenerator::writeMainVariablesSymbols: " 141 "the thermodynamic force associated with the " 142 "strain is not the stress"); 143 } 144 if (dvtype != 1) { 145 tfel::raise( 146 "SymbolsGenerator::writeMainVariablesSymbols: " 147 "invalid type for the strain"); 148 } 149 if (thtype != 1) { 150 tfel::raise( 151 "SymbolsGenerator::writeMainVariablesSymbols: " 152 "invalid type for the stress"); 153 } 154 if (dv.arraySize != 1) { 155 tfel::raise( 156 "SymbolsGenerator::writeMainVariablesSymbols: " 157 "the strain shall not be declared as an array"); 158 } 159 if (th.arraySize != 1) { 160 tfel::raise( 161 "SymbolsGenerator::writeMainVariablesSymbols: " 162 "the stress shall not be declared as an array"); 163 } 164 if ((bd.isStrainMeasureDefined()) && 165 (bd.getStrainMeasure() != BehaviourDescription::LINEARISED)) { 166 if (this->handleStrainMeasure()) { 167 // strain measure is handled by the interface 168 dvnames.push_back("DeformationGradient"); 169 thnames.push_back("Stress"); 170 dvtypes.push_back(3); 171 thtypes.push_back(thtype); 172 } else { 173 // strain measure is handled by the calling finite element solver 174 dvnames.push_back(dvname); 175 thnames.push_back(thname); 176 dvtypes.push_back(dvtype); 177 thtypes.push_back(thtype); 178 } 179 } else { 180 dvnames.push_back(dvname); 181 thnames.push_back(thname); 182 dvtypes.push_back(dvtype); 183 thtypes.push_back(thtype); 184 } 185 } else { 186 if (dv.arraySize == 1u) { 187 dvnames.push_back(dvname); 188 thnames.push_back(thname); 189 dvtypes.push_back(dvtype); 190 thtypes.push_back(thtype); 191 } else { 192 for (unsigned short idx = 0; idx != dv.arraySize; ++idx) { 193 std::ostringstream nb; 194 nb << '[' << idx << ']'; 195 dvnames.push_back(dvname + nb.str()); 196 thnames.push_back(thname + nb.str()); 197 dvtypes.push_back(dvtype); 198 thtypes.push_back(thtype); 199 } 200 } 201 } 202 nmvs += dv.arraySize; 203 } 204 const auto fn = i.getFunctionNameBasis(name); 205 out << "MFRONT_SHAREDOBJ unsigned short " << fn 206 << "_nMainVariables = " << nmvs << ";\n"; 207 out << "MFRONT_SHAREDOBJ unsigned short " << fn << "_nGradients = " << nmvs 208 << ";\n\n"; 209 this->writeArrayOfIntsSymbol(out, fn + "_GradientsTypes", dvtypes); 210 this->writeArrayOfStringsSymbol(out, fn + "_Gradients", dvnames); 211 out << "MFRONT_SHAREDOBJ unsigned short " << fn 212 << "_nThermodynamicForces = " << nmvs << ";\n\n"; 213 this->writeArrayOfIntsSymbol(out, fn + "_ThermodynamicForcesTypes", 214 thtypes); 215 this->writeArrayOfStringsSymbol(out, fn + "_ThermodynamicForces", thnames); 216 } // end of SymbolsGenerator::writeMainVariablesSymbols 217 writeTangentOperatorSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & bd,const std::string & name) const218 void SymbolsGenerator::writeTangentOperatorSymbols( 219 std::ostream& out, 220 const StandardBehaviourInterface& i, 221 const BehaviourDescription& bd, 222 const std::string& name) const { 223 auto write_impl = [this, &out, &i, 224 &name](const std::vector<std::string>& bns) { 225 const auto fn = i.getFunctionNameBasis(name); 226 out << "MFRONT_SHAREDOBJ unsigned short " << fn 227 << "_nTangentOperatorBlocks = " << bns.size() << ";\n\n"; 228 this->writeArrayOfStringsSymbol(out, fn + "_TangentOperatorBlocks", bns); 229 }; 230 auto default_impl = [this, &bd, &write_impl] { 231 std::vector<std::string> bns; 232 for (const auto& b : bd.getTangentOperatorBlocks()) { 233 bns.push_back(b.first.getExternalName()); 234 bns.push_back(b.second.getExternalName()); 235 } 236 write_impl(bns); 237 }; 238 auto empty_impl = [this, &i, &name, &out] { 239 // strain measure is handled by the interface 240 // we don't write any tangent operator here 241 // as the consistent tangent operator 242 // in finite strain is very dependant of the 243 // interface is generally not related 244 // the derivative of a flux with respect to 245 // a gradient 246 const auto fn = i.getFunctionNameBasis(name); 247 out << "MFRONT_SHAREDOBJ unsigned short " << fn 248 << "_nTangentOperatorBlocks = 0;\n\n"; 249 this->writeArrayOfStringsSymbol(out, fn + "_TangentOperatorBlocks", {}); 250 }; 251 if (bd.getBehaviourType() == 252 BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR) { 253 if ((bd.isStrainMeasureDefined()) && 254 (bd.getStrainMeasure() != BehaviourDescription::LINEARISED)) { 255 if (this->handleStrainMeasure()) { 256 empty_impl(); 257 } else { 258 default_impl(); 259 } 260 } else { 261 default_impl(); 262 } 263 } else if (bd.getBehaviourType() == 264 BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR) { 265 empty_impl(); 266 } else { 267 default_impl(); 268 } 269 } // end of SymbolsGenerator::writeTangentOperatorSymbols 270 writeMaterialKnowledgeTypeSymbol(std::ostream & out,const StandardBehaviourInterface & i,const std::string & n) const271 void SymbolsGenerator::writeMaterialKnowledgeTypeSymbol( 272 std::ostream& out, 273 const StandardBehaviourInterface& i, 274 const std::string& n) const { 275 mfront::writeMaterialKnowledgeTypeSymbol(out, i.getFunctionNameBasis(n), 276 BEHAVIOUR); 277 } // end of SymbolsGenerator::writeEntryPointSymbol 278 generateSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & bd,const FileDescription & fd,const std::string & name,const Hypothesis h) const279 void SymbolsGenerator::generateSymbols(std::ostream& out, 280 const StandardBehaviourInterface& i, 281 const BehaviourDescription& bd, 282 const FileDescription& fd, 283 const std::string& name, 284 const Hypothesis h) const { 285 this->writeIsUsableInPurelyImplicitResolutionSymbols(out, i, bd, name, h); 286 this->writeMaterialPropertiesSymbols(out, i, bd, name, h); 287 this->writeStateVariablesSymbols(out, i, bd, name, h); 288 this->writeExternalStateVariablesSymbols(out, i, bd, name, h); 289 this->writeParametersSymbols(out, i, bd, name, h); 290 this->writeParameterDefaultValueSymbols(out, i, bd, name, h); 291 this->writeBoundsSymbols(out, i, bd, name, h); 292 this->writePhysicalBoundsSymbols(out, i, bd, name, h); 293 this->writeRequirementsSymbols(out, i, bd, name, h); 294 this->writeAdditionalSymbols(out, i, bd, fd, name, h); 295 this->writeComputesInternalEnergySymbol(out, i, bd, name, h); 296 this->writeComputesDissipatedEnergySymbol(out, i, bd, name, h); 297 } 298 writeComputesInternalEnergySymbol(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & bd,const std::string & name,const Hypothesis h) const299 void SymbolsGenerator::writeComputesInternalEnergySymbol( 300 std::ostream& out, 301 const StandardBehaviourInterface& i, 302 const BehaviourDescription& bd, 303 const std::string& name, 304 const Hypothesis h) const { 305 const auto b = bd.hasCode(h, BehaviourData::ComputeInternalEnergy) ? 1 : 0; 306 out << "MFRONT_SHAREDOBJ unsigned short " << this->getSymbolName(i, name, h) 307 << "_ComputesInternalEnergy = " << b << ";\n\n"; 308 } // end of SymbolsGenerator::writeComputesInternalEnergySymbol 309 writeComputesDissipatedEnergySymbol(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & bd,const std::string & name,const Hypothesis h) const310 void SymbolsGenerator::writeComputesDissipatedEnergySymbol( 311 std::ostream& out, 312 const StandardBehaviourInterface& i, 313 const BehaviourDescription& bd, 314 const std::string& name, 315 const Hypothesis h) const { 316 const auto b = bd.hasCode(h, BehaviourData::ComputeDissipatedEnergy) ? 1 : 0; 317 out << "MFRONT_SHAREDOBJ unsigned short " << this->getSymbolName(i, name, h) 318 << "_ComputesDissipatedEnergy = " << b << ";\n\n"; 319 } // end of SymbolsGenerator::writeComputesDissipatedEnergySymbol 320 writeSpecificSymbols(std::ostream &,const StandardBehaviourInterface &,const BehaviourDescription &,const FileDescription &,const std::string &) const321 void SymbolsGenerator::writeSpecificSymbols(std::ostream&, 322 const StandardBehaviourInterface&, 323 const BehaviourDescription&, 324 const FileDescription&, 325 const std::string&) const { 326 } // end of SymbolsGenerator::writeSpecificSymbols 327 writeSupportedModellingHypothesis(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription &,const std::set<Hypothesis> & mhs,const std::string & name) const328 void SymbolsGenerator::writeSupportedModellingHypothesis( 329 std::ostream& out, 330 const StandardBehaviourInterface& i, 331 const BehaviourDescription&, 332 const std::set<Hypothesis>& mhs, 333 const std::string& name) const { 334 if (mhs.empty()) { 335 out << "MFRONT_SHAREDOBJ unsigned short " << i.getFunctionNameBasis(name) 336 << "_nModellingHypotheses = 0u;\n\n" 337 << "MFRONT_SHAREDOBJ const char * const * " 338 << i.getFunctionNameBasis(name) << "_ModellingHypotheses = 0;\n\n"; 339 } else { 340 out << "MFRONT_SHAREDOBJ unsigned short " << i.getFunctionNameBasis(name) 341 << "_nModellingHypotheses = " << mhs.size() << "u;\n\n" 342 << "MFRONT_SHAREDOBJ const char * \n" 343 << i.getFunctionNameBasis(name) << "_ModellingHypotheses[" 344 << mhs.size() << "u] = {"; 345 for (auto ph = mhs.begin(); ph != mhs.end();) { 346 out << "\"" << ModellingHypothesis::toString(*ph) << "\""; 347 if (++ph != mhs.end()) { 348 out << ",\n"; 349 } 350 } 351 out << "};\n\n"; 352 } 353 } // end of SymbolsGenerator::writeSupportedModellingHypothesis 354 writeMaterialPropertiesSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const355 void SymbolsGenerator::writeMaterialPropertiesSymbols( 356 std::ostream& out, 357 const StandardBehaviourInterface& i, 358 const BehaviourDescription& mb, 359 const std::string& name, 360 const Hypothesis h) const { 361 using namespace std; 362 auto throw_if = [](const bool b, const std::string& m) { 363 tfel::raise_if(b, 364 "SymbolsGenerator::writeMaterialPropertiesSymbols: " + m); 365 }; 366 const auto mprops = i.buildMaterialPropertiesList(mb, h); 367 if (mprops.first.empty()) { 368 out << "MFRONT_SHAREDOBJ unsigned short " 369 << this->getSymbolName(i, name, h) << "_nMaterialProperties = 0u;\n\n" 370 << "MFRONT_SHAREDOBJ const char * const *" 371 << this->getSymbolName(i, name, h) 372 << "_MaterialProperties = nullptr;\n\n"; 373 } else { 374 const auto& last = mprops.first.back(); 375 SupportedTypes::TypeSize s; 376 throw_if((mprops.second.getTensorSize() != 0) || 377 (mprops.second.getStensorSize() != 0) || 378 (mprops.second.getTVectorSize() != 0), 379 "internal error: the material properties shall all be scalars"); 380 s = last.offset; 381 s += SupportedTypes::getTypeSize(last.type, last.arraySize); 382 s -= mprops.second; 383 throw_if((s.getTensorSize() != 0) || (s.getStensorSize() != 0) || 384 (s.getTVectorSize() != 0), 385 "internal error: the material properties shall all be scalars"); 386 throw_if(s.getScalarSize() < 0, 387 "internal error: negative number of the material properties"); 388 vector<BehaviourMaterialProperty>::size_type ib = 389 0; /* index of the first element which 390 * is not imposed by the material properties */ 391 bool found = false; 392 for (decltype(mprops.first.size()) idx = 0; 393 (idx != mprops.first.size()) && (!found); ++idx) { 394 if (mprops.first[idx].offset == mprops.second) { 395 ib = idx; 396 found = true; 397 } 398 } 399 if (!found) { 400 throw_if(s.getScalarSize() != 0, 401 "internal error: inconsistent offset declaration"); 402 out << "MFRONT_SHAREDOBJ unsigned short " 403 << this->getSymbolName(i, name, h) 404 << "_nMaterialProperties = 0u;\n\n"; 405 out << "MFRONT_SHAREDOBJ const char * const *" 406 << this->getSymbolName(i, name, h) 407 << "_MaterialProperties = nullptr;\n\n"; 408 } else { 409 out << "MFRONT_SHAREDOBJ unsigned short " 410 << this->getSymbolName(i, name, h) 411 << "_nMaterialProperties = " << s.getScalarSize() << "u;\n\n"; 412 out << "MFRONT_SHAREDOBJ const char *" 413 << this->getSymbolName(i, name, h) << "_MaterialProperties[" 414 << s.getScalarSize() << "u] = {"; 415 for (auto idx = ib; idx != mprops.first.size();) { 416 const auto& m = mprops.first[idx]; 417 if (m.arraySize == 1u) { 418 out << "\"" << m.name << "\""; 419 } else { 420 for (unsigned short j = 0; j != m.arraySize;) { 421 out << "\"" << m.name << "[" << j << "]\""; 422 if (++j != m.arraySize) { 423 out << ",\n"; 424 } 425 } 426 } 427 if (++idx != mprops.first.size()) { 428 out << ",\n"; 429 } 430 } 431 out << "};\n\n"; 432 } 433 } 434 } // end of UMATInterface::writeMaterialPropertiesSymbol 435 writeStateVariablesSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const436 void SymbolsGenerator::writeStateVariablesSymbols( 437 std::ostream& out, 438 const StandardBehaviourInterface& i, 439 const BehaviourDescription& mb, 440 const std::string& name, 441 const Hypothesis h) const { 442 const auto& d = mb.getBehaviourData(h); 443 const auto& persistentVarsHolder = d.getPersistentVariables(); 444 const unsigned short nStateVariables = static_cast<unsigned short>( 445 persistentVarsHolder.getNumberOfVariables()); 446 out << "MFRONT_SHAREDOBJ unsigned short " << this->getSymbolName(i, name, h) 447 << "_nInternalStateVariables = " << nStateVariables << ";\n"; 448 std::vector<std::string> stateVariablesNames; 449 mb.getExternalNames(stateVariablesNames, h, persistentVarsHolder); 450 this->writeExternalNames(out, i, name, h, stateVariablesNames, 451 "InternalStateVariables"); 452 if (!persistentVarsHolder.empty()) { 453 out << "MFRONT_SHAREDOBJ int " << this->getSymbolName(i, name, h) 454 << "_InternalStateVariablesTypes [] = {"; 455 for (auto p = persistentVarsHolder.begin(); 456 p != persistentVarsHolder.end();) { 457 const auto t = getVariableTypeId(*p); 458 for (unsigned short is = 0; is != p->arraySize;) { 459 out << t; 460 if (++is != p->arraySize) { 461 out << ","; 462 } 463 } 464 if (++p != persistentVarsHolder.end()) { 465 out << ","; 466 } 467 } 468 out << "};\n\n"; 469 } else { 470 out << "MFRONT_SHAREDOBJ const int * " << this->getSymbolName(i, name, h) 471 << "_InternalStateVariablesTypes = nullptr;\n\n"; 472 } 473 } // end of SymbolsGenerator::writeStateVariablesSymbols 474 writeExternalStateVariablesSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const475 void SymbolsGenerator::writeExternalStateVariablesSymbols( 476 std::ostream& out, 477 const StandardBehaviourInterface& i, 478 const BehaviourDescription& mb, 479 const std::string& name, 480 const Hypothesis h) const { 481 const auto& d = mb.getBehaviourData(h); 482 auto evs = d.getExternalStateVariables(); 483 // removing the temperature 484 evs.erase(evs.begin()); 485 out << "MFRONT_SHAREDOBJ unsigned short " << this->getSymbolName(i, name, h) 486 << "_nExternalStateVariables = " << evs.getNumberOfVariables() << ";\n"; 487 this->writeExternalNames(out, i, name, h, mb.getExternalNames(h, evs), 488 "ExternalStateVariables"); 489 } // end of SymbolsGenerator::writeExternalStateVariablesSymbols 490 writeParametersSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const491 void SymbolsGenerator::writeParametersSymbols( 492 std::ostream& out, 493 const StandardBehaviourInterface& i, 494 const BehaviourDescription& mb, 495 const std::string& name, 496 const Hypothesis h) const { 497 const auto& d = mb.getBehaviourData(h); 498 const auto& parameters = d.getParameters(); 499 out << "MFRONT_SHAREDOBJ unsigned short " << this->getSymbolName(i, name, h) 500 << "_nParameters = " << parameters.getNumberOfVariables() << ";\n"; 501 this->writeExternalNames(out, i, name, h, 502 mb.getExternalNames(h, parameters), "Parameters"); 503 if (!parameters.empty()) { 504 out << "MFRONT_SHAREDOBJ int " << this->getSymbolName(i, name, h) 505 << "_ParametersTypes [] = {"; 506 for (auto p = parameters.begin(); p != parameters.end();) { 507 for (unsigned short is = 0; is != p->arraySize;) { 508 if (p->type == "int") { 509 out << "1"; 510 } else if (p->type == "ushort") { 511 out << "2"; 512 } else { 513 const auto f = SupportedTypes::getTypeFlag(p->type); 514 tfel::raise_if(f != SupportedTypes::SCALAR, 515 "SymbolsGenerator::writeParametersSymbols: " 516 "internal error, unsupported type " 517 "for parameter '" + 518 p->name + "'"); 519 out << "0"; 520 } 521 if (++is != p->arraySize) { 522 out << ","; 523 } 524 } 525 if (++p != parameters.end()) { 526 out << ","; 527 } 528 } 529 out << "};\n\n"; 530 } else { 531 out << "MFRONT_SHAREDOBJ const int * " << this->getSymbolName(i, name, h) 532 << "_ParametersTypes = nullptr;\n\n"; 533 } 534 } // end of SymbolsGenerator::writeParametersSymbols 535 writeParameterDefaultValueSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const536 void SymbolsGenerator::writeParameterDefaultValueSymbols( 537 std::ostream& out, 538 const StandardBehaviourInterface& i, 539 const BehaviourDescription& mb, 540 const std::string& name, 541 const Hypothesis h) const { 542 auto throw_if = [](const bool b, const std::string& m) { 543 tfel::raise_if(b, 544 "SymbolsGenerator::" 545 "writeParameterDefaultValueSymbols: " + 546 m); 547 }; 548 for (const auto& p : mb.getBehaviourData(h).getParameters()) { 549 if (p.type == "int") { 550 throw_if(p.arraySize != 1u, 551 "unsupported parameters array of type '" + p.type + "'"); 552 out << "MFRONT_SHAREDOBJ int " << this->getSymbolName(i, name, h) << "_" 553 << p.getExternalName() << "_ParameterDefaultValue = " 554 << mb.getIntegerParameterDefaultValue(h, p.name) << ";\n\n"; 555 } else if (p.type == "ushort") { 556 throw_if(p.arraySize != 1u, 557 "unsupported parameters array of type '" + p.type + "'"); 558 out << "MFRONT_SHAREDOBJ unsigned short " 559 << this->getSymbolName(i, name, h) << "_" << p.getExternalName() 560 << "_ParameterDefaultValue = " 561 << mb.getUnsignedShortParameterDefaultValue(h, p.name) << ";\n\n"; 562 } else { 563 const auto f = SupportedTypes::getTypeFlag(p.type); 564 throw_if(f != SupportedTypes::SCALAR, 565 "unsupported paramaeter type '" + p.type + "'"); 566 const auto prec = out.precision(); 567 out.precision(14); 568 if (p.arraySize == 1u) { 569 out << "MFRONT_SHAREDOBJ double " << this->getSymbolName(i, name, h) 570 << "_" << p.getExternalName() << "_ParameterDefaultValue" 571 << " = " << mb.getFloattingPointParameterDefaultValue(h, p.name) 572 << ";\n\n"; 573 } else { 574 for (unsigned short is = 0; is != p.arraySize; ++is) { 575 out << "MFRONT_SHAREDOBJ double " << this->getSymbolName(i, name, h) 576 << "_" << p.getExternalName() << "__" << is 577 << "___ParameterDefaultValue = " 578 << mb.getFloattingPointParameterDefaultValue(h, p.name, is) 579 << ";\n\n"; 580 } 581 } 582 out.precision(prec); 583 } 584 } 585 } // end of SymbolsGenerator::writeParameterDefaultValueSymbols 586 587 writeBoundsSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const588 void SymbolsGenerator::writeBoundsSymbols(std::ostream& out, 589 const StandardBehaviourInterface& i, 590 const BehaviourDescription& mb, 591 const std::string& name, 592 const Hypothesis h) const { 593 auto write = [this, &out, &name, &i, 594 h](const VariableDescriptionContainer& vc) { 595 const auto prec = out.precision(); 596 out.precision(14); 597 for (const auto& v : vc) { 598 if (v.arraySize == 1u) { 599 if (!v.hasBounds()) { 600 continue; 601 } 602 mfront::writeBoundsSymbol(out, this->getSymbolName(i, name, h), 603 v.getExternalName(), "", v.getBounds()); 604 } else { 605 for (auto idx = 0; idx != v.arraySize; ++idx) { 606 if (!v.hasBounds(idx)) { 607 continue; 608 } 609 mfront::writeBoundsSymbol( 610 out, this->getSymbolName(i, name, h), 611 v.getExternalName() + "__" + std::to_string(idx) + "__", "", 612 v.getBounds(idx)); 613 } 614 } 615 } 616 out.precision(prec); 617 }; 618 const auto& d = mb.getBehaviourData(h); 619 write(d.getMaterialProperties()); 620 write(d.getPersistentVariables()); 621 write(d.getExternalStateVariables()); 622 write(d.getParameters()); 623 } // end of SymbolsGenerator::writeBoundsSymbols 624 writePhysicalBoundsSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const625 void SymbolsGenerator::writePhysicalBoundsSymbols( 626 std::ostream& out, 627 const StandardBehaviourInterface& i, 628 const BehaviourDescription& mb, 629 const std::string& name, 630 const Hypothesis h) const { 631 auto write = [this, &out, &i, &name, 632 h](const VariableDescriptionContainer& vc) { 633 const auto prec = out.precision(); 634 out.precision(14); 635 for (const auto& v : vc) { 636 if (v.arraySize == 1u) { 637 if (!v.hasPhysicalBounds()) { 638 continue; 639 } 640 mfront::writeBoundsSymbol(out, this->getSymbolName(i, name, h), 641 v.getExternalName(), "Physical", 642 v.getPhysicalBounds()); 643 } else { 644 for (auto idx = 0; idx != v.arraySize; ++idx) { 645 if (!v.hasPhysicalBounds(idx)) { 646 continue; 647 } 648 mfront::writeBoundsSymbol( 649 out, this->getSymbolName(i, name, h), 650 v.getExternalName() + "__" + std::to_string(idx) + "__", 651 "Physical", v.getPhysicalBounds(idx)); 652 } 653 } 654 } 655 out.precision(prec); 656 }; 657 const auto& d = mb.getBehaviourData(h); 658 write(d.getMaterialProperties()); 659 write(d.getPersistentVariables()); 660 write(d.getExternalStateVariables()); 661 write(d.getParameters()); 662 } // end of SymbolsGenerator::writePhysicalBoundsSymbols 663 writeRequirementsSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const664 void SymbolsGenerator::writeRequirementsSymbols( 665 std::ostream& out, 666 const StandardBehaviourInterface& i, 667 const BehaviourDescription& mb, 668 const std::string& name, 669 const Hypothesis h) const { 670 out << "MFRONT_SHAREDOBJ unsigned short " 671 << this->getSymbolName(i, name, h); 672 out << "_requiresStiffnessTensor = "; 673 if (mb.getAttribute(BehaviourDescription::requiresStiffnessTensor, false)) { 674 out << "1"; 675 } else { 676 out << "0"; 677 } 678 out << ";\n"; 679 out << "MFRONT_SHAREDOBJ unsigned short " 680 << this->getSymbolName(i, name, h); 681 out << "_requiresThermalExpansionCoefficientTensor = "; 682 if (mb.getAttribute( 683 BehaviourDescription::requiresThermalExpansionCoefficientTensor, 684 false)) { 685 out << "1"; 686 } else { 687 out << "0"; 688 } 689 out << ";\n"; 690 691 } // end of SymbolsGenerator::writeRequirementsSymbols 692 writeIsUsableInPurelyImplicitResolutionSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name,const Hypothesis h) const693 void SymbolsGenerator::writeIsUsableInPurelyImplicitResolutionSymbols( 694 std::ostream& out, 695 const StandardBehaviourInterface& i, 696 const BehaviourDescription& mb, 697 const std::string& name, 698 const Hypothesis h) const { 699 const auto& d = mb.getBehaviourData(h); 700 out << "MFRONT_SHAREDOBJ unsigned short " << this->getSymbolName(i, name, h) 701 << "_UsableInPurelyImplicitResolution = "; 702 if (d.isUsableInPurelyImplicitResolution()) { 703 out << "1;\n\n"; 704 } else { 705 out << "0;\n\n"; 706 } 707 } // end of 708 // SymbolsGenerator::writeIsUsableInPurelyImplicitResolution 709 writeSymmetryTypeSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name) const710 void SymbolsGenerator::writeSymmetryTypeSymbols( 711 std::ostream& out, 712 const StandardBehaviourInterface& i, 713 const BehaviourDescription& mb, 714 const std::string& name) const { 715 out << "MFRONT_SHAREDOBJ unsigned short " << i.getFunctionNameBasis(name) 716 << "_SymmetryType = "; 717 if (mb.getSymmetryType() == mfront::ISOTROPIC) { 718 out << "0u;\n\n"; 719 } else if (mb.getSymmetryType() == mfront::ORTHOTROPIC) { 720 out << "1u;\n\n"; 721 } else { 722 tfel::raise( 723 "SymbolsGenerator::writeSymmetryTypeSymbols: " 724 "unsupported behaviour type.\n" 725 "only isotropic or orthotropic behaviours " 726 "are supported at this time."); 727 } 728 } // end of SymbolsGenerator::writeSymmetryTypeSymbols 729 writeElasticSymmetryTypeSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription & mb,const std::string & name) const730 void SymbolsGenerator::writeElasticSymmetryTypeSymbols( 731 std::ostream& out, 732 const StandardBehaviourInterface& i, 733 const BehaviourDescription& mb, 734 const std::string& name) const { 735 out << "MFRONT_SHAREDOBJ unsigned short " << i.getFunctionNameBasis(name) 736 << "_ElasticSymmetryType = "; 737 if (mb.getElasticSymmetryType() == mfront::ISOTROPIC) { 738 out << "0u;\n\n"; 739 } else if (mb.getElasticSymmetryType() == mfront::ORTHOTROPIC) { 740 out << "1u;\n\n"; 741 } else { 742 tfel::raise( 743 "SymbolsGenerator::writeElasticSymmetryTypeSymbols: " 744 "unsupported behaviour type.\n" 745 "only isotropic or orthotropic behaviours are " 746 "supported at this time."); 747 } 748 } // end of SymbolsGenerator::writeElasticSymmetryTypeSymbols 749 writeSourceFileSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription &,const mfront::FileDescription & fd,const std::string & name) const750 void SymbolsGenerator::writeSourceFileSymbols( 751 std::ostream& out, 752 const StandardBehaviourInterface& i, 753 const BehaviourDescription&, 754 const mfront::FileDescription& fd, 755 const std::string& name) const { 756 using namespace tfel::system; 757 using namespace tfel::utilities; 758 out << "MFRONT_SHAREDOBJ const char *\n" 759 << i.getFunctionNameBasis(name) << "_src = \"" 760 << tokenize(fd.fileName, dirSeparator()).back() << "\";\n\n"; 761 } 762 writeInterfaceNameSymbols(std::ostream & out,const StandardBehaviourInterface & i,const BehaviourDescription &,const mfront::FileDescription &,const std::string & name) const763 void SymbolsGenerator::writeInterfaceNameSymbols( 764 std::ostream& out, 765 const StandardBehaviourInterface& i, 766 const BehaviourDescription&, 767 const mfront::FileDescription&, 768 const std::string& name) const { 769 writeInterfaceSymbol(out, i.getFunctionNameBasis(name), 770 i.getInterfaceName()); 771 } 772 writeExternalNames(std::ostream & f,const StandardBehaviourInterface & i,const std::string & name,const Hypothesis & h,const std::vector<std::string> & v,const std::string & t) const773 void SymbolsGenerator::writeExternalNames(std::ostream& f, 774 const StandardBehaviourInterface& i, 775 const std::string& name, 776 const Hypothesis& h, 777 const std::vector<std::string>& v, 778 const std::string& t) const { 779 this->writeArrayOfStringsSymbol( 780 f, this->getSymbolName(i, name, h) + "_" + t, v); 781 } // end of SymbolsGenerator::writeExternalNames 782 writeArrayOfStringsSymbol(std::ostream & f,const std::string & s,const std::vector<std::string> & v) const783 void SymbolsGenerator::writeArrayOfStringsSymbol( 784 std::ostream& f, 785 const std::string& s, 786 const std::vector<std::string>& v) const { 787 if (v.empty()) { 788 f << "MFRONT_SHAREDOBJ const char * const * " << s << " = nullptr;\n\n"; 789 } else { 790 auto i = decltype(v.size()){}; 791 auto p = v.begin(); 792 f << "MFRONT_SHAREDOBJ const char * " << s << "[" << v.size() << "] = {"; 793 while (p != v.end()) { 794 f << '"' << *p << '"'; 795 if (++p != v.end()) { 796 if (i % 5 == 0) { 797 f << ",\n"; 798 } else { 799 f << ","; 800 } 801 } 802 ++i; 803 } 804 f << "};\n"; 805 } 806 } // end of SymbolsGenerator::writeArrayOfStringsSymbol 807 writeArrayOfIntsSymbol(std::ostream & f,const std::string & s,const std::vector<int> & v) const808 void SymbolsGenerator::writeArrayOfIntsSymbol( 809 std::ostream& f, const std::string& s, const std::vector<int>& v) const { 810 if (v.empty()) { 811 f << "MFRONT_SHAREDOBJ const int * " << s << " = nullptr;\n\n"; 812 } else { 813 auto i = decltype(v.size()){}; 814 auto p = v.begin(); 815 f << "MFRONT_SHAREDOBJ int " << s << "[" << v.size() << "] = {"; 816 while (p != v.end()) { 817 f << *p; 818 if (++p != v.end()) { 819 if (i % 5 == 0) { 820 f << ",\n"; 821 } else { 822 f << ","; 823 } 824 } 825 ++i; 826 } 827 f << "};\n"; 828 } 829 } // end of SymbolsGenerator::writeArrayOfIntsSymbol 830 831 SymbolsGenerator::~SymbolsGenerator() = default; 832 833 } // end of namespace mfront 834