1 /*!
2  * \file  mfront/src/StandardBehaviourInterface.cxx
3  * \brief
4  * \author Thomas Helfer
5  * \brief 21 juil. 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<ostream>
15 #include"TFEL/Raise.hxx"
16 #include"TFEL/Glossary/Glossary.hxx"
17 #include"TFEL/Glossary/GlossaryEntry.hxx"
18 #include"MFront/DSLUtilities.hxx"
19 #include"MFront/BehaviourDescription.hxx"
20 #include"MFront/StandardBehaviourInterface.hxx"
21 
22 namespace mfront {
23 
24     /*!
25      * \param[out] rp: if true, a least one floatting-point parameter
26      * has been found.
27      * \param[out] ip: if true, a least one integer parameter has been
28      * found.
29      * \param[out] up: if true, a least one parameter of type
30      * `unsigned short` has been found.
31      * \param[in] pc: list of parameters.
32      */
checkParametersType(bool & rp,bool & ip,bool & up,const VariableDescriptionContainer & pc)33   static void checkParametersType(
34       bool& rp,bool& ip,bool& up,
35       const VariableDescriptionContainer& pc) {
36     rp = false;
37     ip = false;
38     up = false;
39     for (const auto& v : pc) {
40       if (v.type == "int") {
41         ip = true;
42       } else if (v.type == "ushort") {
43         up = true;
44       } else {
45         const auto f = SupportedTypes::getTypeFlag(v.type);
46         tfel::raise_if(f != SupportedTypes::SCALAR,
47                        "checkParametersType: "
48                        "unsupport parameter type '" +
49                            v.type + "'.");
50         rp = true;
51       }
52     }
53   }  // end of checkParametersType
54 
55   StandardBehaviourInterface::StandardBehaviourInterface() = default;
56 
57   const char* const StandardBehaviourInterface::generateMTestFileAttribute =
58       "GenerateMTestFileOnFailure";
59 
isBehaviourConstructorRequired(const Hypothesis h,const BehaviourDescription & mb) const60   bool StandardBehaviourInterface::isBehaviourConstructorRequired(
61       const Hypothesis h, const BehaviourDescription& mb) const {
62     const auto mhs = this->getModellingHypothesesToBeTreated(mb);
63     if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) {
64       return !mb.areAllMechanicalDataSpecialised(mhs);
65     }
66     return mhs.find(h) != mhs.end();
67   } // end of StandardBehaviourInterface::isBehaviourConstructorRequired
68 
getHeaderGuard(const BehaviourDescription & mb) const69   std::string StandardBehaviourInterface::getHeaderGuard(
70       const BehaviourDescription& mb) const {
71     const auto& m = mb.getMaterialName();
72     auto header = "LIB_" + makeUpperCase(this->getInterfaceName());
73     if (!mb.getLibrary().empty()) {
74       header += "_";
75       header += makeUpperCase(mb.getLibrary());
76     }
77     if (!m.empty()) {
78       header += "_";
79       header += makeUpperCase(m);
80     }
81     header += "_";
82     header += makeUpperCase(mb.getClassName());
83     header += "_HXX";
84     return header;
85   }  // end of StandardBehaviourInterface::getHeaderGuard
86 
writeVisibilityDefines(std::ostream & out) const87   void StandardBehaviourInterface::writeVisibilityDefines(std::ostream& out) const {
88     out << "#ifdef _WIN32\n"
89         << "#ifndef NOMINMAX\n"
90         << "#define NOMINMAX\n"
91         << "#endif /* NOMINMAX */\n"
92         << "#include <windows.h>\n"
93         << "#ifdef small\n"
94         << "#undef small\n"
95         << "#endif /* small */\n"
96         << "#endif /* _WIN32 */\n\n"
97         << "#ifndef MFRONT_SHAREDOBJ\n"
98         << "#define MFRONT_SHAREDOBJ TFEL_VISIBILITY_EXPORT\n"
99         << "#endif /* MFRONT_SHAREDOBJ */\n\n";
100   }  // end of StandardBehaviourInterface::writeVisibilityDefines
101 
102   std::pair<std::vector<BehaviourMaterialProperty>, SupportedTypes::TypeSize>
buildMaterialPropertiesList(const BehaviourDescription & bd,const Hypothesis h) const103   StandardBehaviourInterface::buildMaterialPropertiesList(const BehaviourDescription& bd,
104                                                  const Hypothesis h) const {
105     if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) {
106       return mfront::buildMaterialPropertiesList(
107           bd, this->getModellingHypothesesToBeTreated(bd));
108     }
109     return mfront::buildMaterialPropertiesList(bd, h);
110   }  // end of StandardBehaviourInterface::buildMaterialPropertiesList
111 
writeSetOutOfBoundsPolicyFunctionDeclaration(std::ostream & out,const std::string & name) const112   void StandardBehaviourInterface::writeSetOutOfBoundsPolicyFunctionDeclaration(
113       std::ostream& out, const std::string& name) const {
114     out << "MFRONT_SHAREDOBJ void\n"
115         << this->getFunctionNameBasis(name)
116         << "_setOutOfBoundsPolicy(const int);\n\n";
117   }
118 
writeGetOutOfBoundsPolicyFunctionImplementation(std::ostream & out,const std::string & name) const119   void StandardBehaviourInterface::writeGetOutOfBoundsPolicyFunctionImplementation(
120       std::ostream& out, const std::string& name) const {
121     out << "static tfel::material::OutOfBoundsPolicy&\n"
122         << this->getFunctionNameBasis(name) << "_getOutOfBoundsPolicy(){\n"
123         << "using namespace tfel::material;\n"
124         << "static OutOfBoundsPolicy policy = None;\n"
125         << "return policy;\n"
126         << "}\n\n";
127   }  // end of
128      // StandardBehaviourInterface::writeGetOutOfBoundsPolicyFunctionImplementation
129 
writeSetOutOfBoundsPolicyFunctionImplementation(std::ostream & out,const std::string & name) const130   void StandardBehaviourInterface::writeSetOutOfBoundsPolicyFunctionImplementation(
131       std::ostream& out, const std::string& name) const {
132     out << "MFRONT_SHAREDOBJ void\n"
133         << this->getFunctionNameBasis(name)
134         << "_setOutOfBoundsPolicy(const int p){\n"
135         << "if(p==0){\n"
136         << this->getFunctionNameBasis(name)
137         << "_getOutOfBoundsPolicy() = tfel::material::None;\n"
138         << "} else if(p==1){\n"
139         << this->getFunctionNameBasis(name)
140         << "_getOutOfBoundsPolicy() = tfel::material::Warning;\n"
141         << "} else if(p==2){\n"
142         << this->getFunctionNameBasis(name)
143         << "_getOutOfBoundsPolicy() = tfel::material::Strict;\n"
144         << "} else {\n"
145         << "std::cerr << \"" << this->getFunctionNameBasis(name)
146         << "_setOutOfBoundsPolicy: invalid argument\\n\";\n"
147         << "}\n"
148         << "}\n\n";
149   }
150 
writeSetParametersFunctionsDeclarations(std::ostream & out,const BehaviourDescription & mb,const std::string & name) const151   void StandardBehaviourInterface::writeSetParametersFunctionsDeclarations(
152       std::ostream& out,
153       const BehaviourDescription& mb,
154       const std::string& name) const {
155     const auto mh = mb.getDistinctModellingHypotheses();
156     const auto mh2 = this->getModellingHypothesesToBeTreated(mb);
157     for (const auto h : mh) {
158       if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) ||
159           (mh2.find(h) != mh2.end())) {
160         bool rp, ip, up;
161         const auto& d = mb.getBehaviourData(h);
162         const auto& pc = d.getParameters();
163         checkParametersType(rp, ip, up, pc);
164         auto fctName = this->getFunctionNameBasis(name);
165         auto suffix = std::string{};
166         if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) {
167           suffix += ModellingHypothesis::toString(h);
168           fctName += "_" + suffix;
169         }
170         if (rp) {
171           out << "MFRONT_SHAREDOBJ int\n"
172               << fctName
173               << "_setParameter(const char *const,const double);\n\n";
174         }
175         if (ip) {
176           out << "MFRONT_SHAREDOBJ int\n"
177               << fctName
178               << "_setIntegerParameter(const char *const,const int);\n\n";
179         }
180         if (up) {
181           out << "MFRONT_SHAREDOBJ int\n"
182               << fctName << "_setUnsignedShortParameter(const char "
183                             "*const,const unsigned short);\n\n";
184         }
185       }
186     }
187   }  // end of StandardBehaviourInterface::writeSetParametersFunctionsDeclarations
188 
writeSetParametersFunctionsImplementations(std::ostream & out,const BehaviourDescription & mb,const std::string & name) const189   void StandardBehaviourInterface::writeSetParametersFunctionsImplementations(
190       std::ostream& out,
191       const BehaviourDescription& mb,
192       const std::string& name) const {
193     const auto mh = mb.getDistinctModellingHypotheses();
194     const auto mh2 = this->getModellingHypothesesToBeTreated(mb);
195     for (const auto& h : mh) {
196       if ((h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) ||
197           (mh2.find(h) != mh2.end())) {
198         const auto& d = mb.getBehaviourData(h);
199         const auto& pc = d.getParameters();
200         bool rp, ip, up;
201         checkParametersType(rp, ip, up, pc);
202         auto fctName = this->getFunctionNameBasis(name);
203         std::string suffix;
204         if (h != ModellingHypothesis::UNDEFINEDHYPOTHESIS) {
205           suffix += ModellingHypothesis::toString(h);
206           fctName += "_" + suffix;
207         }
208         const auto cname = mb.getClassName() + suffix + "ParametersInitializer";
209         if (rp) {
210           out << "MFRONT_SHAREDOBJ int\n"
211               << fctName
212               << "_setParameter(const char *const key,const double value){\n"
213               << "using tfel::material::" << cname << ";\n"
214               << "auto& i = " << cname << "::get();\n"
215               << "try{\n"
216               << "i.set(key,value);\n"
217               << "} catch(std::runtime_error& e){\n"
218               << "std::cerr << e.what() << std::endl;\n"
219               << "return 0;\n"
220               << "}\n"
221               << "return 1;\n"
222               << "}\n\n";
223         }
224         if (ip) {
225           out << "MFRONT_SHAREDOBJ int\n"
226               << fctName << "_setIntegerParameter(const char *const key,const "
227                             "int value){\n"
228               << "using tfel::material::" << cname << ";\n"
229               << "auto& i = " << cname << "::get();\n"
230               << "try{\n"
231               << "i.set(key,value);\n"
232               << "} catch(std::runtime_error& e){\n"
233               << "std::cerr << e.what() << std::endl;\n"
234               << "return 0;\n"
235               << "}\n"
236               << "return 1;\n"
237               << "}\n\n";
238         }
239         if (up) {
240           out << "MFRONT_SHAREDOBJ int\n"
241               << fctName << "_setUnsignedShortParameter(const char *const "
242                             "key,const unsigned short value){\n"
243               << "using tfel::material::" << cname << ";\n"
244               << "auto& i = " << cname << "::get();\n"
245               << "try{\n"
246               << "i.set(key,value);\n"
247               << "} catch(std::runtime_error& e){\n"
248               << "std::cerr << e.what() << std::endl;\n"
249               << "return 0;\n"
250               << "}\n"
251               << "return 1;\n"
252               << "}\n\n";
253         }
254       }
255     }
256   }
257 
setGenerateMTestFileOnFailureAttribute(BehaviourDescription & bd,const bool b) const258   void StandardBehaviourInterface::setGenerateMTestFileOnFailureAttribute(
259       BehaviourDescription& bd, const bool b) const {
260     const auto a = this->getInterfaceName() + "::" +
261                    StandardBehaviourInterface::generateMTestFileAttribute;
262     bd.setAttribute(a, b, false);
263   }  // end of StandardBehaviourInterface::setGenerateMTestFileOnFailureAttribute
264 
shallGenerateMTestFileOnFailure(const BehaviourDescription & bd) const265   bool StandardBehaviourInterface::shallGenerateMTestFileOnFailure(
266       const BehaviourDescription& bd) const {
267     const auto a = this->getInterfaceName() + "::" +
268                    StandardBehaviourInterface::generateMTestFileAttribute;
269     return bd.getAttribute<bool>(a, false);
270   }  // end of StandardBehaviourInterface::shallGenerateMTestFileOnFailure
271 
272   std::pair<bool, SupportedTypes::TypeSize>
checkIfAxialStrainIsDefinedAndGetItsOffset(const BehaviourDescription & mb,const Hypothesis h) const273   StandardBehaviourInterface::checkIfAxialStrainIsDefinedAndGetItsOffset(
274       const BehaviourDescription& mb, const Hypothesis h) const {
275     using tfel::glossary::Glossary;
276     const auto& d = mb.getBehaviourData(h);
277     const auto& sv = d.getPersistentVariables();
278     SupportedTypes::TypeSize o;
279     for (const auto& elem : sv) {
280       if (d.getExternalName(elem.name) == Glossary::AxialStrain) {
281         return {true, o};
282       }
283       o += SupportedTypes::getTypeSize(elem.type, elem.arraySize);
284     }
285     return {false, o};
286   }
287 
288   std::pair<bool, SupportedTypes::TypeSize> StandardBehaviourInterface::
checkIfAxialDeformationGradientIsDefinedAndGetItsOffset(const BehaviourDescription & mb,const Hypothesis h) const289       checkIfAxialDeformationGradientIsDefinedAndGetItsOffset(
290           const BehaviourDescription& mb, const Hypothesis h) const {
291     using tfel::glossary::Glossary;
292     const auto& d = mb.getBehaviourData(h);
293     const auto& sv = d.getPersistentVariables();
294     SupportedTypes::TypeSize o;
295     for (const auto& elem : sv) {
296       if (d.getExternalName(elem.name) == Glossary::AxialDeformationGradient) {
297         return {true, o};
298       }
299       o += SupportedTypes::getTypeSize(elem.type, elem.arraySize);
300     }
301     return {false, o};
302   }
303 
readBooleanValue(const std::string & key,tokens_iterator & current,const tokens_iterator end) const304   bool StandardBehaviourInterface::readBooleanValue(
305       const std::string& key,
306       tokens_iterator& current,
307       const tokens_iterator end) const {
308     auto throw_if = [&key](const bool b, const std::string& m) {
309       tfel::raise_if(b, "UMATInterfaceBase::readBooleanValue: " + m +
310                             ".\nError while treating key (" + key + ")\n");
311     };
312     throw_if(current == end, "unexpected end of file");
313     const auto b = [&current, &throw_if]() -> bool {
314       if (current->value == "true") {
315         return true;
316       } else if (current->value == "false") {
317         return false;
318       } else {
319         throw_if(true, "expected 'true' or 'false'");
320       }
321     }();
322     ++(current);
323     throw_if(current == end, "unexpected end of file");
324     throw_if(current->value != ";",
325              "expected ';', read '" + current->value + "'");
326     ++(current);
327     return b;
328   }  // end of StandardBehaviourInterface::readBooleanValue
329 
330   StandardBehaviourInterface::~StandardBehaviourInterface() = default;
331 
332 }  // end of namespace mfront
333