1 /*****************************************************************************/
2 /*                                    XDMF                                   */
3 /*                       eXtensible Data Model and Format                    */
4 /*                                                                           */
5 /*  Id : XdmfTemplate.cpp                                                    */
6 /*                                                                           */
7 /*  Author:                                                                  */
8 /*     Andrew Burns                                                          */
9 /*     andrew.j.burns2@us.army.mil                                           */
10 /*     US Army Research Laboratory                                           */
11 /*     Aberdeen Proving Ground, MD                                           */
12 /*                                                                           */
13 /*     Copyright @ 2013 US Army Research Laboratory                          */
14 /*     All Rights Reserved                                                   */
15 /*     See Copyright.txt for details                                         */
16 /*                                                                           */
17 /*     This software is distributed WITHOUT ANY WARRANTY; without            */
18 /*     even the implied warranty of MERCHANTABILITY or FITNESS               */
19 /*     FOR A PARTICULAR PURPOSE.  See the above copyright notice             */
20 /*     for more information.                                                 */
21 /*                                                                           */
22 /*****************************************************************************/
23 
24 #include <sstream>
25 #include <utility>
26 #include "XdmfArray.hpp"
27 #include "XdmfCurvilinearGrid.hpp"
28 #include "XdmfItem.hpp"
29 #include "XdmfItemFactory.hpp"
30 #include "XdmfReader.hpp"
31 #include "XdmfGridCollection.hpp"
32 #include "XdmfGridCollectionType.hpp"
33 #include "XdmfGridTemplate.hpp"
34 #include "XdmfRectilinearGrid.hpp"
35 #include "XdmfRegularGrid.hpp"
36 #include "XdmfTemplate.hpp"
37 #include "XdmfTopology.hpp"
38 #include "XdmfError.hpp"
39 #include "XdmfUnstructuredGrid.hpp"
40 #include "XdmfVisitor.hpp"
41 #include "XdmfWriter.hpp"
42 
43 #include "XdmfSystemUtils.hpp"
44 
45 #include <boost/tokenizer.hpp>
46 
47 #include <stdio.h>
48 
49 shared_ptr<XdmfGridTemplate>
New()50 XdmfGridTemplate::New()
51 {
52   shared_ptr<XdmfGridTemplate> p(new XdmfGridTemplate());
53   return p;
54 }
55 
56 
XdmfGridTemplate()57 XdmfGridTemplate::XdmfGridTemplate() :
58   XdmfTemplate(),
59   XdmfGridCollection(),
60   mTimeCollection(XdmfArray::New())
61 {
62   mTimeCollection->setName("Time Collection");
63 }
64 
XdmfGridTemplate(XdmfGridTemplate & refTemplate)65 XdmfGridTemplate::XdmfGridTemplate(XdmfGridTemplate & refTemplate) :
66   XdmfTemplate(refTemplate),
67   XdmfGridCollection(refTemplate),
68   mTimeCollection(refTemplate.mTimeCollection)
69 {
70 }
71 
~XdmfGridTemplate()72 XdmfGridTemplate::~XdmfGridTemplate()
73 {
74 }
75 
76 const std::string XdmfGridTemplate::ItemTag = "Template";
77 
78 unsigned int
addStep()79 XdmfGridTemplate::addStep()
80 {
81   XdmfTemplate::addStep();
82   if (shared_dynamic_cast<XdmfGrid>(mBase)->getTime()) {
83     if (!mTimeCollection->isInitialized()) {
84       mTimeCollection->read();
85     }
86     mTimeCollection->pushBack(shared_dynamic_cast<XdmfGrid>(mBase)->getTime()->getValue());
87   }
88   return mCurrentStep;
89 }
90 
91 std::map<std::string, std::string>
getItemProperties() const92 XdmfGridTemplate::getItemProperties() const
93 {
94   std::map<std::string, std::string> templateProperties = XdmfGridCollection::getItemProperties();
95 
96   templateProperties["BaseType"] = "Grid";
97   return templateProperties;
98 }
99 
100 std::string
getItemTag() const101 XdmfGridTemplate::getItemTag() const
102 {
103   return ItemTag;
104 }
105 
106 shared_ptr<XdmfArray>
getTimes()107 XdmfGridTemplate::getTimes()
108 {
109   return mTimeCollection;
110 }
111 
112 shared_ptr<XdmfGridCollection>
getGridCollection(const unsigned int index)113 XdmfGridTemplate::getGridCollection(const unsigned int index)
114 {
115   if (mBase) {
116     if (index < getNumberSteps()) {
117       this->clearStep();
118       this->setStep(index);
119       if (shared_ptr<XdmfGridCollection> grid =
120             shared_dynamic_cast<XdmfGridCollection>(mBase)) {
121         return grid;
122       }
123       else {
124         return shared_ptr<XdmfGridCollection>();
125       }
126     }
127     else {
128       return shared_ptr<XdmfGridCollection>();
129     }
130   }
131   else {
132     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get GridCollection from template without a base");
133     return shared_ptr<XdmfGridCollection>();
134   }
135 }
136 
137 shared_ptr<const XdmfGridCollection>
getGridCollection(const unsigned int index) const138 XdmfGridTemplate::getGridCollection(const unsigned int index) const
139 {
140   if (shared_ptr<XdmfGridCollection> grid =
141       shared_dynamic_cast<XdmfGridCollection>(mBase)) {
142     if (index != mCurrentStep)
143     {
144       XdmfError::message(XdmfError::FATAL, "Error: GridTemplates can not return a constant reference to its base on an index other than the currently loaded one.");
145       return shared_ptr<XdmfGridCollection>();
146     }
147     else
148     {
149       return grid;
150     }
151   }
152   else {
153     return shared_ptr<XdmfGridCollection>();
154   }
155 }
156 
157 shared_ptr<XdmfGridCollection>
getGridCollection(const std::string & Name)158 XdmfGridTemplate::getGridCollection(const std::string & Name)
159 {
160   if (mBase) {
161    if (shared_ptr<XdmfGridCollection> grid =
162           shared_dynamic_cast<XdmfGridCollection>(mBase)) {
163       if (grid->getName().compare(Name) == 0) {
164         return grid;
165       }
166       else {
167         return shared_ptr<XdmfGridCollection>();
168       }
169     }
170     else {
171       return shared_ptr<XdmfGridCollection>();
172     }
173   }
174   else {
175     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get GridCollection from template without a base");
176     return shared_ptr<XdmfGridCollection>();
177   }
178 }
179 
180 shared_ptr<const XdmfGridCollection>
getGridCollection(const std::string & Name) const181 XdmfGridTemplate::getGridCollection(const std::string & Name) const
182 {
183   if (mBase) {
184    if (shared_ptr<XdmfGridCollection> grid =
185           shared_dynamic_cast<XdmfGridCollection>(mBase)) {
186       if (grid->getName().compare(Name) == 0) {
187         return grid;
188       }
189       else {
190         return shared_ptr<XdmfGridCollection>();
191       }
192     }
193     else {
194       return shared_ptr<XdmfGridCollection>();
195     }
196   }
197   else {
198     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get GridCollection from template without a base");
199     return shared_ptr<XdmfGridCollection>();
200   }
201 }
202 
203 unsigned int
getNumberGridCollections() const204 XdmfGridTemplate::getNumberGridCollections() const
205 {
206   if (shared_ptr<XdmfGridCollection> grid =
207         shared_dynamic_cast<XdmfGridCollection>(mBase)) {
208     return this->getNumberSteps();
209   }
210   else {
211     return 0;
212   }
213 }
214 
215 void
insert(const shared_ptr<XdmfGridCollection>)216 XdmfGridTemplate::insert(const shared_ptr<XdmfGridCollection> /*GridCollection*/)
217 {
218   XdmfError::message(XdmfError::FATAL, "Error: Attempting to use insert to add an XdmfGridCollection to an XdmfGridTemplate. "
219                                        "Use addStep instead of insert to add to an XdmfGridTemplate");
220 }
221 
222 void
removeGridCollection(const unsigned int index)223 XdmfGridTemplate::removeGridCollection(const unsigned int index)
224 {
225   if (mBase) {
226     if (index < getNumberSteps()) {
227       if (shared_ptr<XdmfGridCollection> grid =
228             shared_dynamic_cast<XdmfGridCollection>(mBase)) {
229         this->removeStep(index);
230       }
231     }
232   }
233   else {
234     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get GridCollection from template without a base");
235   }
236 }
237 
238 void
removeGridCollection(const std::string &)239 XdmfGridTemplate::removeGridCollection(const std::string & /*Name*/)
240 {
241   XdmfError::message(XdmfError::FATAL, "Error: Removing Grids by name from XdmfGridTemplate is not supported");
242 }
243 
244 shared_ptr<XdmfCurvilinearGrid>
getCurvilinearGrid(const unsigned int index)245 XdmfGridTemplate::getCurvilinearGrid(const unsigned int index)
246 {
247   if (mBase) {
248     if (index < getNumberSteps()) {
249       this->clearStep();
250       this->setStep(index);
251       if (shared_ptr<XdmfCurvilinearGrid> grid =
252             shared_dynamic_cast<XdmfCurvilinearGrid>(mBase)) {
253         return grid;
254       }
255       else {
256         return shared_ptr<XdmfCurvilinearGrid>();
257       }
258     }
259     else {
260       return shared_ptr<XdmfCurvilinearGrid>();
261     }
262   }
263   else {
264     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get CurvilinearGrid from template without a base");
265     return shared_ptr<XdmfCurvilinearGrid>();
266   }
267 }
268 
269 shared_ptr<const XdmfCurvilinearGrid>
getCurvilinearGrid(const unsigned int index) const270 XdmfGridTemplate::getCurvilinearGrid(const unsigned int index) const
271 {
272   if (shared_ptr<XdmfCurvilinearGrid> grid =
273       shared_dynamic_cast<XdmfCurvilinearGrid>(mBase)) {
274     if (index != mCurrentStep)
275     {
276       XdmfError::message(XdmfError::FATAL, "Error: GridTemplates can not return a constant reference to its base on an index other than the currently loaded one.");
277       return shared_ptr<XdmfCurvilinearGrid>();
278     }
279     else
280     {
281       return grid;
282     }
283   }
284   else {
285     return shared_ptr<XdmfCurvilinearGrid>();
286   }
287 }
288 
289 shared_ptr<XdmfCurvilinearGrid>
getCurvilinearGrid(const std::string & Name)290 XdmfGridTemplate::getCurvilinearGrid(const std::string & Name)
291 {
292   if (mBase) {
293    if (shared_ptr<XdmfCurvilinearGrid> grid =
294           shared_dynamic_cast<XdmfCurvilinearGrid>(mBase)) {
295       if (grid->getName().compare(Name) == 0) {
296         return grid;
297       }
298       else {
299         return shared_ptr<XdmfCurvilinearGrid>();
300       }
301     }
302     else {
303       return shared_ptr<XdmfCurvilinearGrid>();
304     }
305   }
306   else {
307     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get CurvilinearGrid from template without a base");
308     return shared_ptr<XdmfCurvilinearGrid>();
309   }
310 }
311 
312 shared_ptr<const XdmfCurvilinearGrid>
getCurvilinearGrid(const std::string & Name) const313 XdmfGridTemplate::getCurvilinearGrid(const std::string & Name) const
314 {
315   if (mBase) {
316    if (shared_ptr<XdmfCurvilinearGrid> grid =
317           shared_dynamic_cast<XdmfCurvilinearGrid>(mBase)) {
318       if (grid->getName().compare(Name) == 0) {
319         return grid;
320       }
321       else {
322         return shared_ptr<XdmfCurvilinearGrid>();
323       }
324     }
325     else {
326       return shared_ptr<XdmfCurvilinearGrid>();
327     }
328   }
329   else {
330     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get CurvilinearGrid from template without a base");
331     return shared_ptr<XdmfCurvilinearGrid>();
332   }
333 }
334 
335 unsigned int
getNumberCurvilinearGrids() const336 XdmfGridTemplate::getNumberCurvilinearGrids() const
337 {
338   if (shared_ptr<XdmfCurvilinearGrid> grid =
339         shared_dynamic_cast<XdmfCurvilinearGrid>(mBase)) {
340     return this->getNumberSteps();
341   }
342   else {
343     return 0;
344   }
345 }
346 
347 void
insert(const shared_ptr<XdmfCurvilinearGrid>)348 XdmfGridTemplate::insert(const shared_ptr<XdmfCurvilinearGrid> /*CurvilinearGrid*/)
349 {
350   XdmfError::message(XdmfError::FATAL, "Error: Attempting to use insert to add an XdmfCurvilinearGrid to an XdmfGridTemplate. "
351                                        "Use addStep instead of insert to add to an XdmfGridTemplate");
352 }
353 
354 void
removeCurvilinearGrid(const unsigned int index)355 XdmfGridTemplate::removeCurvilinearGrid(const unsigned int index)
356 {
357   if (mBase) {
358     if (index < getNumberSteps()) {
359       if (shared_ptr<XdmfCurvilinearGrid> grid =
360             shared_dynamic_cast<XdmfCurvilinearGrid>(mBase)) {
361         this->removeStep(index);
362       }
363     }
364   }
365   else {
366     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get CurvilinearGrid from template without a base");
367   }
368 }
369 
370 void
removeCurvilinearGrid(const std::string &)371 XdmfGridTemplate::removeCurvilinearGrid(const std::string & /*Name*/)
372 {
373   XdmfError::message(XdmfError::FATAL, "Error: Removing Grids by name from XdmfGridTemplate is not supported");
374 }
375 
376 shared_ptr<XdmfRectilinearGrid>
getRectilinearGrid(const unsigned int index)377 XdmfGridTemplate::getRectilinearGrid(const unsigned int index)
378 {
379   if (mBase) {
380     if (index < getNumberSteps()) {
381       this->clearStep();
382       this->setStep(index);
383       if (shared_ptr<XdmfRectilinearGrid> grid =
384             shared_dynamic_cast<XdmfRectilinearGrid>(mBase)) {
385         return grid;
386       }
387       else {
388         return shared_ptr<XdmfRectilinearGrid>();
389       }
390     }
391     else {
392       return shared_ptr<XdmfRectilinearGrid>();
393     }
394   }
395   else {
396     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RectilinearGrid from template without a base");
397     return shared_ptr<XdmfRectilinearGrid>();
398   }
399 }
400 
401 shared_ptr<const XdmfRectilinearGrid>
getRectilinearGrid(const unsigned int index) const402 XdmfGridTemplate::getRectilinearGrid(const unsigned int index) const
403 {
404   if (shared_ptr<XdmfRectilinearGrid> grid =
405       shared_dynamic_cast<XdmfRectilinearGrid>(mBase)) {
406     if (index != mCurrentStep)
407     {
408       XdmfError::message(XdmfError::FATAL, "Error: GridTemplates can not return a constant reference to its base on an index other than the currently loaded one.");
409       return shared_ptr<XdmfRectilinearGrid>();
410     }
411     else
412     {
413       return grid;
414     }
415   }
416   else {
417     return shared_ptr<XdmfRectilinearGrid>();
418   }
419 }
420 
421 shared_ptr<XdmfRectilinearGrid>
getRectilinearGrid(const std::string & Name)422 XdmfGridTemplate::getRectilinearGrid(const std::string & Name)
423 {
424   if (mBase) {
425    if (shared_ptr<XdmfRectilinearGrid> grid =
426           shared_dynamic_cast<XdmfRectilinearGrid>(mBase)) {
427       if (grid->getName().compare(Name) == 0) {
428         return grid;
429       }
430       else {
431         return shared_ptr<XdmfRectilinearGrid>();
432       }
433     }
434     else {
435       return shared_ptr<XdmfRectilinearGrid>();
436     }
437   }
438   else {
439     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RectilinearGrid from template without a base");
440     return shared_ptr<XdmfRectilinearGrid>();
441   }
442 }
443 
444 shared_ptr<const XdmfRectilinearGrid>
getRectilinearGrid(const std::string & Name) const445 XdmfGridTemplate::getRectilinearGrid(const std::string & Name) const
446 {
447   if (mBase) {
448    if (shared_ptr<XdmfRectilinearGrid> grid =
449           shared_dynamic_cast<XdmfRectilinearGrid>(mBase)) {
450       if (grid->getName().compare(Name) == 0) {
451         return grid;
452       }
453       else {
454         return shared_ptr<XdmfRectilinearGrid>();
455       }
456     }
457     else {
458       return shared_ptr<XdmfRectilinearGrid>();
459     }
460   }
461   else {
462     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RectilinearGrid from template without a base");
463     return shared_ptr<XdmfRectilinearGrid>();
464   }
465 }
466 
467 unsigned int
getNumberRectilinearGrids() const468 XdmfGridTemplate::getNumberRectilinearGrids() const
469 {
470   if (shared_ptr<XdmfRectilinearGrid> grid =
471         shared_dynamic_cast<XdmfRectilinearGrid>(mBase)) {
472     return this->getNumberSteps();
473   }
474   else {
475     return 0;
476   }
477 }
478 
479 void
insert(const shared_ptr<XdmfRectilinearGrid>)480 XdmfGridTemplate::insert(const shared_ptr<XdmfRectilinearGrid> /*RectilinearGrid*/)
481 {
482   XdmfError::message(XdmfError::FATAL, "Error: Attempting to use insert to add a XdmfRectilinearGrid to an XdmfGridTemplate."
483                                        "Use addStep instead of insert to add to an XdmfGridTemplate");
484 }
485 
486 void
removeRectilinearGrid(const unsigned int index)487 XdmfGridTemplate::removeRectilinearGrid(const unsigned int index)
488 {
489   if (mBase) {
490     if (index < getNumberSteps()) {
491       if (shared_ptr<XdmfRectilinearGrid> grid =
492             shared_dynamic_cast<XdmfRectilinearGrid>(mBase)) {
493         this->removeStep(index);
494       }
495     }
496   }
497   else {
498     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RectilinearGrid from template without a base");
499   }
500 }
501 
502 void
removeRectilinearGrid(const std::string &)503 XdmfGridTemplate::removeRectilinearGrid(const std::string & /*Name*/)
504 {
505   XdmfError::message(XdmfError::FATAL, "Error: Removing Grids by name from XdmfGridTemplate is not supported");
506 }
507 
508 shared_ptr<XdmfRegularGrid>
getRegularGrid(const unsigned int index)509 XdmfGridTemplate::getRegularGrid(const unsigned int index)
510 {
511   if (mBase) {
512     if (index < getNumberSteps()) {
513       this->clearStep();
514       this->setStep(index);
515       if (shared_ptr<XdmfRegularGrid> grid =
516             shared_dynamic_cast<XdmfRegularGrid>(mBase)) {
517         return grid;
518       }
519       else {
520         return shared_ptr<XdmfRegularGrid>();
521       }
522     }
523     else {
524       return shared_ptr<XdmfRegularGrid>();
525     }
526   }
527   else {
528     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RegularGrid from template without a base");
529     return shared_ptr<XdmfRegularGrid>();
530   }
531 }
532 
533 shared_ptr<const XdmfRegularGrid>
getRegularGrid(const unsigned int index) const534 XdmfGridTemplate::getRegularGrid(const unsigned int index) const
535 {
536   if (shared_ptr<XdmfRegularGrid> grid =
537       shared_dynamic_cast<XdmfRegularGrid>(mBase)) {
538     if (index != mCurrentStep)
539     {
540       XdmfError::message(XdmfError::FATAL, "Error: GridTemplates can not return a constant reference to its base on an index other than the currently loaded one.");
541       return shared_ptr<XdmfRegularGrid>();
542     }
543     else
544     {
545       return grid;
546     }
547   }
548   else {
549     return shared_ptr<XdmfRegularGrid>();
550   }
551 }
552 
553 shared_ptr<XdmfRegularGrid>
getRegularGrid(const std::string & Name)554 XdmfGridTemplate::getRegularGrid(const std::string & Name)
555 {
556   if (mBase) {
557    if (shared_ptr<XdmfRegularGrid> grid =
558           shared_dynamic_cast<XdmfRegularGrid>(mBase)) {
559       if (grid->getName().compare(Name) == 0) {
560         return grid;
561       }
562       else {
563         return shared_ptr<XdmfRegularGrid>();
564       }
565     }
566     else {
567       return shared_ptr<XdmfRegularGrid>();
568     }
569   }
570   else {
571     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RegularGrid from template without a base");
572     return shared_ptr<XdmfRegularGrid>();
573   }
574 }
575 
576 shared_ptr<const XdmfRegularGrid>
getRegularGrid(const std::string & Name) const577 XdmfGridTemplate::getRegularGrid(const std::string & Name) const
578 {
579   if (mBase) {
580    if (shared_ptr<XdmfRegularGrid> grid =
581           shared_dynamic_cast<XdmfRegularGrid>(mBase)) {
582       if (grid->getName().compare(Name) == 0) {
583         return grid;
584       }
585       else {
586         return shared_ptr<XdmfRegularGrid>();
587       }
588     }
589     else {
590       return shared_ptr<XdmfRegularGrid>();
591     }
592   }
593   else {
594     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RegularGrid from template without a base");
595     return shared_ptr<XdmfRegularGrid>();
596   }
597 }
598 
599 unsigned int
getNumberRegularGrids() const600 XdmfGridTemplate::getNumberRegularGrids() const
601 {
602   if (shared_ptr<XdmfRegularGrid> grid =
603         shared_dynamic_cast<XdmfRegularGrid>(mBase)) {
604     return this->getNumberSteps();
605   }
606   else {
607     return 0;
608   }
609 }
610 
611 void
insert(const shared_ptr<XdmfRegularGrid>)612 XdmfGridTemplate::insert(const shared_ptr<XdmfRegularGrid> /*RegularGrid*/)
613 {
614   XdmfError::message(XdmfError::FATAL, "Error: Attempting to use insert to add an XdmfRegularGrid to an XdmfGridTemplate."
615                                        "Use addStep instead of insert to add to an XdmfGridTemplate");
616 }
617 
618 void
removeRegularGrid(const unsigned int index)619 XdmfGridTemplate::removeRegularGrid(const unsigned int index)
620 {
621   if (mBase) {
622     if (index < getNumberSteps()) {
623       if (shared_ptr<XdmfRegularGrid> grid =
624             shared_dynamic_cast<XdmfRegularGrid>(mBase)) {
625         this->removeStep(index);
626       }
627     }
628   }
629   else {
630     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get RegularGrid from template without a base");
631   }
632 }
633 
634 void
removeRegularGrid(const std::string & Name)635 XdmfGridTemplate::removeRegularGrid(const std::string & Name)
636 {
637   XdmfError::message(XdmfError::FATAL, "Error: Removing Grids by name from XdmfGridTemplate is not supported");
638 }
639 
640 shared_ptr<XdmfUnstructuredGrid>
getUnstructuredGrid(const unsigned int index)641 XdmfGridTemplate::getUnstructuredGrid(const unsigned int index)
642 {
643   if (mBase) {
644     if (index < getNumberSteps()) {
645       this->clearStep();
646       this->setStep(index);
647       if (shared_ptr<XdmfUnstructuredGrid> grid =
648             shared_dynamic_cast<XdmfUnstructuredGrid>(mBase)) {
649         return grid;
650       }
651       else {
652         return shared_ptr<XdmfUnstructuredGrid>();
653       }
654     }
655     else {
656       return shared_ptr<XdmfUnstructuredGrid>();
657     }
658   }
659   else {
660     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get UnstructuredGrid from template without a base");
661     return shared_ptr<XdmfUnstructuredGrid>();
662   }
663 }
664 
665 shared_ptr<const XdmfUnstructuredGrid>
getUnstructuredGrid(const unsigned int index) const666 XdmfGridTemplate::getUnstructuredGrid(const unsigned int index) const
667 {
668   if (shared_ptr<XdmfUnstructuredGrid> grid =
669       shared_dynamic_cast<XdmfUnstructuredGrid>(mBase)) {
670     if (index != mCurrentStep)
671     {
672       XdmfError::message(XdmfError::FATAL, "Error: GridTemplates can not return a constant reference to its base on an index other than the currently loaded one.");
673       return shared_ptr<XdmfUnstructuredGrid>();
674     }
675     else
676     {
677       return grid;
678     }
679   }
680   else {
681     return shared_ptr<XdmfUnstructuredGrid>();
682   }
683 }
684 
685 shared_ptr<XdmfUnstructuredGrid>
getUnstructuredGrid(const std::string & Name)686 XdmfGridTemplate::getUnstructuredGrid(const std::string & Name)
687 {
688   if (mBase) {
689    if (shared_ptr<XdmfUnstructuredGrid> grid =
690           shared_dynamic_cast<XdmfUnstructuredGrid>(mBase)) {
691       if (grid->getName().compare(Name) == 0) {
692         return grid;
693       }
694       else {
695         return shared_ptr<XdmfUnstructuredGrid>();
696       }
697     }
698     else {
699       return shared_ptr<XdmfUnstructuredGrid>();
700     }
701   }
702   else {
703     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get UnstructuredGrid from template without a base");
704     return shared_ptr<XdmfUnstructuredGrid>();
705   }
706 }
707 
708 shared_ptr<const XdmfUnstructuredGrid>
getUnstructuredGrid(const std::string & Name) const709 XdmfGridTemplate::getUnstructuredGrid(const std::string & Name) const
710 {
711   if (mBase) {
712    if (shared_ptr<XdmfUnstructuredGrid> grid =
713           shared_dynamic_cast<XdmfUnstructuredGrid>(mBase)) {
714       if (grid->getName().compare(Name) == 0) {
715         return grid;
716       }
717       else {
718         return shared_ptr<XdmfUnstructuredGrid>();
719       }
720     }
721     else {
722       return shared_ptr<XdmfUnstructuredGrid>();
723     }
724   }
725   else {
726     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get UnstructuredGrid from template without a base");
727     return shared_ptr<XdmfUnstructuredGrid>();
728   }
729 }
730 
731 unsigned int
getNumberUnstructuredGrids() const732 XdmfGridTemplate::getNumberUnstructuredGrids() const
733 {
734   if (shared_ptr<XdmfUnstructuredGrid> grid =
735         shared_dynamic_cast<XdmfUnstructuredGrid>(mBase)) {
736     return this->getNumberSteps();
737   }
738   else {
739     return 0;
740   }
741 }
742 
743 
744 void
insert(const shared_ptr<XdmfUnstructuredGrid> UnstructuredGrid)745 XdmfGridTemplate::insert(const shared_ptr<XdmfUnstructuredGrid> UnstructuredGrid)
746 {
747   XdmfError::message(XdmfError::FATAL, "Error: Attempting to use insert to add an XdmfUnstructuredGrid to an XdmfGridTemplate."
748                                        "Use addStep instead of insert to add to an XdmfGridTemplate");
749 }
750 
751 void
removeUnstructuredGrid(const unsigned int index)752 XdmfGridTemplate::removeUnstructuredGrid(const unsigned int index)
753 {
754   if (mBase) {
755     if (index < getNumberSteps()) {
756       if (shared_ptr<XdmfUnstructuredGrid> grid =
757             shared_dynamic_cast<XdmfUnstructuredGrid>(mBase)) {
758         this->removeStep(index);
759       }
760     }
761   }
762   else {
763     XdmfError::message(XdmfError::FATAL, "Error: Attempting to get UnstructuredGrid from template without a base");
764   }
765 }
766 
767 
768 void
removeUnstructuredGrid(const std::string & Name)769 XdmfGridTemplate::removeUnstructuredGrid(const std::string & Name)
770 {
771   XdmfError::message(XdmfError::FATAL, "Error: Removing Grids by name from XdmfGridTemplate is not supported");
772 }
773 
774 void
populateItem(const std::map<std::string,std::string> & itemProperties,const std::vector<shared_ptr<XdmfItem>> & childItems,const XdmfCoreReader * const reader)775 XdmfGridTemplate::populateItem(const std::map<std::string, std::string> & itemProperties,
776                                const std::vector<shared_ptr<XdmfItem> > & childItems,
777                                const XdmfCoreReader * const reader)
778 {
779   // We are overrriding the populate item of the template and grid collection here
780   // The template functions internally different from either.
781 
782   this->setType(XdmfGridCollectionType::New(itemProperties));
783 
784   // The first child item is the base
785   mBase = childItems[0];
786   mCurrentStep = 0;
787 
788   if (childItems.size() > 1) {
789     for(std::vector<shared_ptr<XdmfItem> >::const_iterator iter =
790           childItems.begin() + 1;
791         iter != childItems.end();
792         ++iter) {
793       if(shared_ptr<XdmfArray> array = shared_dynamic_cast<XdmfArray>(*iter)) {
794         if (array->getName().compare("Data Description") == 0) {
795           // Split description into substrings based on the " character
796 
797           if (array->getNumberHeavyDataControllers() > 0 && !mHeavyWriter) {
798             mHeavyWriter = reader->generateHeavyDataWriter(array->getHeavyDataController(0)->getName(), array->getHeavyDataController(0)->getFilePath());
799           }
800 
801           array->read();
802 
803           // If a character array, create std::string version? TODO
804           std::string descriptionString;
805           if (array->getArrayType() == XdmfArrayType::Int8())
806           {
807             descriptionString = std::string((char *)array->getValuesInternal());
808           }
809           else if (array->getArrayType() == XdmfArrayType::String())
810           {
811             descriptionString = array->getValue<std::string>(0);
812           }
813 
814           size_t index = descriptionString.find_first_of("\"");
815           size_t previousIndex = 0;
816 
817           if (index != std::string::npos) {
818             // Removing the prepended "
819             previousIndex = index + 1;
820             index = descriptionString.find_first_of("\"", previousIndex);
821           }
822 
823           while (index != std::string::npos) {
824             std::string type = descriptionString.substr(previousIndex, index - previousIndex);
825             mDataTypes.push_back(type);
826             previousIndex = index + 1;
827             index = descriptionString.find_first_of("\"", previousIndex);
828             if (index - previousIndex > 0) {
829               std::string description;
830               description = descriptionString.substr(previousIndex, index - previousIndex);
831               mDataDescriptions.push_back(description);
832               // create controllers here based on the type/description?
833               // Is array type already filled?
834               // Potentially call "fillControllers" after populating?
835               if (index != std::string::npos) {
836                 previousIndex = index + 1;
837                 index = descriptionString.find_first_of("\"", previousIndex);
838               }
839             }
840             else {
841               XdmfError::message(XdmfError::FATAL, "Error: Type without a description in XdmfTemplate::populateItem");
842             }
843           }
844         }
845         else if (array->getName().compare("Time Collection") == 0) {
846           mTimeCollection = array;
847         }
848         else {
849           mTrackedArrays.push_back(array.get());
850           mTrackedArrayDims.push_back(array->getDimensions());
851           mTrackedArrayTypes.push_back(array->getArrayType());
852         }
853       }
854     }
855   }
856   mDataControllers.resize(mDataTypes.size());
857   if (!mItemFactory) {
858     mItemFactory = XdmfItemFactory::New();
859   }
860   std::map<std::string, std::string> populateProperties;
861   if (mHeavyWriter) {
862     // The heavy writer provides the XMLDir, which is used to get full paths for the controllers
863     // It is assumed that the files that the controllers reference are in the same directory
864     // as the file that the writer references
865     std::string filepath = XdmfSystemUtils::getRealPath(mHeavyWriter->getFilePath());
866     size_t index = filepath.find_last_of("/\\");
867     filepath = filepath.substr(0, index + 1);
868     populateProperties["XMLDir"] = filepath;
869   }
870   for (unsigned int i = 0;  i < mDataDescriptions.size(); ++i) {
871     populateProperties["Content"] = mDataDescriptions[i];
872     std::vector<shared_ptr<XdmfHeavyDataController> > readControllers =
873       reader->generateHeavyDataControllers(populateProperties, mTrackedArrayDims[i % mTrackedArrays.size()], mTrackedArrayTypes[i % mTrackedArrays.size()], mDataTypes[i]);
874     if (readControllers.size() > 0) {
875       // Heavy data controllers reference the data
876       for (unsigned int j = 0; j < readControllers.size(); ++j) {
877         mDataControllers[i].push_back(readControllers[j]);
878       }
879     }
880   }
881   // Compare the first set of controllers to the size of the first array
882   unsigned int controllerTotal = 0;
883   for (unsigned int i = 0; i < mDataControllers[0].size(); ++i)
884   {
885     controllerTotal += mDataControllers[0][i]->getSize();
886   }
887   // If the array is smaller, set the writer to append.
888   if (controllerTotal > mTrackedArrays[0]->getSize())
889   {
890     mHeavyWriter->setMode(XdmfHeavyDataWriter::Append);
891     mNumSteps = controllerTotal / mTrackedArrays[0]->getSize();
892   }
893   else {
894     mNumSteps = mDataControllers.size() / mTrackedArrays.size();
895   }
896 }
897 
898 void
removeStep(unsigned int stepId)899 XdmfGridTemplate::removeStep(unsigned int stepId)
900 {
901   if (stepId < this->getNumberSteps()) {
902     XdmfTemplate::removeStep(stepId);
903     mTimeCollection->erase(stepId);
904   }
905   this->setIsChanged(true);
906 }
907 
908 void
setBase(shared_ptr<XdmfItem> newBase)909 XdmfGridTemplate::setBase(shared_ptr<XdmfItem> newBase)
910 {
911   if (shared_ptr<XdmfGrid> grid = shared_dynamic_cast<XdmfGrid>(newBase)) {
912     XdmfTemplate::setBase(newBase);
913   }
914   else {
915     XdmfError::message(XdmfError::FATAL, "Error: XdmfGridTemplate::setBase,"
916                                          " attempting to set a Base that is not grid type.");
917   }
918 }
919 
920 void
setStep(unsigned int stepId)921 XdmfGridTemplate::setStep(unsigned int stepId)
922 {
923   XdmfTemplate::setStep(stepId);
924   if (mTimeCollection->getSize() >= stepId) {
925     if (!mTimeCollection->isInitialized()) {
926       mTimeCollection->read();
927     }
928     if (shared_dynamic_cast<XdmfGrid>(mBase)->getTime()) {
929       shared_dynamic_cast<XdmfGrid>(mBase)->getTime()->setValue(mTimeCollection->getValue<double>(stepId));
930     }
931     else {
932       shared_dynamic_cast<XdmfGrid>(mBase)->setTime(XdmfTime::New(mTimeCollection->getValue<double>(stepId)));
933     }
934   }
935 }
936 
937 void
setStep(shared_ptr<XdmfTime> time)938 XdmfGridTemplate::setStep(shared_ptr<XdmfTime> time)
939 {
940   if (mTimeCollection->getSize() > 0)
941   {
942     if (!mTimeCollection->isInitialized()) {
943       mTimeCollection->read();
944     }
945     unsigned int index = 0;
946     while (index < mTimeCollection->getSize() &&
947            time->getValue() != mTimeCollection->getValue<double>(index))
948     {
949       ++index;
950     }
951     if (index < mTimeCollection->getSize())
952     {
953       this->setStep(index);
954     }
955   }
956 }
957 
958 void
traverse(const shared_ptr<XdmfBaseVisitor> visitor)959 XdmfGridTemplate::traverse(const shared_ptr<XdmfBaseVisitor> visitor)
960 {
961   // We are only using the template traverse
962   // since the grid data is only held in the Base
963   if (mTimeCollection->getSize() > 0)
964   {
965     this->setType(XdmfGridCollectionType::Temporal());
966   }
967   else
968   {
969     this->setType(XdmfGridCollectionType::Spatial());
970   }
971   XdmfTemplate::traverse(visitor);
972   mTimeCollection->accept(visitor);
973 }
974 
975 XDMF_ITEM_C_CHILD_WRAPPER(XdmfGridTemplate, XDMFGRIDTEMPLATE)
976