1 /*!
2  * \file   AbaqusInterfaceBase.cxx
3  * \brief
4  * \author Thomas Helfer
5  * \date   17 mars 2016
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<fstream>
15 #include"TFEL/Raise.hxx"
16 #include"MFront/DSLUtilities.hxx"
17 #include"MFront/FileDescription.hxx"
18 #include"MFront/AbaqusInterfaceBase.hxx"
19 
20 #ifndef _MSC_VER
21 static const char * const constexpr_c = "constexpr";
22 #else
23 static const char * const constexpr_c = "const";
24 #endif
25 
26 namespace mfront{
27 
28   const char* const
29   AbaqusInterfaceBase::finiteStrainStrategy = "abaqus::finiteStrainStrategy";
30 
31   const char* const
32   AbaqusInterfaceBase::orthotropyManagementPolicy = "abaqus::orthotropyManagementPolicy";
33 
checkFiniteStrainStrategy(const std::string & fs)34   static void checkFiniteStrainStrategy(const std::string& fs){
35     tfel::raise_if((fs!="Native")&&
36 		   (fs!="FiniteRotationSmallStrain")&&
37 		   (fs!="MieheApelLambrechtLogarithmicStrain"),
38 		   "checkFiniteStrainStrategy: "
39 		   "unsupported strategy '"+fs+"'\n"
40 		   "The only supported strategies are "
41 		   "'Native', 'FiniteRotationSmallStrain', "
42 		   "'MieheApelLambrechtLogarithmicStrain'");
43   } // end of checkFiniteStrainStrategy
44 
45   void
checkFiniteStrainStrategyDefinitionConsistency(const BehaviourDescription & bd,const std::string & fs)46   AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency(const BehaviourDescription& bd,
47 								      const std::string& fs)
48   {
49     auto throw_if = [](const bool c,const std::string& msg){
50       tfel::raise_if(c,"AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency: "+msg);
51     };
52     checkFiniteStrainStrategy(fs);
53     if(bd.isStrainMeasureDefined()){
54       const auto ms = bd.getStrainMeasure();
55       if(ms==BehaviourDescription::LINEARISED){
56 	throw_if(fs!="Native","incompatible finite strain strategy "
57 		 "'"+fs+"' (only `Native` accepted)");
58       } else if(ms==BehaviourDescription::GREENLAGRANGE){
59 	throw_if(fs!="FiniteRotationSmallStrain",
60 		 "incompatible finite strain strategy "
61 		 "'"+fs+"' (only `FiniteRotationSmallStrain` accepted)");
62       } else if(ms==BehaviourDescription::HENCKY){
63  	throw_if(fs!="MieheApelLambrechtLogarithmicStrain",
64 		 "incompatible finite strain strategy '"+fs+"' "
65 		 "(only `MieheApelLambrechtLogarithmicStrain` accepted)");
66       } else {
67 	throw_if(true,"unsupported finite strain strategy");
68       }
69     }
70   } // end of AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency
71 
72   void
checkFiniteStrainStrategyDefinitionConsistency(const BehaviourDescription & bd)73   AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency(const BehaviourDescription& bd){
74     auto throw_if = [](const bool c,const std::string& msg){
75       tfel::raise_if(c,"AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency: "+msg);
76     };
77     if(bd.getBehaviourType()!=BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR){
78       throw_if(bd.hasAttribute(AbaqusInterfaceBase::finiteStrainStrategy),
79 	       "finite strain strategy is only supported for strain based behaviours");
80     } else {
81       if(bd.hasAttribute(AbaqusInterfaceBase::finiteStrainStrategy)){
82 	const auto fs = bd.getAttribute<std::string>(AbaqusInterfaceBase::finiteStrainStrategy);
83 	AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency(bd,fs);
84       }
85     }
86   } // end of AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency
87 
hasFiniteStrainStrategy(const BehaviourDescription & bd)88   bool AbaqusInterfaceBase::hasFiniteStrainStrategy(const BehaviourDescription& bd){
89     checkFiniteStrainStrategyDefinitionConsistency(bd);
90     if(bd.isStrainMeasureDefined()){
91       return bd.getStrainMeasure()!=BehaviourDescription::LINEARISED;
92     }
93     return  bd.hasAttribute(AbaqusInterfaceBase::finiteStrainStrategy);
94   } // end of AbaqusInterfaceBase::hasFiniteStrainStrategy
95 
getFiniteStrainStrategy(const BehaviourDescription & bd)96   std::string AbaqusInterfaceBase::getFiniteStrainStrategy(const BehaviourDescription& bd){
97     checkFiniteStrainStrategyDefinitionConsistency(bd);
98     auto throw_if = [](const bool c,const std::string& msg){
99       tfel::raise_if(c,"AbaqusInterfaceBase::getFiniteStrainStrategy: "+msg);
100     };
101     if(bd.isStrainMeasureDefined()){
102       const auto ms = bd.getStrainMeasure();
103       if(ms==BehaviourDescription::GREENLAGRANGE){
104 	return "FiniteRotationSmallStrain";
105       } else if(ms==BehaviourDescription::HENCKY){
106 	return "MieheApelLambrechtLogarithmicStrain";
107       } else {
108 	throw_if(true,"unsupported strain measure");
109       }
110     }
111     throw_if(!bd.hasAttribute(AbaqusInterfaceBase::finiteStrainStrategy),
112 	     "no finite strain strategy defined");
113     return bd.getAttribute<std::string>(AbaqusInterfaceBase::finiteStrainStrategy);
114   } // end of AbaqusInterfaceBase::getFiniteStrainStrategy
115 
hasOrthotropyManagementPolicy(const BehaviourDescription & mb)116   bool AbaqusInterfaceBase::hasOrthotropyManagementPolicy(const BehaviourDescription& mb){
117     return mb.hasAttribute(AbaqusInterfaceBase::orthotropyManagementPolicy);
118   } // end of AbaqusInterfaceBase::hasOrthotropyManagementPolicy
119 
getOrthotropyManagementPolicy(const BehaviourDescription & mb)120   std::string AbaqusInterfaceBase::getOrthotropyManagementPolicy(const BehaviourDescription& mb){
121     return mb.getAttribute<std::string>(AbaqusInterfaceBase::orthotropyManagementPolicy);
122   } // end of AbaqusInterfaceBase::getOrthotropyManagementPolicy
123 
124   void
checkOrthotropyManagementPolicyConsistency(const BehaviourDescription & mb)125   AbaqusInterfaceBase::checkOrthotropyManagementPolicyConsistency(const BehaviourDescription& mb){
126     if(AbaqusInterfaceBase::hasOrthotropyManagementPolicy(mb)){
127       tfel::raise_if(mb.getSymmetryType()!=mfront::ORTHOTROPIC,
128 		     "AbaqusInterfaceBase::checkOrthotropyManagementPolicyConsistency: "
129 		     "orthotropy management policy is only valid "
130 		     "for orthotropic behaviour");
131     }
132   } // end of AbaqusInterfaceBase::checkOrthotropyManagementPolicyConsistency
133 
134   std::string
getLibraryName(const BehaviourDescription & mb) const135   AbaqusInterfaceBase::getLibraryName(const BehaviourDescription& mb) const
136   {
137     auto lib = std::string{};
138     if(mb.getLibrary().empty()){
139       if(!mb.getMaterialName().empty()){
140 	lib = this->getInterfaceName()+mb.getMaterialName();
141       } else {
142 	lib = this->getInterfaceName()+"Behaviour";
143       }
144     } else {
145       lib = this->getInterfaceName()+mb.getLibrary();
146     }
147     return makeUpperCase(lib);
148   } // end of AbaqusInterfaceBase::getLibraryName
149 
150   std::pair<bool,tfel::utilities::CxxTokenizer::TokensContainer::const_iterator>
treatCommonKeywords(BehaviourDescription & bd,const std::string & k,tokens_iterator current,const tokens_iterator end)151   AbaqusInterfaceBase::treatCommonKeywords(BehaviourDescription& bd,
152 					   const std::string& k,
153 					   tokens_iterator current,
154 					   const tokens_iterator end)
155   {
156     auto throw_if = [](const bool b,const std::string& m){
157       tfel::raise_if(b,"AbaqusInterfaceBase::treatCommonKeywords: "+m);
158     };
159     if (k=="@AbaqusFiniteStrainStrategy"){
160       throw_if(bd.hasAttribute(AbaqusInterfaceBase::finiteStrainStrategy),
161 	       "a finite strain strategy has already been defined");
162       throw_if(current==end,"unexpected end of file");
163       const auto fs = current->value;
164       throw_if(++current==end,"unexpected end of file");
165       throw_if(current->value!=";","expected ';', read '"+current->value+'\'');
166       ++(current);
167       AbaqusInterfaceBase::checkFiniteStrainStrategyDefinitionConsistency(bd,fs);
168       bd.setAttribute(AbaqusInterfaceBase::finiteStrainStrategy,fs,false);
169       return {true,current};
170     }
171     if(k=="@AbaqusOrthotropyManagementPolicy"){
172       auto read = [&throw_if](const std::string& s){
173 	throw_if((s!="Native")&&(s!="MFront"),
174 		 "unsupported orthotropy management "
175 		 "policy '"+s+"'\n"
176 		 "The only supported policies are "
177 		 "'MFront' and 'Native'");
178 	return s;
179       };
180       throw_if(bd.getSymmetryType()!=mfront::ORTHOTROPIC,
181 	       "orthotropy management policy is only valid "
182 	       "for orthotropic behaviour");
183       throw_if(bd.hasAttribute(AbaqusInterfaceBase::orthotropyManagementPolicy),
184 	       "an orthotropy management policy has already been defined");
185       throw_if(current==end,"unexpected end of file");
186       bd.setAttribute(AbaqusInterfaceBase::orthotropyManagementPolicy,
187 		      read(current->value),false);
188       throw_if(++current==end,"unexpected end of file");
189       throw_if(current->value!=";","expected ';', read '"+current->value+'\'');
190       ++(current);
191       return {true,current};
192     }
193     return {false,current};
194   } // end of AbaqusInterfaceBase::treatCommonKeyword
195 
196   unsigned short
getStateVariablesOffset(const BehaviourDescription & bd,const Hypothesis h) const197   AbaqusInterfaceBase::getStateVariablesOffset(const BehaviourDescription& bd,
198 					       const Hypothesis h) const{
199     if((bd.hasAttribute(AbaqusInterfaceBase::orthotropyManagementPolicy))&&
200        (bd.getAttribute<std::string>(AbaqusInterfaceBase::orthotropyManagementPolicy)=="MFront")){
201       if((h==ModellingHypothesis::AXISYMMETRICAL)||
202 	 (h==ModellingHypothesis::PLANESTRAIN)||
203 	 (h==ModellingHypothesis::PLANESTRESS)){
204 	return 2u;
205       } else if(h==ModellingHypothesis::TRIDIMENSIONAL){
206 	return 6u;
207       }
208       tfel::raise("AbaqusInterfaceBase::getStateVariablesOffset: "
209 		  "invalid hypothesis");
210     }
211     return 0u;
212   }
213 
214   std::vector<std::string>
getCommonKeywords() const215   AbaqusInterfaceBase::getCommonKeywords() const{
216     return {"@AbaqusFiniteStrainStrategy","@AbaqusOrthotropyManagementPolicy"};
217   } // end of AbaqusInterfaceBase::getCommonKeywords
218 
getFunctionNameBasis(const std::string & name) const219   std::string AbaqusInterfaceBase::getFunctionNameBasis(
220       const std::string& name) const {
221     return makeUpperCase(name);
222   } // end of AbaqusInterfaceBase::getFunctionName
223 
getFunctionNameForHypothesis(const std::string & name,const Hypothesis h) const224   std::string AbaqusInterfaceBase::getFunctionNameForHypothesis(const std::string& name,
225 								const Hypothesis h) const
226   {
227     const auto s = [h]() -> std::string {
228       if(h==ModellingHypothesis::AXISYMMETRICAL){
229 	return "AXIS";
230       } else if(h==ModellingHypothesis::PLANESTRAIN){
231 	return "PSTRAIN";
232       } else if(h==ModellingHypothesis::PLANESTRESS){
233 	return "PSTRESS";
234       } else if(h==ModellingHypothesis::TRIDIMENSIONAL){
235 	return "3D";
236       }
237       tfel::raise("AbaqusInterfaceBase::getFunctionNameForHypothesis: "
238 		  "invalid hypothesis.");
239     }();
240     return makeUpperCase(name)+"_"+s;
241   } // end of AbaqusInterfaceBase::getFunctionNameForHypothesis
242 
243   std::set<AbaqusInterfaceBase::Hypothesis>
getModellingHypothesesToBeTreated(const BehaviourDescription & mb) const244   AbaqusInterfaceBase::getModellingHypothesesToBeTreated(const BehaviourDescription& mb) const
245   {
246     auto h = std::set<Hypothesis>{};
247     const auto& bh = mb.getModellingHypotheses();
248     if(bh.find(ModellingHypothesis::AXISYMMETRICAL)!=bh.end()){
249       h.insert(ModellingHypothesis::AXISYMMETRICAL);
250     }
251     if(bh.find(ModellingHypothesis::PLANESTRAIN)!=bh.end()){
252       h.insert(ModellingHypothesis::PLANESTRAIN);
253     }
254     if(bh.find(ModellingHypothesis::PLANESTRESS)!=bh.end()){
255       h.insert(ModellingHypothesis::PLANESTRESS);
256     }
257     if(bh.find(ModellingHypothesis::TRIDIMENSIONAL)!=bh.end()){
258       h.insert(ModellingHypothesis::TRIDIMENSIONAL);
259     }
260     if(h.empty()){
261       tfel::raise("AbaqusInterfaceBase::getModellingHypothesesToBeTreated : "
262 		  "no hypotheses selected. This means that the given beahviour "
263 		  "can't be used neither in 'AxisymmetricalGeneralisedPlaneStrain' "
264 		  "nor in 'AxisymmetricalGeneralisedPlaneStress', so it does not "
265 		  "make sense to use the Abaqus interface");
266     }
267     return h;
268   } // end of AbaqusInterfaceBase::getModellingHypothesesToBeTreated
269 
writeAbaqusBehaviourTraits(std::ostream & out,const BehaviourDescription & mb,const Hypothesis h) const270   void AbaqusInterfaceBase::writeAbaqusBehaviourTraits(
271       std::ostream& out,
272       const BehaviourDescription& mb,
273       const Hypothesis h) const {
274     using namespace std;
275     const auto mvs = mb.getMainVariablesSize();
276     const auto mprops = this->buildMaterialPropertiesList(mb,h);
277     if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) {
278       out << "template<tfel::material::ModellingHypothesis::Hypothesis "
279              "H,typename Type";
280       if (mb.useQt()) {
281         out << ",bool use_qt";
282       }
283     } else {
284       out << "template<typename Type";
285       if (mb.useQt()) {
286         out << ",bool use_qt";
287       }
288     }
289     out << ">\n";
290     out << "struct AbaqusTraits<tfel::material::" << mb.getClassName() << "<";
291     if (h == ModellingHypothesis::UNDEFINEDHYPOTHESIS) {
292       out << "H";
293     } else {
294       out << "tfel::material::ModellingHypothesis::"
295 	  << ModellingHypothesis::toUpperCaseString(h);
296     }
297     out << ",Type,";
298     if(mb.useQt()){
299       out << "use_qt";
300     } else {
301       out << "false";
302     }
303     out << "> >\n{\n";
304     out << "//! behaviour type\n";
305     if(mb.getBehaviourType()==BehaviourDescription::STANDARDSTRAINBASEDBEHAVIOUR){
306       out << "static " << constexpr_c << " AbaqusBehaviourType btype = abaqus::STANDARDSTRAINBASEDBEHAVIOUR;\n";
307     } else if(mb.getBehaviourType()==BehaviourDescription::STANDARDFINITESTRAINBEHAVIOUR){
308       out << "static " << constexpr_c << " AbaqusBehaviourType btype = abaqus::STANDARDFINITESTRAINBEHAVIOUR;\n";
309     } else {
310       tfel::raise("AbaqusInterfaceBase::writeAbaqusBehaviourTraits : "
311 		  "unsupported behaviour type");
312     }
313     out << "//! space dimension\n";
314     if(h==ModellingHypothesis::UNDEFINEDHYPOTHESIS){
315       out << "static " << constexpr_c << " unsigned short N           = tfel::material::ModellingHypothesisToSpaceDimension<H>::value;\n";
316     } else {
317       out << "static " << constexpr_c << " unsigned short N           = tfel::material::ModellingHypothesisToSpaceDimension<"
318 	  << "tfel::material::ModellingHypothesis::"
319 	  << ModellingHypothesis::toUpperCaseString(h)
320 	  << ">::value;\n";
321     }
322     out << "// tiny vector size\n";
323     out << "static " << constexpr_c << " unsigned short TVectorSize = N;\n";
324     out << "// symmetric tensor size\n";
325     out << "static " << constexpr_c << " unsigned short StensorSize = tfel::math::StensorDimeToSize<N>::value;\n";
326     out << "// tensor size\n";
327     out << "static " << constexpr_c << " unsigned short TensorSize  = tfel::math::TensorDimeToSize<N>::value;\n";
328     out << "// size of the driving variable array\n";
329     out << "static " << constexpr_c << " unsigned short GradientSize = " << mvs.first <<  ";\n";
330     out << "// size of the thermodynamic force variable array (STRESS)\n";
331     out << "static " << constexpr_c << " unsigned short ThermodynamicForceVariableSize = " << mvs.second <<  ";\n";
332     if(mb.getAttribute(BehaviourDescription::requiresUnAlteredStiffnessTensor,false)){
333       out << "static " << constexpr_c << " bool requiresUnAlteredStiffnessTensor = true;\n";
334     } else {
335       out << "static " << constexpr_c << " bool requiresUnAlteredStiffnessTensor = false;\n";
336     }
337     if(mb.getAttribute(BehaviourDescription::requiresStiffnessTensor,false)){
338       out << "static " << constexpr_c << " bool requiresStiffnessTensor = true;\n";
339     } else {
340       out << "static " << constexpr_c << " bool requiresStiffnessTensor = false;\n";
341     }
342     if(mb.getAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor,false)){
343       out << "static " << constexpr_c << " bool requiresThermalExpansionCoefficientTensor = true;\n";
344     } else {
345       out << "static " << constexpr_c << " bool requiresThermalExpansionCoefficientTensor = false;\n";
346     }
347     if(mb.getSymmetryType()==mfront::ISOTROPIC){
348       out << "static " << constexpr_c << " AbaqusSymmetryType type = abaqus::ISOTROPIC;\n";
349     } else if (mb.getSymmetryType()==mfront::ORTHOTROPIC){
350       out << "static " << constexpr_c << " AbaqusSymmetryType type = abaqus::ORTHOTROPIC;\n";
351     } else {
352       tfel::raise("AbaqusInterfaceBase::writeAbaqusBehaviourTraits: "
353 		  "unsupported behaviour type.\n"
354 		  "The abaqus interface only support isotropic or orthotropic "
355 		  "behaviour at this time.");
356     }
357     // computing material properties size
358     auto msize = SupportedTypes::TypeSize{};
359     if(!mprops.first.empty()){
360       const auto& m = mprops.first.back();
361       msize  = m.offset;
362       msize += SupportedTypes::getTypeSize(m.type,m.arraySize);
363       msize -= mprops.second;
364     }
365     out << "static " << constexpr_c << " unsigned short material_properties_nb = " << msize << ";\n";
366     if(mb.getElasticSymmetryType()==mfront::ISOTROPIC){
367       out << "static " << constexpr_c << " AbaqusSymmetryType etype = abaqus::ISOTROPIC;\n";
368       if(mb.getAttribute(BehaviourDescription::requiresStiffnessTensor,false)){
369 	out << "static " << constexpr_c << " unsigned short elasticPropertiesOffset = 2u;\n";
370       } else {
371 	out << "static " << constexpr_c << " unsigned short elasticPropertiesOffset = 0u;\n";
372       }
373       if(mb.getAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor,false)){
374 	out << "static " << constexpr_c << " unsigned short thermalExpansionPropertiesOffset = 1u;\n";
375       } else {
376 	out << "static " << constexpr_c << " unsigned short thermalExpansionPropertiesOffset = 0u;\n";
377       }
378     } else if (mb.getElasticSymmetryType()==mfront::ORTHOTROPIC){
379       out << "static " << constexpr_c << " AbaqusSymmetryType etype = abaqus::ORTHOTROPIC;\n";
380       if(mb.getAttribute(BehaviourDescription::requiresStiffnessTensor,false)){
381     	out << "static " << constexpr_c << " unsigned short elasticPropertiesOffset "
382     	    << "= AbaqusOrthotropicElasticPropertiesOffset<N>::value;\n";
383       } else {
384 	out << "static " << constexpr_c << " unsigned short elasticPropertiesOffset = 0u;\n";
385       }
386       if(mb.getAttribute(BehaviourDescription::requiresThermalExpansionCoefficientTensor,false)){
387 	out << "static " << constexpr_c << " unsigned short thermalExpansionPropertiesOffset = 3u;\n";
388       } else {
389 	out << "static " << constexpr_c << " unsigned short thermalExpansionPropertiesOffset = 0u;\n";
390       }
391     } else {
392       tfel::raise("AbaqusInterfaceBase::writeAbaqusBehaviourTraits: "
393 		  "unsupported behaviour type.\n"
394 		  "The abaqus interface only support isotropic or "
395 		  "orthotropic behaviour at this time.");
396     }
397     out << "}; // end of class AbaqusTraits\n\n";
398   }
399 
writeMTestFileGeneratorSetModellingHypothesis(std::ostream & out) const400   void AbaqusInterfaceBase::writeMTestFileGeneratorSetModellingHypothesis(
401       std::ostream& out) const {
402     out << "mg.setModellingHypothesis(h);\n";
403   } // end of AbaqusInterfaceBase::writeMTestFileGeneratorSetModellingHypothesis
404 
405   void
writeInputFileExample(const BehaviourDescription & mb,const FileDescription & fd,const bool b) const406   AbaqusInterfaceBase::writeInputFileExample(const BehaviourDescription& mb,
407 					     const FileDescription& fd,
408 					     const bool b) const{
409     auto throw_if = [](const bool c,const std::string& m){
410       tfel::raise_if(c,"AbaqusInterfaceBase::writeInputFileExample: "+m);
411     };
412     const auto name =  mb.getLibrary()+mb.getClassName();
413     const auto mn = this->getLibraryName(mb)+"_"+mb.getClassName();
414     const auto fn = (b ? "abaqus/" : "abaqus-explicit/") +name+".inp";
415     std::ofstream out{fn};
416     throw_if(!out,"could not open file '"+fn+"'");
417     // header
418     out << "** \n"
419 	<< "** File generated by MFront from the "  << fd.fileName << " source\n"
420 	<< "** Example of how to use the " << mb.getClassName() << " behaviour law\n"
421 	<< "** Author "  << fd.authorName << '\n'
422 	<< "** Date   "  << fd.date       << '\n'
423 	<< "**\n\n";
424     // loop over hypothesis
425     for(const auto & h : this->getModellingHypothesesToBeTreated(mb)){
426       const auto& d = mb.getBehaviourData(h);
427       const auto mps = this->buildMaterialPropertiesList(mb,h);
428       auto msize = SupportedTypes::TypeSize{};
429       if(!mps.first.empty()){
430 	const auto& m = mps.first.back();
431 	msize  = m.offset;
432 	msize += SupportedTypes::getTypeSize(m.type,m.arraySize);
433       }
434       const auto& persistentVarsHolder = d.getPersistentVariables();
435       auto vs = SupportedTypes::TypeSize{};
436       for(const auto& v : persistentVarsHolder){
437 	vs+=SupportedTypes::getTypeSize(v.type,v.arraySize);
438       }
439       const auto vsize = vs.getValueForModellingHypothesis(h)+
440 	this->getStateVariablesOffset(mb,h);
441       const auto& externalStateVarsHolder = d.getExternalStateVariables();
442       out << "** Example for the '" << ModellingHypothesis::toString(h) << "' modelling hypothesis\n";
443       if(!externalStateVarsHolder.empty()){
444 	out << "** This behaviour requires " << externalStateVarsHolder.size()
445 	    <<  " field variables to be defined:\n";
446 	int i=1;
447 	for(auto pv=std::next(externalStateVarsHolder.begin()); // skipping the temperature
448 	    pv!=externalStateVarsHolder.end();++pv,++i){
449 	  out << "** " << i << ": " << mb.getExternalName(h,pv->name);
450 	}
451       }
452       out << "*Material, name="
453 	  << this->getFunctionNameForHypothesis(mn,h) << '\n';
454       if(!b){
455 	out << "*DENSITY\n<density>\n";
456       }
457       if(vsize!=0){
458 	out << "*Depvar\n" << vsize  << ",\n";
459 	int i=1;
460 	if(mb.hasAttribute(AbaqusInterfaceBase::orthotropyManagementPolicy)){
461 	  const auto omp =
462 	    mb.getAttribute<std::string>(AbaqusInterfaceBase::orthotropyManagementPolicy);
463 	  if(omp=="MFront"){
464 	    if((h==ModellingHypothesis::AXISYMMETRICAL)||
465 	       (h==ModellingHypothesis::PLANESTRAIN)||
466 	       (h==ModellingHypothesis::PLANESTRESS)){
467 	      out << i++ << ", FirstOrthotropicAxis_1\n";
468 	      out << i++ << ", FirstOrthotropicAxis_2\n";
469 	    } else if(h==ModellingHypothesis::TRIDIMENSIONAL){
470 	      out << i++ << ", FirstOrthotropicAxis_1\n";
471 	      out << i++ << ", FirstOrthotropicAxis_2\n";
472 	      out << i++ << ", FirstOrthotropicAxis_3\n";
473 	      out << i++ << ", SecondOrthotropicAxis_1\n";
474 	      out << i++ << ", SecondOrthotropicAxis_2\n";
475 	      out << i++ << ", SecondOrthotropicAxis_3\n";
476 	    }
477 	  } else {
478 	    throw_if(omp!="Native","unsupported orthotropy "
479 		     "management policy");
480 	  }
481 	}
482 	for(const auto& v : persistentVarsHolder){
483 	  const auto vn = mb.getExternalName(h,v.name);
484 	  if(v.arraySize==1){
485 	    this->writeDepvar(out,i,h,v,vn);
486 	  } else {
487 	    for(unsigned short a=0;a!=v.arraySize;++a){
488 	      this->writeDepvar(out,i,h,v,vn+'['+std::to_string(a)+']');
489 	    }
490 	  }
491 	}
492       }
493       if(!mps.first.empty()){
494 	out << "** The material properties are given as if we used parameters to explicitly\n"
495 	    << "** display their names. Users shall replace those declaration by\n"
496 	    << "** theirs values and/or declare those parameters in the appropriate *parameters\n"
497 	    << "** section of the input file\n";
498       }
499       out << "*User Material, constants=" << msize.getValueForModellingHypothesis(h);
500       if(!mb.getAttribute(h,BehaviourData::isConsistentTangentOperatorSymmetric,false)){
501 	out << ", unsymm";
502       }
503       out << '\n';
504       if(!mps.first.empty()){
505 	int i=1;
506 	auto write = [&i,&out](const std::string& n){
507 	  if(i%9==0){
508 	    out << "\n";
509 	    i=1;
510 	  }
511 	  out << '<' << n << '>';
512 	  ++i;
513 	};
514 	for(auto pm =mps.first.begin();pm!=mps.first.end();){
515 	  if(pm->arraySize==1u){
516 	    write(pm->name);
517 	  } else {
518 	    for(unsigned short a=0;a!=pm->arraySize;){
519 	      write(pm->name+"_"+std::to_string(a));
520 	      if(++a!=pm->arraySize){
521 		out << ", ";
522 	      }
523 	    }
524 	  }
525 	  if(++pm!=mps.first.end()){
526 	    out << ", ";
527 	  }
528 	}
529       }
530       out << "\n\n";
531     }
532   } // end of AbaqusInterfaceBase::writeInputFileExample
533 
534   void
writeDepvar(std::ostream & out,int & i,const Hypothesis & h,const VariableDescription & v,const std::string & n) const535   AbaqusInterfaceBase::writeDepvar(std::ostream& out,
536 				   int& i,
537 				   const Hypothesis& h,
538 				   const VariableDescription& v,
539 				   const std::string& n) const {
540     if(SupportedTypes::getTypeFlag(v.type)==SupportedTypes::SCALAR){
541       out << i++ << ", " << n << '\n';
542     } else if(SupportedTypes::getTypeFlag(v.type)==SupportedTypes::STENSOR){
543       out << i++ << ", " << n << "_11\n";
544       out << i++ << ", " << n << "_22\n";
545       out << i++ << ", " << n << "_33\n";
546       out << i++ << ", " << n << "_12\n";
547       if(h==ModellingHypothesis::TRIDIMENSIONAL){
548 	out << i++ << ", " << n << "_13\n";
549 	out << i++ << ", " << n << "_23\n";
550       }
551     } else if(SupportedTypes::getTypeFlag(v.type)==SupportedTypes::TENSOR){
552       out << i++ << ", " << n << "_11\n";
553       out << i++ << ", " << n << "_22\n";
554       out << i++ << ", " << n << "_33\n";
555       out << i++ << ", " << n << "_12\n";
556       out << i++ << ", " << n << "_21\n";
557       if(h==ModellingHypothesis::TRIDIMENSIONAL){
558 	out << i++ << ", " << n << "_13\n";
559 	out << i++ << ", " << n << "_31\n";
560 	out << i++ << ", " << n << "_23\n";
561 	out << i++ << ", " << n << "_32\n";
562       }
563     } else {
564       tfel::raise("AbaqusInterfaceBase::writeDepvar: "
565 		  "unsupported variable type");
566     }
567   }
568 
569   AbaqusInterfaceBase::~AbaqusInterfaceBase() = default;
570 
571 } // end of namespace mfront
572