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