1 /*!
2  * \file  mfront/include/MFront/BehaviourDescription.hxx
3  * \brief
4  * \author Thomas Helfer
5  * \brief 07 mars 2014
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 #ifndef LIB_MFRONT_BEHAVIOURDESCRIPTION_HXX
15 #define LIB_MFRONT_BEHAVIOURDESCRIPTION_HXX
16 
17 #include <set>
18 #include <vector>
19 #include <memory>
20 #include <utility>
21 
22 #include "TFEL/Utilities/GenTypeBase.hxx"
23 #include "TFEL/Math/tvector.hxx"
24 #include "TFEL/Material/CrystalStructure.hxx"
25 #include "TFEL/Material/SlipSystemsDescription.hxx"
26 #include "TFEL/Material/MechanicalBehaviour.hxx"
27 #include "TFEL/Material/ModellingHypothesis.hxx"
28 #include "TFEL/Material/OrthotropicAxesConvention.hxx"
29 
30 #include "MFront/MFrontConfig.hxx"
31 #include "MFront/CodeBlock.hxx"
32 #include "MFront/SupportedTypes.hxx"
33 #include "MFront/BehaviourAttribute.hxx"
34 #include "MFront/BehaviourData.hxx"
35 #include "MFront/BehaviourSymmetryType.hxx"
36 
37 namespace mfront {
38 
39   // forward declaration
40   struct LocalDataStructure;
41   // forward declaration
42   struct MaterialPropertyDescription;
43 
44   /*!
45    * This structure describes a mechanical behaviour
46    *
47    * This class handles the fact that the mechanical behaviour
48    * data may depend on the modelling hypothesis considered,
49    * altough most of the time they won't.
50    *
51    * This class thus stores a default mechanical behaviour data
52    * which is intendend to be valid for most hypotheses, and specific
53    * mechanical behaviour datas when required.
54    */
55   struct MFRONT_VISIBILITY_EXPORT BehaviourDescription
56       : public tfel::material::MechanicalBehaviourBase,
57         public SupportedTypes {
58     //! a simple alias
59     using ModellingHypothesis = tfel::material::ModellingHypothesis;
60     //! a simple alias
61     using Hypothesis = ModellingHypothesis::Hypothesis;
62     //! a simple alias
63     using CrystalStructure = tfel::material::CrystalStructure;
64     //! a simple alias
65     using SlipSystemsDescription = tfel::material::SlipSystemsDescription;
66     //! a simple alias
67     using SlipSystem = SlipSystemsDescription::system;
68     //! a simple alias
69     using InteractionMatrixStructure =
70         SlipSystemsDescription::InteractionMatrixStructure;
71     //! a simple alias
72     using OrthotropicAxesConvention = tfel::material::OrthotropicAxesConvention;
73     //! a simple alias
74     using Mode = BehaviourData::Mode;
75     //! a simple alias
76     using Position = BehaviourData::Position;
77     //! validation tatus
78     enum VerificationStatus {
79       UNVERIFIED,
80       VERIFIED
81     };  // end of VerificationStatus
82     //! validation tatus
83     enum ValidationStatus {
84       UNVALIDATED,
85       VALIDATED
86     };  // end of ValidationStatus
87     //! Strain measure
88     enum StrainMeasure {
89       LINEARISED,
90       GREENLAGRANGE,
91       HENCKY
92     };  // end of enum StrainMeasure
93         /*!
94          * \brief this structure holds the value of a constant material
95          * property
96          */
97     struct ConstantMaterialProperty {
98       //! parameter name associated with the material property
99       std::string name;
100       //! default value for the constant material property
101       double value;
102     };
103     /*!
104      * \brief this structure holds the value of a material
105      * property defined through an analytic expression
106      */
107     struct AnalyticMaterialProperty {
108       //! return the list of the variables
109       std::vector<std::string> getVariablesNames() const;
110       //! description of a material property
111       std::string f;
112     };  // end of AnalyticMaterialProperty
113         /*!
114          * \brief this structure holds the value of a material
115          * property defined through an mfront file
116          */
117     struct ExternalMFrontMaterialProperty {
118       //! description of a material property
119       std::shared_ptr<MaterialPropertyDescription> mpd;
120     };
121     //! list of supported material properties types
122     using MaterialPropertyTypes =
123         tfel::meta::GenerateTypeList<ConstantMaterialProperty,
124                                      AnalyticMaterialProperty,
125                                      ExternalMFrontMaterialProperty>::type;
126     //! a simple alias
127     using StressFreeExpansionDescription =
128         BehaviourData::StressFreeExpansionDescription;
129     /*!
130      * The description of a material property from the point of
131      * view of a behaviour.
132      */
133     using MaterialProperty =
134         tfel::utilities::GenTypeBase<MaterialPropertyTypes>;
135     /*!
136      * structure used to defined a Hill tensor
137      */
138     struct HillTensor {
139       //! name of the Hill tensor
140       std::string name;
141       //! Hill coeffients
142       std::vector<MaterialProperty> c;
143     };  // end of struct HillTensor
144         /*!
145          * \brief Available integration schemes.
146          * One of the first thing a dsl shall do is to set the
147          * integration scheme it uses.
148          */
149     enum IntegrationScheme {
150       IMPLICITSCHEME,  //!< value set by the `Implicit` Dsl family
151       EXPLICITSCHEME,  //!< value set by the `Runge-Kutta` Dsl
152       SPECIFICSCHEME,  /*!< value set by the `	IsotropicMisesCreepDSL`,
153                         * `IsotropicMisesPlasticFlowDSL`,
154                         * `IsotropicStrainHardeningMisesCreepDSL`
155                         * `MultipleIsotropicMisesFlowsDSL` dsls. */
156       UNDEFINEDINTEGRATIONSCHEME  //! default value.
157     };
158     /*!
159      * a simple structure used to compte the value of a material
160      * property
161      */
162     struct MaterialPropertyInput {
163       //! variable name
164       std::string name;
165       //! external name
166       std::string ename;
167       //! variable type
168       enum Category {
169         TEMPERATURE,
170         MATERIALPROPERTY,
171         STATEVARIABLE,
172         AUXILIARYSTATEVARIABLEFROMEXTERNALMODEL,
173         EXTERNALSTATEVARIABLE,
174         PARAMETER,
175         STATICVARIABLE
176       };
177       Category category;
178     };  // end of
179     //! attribute name
180     static const char* const requiresStiffnessTensor;
181     //! attribute name
182     static const char* const computesStiffnessTensor;
183     //! attribute name
184     static const char* const requiresUnAlteredStiffnessTensor;
185     //! attribute name
186     static const char* const requiresThermalExpansionCoefficientTensor;
187     //! attribute name
188     static const char* const setRequireThermalExpansionCoefficientTensor;
189     //! constructor
190     BehaviourDescription();
191     //! copy constructor
192     BehaviourDescription(const BehaviourDescription&);
193     /*!
194      * \brief return true if the behaviour description allows the
195      * declaration of user defined variables
196      */
197     bool allowsNewUserDefinedVariables() const;
198     //! \brief disallow the declaration of user defined variables
199     void disallowNewUserDefinedVariables();
200     //! \brief set if dynamically allocated vectors are allowed
201     void areDynamicallyAllocatedVectorsAllowed(const bool);
202     //! \return true if dynamically allocated vectors are allowed
203     bool areDynamicallyAllocatedVectorsAllowed() const;
204     //! \return true of the parser shall declare a dynamically
205     bool useDynamicallyAllocatedVector(const unsigned short) const;
206     /*!
207      * \brief set the behaviour name
208      * \param[in] b: behaviour name
209      */
210     void setBehaviourName(const std::string&);
211     //! \return the behaviour name
212     const std::string& getBehaviourName() const;
213     /*!
214      * \brief set the dsl name
215      * \param[in] b: dsl name
216      */
217     void setDSLName(const std::string&);
218     //! \return the dsl name
219     const std::string& getDSLName() const;
220     /*!
221      * \brief set the material name
222      * \param[in] m: material name
223      */
224     void setMaterialName(const std::string&);
225     //! \return the material name
226     const std::string& getMaterialName() const;
227     /*!
228      * \brief set the library name
229      * \param[in] l: library name
230      */
231     void setLibrary(const std::string&);
232     //! \return the library name
233     const std::string& getLibrary() const;
234     /*!
235      * \brief set the class name
236      * \param[in] n: class name
237      */
238     void setClassName(const std::string&);
239     //! \return the class name
240     const std::string& getClassName() const;
241     /*!
242      * \return the inputs of a material property
243      * \param[in] i: list of variables used to evaluated the material
244      * property.
245      * \param[in] b: if true, the modelling hypotheses must be
246      * defined. In this case, inputs are searched in the BehaviourData
247      * associed with each modelling hypothesis and consistency of the
248      * definition of each input is checked. If false, all inputs are
249      * searched in the root BehaviourData only (the one associated
250      * with UNDEFINEDHYPOTESIS).
251      */
252     std::vector<MaterialPropertyInput> getMaterialPropertyInputs(
253         const std::vector<std::string>&, const bool = true) const;
254     /*!
255      * \return the inputs of a material property
256      * \param[in] mpd: material property description
257      * \param[in] b: if true, the modelling hypotheses must be
258      * defined. In this case, inputs are searched in the BehaviourData
259      * associed with each modelling hypothesis and consistency of the
260      * definition of each input is checked. If false, all inputs are
261      * searched in the root BehaviourData only (the one associated
262      * with UNDEFINEDHYPOTESIS).
263      */
264     std::vector<MaterialPropertyInput> getMaterialPropertyInputs(
265         const MaterialPropertyDescription&, const bool = true) const;
266     /*!
267      * \brief append the given code to the sources
268      * \param[in] s: sources
269      */
270     void appendToSources(const std::string&);
271     //! \return the material name
272     const std::string& getSources() const;
273     /*!
274      * \brief append the given code to the members
275      * \param[in] h: hypothesis
276      * \param[in] s: members
277      * \param[in] b: if h is UNDEFINEDHYPOTHIS, propagate to all specialised
278      * data
279      */
280     void appendToMembers(const Hypothesis, const std::string&, const bool);
281     //! \return the aditional members
282     std::string getMembers(const Hypothesis) const;
283     /*!
284      * \brief append the given code to the members
285      * \param[in] h: hypothesis
286      * \param[in] s: members
287      * \param[in] b: if h is UNDEFINEDHYPOTHIS, propagate to all specialised
288      * data
289      */
290     void appendToPrivateCode(const Hypothesis, const std::string&, const bool);
291     /*!
292      * \return the material private code
293      * \param[in] h: hypothesis
294      */
295     std::string getPrivateCode(const Hypothesis) const;
296     /*!
297      * \brief append the given code to the includes
298      * \param[in] s: includes
299      */
300     void appendToIncludes(const std::string&);
301     //! \return the includes
302     const std::string& getIncludes() const;
303     /*!
304      * add a material law
305      * \param[in] m:material law
306      */
307     void addMaterialLaw(const std::string&);
308     /*!
309      * \brief add a model description.
310      * All outputs of the model are automatically added as auxiliary state
311      * variables
312      * \param[in] md: model description
313      */
314     void addModelDescription(const ModelDescription&);
315     /*!
316      * add a local data structure
317      * \param[in] lds: local data structure
318      * \param[in] s: registration status
319      */
320     void addLocalDataStructure(
321         const LocalDataStructure&,
322         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
323     //! \return the list of material laws
324     const std::vector<std::string>& getMaterialLaws() const;
325     //! \return the size of the main variables
326     std::pair<SupportedTypes::TypeSize, SupportedTypes::TypeSize>
327     getMainVariablesSize() const;
328     /*!
329      * \brief add a new main variable
330      * \note using this method means that the behaviour type is always
331      * 'GENERALBEHAVIOUR'. This can't be changed afterwards.
332      */
333     void addMainVariable(const Gradient&, const ThermodynamicForce&);
334     //! \return the main variables of the behaviour
335     const std::vector<std::pair<Gradient, ThermodynamicForce>>&
336     getMainVariables() const;
337     /*!
338      * \return the driving variable with the associated name
339      * \param[in] n: name
340      */
341     const Gradient& getGradient(const std::string&) const;
342     /*!
343      * \return the thermodynamic force with the associated name
344      * \param[in] n: name
345      */
346     const ThermodynamicForce& getThermodynamicForce(const std::string&) const;
347     /*!
348      * \brief set the behaviour to be a small strain standard
349      * behaviour
350      */
351     void declareAsASmallStrainStandardBehaviour();
352     /*!
353      * \brief set the behaviour to be a finite strain standard
354      * behaviour
355      * \param[in] b: if true, declare F and dF as members
356      */
357     void declareAsAFiniteStrainStandardBehaviour(const bool);
358     //! \brief set the behaviour to be a cohesive zone model
359     void declareAsACohesiveZoneModel();
360     /*!
361      * \brief set the strain measure to be used
362      * \param[in] m: measure
363      */
364     void setStrainMeasure(const StrainMeasure);
365     //! \return the strain measure associated with the behaviour
366     StrainMeasure getStrainMeasure() const;
367     //! \return if the strain measure has been set
368     bool isStrainMeasureDefined() const;
369     //! \return the type of the stiffness operator
370     std::string getTangentOperatorType() const;
371 
372     bool useQt() const;
373 
374     void setUseQt(const bool);
375 
376     bool isGradientName(const std::string&) const;
377 
378     bool isGradientIncrementName(const std::string&) const;
379 
380     bool isThermodynamicForceName(const std::string&) const;
381     //! \return the behaviour type
382     BehaviourType getBehaviourType() const;
383     /*!
384      * \brief set the integration scheme
385      * \param[in] s: integration scheme
386      */
387     void setIntegrationScheme(const IntegrationScheme);
388     //! \return the integration scheme used
389     IntegrationScheme getIntegrationScheme() const;
390     //! \return a string describing the behaviour type
391     std::string getBehaviourTypeFlag() const;
392     //! \return the symmetry type of the behaviour
393     BehaviourSymmetryType getSymmetryType() const;
394 
395     void setSymmetryType(const BehaviourSymmetryType);
396 
397     bool isSymmetryTypeDefined() const;
398 
399     BehaviourSymmetryType getElasticSymmetryType() const;
400 
401     void setElasticSymmetryType(const BehaviourSymmetryType);
402 
403     bool isElasticSymmetryTypeDefined() const;
404     /*!
405      * \brief set the orthotropic axes convention.
406      * \param[in] c: new value for the orthotropic axes convention.
407      * \note this method can be only call once.
408      */
409     void setOrthotropicAxesConvention(const OrthotropicAxesConvention);
410     /*!
411      * \return the orthotropic axes convention.
412      * \note if the orthotropic axes convention has not been defined,
413      * the UNDEFINED convention is assumed and oacIsDefined is set to
414      * true.
415      */
416     OrthotropicAxesConvention getOrthotropicAxesConvention() const;
417     /*!
418      * \return true if the crystal structure of the material has been
419      * defined.
420      */
421     bool hasCrystalStructure() const;
422     //! \return the crystal structure of the material
423     CrystalStructure getCrystalStructure() const;
424     /*!
425      * \brief set the crystal structure
426      * \param[in] cs: crystal structure
427      */
428     void setCrystalStructure(const CrystalStructure);
429     //! \return true if slip systems were defined
430     bool areSlipSystemsDefined() const;
431     /*!
432      * \brief set the behaviour slip systems
433      * \param[in] gss: slip systems
434      */
435     void setSlipSystems(const std::vector<SlipSystem>&);
436     //! \return the slip systemss
437     const SlipSystemsDescription& getSlipSystems() const;
438     /*!
439      * \brief set the interaction matrix.
440      * \param[in] m: interaction matrix
441      * \note: this method is only valid if one and only one slip
442      * system is defined.
443      */
444     void setInteractionMatrix(const std::vector<long double>&);
445     /*!
446      * \brief return the interaction matrix structure.
447      * \note: this method is only valid if one and only one slip
448      * system is defined.
449      */
450     InteractionMatrixStructure getInteractionMatrixStructure() const;
451     /*!
452      * \brief return true if an interaction matrix is defined.
453      * \note: this method is only valid if one and only one slip
454      * system is defined.
455      */
456     bool hasInteractionMatrix() const;
457     /*!
458      * \brief return true if an interaction matrix is defined.
459      * \note: this method is only valid if one and only one slip
460      * system is defined.
461      */
462     bool hasDislocationsMeanFreePathInteractionMatrix() const;
463     /*!
464      * \brief set the interaction matrix.
465      * \param[in] m: interaction matrix
466      * \note: this method is only valid if one and only one slip
467      * system is defined.
468      */
469     void setDislocationsMeanFreePathInteractionMatrix(
470         const std::vector<long double>&);
471     /*!
472      * \return true if the material property is constant over the time step
473      * \param[in] mp: material property
474      */
475     bool isMaterialPropertyConstantDuringTheTimeStep(
476         const MaterialProperty&) const;
477     /*!
478      * \return true if the material property depends on state variables
479      * \param[in] mp: material property
480      */
481     bool isMaterialPropertyDependantOnStateVariables(
482         const MaterialProperty&) const;
483     //! \return registred models
484     const std::vector<ModelDescription>& getModelsDescriptions() const;
485     /*!
486      * \brief set the elastic material properties
487      * \param[in] emps: elastic material properties
488      */
489     void setElasticMaterialProperties(const std::vector<MaterialProperty>&);
490     /*!
491      * \return the elastic material properties
492      */
493     const std::vector<MaterialProperty>& getElasticMaterialProperties() const;
494     /*!
495      * \return true if the elastic material properties have been defined
496      */
497     bool areElasticMaterialPropertiesDefined() const;
498     /*!
499      * \return true if the elastic material properties are constant
500      * over the time step
501      */
502     bool areElasticMaterialPropertiesConstantDuringTheTimeStep() const;
503     /*!
504      * \return true if the given material properties are constant over
505      * the time step
506      * \param[in] mps: list of material properties
507      */
508     bool areMaterialPropertiesConstantDuringTheTimeStep(
509         const std::vector<MaterialProperty>&) const;
510     /*!
511      * \return true if the elastic material properties depend on state
512      * variables
513      */
514     bool areElasticMaterialPropertiesDependantOnStateVariables() const;
515     /*!
516      * \return true if the given material properties depend on state variables
517      * \param[in] mps: list of material properties
518      */
519     bool areMaterialPropertiesDependantOnStateVariables(
520         const std::vector<MaterialProperty>&) const;
521     /*!
522      * \brief add a new Hill tensor
523      * \param[in] v:   variable description
524      * \param[in] hcs: Hill tensor coefficents
525      * \pre the behaviour must be either small strain or finite strain
526      * \pre the material must be orthotropic
527      * \pre the number of Hill tensor coefficients must be 6
528      * \pre the variable name must be valid and unused yet
529      * \pre the type of the variable must be "tfel::math::st2tost2<N,stress>"
530      * \pre the array size of the variable must be 1
531      */
532     void addHillTensor(const VariableDescription&,
533                        const std::vector<MaterialProperty>&);
534     /*!
535      * \return the list of Hill tensors that have been defined
536      */
537     const std::vector<HillTensor>& getHillTensors() const;
538     /*!
539      * \return a mechanical behaviour data associated with the
540      * given modelling hypothesis
541      * \param[in] h: modelling hypothesis
542      */
543     const BehaviourData& getBehaviourData(const Hypothesis&) const;
544     //! \return true if modelling hypotheses are defined.
545     bool areModellingHypothesesDefined() const;
546     /*!
547      * \return all the modelling hypotheses supported by the
548      * behaviour.
549      */
550     const std::set<Hypothesis>& getModellingHypotheses() const;
551     /*!
552      * \return all the modelling hypotheses which are distinct.
553      *
554      * This method returns, among all the supported modelling
555      * hypotheses (see getModellingHypotheses), the ones which have
556      * specialised mechanical data and, if at least one modelling
557      * hypothesis has no specialisation, UNDEFINEDHYPOTHESIS.
558      *
559      * This method has been introduced for iteration purpose in
560      * behaviour dsls.
561      */
562     std::set<Hypothesis> getDistinctModellingHypotheses() const;
563     /*!
564      * \return true if the given modelling hypothesis is supported
565      * \param[in] h: modelling hypothesis
566      * \see hasSpecialisedMechanicalData
567      */
568     bool isModellingHypothesisSupported(const Hypothesis) const;
569     /*!
570      * \brief set the list of supported modelling hypotheses
571      * \param[in] h: supported modelling hypotheses
572      * \param[in] b: parameter used if some modelling hypotheses are
573      * already defined. In this case:
574      * - if b is true, the resulting modelling hypotheses
575      *   will be the intersection of the given modelling hypotheses and
576      *   the already declared ones. If such intersection is empty, an
577      *   exception is thrown.
578      * - if b is false, an exception is thrown.
579      */
580     void setModellingHypotheses(const std::set<Hypothesis>&,
581                                 const bool b = false);
582     /*!
583      * \brief add material properties
584      * \param[in] h: modelling hypothesis
585      * \param[in] v: material properties added
586      * \param[in] s: registration status
587      *
588      * \note if h is UNDEFINEDHYPOTHESIS, add the material properties
589      * to the default data and to all the specialisations
590      */
591     void addMaterialProperties(
592         const Hypothesis,
593         const VariableDescriptionContainer&,
594         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
595     /*!
596      * \brief add a material property
597      * \param[in] h: modelling hypothesis
598      * \param[in] v: material property added
599      * \param[in] s: registration status
600      *
601      * \note if h is UNDEFINEDHYPOTHESIS, add the material properties
602      * to the default data and to all the specialisations
603      */
604     void addMaterialProperty(
605         const Hypothesis,
606         const VariableDescription&,
607         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
608     /*!
609      * \brief add a state variables
610      * \param[in] h: modelling hypothesis
611      * \param[in] v: state variable added
612      * \param[in] s: registration status
613      *
614      * \note if h is UNDEFINEDHYPOTHESIS, add the state variables
615      * to the default data and to all the specialisations
616      */
617     void addIntegrationVariable(
618         const Hypothesis,
619         const VariableDescription&,
620         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
621     /*!
622      * \brief add state variables
623      * \param[in] h: modelling hypothesis
624      * \param[in] v: state variables added
625      * \param[in] s: registration status
626      *
627      * \note if h is UNDEFINEDHYPOTHESIS, add the state variables
628      * to the default data and to all the specialisations
629      */
630     void addIntegrationVariables(
631         const Hypothesis,
632         const VariableDescriptionContainer&,
633         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
634     /*!
635      * \brief add a state variables
636      * \param[in] h: modelling hypothesis
637      * \param[in] v: state variable added
638      * \param[in] s: registration status
639      *
640      * \note if h is UNDEFINEDHYPOTHESIS, add the state variables
641      * to the default data and to all the specialisations
642      */
643     void addStateVariable(
644         const Hypothesis,
645         const VariableDescription&,
646         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
647     /*!
648      * \brief add state variables
649      * \param[in] h: modelling hypothesis
650      * \param[in] v: state variables added
651      * \param[in] s: registration status
652      *
653      * \note if h is UNDEFINEDHYPOTHESIS, add the state variables
654      * to the default data and to all the specialisations
655      */
656     void addStateVariables(
657         const Hypothesis,
658         const VariableDescriptionContainer&,
659         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
660     /*!
661      * \brief add auxiliary state variables
662      * \param[in] h: modelling hypothesis
663      * \param[in] v: auxiliary state variables added
664      * \param[in] s: registration status
665      *
666      * \note if h is UNDEFINEDHYPOTHESIS, add the auxiliary state
667      * variables to the default data and to all the specialisations
668      */
669     void addAuxiliaryStateVariables(
670         const Hypothesis,
671         const VariableDescriptionContainer&,
672         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
673     /*!
674      * \brief add an auxiliary state variable
675      * \param[in] h: modelling hypothesis
676      * \param[in] v: auxiliary state variable added
677      * \param[in] s: registration status
678      *
679      * \note if h is UNDEFINEDHYPOTHESIS, add the auxiliary state
680      * variables to the default data and to all the specialisations
681      */
682     void addAuxiliaryStateVariable(
683         const Hypothesis,
684         const VariableDescription&,
685         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
686     /*!
687      * \brief add external state variables
688      * \param[in] h: modelling hypothesis
689      * \param[in] v: external state variables added
690      * \param[in] s: registration status
691      *
692      * \note if h is UNDEFINEDHYPOTHESIS, add the external state
693      * variables to the default data and to all the specialisations
694      */
695     void addExternalStateVariables(
696         const Hypothesis,
697         const VariableDescriptionContainer&,
698         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
699     /*!
700      * \brief add external state variable
701      * \param[in] h: modelling hypothesis
702      * \param[in] v: external state variable added
703      * \param[in] s: registration status
704      *
705      * \note if h is UNDEFINEDHYPOTHESIS, add the external state
706      * variables to the default data and to all the specialisations
707      */
708     void addExternalStateVariable(
709         const Hypothesis,
710         const VariableDescription&,
711         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
712     /*!
713      * \brief add a local variable
714      * \param[in] h: modelling hypothesis
715      * \param[in] v: local variable added
716      * \param[in] s: registration status
717      *
718      * \note if h is UNDEFINEDHYPOTHESIS, add the local variables to
719      * the default data and to all the specialisations
720      */
721     void addLocalVariable(
722         const Hypothesis,
723         const VariableDescription&,
724         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
725     /*!
726      * \brief add local variables
727      * \param[in] h: modelling hypothesis
728      * \param[in] v: local variables added
729      * \param[in] s: registration status
730      *
731      * \note if h is UNDEFINEDHYPOTHESIS, add the local variables to
732      * the default data and to all the specialisations
733      */
734     void addLocalVariables(
735         const Hypothesis,
736         const VariableDescriptionContainer&,
737         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
738     /*!
739      * \brief add a static variable
740      * \param[in] h: modelling hypothesis
741      * \param[in] v: static variable
742      * \param[in] s: registration status
743      *
744      * \note if h is UNDEFINEDHYPOTHESIS, add the local variable to
745      * the default data and to all the specialisations
746      */
747     void addStaticVariable(
748         const Hypothesis,
749         const StaticVariableDescription&,
750         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
751     /*!
752      * \return the value of an integer constant
753      * \param[in] h: modelling hypothesis
754      * \param[in] n: variable name
755      */
756     int getIntegerConstant(const Hypothesis, const std::string&) const;
757     /*!
758      * \brief add a material property
759      * \param[in] h: modelling hypothesis
760      * \param[in] v: parameter
761      * \param[in] s: registration status
762      * \note if h is UNDEFINEDHYPOTHESIS, add the material properties
763      * to the default data and to all the specialisations
764      */
765     void addParameter(
766         const Hypothesis,
767         const VariableDescription&,
768         const BehaviourData::RegistrationStatus = BehaviourData::UNREGISTRED);
769     /*!
770      * \brief assign an attribute to variable
771      * \param[in] h: modelling hypothesis
772      * \param[in] v: variable name
773      * \param[in] n: attribute name
774      * \param[in] a: attribute
775      * \param[in] b: don't throw if the attribute already exists.  In
776      * this case, the attribute is left unchanged. However the type of
777      * the attribute is checked.
778      */
779     void setVariableAttribute(const Hypothesis,
780                               const std::string&,
781                               const std::string&,
782                               const VariableAttribute&,
783                               const bool);
784     //! \return a type suitable for storing stress-free expansion
785     std::string getStressFreeExpansionType() const;
786     /*!
787      * \brief add a new stress free expansion description
788      * \param[in] h: modelling hypothesis
789      * \param[in] sfed: stress free expansion description
790      */
791     void addStressFreeExpansion(const Hypothesis,
792                                 const StressFreeExpansionDescription&);
793     /*!
794      * \return the registred stress free expansion descriptions
795      * \param[in] h: modelling hypothesis
796      */
797     const std::vector<BehaviourData::StressFreeExpansionDescription>&
798     getStressFreeExpansionDescriptions(const Hypothesis) const;
799     /*!
800      * \return true if a least one modelling hypothesis is anisotropic
801      * \param[in] h: modelling hypothesis
802      */
803     bool isStressFreeExansionAnisotropic(const Hypothesis) const;
804     /*!
805      * \return true if the given name is the one of a material
806      * property.
807      * \param[in] h: modelling hypothesis
808      * \param[in] n: name
809      */
810     bool isMaterialPropertyName(const Hypothesis, const std::string&) const;
811     /*!
812      * \return true if the given name is the one of a local variable.
813      * \param[in] h: modelling hypothesis
814      * \param[in] n: name
815      */
816     bool isLocalVariableName(const Hypothesis, const std::string&) const;
817     /*!
818      * \return true if the given name is the one of an persistent
819      * variable.
820      * \param[in] h: modelling hypothesis
821      * \param[in] n: name
822      */
823     bool isPersistentVariableName(const Hypothesis, const std::string&) const;
824     /*!
825      * \return true if the given name is the one of an integration
826      * variable.
827      * \param[in] h: modelling hypothesis
828      * \param[in] n: name
829      */
830     bool isIntegrationVariableName(const Hypothesis, const std::string&) const;
831     /*!
832      * \return true if the given name is the one of an integration
833      * variable increment.
834      * \param[in] h: modelling hypothesis
835      * \param[in] n: name
836      */
837     bool isIntegrationVariableIncrementName(const Hypothesis,
838                                             const std::string&) const;
839     /*!
840      * \return true if the given name is the one of an state
841      * variable.
842      * \param[in] h: modelling hypothesis
843      * \param[in] n: name
844      */
845     bool isStateVariableName(const Hypothesis, const std::string&) const;
846     /*!
847      * \return true if the given name is the one of an state
848      * variable increment.
849      * \param[in] h: modelling hypothesis
850      * \param[in] n: name
851      */
852     bool isStateVariableIncrementName(const Hypothesis,
853                                       const std::string&) const;
854     /*!
855      * \return true if the given name is the one of an auxiliary
856      * internal state variable.
857      * \param[in] h: modelling hypothesis
858      * \param[in] n: name
859      */
860     bool isAuxiliaryStateVariableName(const Hypothesis,
861                                       const std::string&) const;
862     /*!
863      * \return true if the given name is the one of an external state
864      * variable.
865      * \param[in] h: modelling hypothesis
866      * \param[in] n: name
867      */
868     bool isExternalStateVariableName(const Hypothesis,
869                                      const std::string&) const;
870     /*!
871      * \return true if the given name is the one of an external state
872      * variable increment
873      * \param[in] h: modelling hypothesis
874      * \param[in] n: name
875      */
876     bool isExternalStateVariableIncrementName(const Hypothesis,
877                                               const std::string&) const;
878     /*!
879      * \return true if the given name is the one of a static variable
880      * \param[in] h: modelling hypothesis
881      * \param[in] n: name
882      */
883     bool isStaticVariableName(const Hypothesis, const std::string&) const;
884     /*!
885      * \brief check if one has to include tvector.hxx or vector.hxx
886      * \param[in] b1: requires true if one has to include tvector.hxx
887      * \param[in] b2: requires true if one has to include vector.hxx
888      */
889     void requiresTVectorOrVectorIncludes(bool&, bool&) const;
890     /*!
891      * \brief check if one has to include tvector.hxx or vector.hxx
892      * \param[in] d:  behaviour data
893      * \param[in] b1: requires true if one has to include tvector.hxx
894      * \param[in] b2: requires true if one has to include vector.hxx
895      */
896     void requiresTVectorOrVectorIncludes(bool&,
897                                          bool&,
898                                          const BehaviourData&) const;
899 
900     /*!
901      * \return true if all mechanical data are specialised
902      * This means that the default mechanical data is useless
903      */
904     bool areAllMechanicalDataSpecialised() const;
905     /*!
906      * \return true if all mechanical data associated with the given
907      * modelling hypothesis are specialised.
908      * \param[in] h: modelling hypotheses considered
909      */
910     bool areAllMechanicalDataSpecialised(const std::set<Hypothesis>&) const;
911     /*!
912      * \return true if the mechanical data associated with the given
913      * modelling hypothesis is specialised.
914      * \param[in] h: modelling hypothesis considered
915      */
916     bool hasSpecialisedMechanicalData(const Hypothesis) const;
917     //! \return true if a stress free expansion has been defined
918     bool requiresStressFreeExpansionTreatment(const Hypothesis) const;
919     //! \return true if thermal expansion coefficient were defined
920     bool areThermalExpansionCoefficientsDefined() const;
921     //! \return the thermal expansion coefficients
922     const std::vector<MaterialProperty>& getThermalExpansionCoefficients()
923         const;
924     /*!
925      * set the behaviour thermal expansion coefficient (isotropic behaviour)
926      * \param[in] a: thermal expansion
927      */
928     void setThermalExpansionCoefficient(MaterialProperty);
929     /*!
930      * set the behaviour thermal expansions coefficient (orthotropic behaviour)
931      * \param[in] a1: thermal expansion in the first direction
932      * \param[in] a2: thermal expansion in the second direction
933      * \param[in] a3: thermal expansion in the third  direction
934      */
935     void setThermalExpansionCoefficients(MaterialProperty,
936                                          MaterialProperty,
937                                          MaterialProperty);
938     /*!
939      * \return the external names associated with the variables
940      * contained in the given container
941      * \param[in] h: modelling Hypothesis
942      * \param[in] v: variables for which external names are requested
943      */
944     std::vector<std::string> getExternalNames(const Hypothesis,
945                                               const VarContainer&) const;
946     /*!
947      * get the external names associated with the variables
948      * contained in the given container
949      * \param[out] n: names
950      * \param[in]  h: modelling Hypothesis
951      * \param[in]  v: variables for which external names are requested
952      */
953     void getExternalNames(std::vector<std::string>&,
954                           const Hypothesis,
955                           const VarContainer&) const;
956     /*!
957      * get the external names associated with the variables
958      * contained in the given container
959      * \param[out] n: names
960      * \param[in]  h: modelling Hypothesis
961      * \param[in]  v: variables for which external names are requested
962      */
963     void appendExternalNames(std::vector<std::string>&,
964                              const Hypothesis,
965                              const VarContainer&) const;
966     /*!
967      * \return true if the given member is used in a code block
968      * \param[in] h: modelling hypothesis
969      * \param[in] n: name
970      */
971     bool isMemberUsedInCodeBlocks(const Hypothesis, const std::string&) const;
972     /*!
973      * \return true if the given name is a parameter name
974      * \param[in] h: modelling hypothesis
975      * \param[in] n: name
976      */
977     bool isParameterName(const Hypothesis, const std::string&) const;
978     /*!
979      * \param[in] h: modelling hypothesis
980      * \param[in] n: parameter name
981      * \param[in] v: parameter default value
982      */
983     void setParameterDefaultValue(const Hypothesis,
984                                   const std::string&,
985                                   const double);
986     /*!
987      * \param[in] h: modelling hypothesis
988      * \param[in] n: parameter name
989      * \param[in] i: index
990      * \param[in] v: parameter default value
991      */
992     void setParameterDefaultValue(const Hypothesis,
993                                   const std::string&,
994                                   const unsigned short i,
995                                   const double);
996     /*!
997      * \param[in] h: modelling hypothesis
998      * \param[in] n: parameter name
999      * \param[in] v: parameter default value
1000      */
1001     void setParameterDefaultValue(const Hypothesis,
1002                                   const std::string&,
1003                                   const int);
1004     /*!
1005      * \param[in] h: modelling hypothesis
1006      * \param[in] n: parameter name
1007      * \param[in] v: parameter default value
1008      */
1009     void setParameterDefaultValue(const Hypothesis,
1010                                   const std::string&,
1011                                   const unsigned short);
1012     /*!
1013      * \return the default value of a parameter
1014      * \param[in] h: modelling hypothesis
1015      * \param[in] v: parameter default value
1016      */
1017     double getFloattingPointParameterDefaultValue(const Hypothesis,
1018                                                   const std::string&) const;
1019     /*!
1020      * \return the default value of a parameter (array case)
1021      * \param[in] h: modelling hypothesis
1022      * \param[in] v: parameter default value
1023      * \param[in] i: index
1024      */
1025     double getFloattingPointParameterDefaultValue(const Hypothesis,
1026                                                   const std::string&,
1027                                                   const unsigned short) const;
1028     /*!
1029      * \return the default value of a parameter
1030      * \param[in] h: modelling hypothesis
1031      * \param[in] v: parameter default value
1032      */
1033     int getIntegerParameterDefaultValue(const Hypothesis,
1034                                         const std::string&) const;
1035     /*!
1036      * \return the default value of a parameter
1037      * \param[in] h: modelling hypothesis
1038      * \param[in] v: parameter default value
1039      */
1040     unsigned short getUnsignedShortParameterDefaultValue(
1041         const Hypothesis, const std::string&) const;
1042     /*!
1043      * associate a glossary name to a variable
1044      * \param[in] h: modelling Hypothesis
1045      * \param[in] n: variable name
1046      * \param[in] g: glossary name
1047      */
1048     void setGlossaryName(const Hypothesis,
1049                          const std::string&,
1050                          const std::string&);
1051     /*!
1052      * \return true if the given glossary name is used
1053      * \param[in] h: modelling Hypothesis
1054      * \param[in] n: name
1055      */
1056     bool isGlossaryNameUsed(const Hypothesis, const std::string&) const;
1057     /*!
1058      * \return true if the given variable name is associated with a
1059      * glossary name
1060      * \param[in] h: modelling hypothesis
1061      * \param[in] n: name
1062      */
1063     bool hasGlossaryName(const Hypothesis, const std::string&) const;
1064     /*!
1065      * \return true if the given variable name is associated with a
1066      * entry name
1067      * \param[in] h: modelling hypothesis
1068      * \param[in] n: name
1069      */
1070     bool hasEntryName(const Hypothesis, const std::string&) const;
1071     /*!
1072      * associate an entry name to a variable
1073      * \param[in] h: modelling Hypothesis
1074      * \param[in] n: variable name
1075      * \param[in] e: entry name
1076      */
1077     void setEntryName(const Hypothesis, const std::string&, const std::string&);
1078     /*!
1079      * get the glossary name or the entry name of a variable
1080      * \param[in] h: modelling Hypothesis
1081      * \param[in] n: variable name
1082      */
1083     std::string getExternalName(const Hypothesis h, const std::string& n) const;
1084     /*!
1085      * \return the variable description associated with the given
1086      * glossary or entry name.
1087      * \param[in] h: modelling Hypothesis
1088      * \param[in] n: name
1089      */
1090     const VariableDescription& getVariableDescriptionByExternalName(
1091         const Hypothesis, const std::string&) const;
1092     /*!
1093      * \return the name of the variable associated with the given
1094      * glossary or entry name
1095      * \param[in] h: modelling Hypothesis
1096      * \param[in] n: name
1097      */
1098     std::string getVariableNameFromGlossaryNameOrEntryName(
1099         const Hypothesis, const std::string&) const;
1100     /*!
1101      * \return true if the given name is an entry name
1102      * \param[in] h: modelling Hypothesis
1103      * \param[in] n: name
1104      */
1105     bool isUsedAsEntryName(const Hypothesis, const std::string&) const;
1106     /*!
1107      * \brief add bounds to a variable
1108      * \param[in] h: modelling hypothesis
1109      * \param[in] n: variable name
1110      * \param[in] b: bounds description
1111      */
1112     void setBounds(const Hypothesis,
1113                    const std::string&,
1114                    const VariableBoundsDescription&);
1115     /*!
1116      * \brief add bounds to a variable
1117      * \param[in] h: modelling hypothesis
1118      * \param[in] n: variable name
1119      * \param[in] i: index (for array of variables)
1120      * \param[in] b: bounds description
1121      */
1122     void setBounds(const Hypothesis,
1123                    const std::string&,
1124                    const unsigned short,
1125                    const VariableBoundsDescription&);
1126     /*!
1127      * \brief add physical bounds to a variable
1128      * \param[in] h: modelling hypothesis
1129      * \param[in] n: variable name
1130      * \param[in] b: bounds description
1131      */
1132     void setPhysicalBounds(const Hypothesis,
1133                            const std::string&,
1134                            const VariableBoundsDescription&);
1135     /*!
1136      * \brief add physical bounds to a variable
1137      * \param[in] h: modelling hypothesis
1138      * \param[in] n: variable name
1139      * \param[in] i: index (for array of variables)
1140      * \param[in] b: bounds description
1141      */
1142     void setPhysicalBounds(const Hypothesis,
1143                            const std::string&,
1144                            const unsigned short,
1145                            const VariableBoundsDescription&);
1146     /*!
1147      * \brief declares an external state variable to be probably
1148      * unusable in a purely implicit resolution. This means that its
1149      * increment is used somewhere.
1150      *
1151      * The term "probably" refers to the fact that it may happens that
1152      * the increment is only used to get the value of the external
1153      * state variable at a given date. For example, in a standard
1154      * resolution (non implicit), the value of \(T+\theta\,\Delta\,T\)
1155      * gives the temperature value at
1156      * \(t+\theta\,\Delta\,t\). However, this expression is still
1157      * valid in a purely implicit resolution.
1158      *
1159      * \param[in] h: modelling hypothesis
1160      * \param[in] n: variable name
1161      */
1162     void declareExternalStateVariableProbablyUnusableInPurelyImplicitResolution(
1163         const Hypothesis, const std::string&);
1164     /*!
1165      * \brief set if this behaviour can be used in a purely implicit
1166      * resolution.
1167      * \param[in] h: modelling hypothesis
1168      * \param[in] b: new value of the
1169      * usableInPurelyImplicitResolution member
1170      * \see isUsableInPurelyImplicitResolution for details about
1171      * purely implicit resolution.
1172      */
1173     void setUsableInPurelyImplicitResolution(const Hypothesis, const bool);
1174     /*!
1175      * \brief declare or update a code block
1176      * \param[in] h: modelling hypothesis
1177      * \param[in] n: name
1178      * \param[in] c: code
1179      * \param[in] m: mode
1180      * \param[in] p: position
1181      * \param[in] b: if true, the code can be overriden or completed
1182      */
1183     void setCode(const Hypothesis,
1184                  const std::string&,
1185                  const CodeBlock&,
1186                  const Mode,
1187                  const Position,
1188                  const bool = true);
1189     /*!
1190      * \brief return the name of the code blocks defined so far
1191      * \param[in] h: modelling hypothesis
1192      */
1193     std::vector<std::string> getCodeBlockNames(const Hypothesis) const;
1194     /*!
1195      * \return the code block with the given name
1196      * \param[in] h: modelling hypothesis
1197      * \param[in] n: name
1198      */
1199     const CodeBlock& getCodeBlock(const Hypothesis, const std::string&) const;
1200     /*!
1201      * \return the code with the given name
1202      * \param[in] h: modelling hypothesis
1203      * \param[in] n: name
1204      */
1205     std::string getCode(const Hypothesis, const std::string&) const;
1206     /*!
1207      * \return the code with the given name
1208      * \param[in] h: modelling hypothesis
1209      * \param[in] n: name
1210      */
1211     bool hasCode(const Hypothesis, const std::string&) const;
1212     /*!
1213      * \brief set a mechanical attribute
1214      * \param[in] h: modelling hypothesis
1215      * \param[in] n: name
1216      * \param[in] a: attribute
1217      * \param[in] b: don't throw if the the
1218      *                attribute already exists.
1219      *                The attribute is left unchanged.
1220      *                However the type of the attribute is checked.
1221      */
1222     void setAttribute(const Hypothesis,
1223                       const std::string&,
1224                       const BehaviourAttribute&,
1225                       const bool = false);
1226     /*!
1227      * \brief update an attribute
1228      * \param[in] h: modelling hypothesis
1229      * \param[in] n: name
1230      * \param[in] a: attribute
1231      */
1232     void updateAttribute(const Hypothesis,
1233                          const std::string&,
1234                          const BehaviourAttribute&);
1235     /*!
1236      * \return a mechanical attribute
1237      * \param[in] h: modelling hypothesis
1238      * \param[in] n: name
1239      */
1240     template <typename T>
1241     const T& getAttribute(const Hypothesis, const std::string&) const;
1242     /*!
1243      * \return a mechanical attribute if it exists or the default
1244      * value
1245      * \param[in] h: modelling hypothesis
1246      * \param[in] n: name
1247      * \param[in] v: default value
1248      */
1249     template <typename T>
1250     T getAttribute(const Hypothesis, const std::string&, const T&) const;
1251     /*!
1252      * \return true an attribute with the given name has been declared
1253      * \param[in] h: modelling hypothesis
1254      * \param[in] n: name
1255      */
1256     bool hasAttribute(const Hypothesis, const std::string&) const;
1257     /*!
1258      * \return true a parameter with the given name has been declared
1259      * \param[in] h: modelling hypothesis
1260      * \param[in] n: name
1261      */
1262     bool hasParameter(const Hypothesis, const std::string&) const;
1263     /*!
1264      * \return true the given modelling hypothesis has a
1265      * parameter.
1266      * \param[in] h: modelling hypothesis \param[in] n:
1267      * name
1268      */
1269     bool hasParameters(const Hypothesis) const;
1270     /*!
1271      * \return true if at least one modelling hypothesis has a
1272      * parameter.
1273      */
1274     bool hasParameters() const;
1275     /*!
1276      * \brief insert a new attribute
1277      * \param[in] n: name
1278      * \param[in] a: attribute
1279      * \param[in] b: don't throw if the the
1280      *                attribute already exists.
1281      *                The attribute is left unchanged.
1282      *                However the type of the attribute is checked.
1283      */
1284     void setAttribute(const std::string&,
1285                       const BehaviourAttribute&,
1286                       const bool);
1287     /*!
1288      * \return true if an attribute with the given name as been registred
1289      * \param[in] n: name
1290      */
1291     bool hasAttribute(const std::string&) const;
1292     /*!
1293      * \return the attribute with the given name
1294      * \param[in] n: name
1295      */
1296     template <typename T>
1297     typename std::enable_if<
1298         tfel::meta::TLCountNbrOfT<T, BehaviourAttributeTypes>::value == 1,
1299         T&>::type
1300     getAttribute(const std::string&);
1301     /*!
1302      * \return the attribute with the given name
1303      * \param[in] n: name
1304      */
1305     template <typename T>
1306     typename std::enable_if<
1307         tfel::meta::TLCountNbrOfT<T, BehaviourAttributeTypes>::value == 1,
1308         const T&>::type
1309     getAttribute(const std::string&) const;
1310     /*!
1311      * \return the attribute with the given name
1312      * \param[in] n: name
1313      */
1314     template <typename T>
1315     typename std::enable_if<
1316         tfel::meta::TLCountNbrOfT<T, BehaviourAttributeTypes>::value == 1,
1317         T>::type
1318     getAttribute(const std::string&, const T&) const;
1319     /*!
1320      * \return all the attribute registred
1321      * \param[in] n: name
1322      */
1323     const std::map<std::string, BehaviourAttribute>& getAttributes() const;
1324     /*!
1325      * reserve the given name
1326      * \param[in] h: hypothesis
1327      * \param[in] n: variable name
1328      */
1329     void reserveName(const Hypothesis, const std::string&);
1330     /*!
1331      * \brief look if a name is reserved
1332      * \param[in] n: name
1333      */
1334     bool isNameReserved(const std::string&) const;
1335     /*!
1336      * register the given member name
1337      * \param[in] h: hypothesis
1338      * \param[in] n: variable name
1339      */
1340     void registerMemberName(const Hypothesis, const std::string&);
1341     /*!
1342      * register the given static member name
1343      * \param[in] h: hypothesis
1344      * \param[in] n: variable name
1345      */
1346     void registerStaticMemberName(const Hypothesis, const std::string&);
1347     /*!
1348      * \brief check variable existence
1349      * \return a pair of iterator. The first part tells if the
1350      * variable was found in a least one specialisation of the
1351      * behaviour and the second tells if the variable is available
1352      * for all distinct modelling hypothesis.
1353      * The variable could be any sort of variable (local variable,
1354      * integration variable, static variable, ...)
1355      * \param[in] v : variable name
1356      */
1357     std::pair<bool, bool> checkVariableExistence(const std::string&) const;
1358     /*!
1359      * \brief check variable existence for a particular sort of variable.
1360      * \return a pair of iterator. The first part tells if the
1361      * variable was found in a least one specialisation of the
1362      * behaviour and the second tells if the variable is available
1363      * for all distinct modelling hypothesis.
1364      * \param[in] v: variable name
1365      * \param[in] c: variable category
1366      * \param[in] b: if true, an exception if thrown if the variable is not
1367      * found
1368      */
1369     std::pair<bool, bool> checkVariableExistence(const std::string&,
1370                                                  const std::string&,
1371                                                  const bool = true) const;
1372     /*!
1373      * \brief check variable glossary name.
1374      * The variable must exists for all modelling hypothesis and have
1375      * the given glossary name. If not, an exception is thrown. If
1376      * another variable has the given glossary name, an exception if
1377      * thrown.
1378      * \param[in] v: variable name
1379      * \param[in] g: glossary name
1380      */
1381     void checkVariableGlossaryName(const std::string&,
1382                                    const std::string&) const;
1383     /*!
1384      * \brief check variable entry name.
1385      * The variable must exists for all modelling hypothesis and have
1386      * the given entry name. If not, an exception is thrown. If
1387      * another variable has the given entry name, an exception if
1388      * thrown.
1389      * \param[in] v: variable name
1390      * \param[in] g: entry name
1391      */
1392     void checkVariableEntryName(const std::string&, const std::string&) const;
1393     /*!
1394      * \brief check a variable position. Throw an exception if this
1395      * check is not satisfied.
1396      * \param[in] v: variable name
1397      * \param[in] c: variable category
1398      * \param[in] p: variable position
1399      * \pre The number of variables of the given type must be greater
1400      * than the position given, otherwise an exception is thrown
1401      */
1402     void checkVariablePosition(const std::string&,
1403                                const std::string&,
1404                                const size_t);
1405     //! destructor
1406     ~BehaviourDescription();
1407 
1408    private:
1409     //! a simple alias (std::optional is not yet available)
1410     template <typename T>
1411     using optional = tfel::utilities::GenType<T>;
1412     /*!
1413      * \brief throw an exception saying that no attribute with the
1414      * given name exists
1415      */
1416     TFEL_NORETURN static void throwUndefinedAttribute(const std::string&);
1417     /*!
1418      * \return the driving variable with the associated name
1419      * \param[in] n: name
1420      */
1421     Gradient& getGradient(const std::string&);
1422     /*!
1423      * \return the thermodynamic force with the associated name
1424      * \param[in] n: name
1425      */
1426     ThermodynamicForce& getThermodynamicForce(const std::string&);
1427     //! update the class name
1428     void updateClassName();
1429     /*!
1430      * \brief create the mechanical behaviour data associated with the
1431      * given modelling hypothesis if necessary, and returns it.
1432      * \param[in] h: modelling hypothesis
1433      */
1434     BehaviourData& getBehaviourData2(const ModellingHypothesis::Hypothesis&);
1435     /*!
1436      * \call the behaviour data associated with the given hypothesis
1437      * \param[in] h: modelling hypothesis
1438      * \param[in] m: behaviour data method
1439      * \param[in] a: argument given to the behaviour data's method
1440      */
1441     template <typename Res, typename Arg1>
1442     Res getData(const Hypothesis,
1443                 Res (BehaviourData::*)(const Arg1&) const,
1444                 const Arg1&) const;
1445     /*!
1446      * \brief call the behaviour data associated with the given hypothesis
1447      * \param[in] h: modelling hypothesis
1448      * \param[in] m: behaviour data method
1449      * \param[in] a: argument given to the behaviour data's method
1450      * \param[in] b: propagate to all hypothesis if h is UNDEFINEDHYPOTHESIS
1451      * \note if h is UNDEFINEDHYPOTHESIS, the default data
1452      * and all the specialisations are called, unless the last parameter is
1453      * false.
1454      */
1455     template <typename Arg1>
1456     void callBehaviourData(const Hypothesis,
1457                            void (BehaviourData::*)(const Arg1&),
1458                            const Arg1&,
1459                            const bool);
1460     /*!
1461      * \brief call the behaviour data associated with the given hypothesis
1462      * \param[in] h: modelling hypothesis
1463      * \param[in] m: behaviour data method
1464      * \param[in] a1: first  argument given to the behaviour data's method
1465      * \param[in] a2: second argument given to the behaviour data's method
1466      * \param[in] b: propagate to all hypothesis if h is UNDEFINEDHYPOTHESIS
1467      * \note if h is UNDEFINEDHYPOTHESIS, the default data
1468      * and all the specialisations are called, unless the last parameter is
1469      * false.
1470      */
1471     template <typename Arg1, typename Arg2>
1472     void callBehaviourData(const Hypothesis,
1473                            void (BehaviourData::*)(const Arg1&, const Arg2),
1474                            const Arg1&,
1475                            const Arg2,
1476                            const bool);
1477     /*!
1478      * \brief call the behaviour data associated with the given hypothesis
1479      * \param[in] h: modelling hypothesis
1480      * \param[in] m: behaviour data method
1481      * \param[in] a1: first  argument given to the behaviour data's method
1482      * \param[in] a2: second argument given to the behaviour data's method
1483      * \param[in] b: propagate to all hypothesis if h is UNDEFINEDHYPOTHESIS
1484      * \note if h is UNDEFINEDHYPOTHESIS, the default data
1485      * and all the specialisations are called, unless the last parameter is
1486      * false.
1487      */
1488     template <typename Arg1, typename Arg2, typename Arg3>
1489     void callBehaviourData(const Hypothesis,
1490                            void (BehaviourData::*)(const Arg1&,
1491                                                    const Arg2&,
1492                                                    const Arg3&),
1493                            const Arg1&,
1494                            const Arg2&,
1495                            const Arg3&,
1496                            const bool);
1497     /*!
1498      * \brief call the behaviour data associated with the given hypothesis
1499      * \param[in] h: modelling hypothesis
1500      * \param[in] m: behaviour data method
1501      * \param[in] a1: first  argument given to the behaviour data's method
1502      * \param[in] a2: second argument given to the behaviour data's method
1503      * \param[in] b: propagate to all hypothesis if h is UNDEFINEDHYPOTHESIS
1504      * \note if h is UNDEFINEDHYPOTHESIS, the default data
1505      * and all the specialisations are called, unless the last parameter is
1506      * false.
1507      */
1508     template <typename Arg1, typename Arg2>
1509     void callBehaviourData(const Hypothesis,
1510                            void (BehaviourData::*)(const Arg1&, const Arg2&),
1511                            const Arg1&,
1512                            const Arg2&,
1513                            const bool);
1514     /*!
1515      * \brief call the behaviour data associated with the given hypothesis
1516      * \param[in] h: modelling hypothesis
1517      * \param[in] m: behaviour data method
1518      * \param[in] a: argument given to the behaviour data's method
1519      * \param[in] b: propagate to all hypothesis if h is UNDEFINEDHYPOTHESIS
1520      * \note if h is UNDEFINEDHYPOTHESIS, the default data
1521      * and all the specialisations are called, unless the last parameter is
1522      * false.
1523      */
1524     template <typename Arg1>
1525     void callBehaviourData(const Hypothesis,
1526                            void (BehaviourData::*)(const Arg1),
1527                            const Arg1,
1528                            const bool);
1529     /*!
1530      * \brief add variables to the behaviour data
1531      * \param[in] h: modelling hypothesis
1532      * \param[in] v: variables to be added
1533      * \param[in] s: registration status
1534      * \param[in] m: method retrieving the variable container
1535      *
1536      * \note if h is UNDEFINEDHYPOTHESIS, add the material properties
1537      * to the default data and to all the specialisations
1538      */
1539     void addVariables(
1540         const Hypothesis,
1541         const VariableDescriptionContainer&,
1542         const BehaviourData::RegistrationStatus,
1543         void (BehaviourData::*)(const VariableDescription&,
1544                                 const BehaviourData::RegistrationStatus));
1545     /*!
1546      * \brief add a variable to the behaviour data
1547      * \param[in] h: modelling hypothesis
1548      * \param[in] v: variable to be added
1549      * \param[in] s: registration status
1550      * \param[in] m: method retrieving the variable container
1551      *
1552      * \note if h is UNDEFINEDHYPOTHESIS, add the material properties
1553      * to the default data and to all the specialisations
1554      */
1555     void addVariable(
1556         const Hypothesis,
1557         const VariableDescription&,
1558         const BehaviourData::RegistrationStatus,
1559         void (BehaviourData::*)(const VariableDescription&,
1560                                 const BehaviourData::RegistrationStatus));
1561     /*!
1562      * \brief add variables to the behaviour data
1563      * \param[out] b: behaviour data
1564      * \param[in]  v: variables to be added
1565      * \param[in]  s: registration status
1566      * \param[in]  m: method retrieving the variable container
1567      */
1568     void addVariables(
1569         BehaviourData&,
1570         const VariableDescriptionContainer&,
1571         const BehaviourData::RegistrationStatus,
1572         void (BehaviourData::*)(const VariableDescription&,
1573                                 const BehaviourData::RegistrationStatus));
1574     /*!
1575      * \brief add a variable to the behaviour data
1576      * \param[out] b: behaviour data
1577      * \param[in]  v: variable to be added
1578      * \param[in]  s: registration status
1579      * \param[in]  m: method retrieving the variable container
1580      */
1581     void addVariable(
1582         BehaviourData&,
1583         const VariableDescription&,
1584         const BehaviourData::RegistrationStatus,
1585         void (BehaviourData::*)(const VariableDescription&,
1586                                 const BehaviourData::RegistrationStatus));
1587     /*!
1588      * \return the category associated with the given variable
1589      * \param[in] h: modelling hypothesis
1590      * \param[in] v: variable name
1591      */
1592     MaterialPropertyInput::Category getMaterialPropertyInputCategory(
1593         const Hypothesis, const std::string&) const;
1594     /*!
1595      * \brief check that the given hypothesis is supported
1596      * \param[in] h: modelling hypothesis
1597      */
1598     void checkModellingHypothesis(const Hypothesis&) const;
1599     //! a simple alias
1600     typedef std::shared_ptr<BehaviourData> MBDPtr;
1601     //! behaviour attributes
1602     std::map<std::string, BehaviourAttribute> attributes;
1603     //! behaviour name
1604     std::string behaviour;
1605     //! dsl name
1606     std::string dsl;
1607     //! library name
1608     std::string library;
1609     //! material name
1610     std::string material;
1611     //! name of the generated class
1612     std::string className;
1613     //! included header files
1614     std::string includes;
1615     //! specific sources
1616     std::string sources;
1617     /*!
1618      * list of modelling hypotheses for
1619      * which the behaviour is defined
1620      */
1621     mutable std::set<Hypothesis> hypotheses;
1622     /*!
1623      * list of modelling hypotheses for
1624      * which this class returned a mechanical data
1625      */
1626     mutable std::set<Hypothesis> requestedHypotheses;
1627     //! default behaviour data
1628     BehaviourData d;
1629     //! specialisations
1630     std::map<Hypothesis, MBDPtr> sd;
1631     /*!
1632      * main variables, association of a driving variable and a
1633      * thermodynamicforce
1634      */
1635     std::vector<std::pair<Gradient, ThermodynamicForce>> mvariables;
1636     /*!
1637      * elastic material properties
1638      * For isotropic   behaviours, only two elastic material properties must be
1639      * defined.
1640      * For orthotropic behaviours, two or nine elastic material properties must
1641      * be defined.
1642      */
1643     std::vector<MaterialProperty> elasticMaterialProperties;
1644     /*!
1645      * average thermal coefficient
1646      * For isotropic   behaviours, only one thermal expansion coefficient must
1647      * be defined.
1648      * For orthotropic behaviours, one or three thermal expansions coefficients
1649      * must be defined.
1650      */
1651     std::vector<MaterialProperty> thermalExpansionCoefficients;
1652     /*!
1653      * elastic material properties
1654      * For isotropic   behaviours, only two elastic material properties must be
1655      * defined.
1656      * For orthotropic behaviours, two or nine elastic material properties must
1657      * be defined.
1658      */
1659     std::vector<ModelDescription> models;
1660     //! slip systems
1661     optional<SlipSystemsDescription> gs;
1662     //! \brief list of all Hill tensors defined
1663     std::vector<HillTensor> hillTensors;
1664     //! strain measure
1665     optional<StrainMeasure> strainMeasure;
1666     //! use units
1667     bool use_qt = false;
1668     //! type of behaviour
1669     BehaviourType type = GENERALBEHAVIOUR;
1670     //! symmetry of behaviour (isotropic or orthotropic)
1671     mutable BehaviourSymmetryType stype = mfront::ISOTROPIC;
1672     //! orthotropic axes convention
1673     OrthotropicAxesConvention oac = OrthotropicAxesConvention::DEFAULT;
1674     //! flag telling if the orthotropic axes convention has been defined
1675     mutable bool oacIsDefined = false;
1676     //! flag telling the behaviour symmetry has been defined
1677     mutable bool stypeIsDefined = false;
1678     //! symmetry of elastic behaviour (isotropic or orthotropic)
1679     mutable BehaviourSymmetryType estype = mfront::ISOTROPIC;
1680     //! flag telling the elastic symmetry has been defined
1681     mutable bool estypeIsDefined = false;
1682     //! integration schemes
1683     IntegrationScheme ischeme = UNDEFINEDINTEGRATIONSCHEME;
1684     //! list of material laws used
1685     std::vector<std::string> materialLaws;
1686     /*!
1687      * Support for dynamically allocated vectors is not allowed in all
1688      * dsl's. A dsl may change this value to disable the use of
1689      * dynamically allocated vectors.
1690      */
1691     tfel::utilities::GenType<bool> areDynamicallyAllocatedVectorsAllowed_;
1692   };  // end of struct BehaviourDescription
1693 
1694   /*!
1695    * \brief set the elastic symmetry of a material if not already
1696    * defined. If already defined, check that the symmetry is the same
1697    * as the one given in argument
1698    * \param[in,out] bd: behaviour description
1699    * \param[in]     s:  symmetry type
1700    */
1701   MFRONT_VISIBILITY_EXPORT void setElasticSymmetryType(
1702       BehaviourDescription&, const BehaviourSymmetryType);
1703   /*!
1704    * \brief check that the given material property description is strictly
1705    * positive, when described by a constant material property
1706    * \param[in] mp: material property description
1707    */
1708   MFRONT_VISIBILITY_EXPORT void checkIsStrictlyPositive(
1709       const BehaviourDescription::MaterialProperty&);
1710   /*!
1711    * \brief check that the given material property description is strictly
1712    * negative,when described by a constant material property
1713    * \param[in] mp: material property description
1714    */
1715   MFRONT_VISIBILITY_EXPORT void checkIsStrictlyNegative(
1716       const BehaviourDescription::MaterialProperty&);
1717 
1718 }  // end of namespace mfront
1719 
1720 #include "MFront/BehaviourDescription.ixx"
1721 
1722 #endif /* LIB_MFRONT_BEHAVIOURDESCRIPTION_HXX */
1723