1 /*!
2  * \file  ModelDescription.cxx
3  * \brief
4  * \author Thomas Helfer
5  * \date   21 janv. 2015
6  * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights
7  * reserved.
8  * This project is publicly released under either the GNU GPL Licence
9  * or the CECILL-A licence. A copy of thoses licences are delivered
10  * with the sources of TFEL. CEA or EDF may also distribute this
11  * project under specific licensing conditions.
12  */
13 
14 #include<algorithm>
15 #include"TFEL/Raise.hxx"
16 #include"TFEL/Utilities/CxxTokenizer.hxx"
17 #include"TFEL/Glossary/Glossary.hxx"
18 #include"TFEL/Glossary/GlossaryEntry.hxx"
19 #include"MFront/ModelDescription.hxx"
20 
21 namespace mfront
22 {
23 
24   ModelDescription::Function::Function() = default;
25   ModelDescription::Function::Function(const ModelDescription::Function&) = default;
26   ModelDescription::Function::Function(ModelDescription::Function&&) = default;
27   ModelDescription::Function&
28   ModelDescription::Function::operator=(const ModelDescription::Function&) = default;
29   ModelDescription::Function&
30   ModelDescription::Function::operator=(ModelDescription::Function&&) = default;
31   ModelDescription::Function::~Function() = default;
32 
33   std::pair<std::string,unsigned short>
decomposeVariableName(const std::string & n) const34   ModelDescription::decomposeVariableName(const std::string& n) const
35   {
36     auto get = [&n](const VariableDescriptionContainer& vc)
37       -> std::pair<std::string,unsigned short>
38     {
39       using size_type = unsigned short;
40       for(const auto& v:vc){
41 	if(v.name==n){
42 	  return {v.name,0u};
43 	}
44 	const auto d = v.getAttribute<size_type>(VariableDescription::depth,0);
45 	for(size_type j=1;j<=d;++j){
46 	  auto fn = v.name + "_" + std::to_string(j);
47 	  if(fn==n){
48 	    return {v.name,j};
49 	  }
50 	}
51       }
52       return {};
53     };
54     auto r = get(this->outputs);
55     if(!r.first.empty()){
56       return r;
57     }
58     r = get(this->inputs);
59     tfel::raise_if(r.first.empty(),"decomposeVariableName: "
60 		   "field name '"+n+"' has not been found");
61     return r;
62   } // end of ModelDescription::decomposeVariableName
63 
64   ModelDescription::ModelDescription() = default;
65   ModelDescription::ModelDescription(const ModelDescription&) = default;
66   ModelDescription::ModelDescription(ModelDescription&&) = default;
67   ModelDescription&
68   ModelDescription::operator=(const ModelDescription&) = default;
69   ModelDescription&
70   ModelDescription::operator=(ModelDescription&&) = default;
71 
reserveName(const std::string & n)72   void ModelDescription::reserveName(const std::string& n){
73     tfel::raise_if(!this->reservedNames.insert(n).second,
74 		   "ModelDescription::reserveName: "
75 		   "name '"+n+"' already reserved");
76   }
77 
isNameReserved(const std::string & n) const78   bool ModelDescription::isNameReserved(const std::string& n) const{
79     return this->reservedNames.count(n)!=0;
80   }
81 
registerMemberName(const std::string & n)82   void ModelDescription::registerMemberName(const std::string& n)
83   {
84     this->reserveName(n);
85     tfel::raise_if(!this->memberNames.insert(n).second,
86 		   "ModelDescription::registerMemberName: "
87 		   "name '"+n+"' already reserved");
88   } // end of ModelDescription::registerMemberName
89 
registerStaticMemberName(const std::string & n)90   void ModelDescription::registerStaticMemberName(const std::string& n)
91   {
92     this->reserveName(n);
93     tfel::raise_if(!this->staticMemberNames.insert(n).second,
94 		   "ModelDescription::registerStaticMemberName: "
95 		   "name '"+n+"' already reserved");
96   } // end of ModelDescription::registerStaticMemberName
97 
98   VariableDescription&
getVariableDescription(const std::string & n)99   ModelDescription::getVariableDescription(const std::string& n)
100   {
101     if(this->outputs.contains(n)){
102       return this->outputs.getVariable(n);
103     }
104     if(this->inputs.contains(n)){
105       return this->inputs.getVariable(n);
106     }
107     if(this->parameters.contains(n)){
108       return this->parameters.getVariable(n);
109     }
110     if(this->constantMaterialProperties.contains(n)){
111       return this->constantMaterialProperties.getVariable(n);
112     }
113     tfel::raise("ModelDescription::getVariableDescription: "
114 		"No variable named '"+n+"'.\n"
115 		"'"+n+"' is neither:\n"
116 		"- An output.\n"
117 		"- An input.\n"
118 		"- A parameter.\n"
119 		"- A constant material properties.");
120   } // end of ModelDescription::getVariableDescription
121 
122   const VariableDescription&
getVariableDescription(const std::string & n) const123   ModelDescription::getVariableDescription(const std::string& n) const
124   {
125     if(this->outputs.contains(n)){
126       return this->outputs.getVariable(n);
127     }
128     if(this->inputs.contains(n)){
129       return this->inputs.getVariable(n);
130     }
131     if(this->parameters.contains(n)){
132       return this->parameters.getVariable(n);
133     }
134     if(this->constantMaterialProperties.contains(n)){
135       return this->constantMaterialProperties.getVariable(n);
136     }
137     tfel::raise("ModelDescription::getVariableDescription: "
138 		"No variable named '"+n+"'.\n"
139 		"'"+n+"' is neither:\n"
140 		"- An output.\n"
141 		"- An input.\n"
142 		"- A parameter.\n"
143 		"- A constant material properties.");
144   } // end of ModelDescription::getVariableDescription
145 
checkVariableExistence(const std::string & v) const146   void ModelDescription::checkVariableExistence(const std::string& v) const{
147     tfel::raise_if((!this->inputs.contains(v))&&
148 		   (!this->outputs.contains(v))&&
149 		   (!this->parameters.contains(v))&&
150 		   (!this->staticVars.contains(v))&&
151 		   (!this->constantMaterialProperties.contains(v)),
152 		   "ModelDescription::checkVariableExistence: "
153 		   "no variable named '"+v+"'");
154   } // end of ModelDescription::checkVariableExistence
155 
setGlossaryName(const std::string & v,const std::string & g)156   void ModelDescription::setGlossaryName(const std::string& v,
157 					 const std::string& g){
158     this->checkVariableExistence(v);
159     const auto& glossary = tfel::glossary::Glossary::getGlossary();
160     tfel::raise_if(!glossary.contains(g),
161 		   "ModelDescription::setGlossaryName: "
162 		   "no glossary name '"+g+"'");
163     tfel::raise_if((this->glossaryNames.find(v)!=this->glossaryNames.end())||
164 		   (this->entryNames.find(v)!=this->entryNames.end()),
165 		   "ModelDescription::setGlossaryName: "
166 		   "an external name has already been set "
167 		   "for variable '"+v+"'");
168     if(v!=g){
169       this->reserveName(g);
170     }
171     const auto gn = glossary.getGlossaryEntry(g).getKey();
172     this->getVariableDescription(v).setGlossaryName(g);
173     this->glossaryNames.insert({v,gn});
174   }
175 
setEntryName(const std::string & v,const std::string & e)176   void ModelDescription::setEntryName(const std::string& v,
177 				      const std::string& e){
178     this->checkVariableExistence(v);
179     tfel::raise_if(!tfel::utilities::CxxTokenizer::isValidIdentifier(e,false),
180 		   "ModelDescription::setEntryName: "
181 		   "'"+e+"' is a not a valid entry name");
182     tfel::raise_if(tfel::glossary::Glossary::getGlossary().contains(e),
183 		   "ModelDescription::setEntryName: "
184 		   "'"+e+"' is a glossary name");
185     tfel::raise_if((this->glossaryNames.find(v)!=this->glossaryNames.end())||
186 		   (this->entryNames.find(v)!=this->entryNames.end()),
187 		   "ModelDescription::setEntryName: "
188 		   "an external name has already been set "
189 		   "for variable '"+v+"'");
190     if(v!=e){
191       this->reserveName(e);
192     }
193     this->getVariableDescription(v).setEntryName(e);
194     this->entryNames.insert({v,e});
195   }
196 
getReservedNames()197   std::set<std::string>& ModelDescription::getReservedNames(){
198     return this->reservedNames;
199   }
200 
201   const std::set<std::string>&
getReservedNames() const202   ModelDescription::getReservedNames() const{
203     return this->reservedNames;
204   }
205 
addMaterialLaw(const std::string & m)206   void ModelDescription::addMaterialLaw(const std::string& m)
207   {
208     if(std::find(this->materialLaws.begin(),
209 		 this->materialLaws.end(),m)==this->materialLaws.end()){
210       this->materialLaws.push_back(m);
211     }
212   } // end of ModelDescription::addMaterialLaw
213 
appendToIncludes(const std::string & c)214   void ModelDescription::appendToIncludes(const std::string& c)
215   {
216     this->includes+=c;
217     if(!this->includes.empty()){
218       if(*(this->includes.rbegin())!='\n'){
219 	this->includes+='\n';
220       }
221     }
222   } // end of ModelDescription::appendToIncludes
223 
appendToMembers(const std::string & c)224   void ModelDescription::appendToMembers(const std::string& c)
225   {
226     this->members+=c;
227     if(!this->members.empty()){
228       if(*(this->members.rbegin())!='\n'){
229 	this->members+='\n';
230       }
231     }
232   } // end of ModelDescription::appendToMembers
233 
appendToPrivateCode(const std::string & c)234   void ModelDescription::appendToPrivateCode(const std::string& c)
235   {
236     this->privateCode+=c;
237     if(!this->privateCode.empty()){
238       if(*(this->privateCode.rbegin())!='\n'){
239 	this->privateCode+='\n';
240       }
241     }
242   } // end of ModelDescription::appendToPrivateCode
243 
appendToSources(const std::string & c)244   void ModelDescription::appendToSources(const std::string& c)
245   {
246     this->sources+=c;
247     if(!this->sources.empty()){
248       if(*(this->sources.rbegin())!='\n'){
249 	this->sources+='\n';
250       }
251     }
252   } // end of ModelDescription::appendToSources
253 
254   ModelDescription::~ModelDescription() = default;
255 
256 } // end of namespace mfront
257