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