1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #include "metaFEMObject.h"
20 
21 #include <cctype>
22 #include <cstdio>
23 #include <string>
24 
25 #if (METAIO_USE_NAMESPACE)
26 namespace METAIO_NAMESPACE {
27 #endif
28 
29 FEMObjectNode::
FEMObjectNode(int dim)30 FEMObjectNode(int dim)
31 {
32   m_Dim = dim;
33   m_GN = -1;
34   m_X = new float[m_Dim];
35   for(unsigned int i=0;i<m_Dim;i++)
36     {
37     m_X[i] = 0;
38     }
39 }
40 
41 FEMObjectNode::
~FEMObjectNode()42 ~FEMObjectNode()
43 {
44   delete []m_X;
45 }
46 
47 FEMObjectElement::
FEMObjectElement(int dim)48 FEMObjectElement(int dim)
49 {
50   m_Dim = dim;
51   m_GN = -1;
52   m_NodesId = new int[m_Dim];
53   for(unsigned int i=0;i<m_Dim;i++)
54     {
55     m_NodesId[i] = -1;
56     }
57 }
58 
59 FEMObjectElement::
~FEMObjectElement()60 ~FEMObjectElement()
61 {
62   delete []m_NodesId;
63 }
64 
FEMObjectLoad()65 FEMObjectLoad::FEMObjectLoad()
66 {
67 }
68 
~FEMObjectLoad()69 FEMObjectLoad::~FEMObjectLoad()
70 {
71   for(std::vector<FEMObjectMFCTerm *>::iterator it = this->m_LHS.begin();
72       it != this->m_LHS.end();
73       ++it)
74     {
75     delete (*it);
76     }
77   this->m_LHS.clear();
78   this->m_RHS.clear();
79   this->m_ForceMatrix.clear();
80   this->m_ForceVector.clear();
81 }
82 
83 //
84 // MetaFEMObject Constructors
85 //
86 MetaFEMObject::
MetaFEMObject()87 MetaFEMObject()
88  :MetaObject()
89 {
90   if(META_DEBUG) std::cout << "MetaFEMObject()" << std::endl;
91 
92   Clear();
93 
94   this->m_ClassNameList.push_back("Node");
95   this->m_ClassNameList.push_back("MaterialLinearElasticity");
96   this->m_ClassNameList.push_back("Element2DC0LinearLineStress");
97   this->m_ClassNameList.push_back("Element2DC1Beam");
98   this->m_ClassNameList.push_back("Element2DC0LinearTriangularMembrane");
99   this->m_ClassNameList.push_back("Element2DC0LinearTriangularStrain");
100   this->m_ClassNameList.push_back("Element2DC0LinearTriangularStress");
101   this->m_ClassNameList.push_back("Element2DC0LinearQuadrilateralMembrane");
102   this->m_ClassNameList.push_back("Element2DC0LinearQuadrilateralStrain");
103   this->m_ClassNameList.push_back("Element2DC0LinearQuadrilateralStress");
104   this->m_ClassNameList.push_back("Element2DC0QuadraticTriangularStress");
105   this->m_ClassNameList.push_back("Element2DC0QuadraticTriangularStrain");
106   this->m_ClassNameList.push_back("Element3DC0LinearHexahedronMembrane");
107   this->m_ClassNameList.push_back("Element3DC0LinearHexahedronStrain");
108   this->m_ClassNameList.push_back("Element3DC0LinearTetrahedronMembrane");
109   this->m_ClassNameList.push_back("Element3DC0LinearTetrahedronStrain");
110   this->m_ClassNameList.push_back("LoadBC");
111   this->m_ClassNameList.push_back("LoadBCMFC");
112   this->m_ClassNameList.push_back("LoadNode");
113   this->m_ClassNameList.push_back("LoadEdge");
114   this->m_ClassNameList.push_back("LoadGravConst");
115   this->m_ClassNameList.push_back("LoadLandmark");
116   this->m_ClassNameList.push_back("LoadPoint");
117   this->m_ElementDataFileName =  "LOCAL";
118 }
119 
120 //
121 MetaFEMObject::
MetaFEMObject(const char * _headerName)122 MetaFEMObject(const char *_headerName)
123  :MetaObject()
124 {
125   if(META_DEBUG)
126     {
127     std::cout << "MetaFEMObject()" << std::endl;
128     }
129   Clear();
130   Read(_headerName);
131   this->m_ElementDataFileName = "LOCAL";
132 }
133 
134 //
135 MetaFEMObject::
MetaFEMObject(const MetaFEMObject * _mesh)136 MetaFEMObject(const MetaFEMObject *_mesh)
137  : MetaObject()
138 {
139   if(META_DEBUG)
140     {
141     std::cout << "MetaFEMObject()" << std::endl;
142     }
143   Clear();
144   CopyInfo(_mesh);
145 }
146 
147 
148 
149 //
150 MetaFEMObject::
MetaFEMObject(unsigned int dim)151 MetaFEMObject(unsigned int dim)
152  :MetaObject(dim)
153 {
154   if(META_DEBUG)
155     {
156     std::cout << "MetaFEMObject()" << std::endl;
157     }
158   Clear();
159   this->m_ElementDataFileName = "LOCAL";
160 }
161 
162 /** Destructor */
163 MetaFEMObject::
~MetaFEMObject()164 ~MetaFEMObject()
165 {
166   // Delete the list of pointers to Nodes.
167   NodeListType::iterator it_Node = m_NodeList.begin();
168   while(it_Node != m_NodeList.end())
169     {
170     FEMObjectNode* Node = *it_Node;
171     ++it_Node;
172     delete Node;
173     }
174   // Delete the list of pointers to Materials.
175   MaterialListType::iterator it_Material = m_MaterialList.begin();
176   while(it_Material != m_MaterialList.end())
177     {
178     FEMObjectMaterial* Material = *it_Material;
179     ++it_Material;
180     delete Material;
181     }
182 
183   // Delete the list of pointers to Elements.
184   ElementListType::iterator it_Element = m_ElementList.begin();
185   while(it_Element != m_ElementList.end())
186     {
187     FEMObjectElement* Element = *it_Element;
188     ++it_Element;
189     delete Element;
190     }
191 
192   // Delete the list of pointers to Loads.
193   LoadListType::iterator it_Load = m_LoadList.begin();
194   while(it_Load != m_LoadList.end())
195     {
196     FEMObjectLoad* Load = *it_Load;
197     ++it_Load;
198     delete Load;
199     }
200 
201   M_Destroy();
202 }
203 
204 //
205 void MetaFEMObject::
PrintInfo() const206 PrintInfo() const
207 {
208   MetaObject::PrintInfo();
209 }
210 
211 void MetaFEMObject::
CopyInfo(const MetaObject * _object)212 CopyInfo(const MetaObject * _object)
213 {
214   MetaObject::CopyInfo(_object);
215 }
216 
217 /** Clear FEMObject information */
218 void MetaFEMObject::
Clear()219 Clear()
220 {
221   if(META_DEBUG)
222     {
223     std::cout << "MetaFEMObject: Clear" << std::endl;
224     }
225   MetaObject::Clear();
226   if(META_DEBUG)
227     {
228     std::cout << "MetaFEMObject: Clear: m_NPoints" << std::endl;
229     }
230 
231   // Delete the list of pointers to Nodes.
232   NodeListType::iterator it_Node = m_NodeList.begin();
233   while(it_Node != m_NodeList.end())
234     {
235     FEMObjectNode* Node = *it_Node;
236     ++it_Node;
237     delete Node;
238     }
239 
240   // Delete the list of pointers to Elements.
241   ElementListType::iterator it_Element = m_ElementList.begin();
242   while(it_Element != m_ElementList.end())
243     {
244     FEMObjectElement* Element = *it_Element;
245     ++it_Element;
246     delete Element;
247     }
248 
249   // Delete the list of pointers to Loads.
250   LoadListType::iterator it_Load = m_LoadList.begin();
251   while(it_Load != m_LoadList.end())
252     {
253     FEMObjectLoad* Load = *it_Load;
254     ++it_Load;
255     delete Load;
256     }
257 
258   // Delete the list of pointers to Materials.
259   MaterialListType::iterator it_Material = m_MaterialList.begin();
260   while(it_Material != m_MaterialList.end())
261     {
262     FEMObjectMaterial* Material = *it_Material;
263     ++it_Material;
264     delete Material;
265     }
266 
267   m_NodeList.clear();
268   m_ElementList.clear();
269   m_LoadList.clear();
270   m_MaterialList.clear();
271 }
272 
273 /** Destroy tube information */
274 void MetaFEMObject::
M_Destroy()275 M_Destroy()
276 {
277   MetaObject::M_Destroy();
278 }
279 
280 /** Set Read fields */
281 void MetaFEMObject::
M_SetupReadFields()282 M_SetupReadFields()
283 {
284   if(META_DEBUG)
285     {
286     std::cout << "MetaFEMObject: M_SetupReadFields" << std::endl;
287     }
288 
289   MetaObject::M_SetupReadFields();
290 
291   MET_FieldRecordType * mF;
292 
293   mF = new MET_FieldRecordType;
294   MET_InitWriteField(mF, "ElementDataFile", MET_STRING, true);
295   mF->required = true;
296   mF->terminateRead = true;
297   m_Fields.push_back(mF);
298 
299 }
300 
301 void MetaFEMObject::
M_SetupWriteFields()302 M_SetupWriteFields()
303 {
304   strcpy(m_ObjectTypeName,"FEMObject");
305   MetaObject::M_SetupWriteFields();
306 
307   MET_FieldRecordType * mF;
308 
309   mF = new MET_FieldRecordType;
310   MET_InitWriteField(mF, "ElementDataFile", MET_STRING,
311                      m_ElementDataFileName.length(),
312                      m_ElementDataFileName.c_str());
313   mF->terminateRead = true;
314   m_Fields.push_back(mF);
315 }
316 
317 
318 
319 bool MetaFEMObject::
M_Read()320 M_Read()
321 {
322   if(META_DEBUG)
323     {
324     std::cout << "MetaFEMObject: M_Read: Loading Header" << std::endl;
325     }
326 
327   if(!MetaObject::M_Read())
328     {
329     std::cout << "MetaFEMObject: M_Read: Error parsing file" << std::endl;
330     return false;
331     }
332 
333   if(META_DEBUG)
334     {
335     std::cout << "MetaFEMObject: M_Read: Parsing Header" << std::endl;
336     }
337 
338   // currently reader handles only ASCII data
339   if(m_BinaryData)
340     {
341     std::cout << "MetaFEMObject: M_Read: Data content should be in ASCII format" << std::endl;
342     return false;
343     }
344 
345   // we read 1)node, 2) material, 3) element and 4) load  and the input should be in the afore
346   // mentioned order.
347 
348   int segment_read = 0; // to keep track of what is being read. corresponds to enumerated types in the header file
349   /* then we start reading objects from stream */
350   do
351     {
352     // local variables
353     std::streampos          l(0);
354     char                    buf[256];
355     std::string             s;
356     std::string::size_type  b, e;
357     bool                     clID;
358     std::string             errorMessage;
359 
360     if(segment_read > 3)
361       {
362       this->SkipWhiteSpace();
363       return true; // end of FEM segment in spatial object reader.
364       }
365 
366     l = this->m_ReadStream->tellg();     // remember the stream position
367     this->SkipWhiteSpace();              // skip comments and whitespaces
368     if ( this->m_ReadStream->eof() )
369       {
370       return 0;              // end of stream. all was good
371       }
372     char c;
373     if ( ( c = static_cast<char>(this->m_ReadStream->get()) ) != '<' )
374       {
375       std::string rest;
376       std::getline(*this->m_ReadStream, rest);
377       errorMessage = "Expected < token not found. Instead found '";
378       errorMessage += c;
379       errorMessage += "'.\nRest of line is '";
380       errorMessage += rest;
381       errorMessage += "'.\n";
382       std::cout << errorMessage << std::endl;
383       return false;  // the file is not in proper format
384       }
385     this->m_ReadStream->getline(buf, 256, '>');  // read up to 256 characters until '>' is reached.
386     // we read and discard the '>'
387     s = std::string(buf);
388 
389     // get rid of the whitespaces in front of and the back of token
390     b = s.find_first_not_of(MetaFEMObject::whitespaces);                               // end of
391     // whitespaces
392     // in the
393     // beginning
394     if ( ( e = s.find_first_of(MetaFEMObject::whitespaces, b) ) == std::string::npos ) //
395       // beginning
396       // of
397       // whitespaces
398       // at the
399       // end
400       {
401       e = s.size();
402       }
403     s = s.substr(b, e - b);
404 
405     if ( s == "END" )
406       {
407       /*
408        * We can ignore this token. Start again by reading the next object.
409        */
410       segment_read++;
411       }
412     else
413       {
414       clID = this->IsClassNamePresent(s);  // obtain the class ID from FEMObjectFactory
415       if ( !clID)
416         {
417         errorMessage = s;
418         errorMessage += "   is not a valid FEM data type";
419         errorMessage += "'.";
420         std::cout << errorMessage << std::endl;
421         return false;  // class not found
422         }
423       /*
424        * Now we have to read additional data, which is
425        * specific to the class of object we just created
426        */
427 
428       switch ( segment_read )
429         {
430         case NODE :
431           this->M_Read_Node();
432           break;
433         case MATERIAL :
434           this->M_Read_Material(s);
435           break;
436         case ELEMENT :
437           this->M_Read_Element(s);
438           break;
439         case LOAD :
440           this->M_Read_Load(s);
441           break;
442         }
443       }
444     }while(segment_read <= 3); // end of FEM segment in spatial object reader.
445   return true;
446 }
447 
448 bool MetaFEMObject::
M_Write()449 M_Write()
450 {
451   if(!MetaObject::M_Write())
452     {
453     std::cout << "MetaFEMObject: M_Write: Error parsing file" << std::endl;
454     return false;
455     }
456 
457   NodeListType::iterator it_Node = m_NodeList.begin();
458   while(it_Node != m_NodeList.end())
459     {
460     FEMObjectNode* Node = *it_Node;
461     this->M_Write_Node(Node);
462     ++it_Node;
463     }
464   *this->m_WriteStream << "\n<END>  % End of nodes\n\n";
465 
466   MaterialListType::iterator it_Material = m_MaterialList.begin();
467   while(it_Material != m_MaterialList.end())
468     {
469     FEMObjectMaterial* Material = *it_Material;
470     this->M_Write_Material(Material);
471     ++it_Material;
472     }
473   *this->m_WriteStream << "\n<END>  % End of material definition\n\n";
474 
475 
476   ElementListType::iterator it_Element = m_ElementList.begin();
477   while(it_Element != m_ElementList.end())
478     {
479     FEMObjectElement* Element = *it_Element;
480     this->M_Write_Element(Element);
481     ++it_Element;
482     }
483   *this->m_WriteStream << "\n<END>  % End of element definition\n\n";
484 
485   LoadListType::iterator it_Load = m_LoadList.begin();
486   while(it_Load != m_LoadList.end())
487     {
488     FEMObjectLoad* Load = *it_Load;
489     this->M_Write_Load(Load);
490     ++it_Load;
491     }
492   *this->m_WriteStream << "\n<END>  % End of load definition\n\n";
493 
494   return true;
495 }
496 
M_Write_Node(FEMObjectNode * Node)497 void MetaFEMObject::M_Write_Node(FEMObjectNode *Node)
498 {
499   // first write the class name
500   *this->m_WriteStream << '<' << "Node" << ">\n";
501 
502   // then the global object number
503   *this->m_WriteStream << "\t" << Node->m_GN << "\t% Global object number\n";
504 
505   /* write co-ordinate values */
506   *this->m_WriteStream << "\t" << Node->m_Dim;
507   for (unsigned int i=0; i<Node->m_Dim; i++)
508     {
509     *this->m_WriteStream << " " << Node->m_X[i];
510     }
511   *this->m_WriteStream << "\t% Node coordinates" << "\n";
512 }
513 
M_Write_Material(FEMObjectMaterial * Material)514 void MetaFEMObject::M_Write_Material(FEMObjectMaterial *Material)
515 {
516   if(std::string(Material->m_MaterialName) == "MaterialLinearElasticity")
517     {
518     *this->m_WriteStream << '<' << "MaterialLinearElasticity" << ">\n";
519     *this->m_WriteStream << "\t" << Material->m_GN << "\t% Global object number\n";
520     *this->m_WriteStream << "\tE  : " << Material->E << "\t% Young modulus\n";
521     *this->m_WriteStream << "\tA  : " << Material->A << "\t% Beam crossection area\n";
522     *this->m_WriteStream << "\tI  : " << Material->I << "\t% Moment of inertia\n";
523     *this->m_WriteStream << "\tnu : " << Material->nu << "\t% Poisson's ratio\n";
524     *this->m_WriteStream << "\th : " << Material->h << "\t% Plate thickness\n";
525     *this->m_WriteStream << "\tRhoC : " << Material->RhoC << "\t% Density times capacity\n";
526     *this->m_WriteStream << "\tEND:\t% End of material definition\n";
527     }
528 }
529 
M_Write_Element(FEMObjectElement * Element)530 void MetaFEMObject::M_Write_Element(FEMObjectElement *Element)
531 {
532   *this->m_WriteStream << '<' << Element->m_ElementName << ">\n";
533   *this->m_WriteStream << "\t" << Element->m_GN << "\t% Global object number\n";
534   unsigned int numNodes = Element->m_NumNodes;
535   for ( unsigned int p = 0; p < numNodes; p++ )
536     {
537     *this->m_WriteStream << "\t" << Element->m_NodesId[p] << "\t% Node #" << ( p + 1 ) << " ID\n";
538     }
539   *this->m_WriteStream << "\t" << Element->m_MaterialGN << "\t% Material ID\n";
540 }
541 
M_Write_Load(FEMObjectLoad * Load)542 void MetaFEMObject::M_Write_Load(FEMObjectLoad *Load)
543 {
544   *this->m_WriteStream << '<' << Load->m_LoadName << ">\n";
545   *this->m_WriteStream << "\t" << Load->m_GN << "\t% Global object number\n";
546 
547   // write according to the load type
548   if(std::string(Load->m_LoadName) == "LoadBC")
549     {
550     *this->m_WriteStream << "\t" << Load->m_ElementGN << "\t% GN of element" << "\n";
551     *this->m_WriteStream << "\t" << Load->m_DOF << "\t% DOF# in element" << "\n";
552     *this->m_WriteStream << "\t" << Load->m_NumRHS;
553     for (int i=0; i<Load->m_NumRHS; i++)
554       {
555       *this->m_WriteStream << " " << Load->m_RHS[i];
556       }
557     *this->m_WriteStream << "\t% value of the fixed DOF" << "\n";
558     return;
559     }
560 
561   if(std::string(Load->m_LoadName) == "LoadNode")
562     {
563     *this->m_WriteStream << "\t" << Load->m_ElementGN << "\t% GN of element" << "\n";
564     *this->m_WriteStream << "\t" << Load->m_NodeNumber << " " << "\t% Point number within the element\n";
565     *this->m_WriteStream << "\t" << Load->m_Dim;
566     for (int i=0; i<Load->m_Dim; i++)
567       {
568       *this->m_WriteStream << " " << Load->m_ForceVector[i];
569       }
570     *this->m_WriteStream << "\t% Force vector (first number is the size of a vector)\n";
571     return;
572     }
573 
574   if(std::string(Load->m_LoadName) == "LoadBCMFC")
575     {
576     /** write the number of DOFs affected by this MFC */
577     *this->m_WriteStream << "\t" <<  Load->m_NumLHS << "\t% Number of DOFs in this MFC" << std::endl;
578 
579     /** write each term */
580     *this->m_WriteStream << "\t  %==>\n";
581     for ( int i=0; i<Load->m_NumLHS; i++ )
582       {
583       FEMObjectMFCTerm *mfcTerm = dynamic_cast< FEMObjectMFCTerm * > (&*Load->m_LHS[i]);
584       *this->m_WriteStream << "\t  " <<mfcTerm->m_ElementGN << "\t% GN of element" << std::endl;
585       *this->m_WriteStream << "\t  " << mfcTerm->m_DOF << "\t% DOF# in element" << std::endl;
586       *this->m_WriteStream << "\t  " << mfcTerm->m_Value << "\t% weight" << std::endl;
587       *this->m_WriteStream << "\t  %==>\n";
588       }
589 
590     /** write the rhs */
591     *this->m_WriteStream << "\t" << Load->m_NumRHS;
592     for ( int i=0; i<Load->m_NumRHS; i++ )
593       {
594       *this->m_WriteStream << " "  << Load->m_RHS[i];
595       }
596     *this->m_WriteStream << "\t% rhs of MFC" << std::endl;
597     return;
598     }
599 
600   if(std::string(Load->m_LoadName) == "LoadEdge")
601     {
602     *this->m_WriteStream << "\t" << Load->m_ElementGN << "\t% GN of the element on which the load acts" << "\n";
603     /** ... edge number */
604     *this->m_WriteStream << "\t" << Load->m_EdgeNumber << "\t% Edge number" << "\n";
605 
606     /** ... force matrix */
607     size_t numRows = Load->m_ForceMatrix.size();
608     size_t numCols = Load->m_ForceMatrix[0].size();
609 
610     *this->m_WriteStream << "\t" << numRows << "\t% # rows in force matrix" << "\n";
611     *this->m_WriteStream << "\t" << numCols << "\t% # cols in force matrix" << "\n";
612     *this->m_WriteStream << "\t% force matrix\n";
613     for ( size_t i = 0; i < numRows; i++ )
614       {
615       *this->m_WriteStream << "\t";
616       std::vector<float> F = Load->m_ForceMatrix[i];
617       for ( size_t j = 0; j < numCols; j++ )
618         {
619         *this->m_WriteStream << F[j] << " ";
620         }
621       *this->m_WriteStream << "\n";
622       }
623     return;
624     }
625 
626   if(std::string(Load->m_LoadName) == "LoadGravConst")
627     {
628     /** Write the list of element global numbers */
629     if ( Load->m_NumElements > 0 )
630       {
631       *this->m_WriteStream << "\t" << Load->m_NumElements;
632       *this->m_WriteStream << "\t% # of elements on which the load acts" << std::endl;
633       *this->m_WriteStream << "\t";
634       for ( int i = 0; i < Load->m_NumElements; i++ )
635         {
636         *this->m_WriteStream << Load->m_Elements[i] << " ";
637         }
638       *this->m_WriteStream << "\t% GNs of elements" << std::endl;
639       }
640     else
641       {
642       *this->m_WriteStream << "\t-1\t% Load acts on all elements" << std::endl;
643       }
644     /** then write the actual data force vector */
645     *this->m_WriteStream << "\t" << Load->m_Dim << "\t% Size of the gravity force vector\n";
646     for (int i=0; i<Load->m_Dim; i++)
647       {
648       *this->m_WriteStream << "\t" << Load->m_ForceVector[i] ;
649       }
650     *this->m_WriteStream << "\t% Gravity force vector\n";
651     }
652 
653   if(std::string(Load->m_LoadName) == "LoadLandmark")
654     {
655     // print undeformed coordinates
656     size_t dim = Load->m_Undeformed.size();
657 
658     *this->m_WriteStream << "\t" << dim;
659     for ( size_t i = 0; i < dim; i++ )
660       {
661       *this->m_WriteStream << Load->m_Undeformed[i] << " ";
662       }
663     *this->m_WriteStream << "\t % Dimension , undeformed state local coordinates";
664     *this->m_WriteStream << "\n";
665 
666     // print deformed coordinates
667     *this->m_WriteStream << "\t" << dim;
668     for ( size_t i = 0; i < dim; i++ )
669       {
670       *this->m_WriteStream << Load->m_Deformed[i] << " ";
671       }
672     *this->m_WriteStream << "\t % Dimension , deformed state local coordinates";
673     *this->m_WriteStream << "\n";
674 
675     // print square root of Variance
676     *this->m_WriteStream << Load->m_Variance;
677     *this->m_WriteStream << "\t % Square root of the landmark variance ";
678     *this->m_WriteStream << "\n";
679     return;
680     }
681 }
682 
683 void
SkipWhiteSpace()684 MetaFEMObject::SkipWhiteSpace()
685 {
686   std::string skip;
687 
688   while ( this->m_ReadStream && !this->m_ReadStream->eof() && ( std::ws(*this->m_ReadStream).peek() ) == '%' )
689     {
690     std::getline(*this->m_ReadStream, skip);
691     }
692 }
693 
IsClassNamePresent(std::string c_string)694 bool MetaFEMObject::IsClassNamePresent(std::string c_string)
695 {
696   ClassNameListType::const_iterator it = this->m_ClassNameList.begin();
697   while(it != this->m_ClassNameList.end())
698     {
699     if((*it) == c_string)
700       return true;
701     ++it;
702     }
703   return false;
704 }
705 
M_Read_Node()706 bool MetaFEMObject::M_Read_Node()
707 {
708   unsigned int n;
709   float coor[3];
710   /**
711    * First call the parent's read function
712    */
713   int GN = this->ReadGlobalNumber();
714 
715   if(GN == -1)
716     {
717     std::cout << "Error reading Global Number" << std::endl;
718     return false;
719     }
720   /*
721    * Read and set node coordinates
722    */
723   // read dimensions
724   this->SkipWhiteSpace(); *this->m_ReadStream >> n;
725   if ( !this->m_ReadStream)
726     {
727     std::cout << "Error reading Node dimensions" << std::endl;
728     return false;
729     }
730   FEMObjectNode *node = new FEMObjectNode(n);
731   node->m_GN = GN;
732 
733   this->SkipWhiteSpace();
734   for (unsigned int i = 0; i< n; i++)
735     {
736     *this->m_ReadStream >> coor[i];
737     if ( !this->m_ReadStream )
738       {
739       std::cout << "Error reading Node coordinates" << std::endl;
740       return false;
741       }
742     node->m_X[i] = coor[i];
743     }
744   this->m_NodeList.push_back(node);
745 
746   return true;
747 }
748 
M_Read_Material(std::string material_name)749 bool MetaFEMObject::M_Read_Material(std::string material_name)
750 {
751   /**
752    * First call the parent's read function
753    */
754   int GN = this->ReadGlobalNumber();
755 
756   if(GN == -1)
757     {
758     std::cout << "Error reading Global Number" << std::endl;
759     return false;
760     }
761   /*
762    * Read material properties
763    */
764   double d;
765 
766   std::streampos         l(0);
767   char                   buf[256];
768   std::string            s;
769   std::string::size_type b, e;
770 
771   // clear the data already inside the object
772   double E = 0.0; double A = 0.0; double I = 0.0;
773   double nu = 0.0; double h = 1.0; double RhoC = 1.0;
774 
775   /*
776    * Next we read any known constant from stream. This allows a user to
777    * specify only constants which are actually required by elements in
778    * a system. This makes creating input files a bit easier.
779    */
780   while ( this->m_ReadStream )
781     {
782     l = this->m_ReadStream->tellg();            // remember the stream position
783     this->SkipWhiteSpace();  // skip comments and whitespaces
784 
785     /**
786      * All Constants are in the following format:
787      *    constant_name : value
788      */
789     this->m_ReadStream->getline(buf, 256, ':');  // read up to 256 characters until ':' is
790                                                  // reached. we read and discard the ':'
791     if ( !this->m_ReadStream )
792       {
793       std::cout << "Error reading Material properties" << std::endl;
794       return false;
795       }    // no : was found
796     s = std::string(buf);
797 
798     // Get rid of the whitespaces in front of and the back of token
799     b = s.find_first_not_of(whitespaces);                               // end
800                                                                         // of
801                                                                         // whitespaces
802                                                                         // in
803                                                                         // the
804                                                                         // beginning
805     if ( ( e = s.find_first_of(whitespaces, b) ) == std::string::npos ) //
806                                                                         // beginning
807                                                                         // of
808                                                                         // whitespaces
809                                                                         // at
810                                                                         // the
811                                                                         // end
812       {
813       e = s.size();
814       }
815 
816     /*
817      * s now contains just the name of the constant.
818      * The value is ready to be read next from the stream
819      */
820     s = s.substr(b, e - b);
821 
822     if ( s == "E" )
823       {
824       *this->m_ReadStream >> d;
825       if ( !this->m_ReadStream )
826         {
827         std::cout << "Error reading Material E property" << std::endl;
828         return false;
829         }
830       E = d;
831       continue;
832       }
833 
834     if ( s == "A" )
835       {
836       *this->m_ReadStream >> d;
837       if ( !this->m_ReadStream )
838         {
839         std::cout << "Error reading Material A property" << std::endl;
840         return false;
841         }
842       A = d;
843       continue;
844       }
845 
846     if ( s == "I" )
847       {
848       this->SkipWhiteSpace();
849       *this->m_ReadStream >> d;
850       if ( !this->m_ReadStream )
851         {
852         std::cout << "Error reading Material I property" << std::endl;
853         return false;
854         }
855       I = d;
856       continue;
857       }
858 
859     if ( s == "nu" )
860       {
861       this->SkipWhiteSpace();
862       *this->m_ReadStream >> d;
863       if ( !this->m_ReadStream )
864         {
865         std::cout << "Error reading Material nu property" << std::endl;
866         return false;
867         }
868       nu = d;
869       continue;
870       }
871 
872     if ( s == "h" )
873       {
874       this->SkipWhiteSpace();
875       *this->m_ReadStream >> d;
876       if ( !this->m_ReadStream )
877         {
878         std::cout << "Error reading Material h property" << std::endl;
879         return false;
880         }
881       h = d;
882       continue;
883       }
884 
885     if ( s == "RhoC" )
886       {
887       this->SkipWhiteSpace();
888       *this->m_ReadStream >> d;
889       if ( !this->m_ReadStream )
890         {
891         std::cout << "Error reading Material RhoC property" << std::endl;
892         return false;
893         }
894       RhoC = d;
895       continue;
896       }
897     if ( s == "END" )
898       {
899       // End of constants in material definition
900       // store all the material definitions
901       FEMObjectMaterial *material = new FEMObjectMaterial();
902       strcpy(material->m_MaterialName, material_name.c_str());
903       material->m_GN = GN;
904       material->E = E;
905       material->A = A;
906       material->I = I;
907       material->nu = nu;
908       material->h = h;
909       material->RhoC = RhoC;
910       this->m_MaterialList.push_back(material);
911       break;
912       }
913 
914     /**
915      * If we got here an unknown constant was reached.
916      * We reset the stream position and set the stream error.
917      */
918     this->m_ReadStream->seekg(l);
919     this->m_ReadStream->clear(std::ios::failbit);
920     }
921 
922   if ( !this->m_ReadStream )
923     {
924     std::cout << "Error reading Material properties" << std::endl;
925     return false;
926     }
927   return true;
928 }
929 
M_Read_Element(std::string element_name)930 bool MetaFEMObject::M_Read_Element(std::string element_name)
931 {
932   unsigned int n, materialGN;
933   int info[2];
934   if(this->GetElementDimensionAndNumberOfNodes(element_name, info) == nullptr)
935     {
936     std::cout << "Invalid element_name" << std::endl;
937     return false;
938     }
939 
940   int GN = this->ReadGlobalNumber();
941 
942   if(GN == -1)
943     {
944     std::cout << "Error reading Global Number" << std::endl;
945     return false;
946     }
947   /*
948    * Read and set element connectivity
949    */
950   int *NodesId = new int[info[0]];
951   for ( int p = 0; p < info[0]; p++ )
952     {
953     this->SkipWhiteSpace(); *this->m_ReadStream >> n;
954     if ( !this->m_ReadStream )
955       {
956       delete [] NodesId;
957       std::cout << "Error reading Element node numbers" << std::endl;
958       return false;
959       }
960     NodesId[p] = n;
961     }
962 
963   // read material associated with the element
964   this->SkipWhiteSpace(); *this->m_ReadStream >> materialGN;
965   if ( !this->m_ReadStream )
966     {
967     delete [] NodesId;
968     std::cout << "Error reading Element global number" << std::endl;
969     return false;
970     }
971   // store the read information
972   FEMObjectElement *element = new FEMObjectElement(info[0]);
973   element->m_GN = GN;
974   for ( int p = 0; p < info[0]; p++ )
975     {
976     element->m_NodesId[p] = NodesId[p];
977     }
978   element->m_MaterialGN = materialGN;
979   element->m_NumNodes = info[0];
980   element->m_Dim = info[1];
981   strcpy(element->m_ElementName, element_name.c_str());
982 
983   delete [] NodesId;
984   this->m_ElementList.push_back(element);
985   return true;
986 }
987 
M_Read_Load(std::string load_name)988 bool MetaFEMObject::M_Read_Load(std::string load_name)
989 {
990   int GN;
991   int elementGN;
992   int DOF;
993   int NumRHS;
994   int NodeNumber;
995   int Dim;
996   int NumLHS;
997   int Value;
998 
999   FEMObjectLoad *load = new FEMObjectLoad;
1000   strcpy(load->m_LoadName, load_name.c_str());
1001 
1002   GN = this->ReadGlobalNumber();
1003   if (GN == -1)
1004     {
1005     delete load;
1006     std::cout << "Error reading Load definition - global number" << std::endl;
1007     return false;
1008     }
1009 
1010   load->m_GN = GN;
1011 
1012   if(load_name == "LoadBC")
1013     {
1014     /* read and set pointer to element that we're applying the load to */
1015     this->SkipWhiteSpace();
1016     *this->m_ReadStream >> elementGN;
1017     if(!this->m_ReadStream)
1018       {
1019       delete load;
1020       std::cout << "Error reading Load definition - Element Global Number" << std::endl;
1021       return false;
1022       }
1023     load->m_ElementGN = elementGN;
1024 
1025     /* read the local DOF number within that element */
1026     this->SkipWhiteSpace();
1027     *this->m_ReadStream >> DOF;
1028     if(!this->m_ReadStream)
1029       {
1030       delete load;
1031       std::cout << "Error reading Load definition - Degrees of Freedom" << std::endl;
1032       return false;
1033       }
1034     load->m_DOF = DOF;
1035 
1036     /* read the value to which the DOF is fixed */
1037     this->SkipWhiteSpace();
1038     *this->m_ReadStream >> NumRHS;
1039     if(!this->m_ReadStream)
1040       {
1041       delete load;
1042       std::cout << "Error reading Load definition - Number of fixed degrees of freedom" << std::endl;
1043       return false;
1044       }
1045     load->m_NumRHS = NumRHS;
1046     load->m_RHS.resize(NumRHS);
1047 
1048     for (int i=0; i<NumRHS; i++)
1049       {
1050       this->SkipWhiteSpace();
1051       *this->m_ReadStream >> load->m_RHS[i];
1052       if(!this->m_ReadStream)
1053         {
1054         delete load;
1055         std::cout << "Error reading Load definition - Fixed degree of freedom" << std::endl;
1056         return false;
1057         }
1058       }
1059     }
1060   else if(load_name == "LoadNode")
1061     {
1062     /* read and set pointer to element that we're applying the load to */
1063     this->SkipWhiteSpace();
1064     *this->m_ReadStream >> elementGN;
1065     if(!this->m_ReadStream)
1066       {
1067       delete load;
1068       std::cout << "Error reading LoadNode definition - Element Global Number" << std::endl;
1069       return false;
1070       }
1071     load->m_ElementGN = elementGN;
1072 
1073     /* read the value to which the DOF is fixed */
1074     this->SkipWhiteSpace();
1075     *this->m_ReadStream >> NodeNumber;
1076     if(!this->m_ReadStream)
1077       {
1078       delete load;
1079       std::cout << "Error reading LoadNode definition - Node Number" << std::endl;
1080       return false;
1081       }
1082     load->m_NodeNumber = NodeNumber;
1083 
1084     this->SkipWhiteSpace();
1085     *this->m_ReadStream >> Dim;
1086     if(!this->m_ReadStream)
1087       {
1088       delete load;
1089       std::cout << "Error reading LoadNode definition - Dimension" << std::endl;
1090       return false;
1091       }
1092     load->m_Dim = Dim;
1093 
1094     load->m_ForceVector.resize(Dim);
1095     for (int i=0; i<Dim; i++)
1096       {
1097       this->SkipWhiteSpace();
1098       *this->m_ReadStream >> load->m_ForceVector[i];
1099       if(!this->m_ReadStream)
1100         {
1101         delete load;
1102         std::cout << "Error reading LoadNode definition - Force Vector" << std::endl;
1103         return false;
1104         }
1105       }
1106     }
1107   else if(load_name == "LoadBCMFC")
1108     {
1109     /** read number of terms in lhs of MFC equation */
1110     this->SkipWhiteSpace();
1111     *this->m_ReadStream >> NumLHS;
1112     if(!this->m_ReadStream)
1113       {
1114       delete load;
1115       std::cout << "Error reading LoadBCMFC definition - Number of LHS terms" << std::endl;
1116       return false;
1117       }
1118 
1119     load->m_NumLHS = NumLHS;
1120     for ( int i = 0; i < NumLHS; i++ )
1121       {
1122       /** read and set pointer to element that we're applying the load to */
1123       this->SkipWhiteSpace();
1124       *this->m_ReadStream >> elementGN;
1125       if(!this->m_ReadStream)
1126         {
1127         delete load;
1128         std::cout << "Error reading LoadBCMFC definition - Element Global Number" << std::endl;
1129         return false;
1130         }
1131 
1132       /** read the number of dof within that element */
1133       this->SkipWhiteSpace();
1134       *this->m_ReadStream >> DOF;
1135       if(!this->m_ReadStream)
1136         {
1137         delete load;
1138         std::cout << "Error reading LoadBCMFC definition - Element Degree of Freedom" << std::endl;
1139         return false;
1140         }
1141 
1142       /** read weight */
1143       this->SkipWhiteSpace();
1144       *this->m_ReadStream >> Value;
1145       if(!this->m_ReadStream)
1146         {
1147         delete load;
1148         std::cout << "Error reading LoadBCMFC definition - Weight" << std::endl;
1149         return false;
1150         }
1151 
1152       /** add a new MFCTerm to the lhs */
1153       FEMObjectMFCTerm *mfcTerm = new FEMObjectMFCTerm(elementGN, DOF, static_cast<float>(Value));
1154       load->m_LHS.push_back(mfcTerm);
1155       }
1156 
1157     /** read the rhs */
1158     this->SkipWhiteSpace();
1159     *this->m_ReadStream >> NumRHS;
1160     if (!this->m_ReadStream)
1161       {
1162       delete load;
1163       std::cout << "Error reading LoadBCMFC definition - Number of RHS terms" << std::endl;
1164       return false;
1165       }
1166 
1167     load->m_NumRHS = NumRHS;
1168     load->m_RHS.resize(NumRHS);
1169     for (int i=0; i<NumRHS; i++)
1170       {
1171       this->SkipWhiteSpace();
1172       *this->m_ReadStream >> load->m_RHS[i];
1173       if(!this->m_ReadStream)
1174         {
1175         delete load;
1176         std::cout << "Error reading LoadBCMFC definition - RHS Term" << std::endl;
1177         return false;
1178         }
1179       }
1180     }
1181   else if(load_name == "LoadEdge")
1182     {
1183     int edgeNum, numRows, numCols;
1184 
1185     /* read the global number of the element on which the load acts */
1186     this->SkipWhiteSpace();
1187     *this->m_ReadStream >> elementGN;
1188     if (!this->m_ReadStream)
1189       {
1190       delete load;
1191       std::cout << "Error reading LoadEdge definition - Element Global Number" << std::endl;
1192       return false;
1193       }
1194     load->m_ElementGN = elementGN;
1195 
1196     /** ... edge number */
1197     this->SkipWhiteSpace();
1198     *this->m_ReadStream >> edgeNum;
1199     if (!this->m_ReadStream)
1200       {
1201       delete load;
1202       std::cout << "Error reading LoadEdge definition - Edge Number" << std::endl;
1203       return false;
1204       }
1205     load->m_EdgeNumber = edgeNum;
1206 
1207     /** ... # of rows */
1208     this->SkipWhiteSpace();
1209     *this->m_ReadStream >> numRows;
1210     if (!this->m_ReadStream)
1211       {
1212       delete load;
1213       std::cout << "Error reading LoadEdge definition - Number of Rows" << std::endl;
1214       return false;
1215       }
1216 
1217     /** ... # of cols */
1218     this->SkipWhiteSpace();
1219     *this->m_ReadStream >> numCols;
1220     if (!this->m_ReadStream)
1221       {
1222       delete load;
1223       std::cout << "Error reading LoadEdge definition - Number of Columns" << std::endl;
1224       return false;
1225       }
1226 
1227     for ( int i = 0; i < numRows; i++ )
1228       {
1229       this->SkipWhiteSpace();
1230       std::vector<float> F(numCols);
1231       for ( int j = 0; j < numCols; j++ )
1232         {
1233         *this->m_ReadStream >> F[j];
1234         if (!this->m_ReadStream)
1235           {
1236           delete load;
1237           std::cout << "Error reading LoadEdge definition - Force Matrix" << std::endl;
1238           return false;
1239           }
1240         }
1241       this->SkipWhiteSpace();
1242       load->m_ForceMatrix.push_back(F);
1243       }
1244     }
1245   else if(load_name == "LoadGravConst")
1246     {
1247     // read in the list of elements on which the load acts
1248     this->SkipWhiteSpace();
1249     *this->m_ReadStream >> load->m_NumElements ;
1250     if (!this->m_ReadStream)
1251       {
1252       delete load;
1253       std::cout << "Error reading LoadGravConst definition - Number of Elements" << std::endl;
1254       return false;
1255       }
1256 
1257     for (int i=0; i<load->m_NumElements; i++)
1258       {
1259       this->SkipWhiteSpace();
1260       *this->m_ReadStream >> elementGN ;
1261       if (!this->m_ReadStream)
1262         {
1263         delete load;
1264         std::cout << "Error reading LoadGravConst definition - Element Global Number" << std::endl;
1265         return false;
1266         }
1267       load->m_Elements.push_back(elementGN);
1268       }
1269 
1270     /** first read and set the size of the vector */
1271     this->SkipWhiteSpace();
1272     *this->m_ReadStream >> load->m_Dim;
1273     if (!this->m_ReadStream)
1274       {
1275       delete load;
1276       std::cout << "Error reading LoadGravConst definition - Dimension" << std::endl;
1277       return false;
1278       }
1279 
1280     float loadcomp;
1281     /** then the actual values */
1282     for (int i=0; i<load->m_Dim; i++)
1283       {
1284       this->SkipWhiteSpace();
1285       *this->m_ReadStream >> loadcomp;
1286       if (!this->m_ReadStream)
1287         {
1288         delete load;
1289         std::cout << "Error reading LoadGravConst definition - Force Vector" << std::endl;
1290         return false;
1291         }
1292       load->m_ForceVector.push_back(loadcomp);
1293       }
1294     }
1295   else if(load_name == "LoadLandmark")
1296     {
1297     this->SkipWhiteSpace();
1298     int n1, n2;
1299 
1300     // read the dimensions of the undeformed point and set the size of the point
1301     // accordingly
1302     this->SkipWhiteSpace();
1303     *this->m_ReadStream >> n1; if ( !this->m_ReadStream ) { return false; }
1304     load->m_Undeformed.resize(n1);
1305     for (int i=0; i<n1; i++)
1306       {
1307       this->SkipWhiteSpace();
1308       *this->m_ReadStream >> load->m_Undeformed[i];
1309       std::cout << "  " << load->m_Undeformed[i] << std::endl;
1310       if(!this->m_ReadStream)
1311         {
1312         delete load;
1313         std::cout << "Error reading Loadlandmark definition - Undeformed point" << std::endl;
1314         return false;
1315         }
1316       }
1317 
1318     // Read the dimensions of the deformed point and set the size of the point
1319     // accordingly
1320     this->SkipWhiteSpace();
1321     *this->m_ReadStream >> n2; if ( !this->m_ReadStream ) { return false; }
1322     load->m_Deformed.resize(n2);
1323     for (int i=0; i<n2; i++)
1324       {
1325       this->SkipWhiteSpace();
1326       *this->m_ReadStream >> load->m_Deformed[i];
1327       std::cout << "  " << load->m_Deformed[i] << std::endl;
1328       if(!this->m_ReadStream)
1329         {
1330         delete load;
1331         std::cout << "Error reading Loadlandmark definition - Undeformed point" << std::endl;
1332         return false;
1333         }
1334       }
1335 
1336     // Verify that the undeformed and deformed points are of the same size.
1337     if ( n1 != n2 )
1338       {
1339       delete load;
1340       std::cout << "Error reading Loadlandmark definition - Undeformed point and deformed point should have same dimension" << std::endl;
1341       return false;
1342       }
1343     // read the square root of the m_Variance associated with this landmark
1344     this->SkipWhiteSpace();
1345     *this->m_ReadStream >> load->m_Variance;
1346     }
1347   if(!this->m_ReadStream)
1348     {
1349     delete load;
1350     std::cout << "Error reading Load definition" << std::endl;
1351     return false;
1352     }
1353   this->m_LoadList.push_back(load);
1354   return true;
1355 }
1356 
GetElementDimensionAndNumberOfNodes(std::string c_string,int info[2])1357 int* MetaFEMObject::GetElementDimensionAndNumberOfNodes(std::string c_string, int info[2])
1358 {
1359   if((c_string == "Element2DC0LinearLineStress") ||
1360      (c_string == "Element2DC1Beam"))
1361     {
1362     info[0] = 2;
1363     info[1] = 2;
1364     }
1365 
1366   else if((c_string == "Element2DC0LinearTriangularMembrane") ||
1367           (c_string == "Element2DC0LinearTriangularStrain") ||
1368           (c_string == "Element2DC0LinearTriangularStress"))
1369     {
1370     info[0] = 3;
1371     info[1] = 2;
1372     }
1373 
1374   else if((c_string == "Element2DC0LinearQuadrilateralMembrane") ||
1375           (c_string == "Element2DC0LinearQuadrilateralStrain") ||
1376           (c_string == "Element2DC0LinearQuadrilateralStress"))
1377     {
1378     info[0] = 4;
1379     info[1] = 2;
1380     }
1381 
1382 
1383   else if((c_string == "Element2DC0QuadraticTriangularStrain") ||
1384           (c_string == "Element2DC0QuadraticTriangularStress"))
1385     {
1386     info[0] = 6;
1387     info[1] = 2;
1388     }
1389 
1390   else if((c_string == "Element3DC0LinearHexahedronMembrane") ||
1391           (c_string == "Element3DC0LinearHexahedronStrain"))
1392     {
1393     info[0] = 8;
1394     info[1] = 3;
1395     }
1396 
1397   else if((c_string == "Element3DC0LinearTetrahedronMembrane") ||
1398           (c_string == "Element3DC0LinearTetrahedronStrain"))
1399     {
1400     info[0] = 4;
1401     info[1] = 3;
1402     }
1403 
1404   else
1405     {
1406     return nullptr;
1407     }
1408 
1409   return info;
1410 }
ReadGlobalNumber()1411 int MetaFEMObject::ReadGlobalNumber()
1412 {
1413   int n;
1414 
1415   /** Read and set the global object number */
1416   this->SkipWhiteSpace();
1417   *this->m_ReadStream >> n;
1418   if(this->m_ReadStream)
1419     return n;
1420   else
1421     return -1;
1422 }
1423 
1424 // string containing all whitespace characters
1425 const std::string
1426 MetaFEMObject
1427 :: whitespaces = " \t\n\r";
1428 
1429 #if (METAIO_USE_NAMESPACE)
1430 }
1431 #endif
1432