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