1 /*****************************************************************************/
2 /*                                    XDMF                                   */
3 /*                       eXtensible Data Model and Format                    */
4 /*                                                                           */
5 /*  Id : XdmfUnstructuredGrid.cpp                                            */
6 /*                                                                           */
7 /*  Author:                                                                  */
8 /*     Kenneth Leiter                                                        */
9 /*     kenneth.leiter@arl.army.mil                                           */
10 /*     US Army Research Laboratory                                           */
11 /*     Aberdeen Proving Ground, MD                                           */
12 /*                                                                           */
13 /*     Copyright @ 2011 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 "XdmfError.hpp"
25 #include "XdmfGeometry.hpp"
26 #include "XdmfGeometryType.hpp"
27 #include "XdmfRegularGrid.hpp"
28 #include "XdmfTopology.hpp"
29 #include "XdmfTopologyType.hpp"
30 #include "XdmfUnstructuredGrid.hpp"
31 
32 /**
33  * local functions
34  */
35 namespace {
36 
37   void
convertRegularGeometry(unsigned int index,shared_ptr<XdmfArray> point,shared_ptr<XdmfArray> dimensions,shared_ptr<XdmfArray> brickSize,shared_ptr<XdmfArray> mGeometry)38   convertRegularGeometry(unsigned int          index,
39                          shared_ptr<XdmfArray> point,
40                          shared_ptr<XdmfArray> dimensions,
41                          shared_ptr<XdmfArray> brickSize,
42                          shared_ptr<XdmfArray> mGeometry) {
43 
44     const unsigned int nDim = dimensions->getValue<unsigned int>(index);
45     const double nBrickSize = brickSize->getValue<double>(index);
46     const double originalPoint = point->getValue<double>(index);
47 
48     for(unsigned int i=0; i<nDim; ++i) {
49       if(index == 0) {
50         mGeometry->insert(mGeometry->getSize(),
51                           point,
52                           0,
53                           point->getSize());
54       }
55       else {
56         convertRegularGeometry(index - 1,
57                                point,
58                                dimensions,
59                                brickSize,
60                                mGeometry);
61       }
62       const double currPoint = point->getValue<double>(index);
63       point->insert(index, currPoint + nBrickSize);
64     }
65 
66     point->insert(index, originalPoint);
67   }
68 
69   void
convertRegularTopology(shared_ptr<XdmfArray> dimensions,shared_ptr<XdmfArray> mTopology)70   convertRegularTopology(shared_ptr<XdmfArray> dimensions,
71                          shared_ptr<XdmfArray> mTopology)
72   {
73 
74     if(dimensions->getSize() == 2) {
75       const unsigned int nx = dimensions->getValue<unsigned int>(0);
76       const unsigned int ny = dimensions->getValue<unsigned int>(1);
77       unsigned int offset = 0;
78       for(unsigned int i=1; i<ny; ++i) {
79         for(unsigned int j=1; j<nx; ++j) {
80           mTopology->pushBack<unsigned int>(offset);
81           mTopology->pushBack<unsigned int>(offset + 1);
82           mTopology->pushBack<unsigned int>(offset + nx + 1);
83           mTopology->pushBack<unsigned int>(offset + nx);
84           ++offset;
85         }
86         ++offset;
87       }
88     }
89     else if(dimensions->getSize() == 3) {
90       const unsigned int nx = dimensions->getValue<unsigned int>(0);
91       const unsigned int ny = dimensions->getValue<unsigned int>(1);
92       const unsigned int nz = dimensions->getValue<unsigned int>(2);
93       const unsigned int zOffset = nx * ny;
94       unsigned int offset = 0;
95       for(unsigned int i=1; i<nz; ++i) {
96         for(unsigned int j=1; j<ny; ++j) {
97           for(unsigned int k=1; k<nx; ++k) {
98             mTopology->pushBack<unsigned int>(offset);
99             mTopology->pushBack<unsigned int>(offset + 1);
100             mTopology->pushBack<unsigned int>(offset + nx + 1);
101             mTopology->pushBack<unsigned int>(offset + nx);
102             mTopology->pushBack<unsigned int>(offset + zOffset);
103             mTopology->pushBack<unsigned int>(offset + zOffset + 1);
104             mTopology->pushBack<unsigned int>(offset + zOffset + nx + 1);
105             mTopology->pushBack<unsigned int>(offset + zOffset + nx);
106             ++offset;
107           }
108           ++offset;
109         }
110         offset += nx;
111       }
112     }
113   }
114 }
115 
116 class XdmfUnstructuredGrid::XdmfUnstructuredGridImpl : public XdmfGridImpl
117 {
118   public:
XdmfUnstructuredGridImpl()119   XdmfUnstructuredGridImpl()
120   {
121     mGridType = "Unstructured";
122   }
123 
~XdmfUnstructuredGridImpl()124   ~XdmfUnstructuredGridImpl()
125   {
126   }
127 
duplicate()128   XdmfGridImpl * duplicate()
129   {
130     return new XdmfUnstructuredGridImpl();
131   }
132 
getGridType() const133   std::string getGridType() const
134   {
135     return mGridType;
136   }
137 };
138 
139 shared_ptr<XdmfUnstructuredGrid>
New()140 XdmfUnstructuredGrid::New()
141 {
142   shared_ptr<XdmfUnstructuredGrid> p(new XdmfUnstructuredGrid());
143   return p;
144 }
145 
146 shared_ptr<XdmfUnstructuredGrid>
New(const shared_ptr<XdmfRegularGrid> regularGrid)147 XdmfUnstructuredGrid::New(const shared_ptr<XdmfRegularGrid> regularGrid)
148 {
149   shared_ptr<XdmfUnstructuredGrid> p(new XdmfUnstructuredGrid(regularGrid));
150   return p;
151 }
152 
XdmfUnstructuredGrid()153 XdmfUnstructuredGrid::XdmfUnstructuredGrid() :
154   XdmfGrid(XdmfGeometry::New(), XdmfTopology::New())
155 {
156   mImpl = new XdmfUnstructuredGridImpl();
157 }
158 
XdmfUnstructuredGrid(const shared_ptr<XdmfRegularGrid> regularGrid)159 XdmfUnstructuredGrid::XdmfUnstructuredGrid(const shared_ptr<XdmfRegularGrid> regularGrid) :
160   XdmfGrid(XdmfGeometry::New(), XdmfTopology::New())
161 {
162   mImpl = new XdmfUnstructuredGridImpl();
163 
164   const shared_ptr<XdmfArray> origin = regularGrid->getOrigin();
165 
166   shared_ptr<XdmfArray> brickSize = regularGrid->getBrickSize();
167   shared_ptr<XdmfArray> dimensions = regularGrid->getDimensions();
168 
169   if(dimensions->getSize() != brickSize->getSize() ||
170      dimensions->getSize() != origin->getSize()) {
171     XdmfError::message(XdmfError::FATAL,
172                        "Inconsistent brick, dimension, and origin sizes when"
173                        "converting regular grid to unstructured grid in "
174                        "XdmfUnstructuredGrid constructor");
175   }
176 
177   bool releaseOrigin = false;
178   bool releaseBrickSize = false;
179   bool releaseDimensions = false;
180   if(!origin->isInitialized()) {
181     origin->read();
182     releaseOrigin = true;
183   }
184   if(!brickSize->isInitialized()) {
185     brickSize->read();
186     releaseBrickSize = true;
187   }
188   if(!dimensions->isInitialized()) {
189     dimensions->read();
190     releaseDimensions = true;
191   }
192 
193   shared_ptr<const XdmfGeometryType> geometryType;
194   shared_ptr<const XdmfTopologyType> topologyType;
195   if(origin->getSize() == 2) {
196     geometryType = XdmfGeometryType::XY();
197     topologyType = XdmfTopologyType::Quadrilateral();
198   }
199   else if(origin->getSize() == 3) {
200     geometryType = XdmfGeometryType::XYZ();
201     topologyType = XdmfTopologyType::Hexahedron();
202   }
203   else {
204     XdmfError::message(XdmfError::FATAL,
205                        "Cannot convert regular grid of dimensions not 2 or 3 "
206                        "to XdmfUnstructuredGrid in XdmfUnstructuredGrid "
207                        "constructor");
208   }
209   mGeometry->setType(geometryType);
210   mTopology->setType(topologyType);
211 
212   shared_ptr<XdmfArray> point = XdmfArray::New();
213   point->insert(0, origin, 0, origin->getSize());
214   convertRegularGeometry(dimensions->getSize() - 1,
215                          point,
216                          dimensions,
217                          brickSize,
218                          mGeometry);
219   convertRegularTopology(dimensions,
220                          mTopology);
221 
222   if(releaseOrigin) {
223     origin->release();
224   }
225   if(releaseBrickSize) {
226     brickSize->release();
227   }
228   if(releaseDimensions) {
229     dimensions->release();
230   }
231 }
232 
XdmfUnstructuredGrid(XdmfUnstructuredGrid & refGrid)233 XdmfUnstructuredGrid::XdmfUnstructuredGrid(XdmfUnstructuredGrid & refGrid) :
234   XdmfGrid(refGrid)
235 {
236 }
237 
~XdmfUnstructuredGrid()238 XdmfUnstructuredGrid::~XdmfUnstructuredGrid()
239 {
240   if (mImpl) {
241     delete mImpl;
242   }
243   mImpl = NULL;
244 }
245 
246 const std::string XdmfUnstructuredGrid::ItemTag = "Grid";
247 
248 void
copyGrid(shared_ptr<XdmfGrid> sourceGrid)249 XdmfUnstructuredGrid::copyGrid(shared_ptr<XdmfGrid> sourceGrid)
250 {
251   XdmfGrid::copyGrid(sourceGrid);
252   if (shared_ptr<XdmfUnstructuredGrid> classedGrid = shared_dynamic_cast<XdmfUnstructuredGrid>(sourceGrid))
253   {
254     this->setGeometry(classedGrid->getGeometry());
255     this->setTopology(classedGrid->getTopology());
256   }
257 }
258 
259 shared_ptr<XdmfGeometry>
getGeometry()260 XdmfUnstructuredGrid::getGeometry()
261 {
262   return boost::const_pointer_cast<XdmfGeometry>
263     (static_cast<const XdmfGrid &>(*this).getGeometry());
264 }
265 
266 std::string
getItemTag() const267 XdmfUnstructuredGrid::getItemTag() const
268 {
269   return ItemTag;
270 }
271 
272 shared_ptr<XdmfTopology>
getTopology()273 XdmfUnstructuredGrid::getTopology()
274 {
275   return boost::const_pointer_cast<XdmfTopology>
276     (static_cast<const XdmfGrid &>(*this).getTopology());
277 }
278 
279 void
read()280 XdmfUnstructuredGrid::read()
281 {
282   if (mGridController)
283   {
284     if (shared_ptr<XdmfUnstructuredGrid> grid = shared_dynamic_cast<XdmfUnstructuredGrid>(mGridController->read()))
285     {
286       copyGrid(grid);
287     }
288     else if (shared_ptr<XdmfGrid> grid = shared_dynamic_cast<XdmfGrid>(mGridController->read()))
289     {
290       XdmfError::message(XdmfError::FATAL, "Error: Grid Type Mismatch");
291     }
292     else
293     {
294       XdmfError::message(XdmfError::FATAL, "Error: Invalid Grid Reference");
295     }
296   }
297 }
298 
299 void
release()300 XdmfUnstructuredGrid::release()
301 {
302   XdmfGrid::release();
303   this->setGeometry(shared_ptr<XdmfGeometry>());
304   this->setTopology(shared_ptr<XdmfTopology>());
305 }
306 
307 void
setGeometry(const shared_ptr<XdmfGeometry> geometry)308 XdmfUnstructuredGrid::setGeometry(const shared_ptr<XdmfGeometry> geometry)
309 {
310   mGeometry = geometry;
311 }
312 
313 void
setTopology(const shared_ptr<XdmfTopology> topology)314 XdmfUnstructuredGrid::setTopology(const shared_ptr<XdmfTopology> topology)
315 {
316   mTopology = topology;
317 }
318 
319 // C Wrappers
320 
XdmfUnstructuredGridNew()321 XDMFUNSTRUCTUREDGRID * XdmfUnstructuredGridNew()
322 {
323   try
324   {
325     shared_ptr<XdmfUnstructuredGrid> generatedGrid = XdmfUnstructuredGrid::New();
326     return (XDMFUNSTRUCTUREDGRID *)((void *)((XdmfItem *)(new XdmfUnstructuredGrid(*generatedGrid.get()))));
327   }
328   catch (...)
329   {
330     shared_ptr<XdmfUnstructuredGrid> generatedGrid = XdmfUnstructuredGrid::New();
331     return (XDMFUNSTRUCTUREDGRID *)((void *)((XdmfItem *)(new XdmfUnstructuredGrid(*generatedGrid.get()))));
332   }
333 }
334 
XdmfUnstructuredGridNewFromRegularGrid(XDMFREGULARGRID * regularGrid,int * status)335 XDMFUNSTRUCTUREDGRID * XdmfUnstructuredGridNewFromRegularGrid(XDMFREGULARGRID * regularGrid, int * status)
336 {
337   XDMF_ERROR_WRAP_START(status)
338   try
339   {
340     // Here it works when classed directly to the grid type,
341     // in other cases this may not work.
342     XdmfItem * tempPointer = (XdmfItem *)regularGrid;
343     XdmfRegularGrid * classedPointer = dynamic_cast<XdmfRegularGrid *>(tempPointer);
344     shared_ptr<XdmfRegularGrid> originGrid = shared_ptr<XdmfRegularGrid>(classedPointer, XdmfNullDeleter());
345     shared_ptr<XdmfUnstructuredGrid> generatedGrid = XdmfUnstructuredGrid::New(originGrid);
346     return (XDMFUNSTRUCTUREDGRID *)((void *)((XdmfItem *)(new XdmfUnstructuredGrid(*generatedGrid.get()))));
347   }
348   catch (...)
349   {
350     // Here it works when classed directly to the grid type,
351     // in other cases this may not work.
352     XdmfItem * tempPointer = (XdmfItem *)regularGrid;
353     XdmfRegularGrid * classedPointer = dynamic_cast<XdmfRegularGrid *>(tempPointer);
354     shared_ptr<XdmfRegularGrid> originGrid = shared_ptr<XdmfRegularGrid>(classedPointer, XdmfNullDeleter());
355     shared_ptr<XdmfUnstructuredGrid> generatedGrid = XdmfUnstructuredGrid::New(originGrid);
356     return (XDMFUNSTRUCTUREDGRID *)((void *)((XdmfItem *)(new XdmfUnstructuredGrid(*generatedGrid.get()))));
357   }
358   XDMF_ERROR_WRAP_END(status)
359   return NULL;
360 }
361 
XdmfUnstructuredGridGetGeometry(XDMFUNSTRUCTUREDGRID * grid)362 XDMFGEOMETRY * XdmfUnstructuredGridGetGeometry(XDMFUNSTRUCTUREDGRID * grid)
363 {
364   XdmfItem * tempPointer = (XdmfItem *)grid;
365   XdmfUnstructuredGrid * classedPointer = dynamic_cast<XdmfUnstructuredGrid *>(tempPointer);
366   return (XDMFGEOMETRY *)((void *)(classedPointer->getGeometry().get()));
367 }
368 
XdmfUnstructuredGridGetTopology(XDMFUNSTRUCTUREDGRID * grid)369 XDMFTOPOLOGY * XdmfUnstructuredGridGetTopology(XDMFUNSTRUCTUREDGRID * grid)
370 {
371   XdmfItem * tempPointer = (XdmfItem *)grid;
372   XdmfUnstructuredGrid * classedPointer = dynamic_cast<XdmfUnstructuredGrid *>(tempPointer);
373   return (XDMFTOPOLOGY *)((void *)(classedPointer->getTopology().get()));
374 }
375 
XdmfUnstructuredGridSetGeometry(XDMFUNSTRUCTUREDGRID * grid,XDMFGEOMETRY * geometry,int passControl)376 void XdmfUnstructuredGridSetGeometry(XDMFUNSTRUCTUREDGRID * grid, XDMFGEOMETRY * geometry, int passControl)
377 {
378   XdmfItem * tempPointer = (XdmfItem *)grid;
379   XdmfUnstructuredGrid * classedPointer = dynamic_cast<XdmfUnstructuredGrid *>(tempPointer);
380   if (passControl) {
381     classedPointer->setGeometry(shared_ptr<XdmfGeometry>((XdmfGeometry *)geometry));
382   }
383   else {
384     classedPointer->setGeometry(shared_ptr<XdmfGeometry>((XdmfGeometry *)geometry, XdmfNullDeleter()));
385   }
386 }
387 
XdmfUnstructuredGridSetTopology(XDMFUNSTRUCTUREDGRID * grid,XDMFTOPOLOGY * topology,int passControl)388 void XdmfUnstructuredGridSetTopology(XDMFUNSTRUCTUREDGRID * grid, XDMFTOPOLOGY * topology, int passControl)
389 {
390   XdmfItem * tempPointer = (XdmfItem *)grid;
391   XdmfUnstructuredGrid * classedPointer = dynamic_cast<XdmfUnstructuredGrid *>(tempPointer);
392   if (passControl) {
393     classedPointer->setTopology(shared_ptr<XdmfTopology>((XdmfTopology *)topology));
394   }
395   else {
396     classedPointer->setTopology(shared_ptr<XdmfTopology>((XdmfTopology *)topology, XdmfNullDeleter()));
397   }
398 }
399 
400 XDMF_ITEM_C_CHILD_WRAPPER(XdmfUnstructuredGrid, XDMFUNSTRUCTUREDGRID)
401 XDMF_GRID_C_CHILD_WRAPPER(XdmfUnstructuredGrid, XDMFUNSTRUCTUREDGRID)
402