1 /*!
2  * \file   SingleStructureSchemeParser.cxx
3  * \brief
4  * \author Thomas Helfer
5  * \date   21 déc. 2015
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 <sstream>
15 #include "TFEL/Raise.hxx"
16 #include "TFEL/Math/Parser/ConstantExternalFunction.hxx"
17 #include "TFEL/Material/OutOfBoundsPolicy.hxx"
18 #include "MFront/MFrontLogStream.hxx"
19 #include "MTest/MTest.hxx"
20 #include "MTest/Behaviour.hxx"
21 #include "MTest/Evolution.hxx"
22 #include "MTest/CastemEvolution.hxx"
23 #include "MTest/CyranoEvolution.hxx"
24 #include "MTest/FunctionEvolution.hxx"
25 #include "MTest/SingleStructureSchemeParser.hxx"
26 
27 namespace mtest {
28 
selectVariables(std::vector<std::string> & r,const std::vector<std::string> & names,const std::string & n)29   static void selectVariables(std::vector<std::string>& r,
30                               const std::vector<std::string>& names,
31                               const std::string& n) {
32     r.clear();
33     if (find(names.begin(), names.end(), n) != names.end()) {
34       r.push_back(n);
35     } else {
36       // checking for an array of internal state variables
37       for (const auto& vn : names) {
38         if (vn.compare(0, n.length(), n) == 0) {
39           if (!(vn.size() >= n.length() + 3u)) {
40             continue;
41           }
42           auto pn = vn.crbegin();
43           const auto pne = vn.crbegin() + (vn.size() - n.size() - 1);
44           if ((vn[n.size()] != '[') || (*pn != ']')) {
45             continue;
46           }
47           ++pn;
48           bool ok = true;
49           while ((pn != pne) && (ok)) {
50             ok = ::isdigit(*pn) != 0;
51             ++pn;
52           }
53           if (ok) {
54             r.push_back(vn);
55           }
56         }
57       }
58     }
59   }  // end of selectVariables
60 
getSTensorSize(const unsigned short d)61   static unsigned short getSTensorSize(const unsigned short d) {
62     if (d == 1) {
63       return 3;
64     } else if (d == 2) {
65       return 4;
66     } else if (d == 3) {
67       return 6;
68     }
69     tfel::raise("mfront::getSTensorSize: invalid dimension");
70   }
71 
getTensorSize(const unsigned short d)72   static unsigned short getTensorSize(const unsigned short d) {
73     if (d == 1) {
74       return 3;
75     } else if (d == 2) {
76       return 5;
77     } else if (d == 3) {
78       return 9;
79     }
80     tfel::raise("mfront::getTensorSize: invalid dimension");
81   }
82 
handleHandleThermalExpansion(SingleStructureScheme & t,tokens_iterator & p)83   void SingleStructureSchemeParser::handleHandleThermalExpansion(SingleStructureScheme& t,
84                                                                  tokens_iterator& p) {
85     bool b;
86     this->checkNotEndOfLine("SingleStructureSchemeParser::handleHandleThermalExpansion", p,
87                             this->tokens.end());
88     if (p->value == "true") {
89       b = true;
90     } else if (p->value == "false") {
91       b = false;
92     } else {
93       tfel::raise(
94           "SingleStructureSchemeParser::handleHandleThermalExpansion : "
95           "unexpected token '" +
96           p->value + "'");
97     }
98     ++p;
99     this->readSpecifiedToken("SingleStructureSchemeParser::handleHandleThermalExpansion", ";", p,
100                              this->tokens.end());
101     t.setHandleThermalExpansion(b);
102   }
103 
handleBehaviour(SingleStructureScheme & t,tokens_iterator & p)104   void SingleStructureSchemeParser::handleBehaviour(SingleStructureScheme& t, tokens_iterator& p) {
105     auto i = std::string{};  // interface
106     auto w = std::string{};  // wrapper
107     this->checkNotEndOfLine("SingleStructureSchemeParser::handleBehaviour", p, this->tokens.end());
108     if (p->value == "<") {
109       this->readSpecifiedToken("SingleStructureSchemeParser::handleBehaviour", "<", p,
110                                this->tokens.end());
111       this->checkNotEndOfLine("SingleStructureSchemeParser::handleBehaviour", p,
112                               this->tokens.end());
113       if((p->value == "generic") || (p->value == "Generic")){
114         i = "Generic";
115       }
116 #ifdef HAVE_CASTEM
117       if ((p->value == "umat") || (p->value == "castem") || (p->value == "Castem") ||
118           (p->value == "Cast3M")) {
119         i = "castem";
120       }
121       if (p->value == "mistral") {
122         i = "mistral";
123       }
124       if ((p->value == "mistral") || (p->value == "castem_umat_small_strain") ||
125           (p->value == "castem_umat_finite_strain")) {
126         i = p->value;
127       }
128 #endif /* HAVE_CASTEM */
129 #ifdef HAVE_ASTER
130       if ((p->value == "aster") || (p->value == "Aster")) {
131         i = p->value;
132       }
133 #endif /* HAVE_ASTER */
134 #ifdef HAVE_EUROPLEXUS
135       if((p->value=="europlexus")||(p->value=="epx")){
136         i = p->value;
137       }
138 #endif /* HAVE_EUROPLEXUS */
139 #ifdef HAVE_ABAQUS
140       if ((p->value == "Abaqus") || (p->value == "abaqus") ||
141           (p->value == "abaqus_standard") || (p->value == "abaqus_umat")) {
142         i = "abaqus";
143       }
144       if ((p->value == "AbaqusExplicit") || (p->value == "abaqus_explicit") ||
145           (p->value == "abaqus_vumat")) {
146         i = "abaqus_explicit";
147       }
148 #endif /* HAVE_ABAQUS */
149 #ifdef HAVE_ANSYS
150       if ((p->value == "Ansys") || (p->value == "ansys") ||
151           (p->value == "ansys_usermat")) {
152         i = "ansys";
153       }
154 #endif /* HAVE_ANSYS */
155 #ifdef HAVE_CYRANO
156       if(p->value=="cyrano"){
157         i = p->value;
158       }
159 #endif /* HAVE_CYRANO */
160 #ifdef HAVE_CALCULIX
161       if((p->value=="calculix")||(p->value=="CalculiX")){
162         i = "CalculiX";
163       }
164 #endif /* HAVE_CALCULIX */
165 #ifdef HAVE_DIANAFEA
166       if((p->value=="dianafea")||(p->value=="DianaFEA")){
167         i = "DianaFEA";
168       }
169 #endif /* HAVE_DIANAFEA */
170       tfel::raise_if(i.empty(),
171 		     "SingleStructureSchemeParser::handleBehaviour: "
172 		     "unknown interface '"+p->value+"'");
173       ++p;
174       this->checkNotEndOfLine("SingleStructureSchemeParser::handleBehaviour",p,
175 			      this->tokens.end());
176       if(p->value==","){
177         this->readSpecifiedToken("SingleStructureSchemeParser::handleBehaviour", ",", p,
178                                  this->tokens.end());
179         w = p->value;
180         ++p;
181       }
182       this->readSpecifiedToken("SingleStructureSchemeParser::handleBehaviour",">",p,
183 			       this->tokens.end());
184     }
185     const auto& l = this->readString(p, this->tokens.end());
186     const auto& f = this->readString(p, this->tokens.end());
187     this->checkNotEndOfLine("SingleStructureSchemeParser::handleBehaviour", p, this->tokens.end());
188     tfel::utilities::Data d;
189     if (p->value == "{") {
190       d = tfel::utilities::Data::read(p, this->tokens.end());
191     }
192     this->readSpecifiedToken("SingleStructureSchemeParser::handleBehaviour", ";", p,
193                              this->tokens.end());
194     mfront::getLogStream() << l << " " << f << std::endl;
195     if (w.empty()) {
196       t.setBehaviour(i, l, f, d);
197     } else {
198       t.setBehaviour(w, i, l, f, d);
199     }
200     const auto& b = *(t.getBehaviour());
201     // adding parameters
202     const auto& n = b.getBehaviourName();
203     for (const auto& p : b.getParametersNames()) {
204       const auto cste =
205           std::make_shared<tfel::math::parser::ConstantExternalFunction>(
206               b.getRealParameterDefaultValue(p));
207       this->externalFunctions->insert({n + "::" + p, cste});
208     }
209   }  // end of SingleStructureSchemeParser::handleBehaviour
210 
handleMaterialProperty(SingleStructureScheme & t,tokens_iterator & p)211   void SingleStructureSchemeParser::handleMaterialProperty(SingleStructureScheme& t,
212                                                            tokens_iterator& p) {
213     using namespace std;
214     using namespace tfel::utilities;
215     string i;
216     this->readSpecifiedToken("SingleStructureSchemeParser::handleMaterialProperty", "<", p,
217                              this->tokens.end());
218     this->checkNotEndOfLine("SingleStructureSchemeParser::handleMaterialProperty", p,
219                             this->tokens.end());
220     if ((p->value == "constant") || (p->value == "castem") ||
221         (p->value == "cyrano") || (p->value == "function")) {
222       i = p->value;
223     } else {
224       tfel::raise(
225           "SingleStructureSchemeParser::handleMaterialProperty: "
226           "unknown interface '" +
227           p->value + "'");
228     }
229     ++p;
230     this->readSpecifiedToken("SingleStructureSchemeParser::handleMaterialProperty", ">", p,
231                              this->tokens.end());
232     const auto& n = this->readString(p, this->tokens.end());
233     if (i == "constant") {
234       shared_ptr<Evolution> mpev;
235       this->checkNotEndOfLine("SingleStructureSchemeParser::handleMaterialProperty", p,
236                               this->tokens.end());
237       const real v = this->readDouble(t, p);
238       mpev = shared_ptr<Evolution>(new ConstantEvolution(v));
239       t.setMaterialProperty(n, mpev, true);
240     } else if (i == "function") {
241       shared_ptr<Evolution> mpev;
242       const string f = this->readString(p, this->tokens.end());
243       mpev = shared_ptr<Evolution>(new FunctionEvolution(f, t.getEvolutions()));
244       t.setMaterialProperty(n, mpev, true);
245     } else if (i == "castem") {
246       shared_ptr<Evolution> mpev;
247       const string l = this->readString(p, this->tokens.end());
248       const string f = this->readString(p, this->tokens.end());
249       mpev = shared_ptr<Evolution>(new CastemEvolution(l, f, t.getEvolutions()));
250       t.setMaterialProperty(n, mpev, true);
251     } else if (i == "cyrano") {
252       shared_ptr<Evolution> mpev;
253       const string l = this->readString(p, this->tokens.end());
254       const string f = this->readString(p, this->tokens.end());
255       mpev =
256           shared_ptr<Evolution>(new CyranoEvolution(l, f, t.getEvolutions()));
257       t.setMaterialProperty(n, mpev, true);
258     } else {
259       tfel::raise(
260           "SingleStructureSchemeParser::handleMaterialProperty: "
261           "unknown interface '" +
262           i + "'");
263     }
264     this->readSpecifiedToken("SingleStructureSchemeParser::handleMaterialProperty", ";", p,
265                              this->tokens.end());
266   }
267 
handleOutOfBoundsPolicy(SingleStructureScheme & t,tokens_iterator & p)268   void SingleStructureSchemeParser::handleOutOfBoundsPolicy(SingleStructureScheme& t,
269                                                             tokens_iterator& p) {
270     const std::string& s = this->readString(p, this->tokens.end());
271     this->readSpecifiedToken("SingleStructureSchemeParser::handlePredictionPolicy", ";", p,
272                              this->tokens.end());
273     if (s == "None") {
274       t.setOutOfBoundsPolicy(tfel::material::None);
275     } else if (s == "Warning") {
276       t.setOutOfBoundsPolicy(tfel::material::Warning);
277     } else if (s == "Strict") {
278       t.setOutOfBoundsPolicy(tfel::material::Strict);
279     } else {
280       tfel::raise(
281           "SingleStructureSchemeParser::handleOutOfBoundsPolicy: "
282           "unsupported policy '" +
283           s + "'");
284     }
285   }  // end of SingleStructureSchemeParser::handleOutOfBoundsPolicy
286 
handleParameter(SingleStructureScheme & t,tokens_iterator & p)287   void SingleStructureSchemeParser::handleParameter(SingleStructureScheme& t, tokens_iterator& p) {
288     const auto n = this->readString(p, this->tokens.end());
289     const real v = this->readDouble(t, p);
290     t.setParameter(n, v);
291     this->readSpecifiedToken("SingleStructureSchemeParser::handleParameter", ";", p,
292                              this->tokens.end());
293   }  // end of SingleStructureSchemeParser::handleParameter
294 
handleIntegerParameter(SingleStructureScheme & t,tokens_iterator & p)295   void SingleStructureSchemeParser::handleIntegerParameter(SingleStructureScheme& t,
296                                                            tokens_iterator& p) {
297     const auto n = this->readString(p, this->tokens.end());
298     const int v = this->readInt(p, this->tokens.end());
299     t.setIntegerParameter(n, v);
300     this->readSpecifiedToken("SingleStructureSchemeParser::handleIntegerParameter", ";", p,
301                              this->tokens.end());
302   }  // end of SingleStructureSchemeParser::handleIntegerParameter
303 
handleUnsignedIntegerParameter(SingleStructureScheme & t,tokens_iterator & p)304   void SingleStructureSchemeParser::handleUnsignedIntegerParameter(SingleStructureScheme& t,
305                                                                    tokens_iterator& p) {
306     const auto n = this->readString(p, this->tokens.end());
307     const auto v = this->readUnsignedInt(p, this->tokens.end());
308     t.setUnsignedIntegerParameter(n, v);
309     this->readSpecifiedToken("SingleStructureSchemeParser::handleUnsignedIntegerParameter", ";", p,
310                              this->tokens.end());
311   }  // end of SingleStructureSchemeParser::handleUnsignedIntegerParameteru
312 
handleInternalStateVariable(SingleStructureScheme & t,tokens_iterator & p)313   void SingleStructureSchemeParser::handleInternalStateVariable(SingleStructureScheme& t,
314                                                                 tokens_iterator& p) {
315     using namespace std;
316     shared_ptr<Behaviour> b(t.getBehaviour());
317     const string& n = this->readString(p, this->tokens.end());
318     const vector<string>& ivsnames = b->getInternalStateVariablesNames();
319     vector<string> ivs;
320     selectVariables(ivs, ivsnames, n);
321     tfel::raise_if(ivs.empty(),
322                    "SingleStructureSchemeParser::handleInternalStateVariable: "
323                    "the behaviour does not declare an internal state "
324                    "variable named '" +
325                        n + "'");
326     if (ivs.size() == 1) {
327       this->setInternalStateVariableValue(t, p, ivs[0]);
328     } else {
329       const int type = b->getInternalStateVariableType(ivs[0]);
330       bool uniform = false;
331       if (type == 0) {
332         uniform = p->value != "{";
333       } else {
334         tfel::raise_if(p->value != "{",
335                        "SingleStructureSchemeParser::handleInternalStateVariable: "
336                        "unexpected token '" +
337                            n + "'");
338         ++p;
339         this->checkNotEndOfLine("SingleStructureSchemeParser::handleInternalStateVariable", p,
340                                 this->tokens.end());
341         uniform = p->value != "{";
342         --p;
343       }
344       if (uniform) {
345         vector<string>::const_iterator pn;
346         const tokens_iterator p2 = p;
347         for (pn = ivs.begin(); pn != ivs.end(); ++pn) {
348           p = p2;
349           this->setInternalStateVariableValue(t, p, *pn);
350         }
351       } else {
352         this->readSpecifiedToken("SingleStructureSchemeParser::handleInternalStateVariable", "{", p,
353                                  this->tokens.end());
354         vector<string>::const_iterator pn;
355         for (pn = ivs.begin(); pn != ivs.end();) {
356           this->setInternalStateVariableValue(t, p, *pn);
357           if (++pn != ivs.end()) {
358             this->readSpecifiedToken("SingleStructureSchemeParser::handleInternalStateVariable",
359                                      ",", p, this->tokens.end());
360           }
361         }
362         this->readSpecifiedToken("SingleStructureSchemeParser::handleInternalStateVariable", "}", p,
363                                  this->tokens.end());
364       }
365     }
366     this->readSpecifiedToken("SingleStructureSchemeParser::handleInternalStateVariable", ";", p,
367                              this->tokens.end());
368   }
369 
handleExternalStateVariable(SingleStructureScheme & t,tokens_iterator & p)370   void SingleStructureSchemeParser::handleExternalStateVariable(SingleStructureScheme& t,
371                                                                 tokens_iterator& p) {
372     const auto& evt = this->readEvolutionType(p);
373     const auto& n = this->readString(p, this->tokens.end());
374     t.setExternalStateVariable(n, this->parseEvolution(t, evt, p), true);
375     this->readSpecifiedToken("SingleStructureSchemeParser::handleExternalStateVariable", ";", p,
376                              this->tokens.end());
377   }
378 
setInternalStateVariableValue(SingleStructureScheme & t,tokens_iterator & p,const std::string & n)379   void SingleStructureSchemeParser::setInternalStateVariableValue(SingleStructureScheme& t,
380                                                                   tokens_iterator& p,
381                                                                   const std::string& n) {
382     using namespace std;
383     const int type = t.getBehaviour()->getInternalStateVariableType(n);
384     if (type == 0) {
385       t.setScalarInternalStateVariableInitialValue(n, this->readDouble(t, p));
386     } else if (type == 1) {
387       const unsigned short N = getSTensorSize(t.getDimension());
388       vector<real> v(N);
389       this->readArrayOfSpecifiedSize(v, t, p);
390       t.setStensorInternalStateVariableInitialValues(n, v);
391     } else if (type == 3) {
392       const unsigned short N = getTensorSize(t.getDimension());
393       vector<real> v(N);
394       this->readArrayOfSpecifiedSize(v, t, p);
395       t.setTensorInternalStateVariableInitialValues(n, v);
396     } else {
397       tfel::raise(
398           "SingleStructureSchemeParser::setInternalStateVariableValue : "
399           "unsupported state variable type for "
400           "internal state variable '" +
401           n + "'");
402     }
403   }
404 
registerCallBack(const std::string & k,const SingleStructureSchemeParser::CallBack & p)405   void SingleStructureSchemeParser::registerCallBack(
406       const std::string& k, const SingleStructureSchemeParser::CallBack& p) {
407     this->callbacks.insert({k, p});
408   }  // end of SingleStructureSchemeParser::registerCallBack
409 
registerCallBacks()410   void SingleStructureSchemeParser::registerCallBacks() {
411     this->registerCallBack("@Behaviour", &SingleStructureSchemeParser::handleBehaviour);
412     this->registerCallBack("@MaterialProperty",
413                            &SingleStructureSchemeParser::handleMaterialProperty);
414     this->registerCallBack("@InternalStateVariable",
415                            &SingleStructureSchemeParser::handleInternalStateVariable);
416     this->registerCallBack("@ExternalStateVariable",
417                            &SingleStructureSchemeParser::handleExternalStateVariable);
418     this->registerCallBack("@OutOfBoundsPolicy",
419                            &SingleStructureSchemeParser::handleOutOfBoundsPolicy);
420     this->registerCallBack("@Parameter", &SingleStructureSchemeParser::handleParameter);
421     this->registerCallBack("@IntegerParameter",
422                            &SingleStructureSchemeParser::handleIntegerParameter);
423     this->registerCallBack("@UnsignedIntegerParameter",
424                            &SingleStructureSchemeParser::handleUnsignedIntegerParameter);
425     this->registerCallBack("@HandleThermalExpansion",
426                            &SingleStructureSchemeParser::handleHandleThermalExpansion);
427   }  // end of SingleStructureSchemeParser::registerCallBacks
428 
treatKeyword(SingleStructureScheme & t,tokens_iterator & p)429   bool SingleStructureSchemeParser::treatKeyword(SingleStructureScheme& t, tokens_iterator& p) {
430     auto pc = this->callbacks.find(p->value);
431     if (pc == this->callbacks.end()) {
432       return false;
433     }
434     if (mfront::getVerboseMode() >= mfront::VERBOSE_DEBUG) {
435       auto& log = mfront::getLogStream();
436       log << "SingleStructureSchemeParser::execute : treating keyword '" << p->value
437           << "' at line '" << p->line << "'\n";
438     }
439     ++p;
440     auto line = p->line;
441     try {
442       (this->*(pc->second))(t, p);
443     } catch (std::exception& e) {
444       std::ostringstream msg;
445       msg << "SingleStructureSchemeParser::SingleStructureScheme : error while "
446           << "parsing file '" << this->file << "' at line '" << line << "'.\n"
447           << e.what();
448       tfel::raise(msg.str());
449     }
450     return true;
451   }  // end of SingleStructureSchemeParser::treatKeyword
452 
getKeyWordsList() const453   std::vector<std::string> SingleStructureSchemeParser::getKeyWordsList() const {
454     auto keys = std::vector<std::string>{};
455     for (const auto& k : this->callbacks) {
456       keys.push_back(k.first);
457     }
458     return keys;
459   }  // end of SingleStructureSchemeParser::getKeyWordsList
460 
461   SingleStructureSchemeParser::~SingleStructureSchemeParser() = default;
462 
463 }  // end of namespace mtest
464