XdmfRectilinearGrid.cpp 13 KB
Newer Older
Kenneth Leiter's avatar
Kenneth Leiter committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*****************************************************************************/
/*                                    XDMF                                   */
/*                       eXtensible Data Model and Format                    */
/*                                                                           */
/*  Id : XdmfRectilinearGrid.cpp                                             */
/*                                                                           */
/*  Author:                                                                  */
/*     Kenneth Leiter                                                        */
/*     kenneth.leiter@arl.army.mil                                           */
/*     US Army Research Laboratory                                           */
/*     Aberdeen Proving Ground, MD                                           */
/*                                                                           */
/*     Copyright @ 2011 US Army Research Laboratory                          */
/*     All Rights Reserved                                                   */
/*     See Copyright.txt for details                                         */
/*                                                                           */
/*     This software is distributed WITHOUT ANY WARRANTY; without            */
/*     even the implied warranty of MERCHANTABILITY or FITNESS               */
/*     FOR A PARTICULAR PURPOSE.  See the above copyright notice             */
/*     for more information.                                                 */
/*                                                                           */
/*****************************************************************************/
23 24 25 26 27

#include <cmath>
#include "XdmfArray.hpp"
#include "XdmfGeometry.hpp"
#include "XdmfGeometryType.hpp"
28
#include "XdmfRectilinearGrid.hpp"
29 30
#include "XdmfTopology.hpp"
#include "XdmfTopologyType.hpp"
31
#include "XdmfError.hpp"
32 33 34 35

/**
 * PIMPL
 */
36
class XdmfRectilinearGrid::XdmfRectilinearGridImpl {
37 38 39

public:

40 41 42 43 44
  class XdmfGeometryRectilinear : public XdmfGeometry
  {

  public:

45
    static shared_ptr<XdmfGeometryRectilinear>
46 47
    New(XdmfRectilinearGrid * const rectilinearGrid)
    {
48
      shared_ptr<XdmfGeometryRectilinear>
49 50 51 52 53 54 55
        p(new XdmfGeometryRectilinear(rectilinearGrid));
      return p;
    }

    unsigned int
    getNumberPoints() const
    {
56
      const shared_ptr<const XdmfArray> dimensions =
57 58 59 60 61 62 63 64 65 66 67 68
        mRectilinearGrid->getDimensions();
      if(dimensions->getSize() == 0) {
        return 0;
      }
      unsigned int toReturn = 1;
      for(unsigned int i=0; i<dimensions->getSize(); ++i) {
        toReturn *= dimensions->getValue<unsigned int>(i);
      }
      return toReturn;
    }

    void
69
    traverse(const shared_ptr<XdmfBaseVisitor> visitor)
70
    {
71
      const std::vector<shared_ptr<XdmfArray> > & coordinates =
72
        mRectilinearGrid->getCoordinates();
73
      for(std::vector<shared_ptr<XdmfArray> >::const_iterator iter =
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
            coordinates.begin();
          iter != coordinates.end();
          ++iter) {
        (*iter)->accept(visitor);
      }
    }

  private:

    XdmfGeometryRectilinear(XdmfRectilinearGrid * const rectilinearGrid) :
      mRectilinearGrid(rectilinearGrid)
    {
      this->setType(XdmfGeometryTypeRectilinear::New(mRectilinearGrid));
    }

    const XdmfRectilinearGrid * const mRectilinearGrid;
  };

  class XdmfGeometryTypeRectilinear : public XdmfGeometryType
  {

  public:

97
    static shared_ptr<const XdmfGeometryTypeRectilinear>
98 99
    New(const XdmfRectilinearGrid * const rectilinearGrid)
    {
100
      shared_ptr<const XdmfGeometryTypeRectilinear>
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
        p(new XdmfGeometryTypeRectilinear(rectilinearGrid));
      return p;
    }

    unsigned int
    getDimensions() const
    {
      return mRectilinearGrid->getDimensions()->getSize();
    }

    void
    getProperties(std::map<std::string, std::string> & collectedProperties) const
    {
      const unsigned int dimensions = this->getDimensions();
      if(dimensions == 3) {
        collectedProperties["Type"] = "VXVYVZ";
      }
      else if(dimensions == 2) {
        collectedProperties["Type"] = "VXVY";
      }
      else {
122
        try {
123 124 125
          XdmfError::message(XdmfError::FATAL,
                             "Number of dimensions not 2 or 3 in"
                             " XdmfGeometryTypeRectilinear::getProperties");
126 127 128 129
        }
        catch (XdmfError e) {
          throw e;
        }
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
      }
    }

  private:

    XdmfGeometryTypeRectilinear(const XdmfRectilinearGrid * const rectilinearGrid) :
      XdmfGeometryType("", 0),
      mRectilinearGrid(rectilinearGrid)
    {
    }

    const XdmfRectilinearGrid * const mRectilinearGrid;

  };

  class XdmfTopologyRectilinear : public XdmfTopology
  {

  public:

150
    static shared_ptr<XdmfTopologyRectilinear>
151 152
    New(const XdmfRectilinearGrid * const rectilinearGrid)
    {
153
      shared_ptr<XdmfTopologyRectilinear>
154 155 156 157 158 159 160
        p(new XdmfTopologyRectilinear(rectilinearGrid));
      return p;
    }

    unsigned int
    getNumberElements() const
    {
161
      const shared_ptr<const XdmfArray> dimensions = 
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
        mRectilinearGrid->getDimensions();
      if(dimensions->getSize() == 0) {
        return 0;
      }
      unsigned int toReturn = 1;
      for(unsigned int i=0; i<dimensions->getSize(); ++i) {
        toReturn *= (dimensions->getValue<unsigned int>(i) - 1);
      }
      return toReturn;
    }

  private:

    XdmfTopologyRectilinear(const XdmfRectilinearGrid * const rectilinearGrid) :
      mRectilinearGrid(rectilinearGrid)
    {
      this->setType(XdmfTopologyTypeRectilinear::New(rectilinearGrid));
    }

    const XdmfRectilinearGrid * const mRectilinearGrid;
  };

  class XdmfTopologyTypeRectilinear : public XdmfTopologyType
  {

  public:

189
    static shared_ptr<const XdmfTopologyTypeRectilinear>
190 191
    New(const XdmfRectilinearGrid * const rectilinearGrid)
    {
192
      shared_ptr<const XdmfTopologyTypeRectilinear>
193 194 195 196
        p(new XdmfTopologyTypeRectilinear(rectilinearGrid));
      return p;
    }

197 198 199 200 201 202 203 204 205 206 207 208
    unsigned int
    getEdgesPerElement() const
    {
      const unsigned int dimensions = 
        mRectilinearGrid->getDimensions()->getSize();
      if(dimensions == 2) {
        return 4;
      }
      else if(dimensions == 3) {
        return 12;
      }
      else {
209 210 211 212 213 214 215 216
        try {
          XdmfError::message(XdmfError::FATAL, 
                             "Grid dimensions not 2 or 3 in "
                             "XdmfTopologyTypeRectilinear::getEdgesPerElement");
        }
        catch (XdmfError e) {
          throw e;
        }
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
      }
      return 0;
    }

    unsigned int
    getFacesPerElement() const
    {
      const unsigned int dimensions = 
        mRectilinearGrid->getDimensions()->getSize();
      if(dimensions == 2) {
        return 1;
      }
      else if(dimensions == 3) {
        return 6;
      }
      else {
233 234 235 236 237 238 239 240
        try {
          XdmfError::message(XdmfError::FATAL, 
                             "Grid dimensions not 2 or 3 in "
                             "XdmfTopologyTypeRectilinear::getFacesPerElement");
        }
        catch (XdmfError e) {
          throw e;
        }
241 242 243 244
      }
      return 0;
    }

245 246 247 248 249 250 251 252 253 254 255 256
    unsigned int
    getNodesPerElement() const
    {
      // 2^Dimensions
      // e.g. 1D = 2 nodes per element and 2D = 4 nodes per element.
      return (unsigned int)
        std::pow(2, (double)mRectilinearGrid->getDimensions()->getSize());
    }

    void
    getProperties(std::map<std::string, std::string> & collectedProperties) const
    {
257
      shared_ptr<const XdmfArray> dimensions = 
258 259 260 261 262 263 264 265
        mRectilinearGrid->getDimensions();
      if(dimensions->getSize() == 3) {
        collectedProperties["Type"] = "3DRectMesh";
      }
      else if(dimensions->getSize() == 2) {
        collectedProperties["Type"] = "2DRectMesh";
      }
      else {
266 267 268 269 270 271 272 273
        try {
          XdmfError::message(XdmfError::FATAL, 
                             "Number of dimensions not 2 or 3 in "
                             "XdmfTopologyTypeRectilinear::getProperties");
        }
        catch (XdmfError e) {
          throw e;
        }
274 275 276 277 278 279 280
      }
      collectedProperties["Dimensions"] = dimensions->getValuesString();
    }

  private:

    XdmfTopologyTypeRectilinear(const XdmfRectilinearGrid * const rectilinearGrid) :
281 282 283 284 285 286 287
      XdmfTopologyType(0,
                       0,
                       std::vector<shared_ptr<const XdmfTopologyType> >(),
                       0,
                       "foo",
                       XdmfTopologyType::Structured,
                       0x1101),
288 289 290 291 292 293 294 295
      mRectilinearGrid(rectilinearGrid)
    {
    }

    const XdmfRectilinearGrid * const mRectilinearGrid;

  };

296
  XdmfRectilinearGridImpl(const std::vector<shared_ptr<XdmfArray> > & coordinates) :
297 298 299 300
    mCoordinates(coordinates.begin(), coordinates.end())
  {
  }

301
  std::vector<shared_ptr<XdmfArray> > mCoordinates;
302 303 304

};

305 306 307
shared_ptr<XdmfRectilinearGrid>
XdmfRectilinearGrid::New(const shared_ptr<XdmfArray> xCoordinates,
                         const shared_ptr<XdmfArray> yCoordinates)
308
{
309
  std::vector<shared_ptr<XdmfArray> > axesCoordinates;
310 311 312
  axesCoordinates.resize(2);
  axesCoordinates[0] = xCoordinates;
  axesCoordinates[1] = yCoordinates;
313
  shared_ptr<XdmfRectilinearGrid> p(new XdmfRectilinearGrid(axesCoordinates));
314
  return p;
315 316
}

317 318 319 320
shared_ptr<XdmfRectilinearGrid>
XdmfRectilinearGrid::New(const shared_ptr<XdmfArray> xCoordinates,
                         const shared_ptr<XdmfArray> yCoordinates,
                         const shared_ptr<XdmfArray> zCoordinates)
321
{
322
  std::vector<shared_ptr<XdmfArray> > axesCoordinates;
323 324 325 326
  axesCoordinates.resize(3);
  axesCoordinates[0] = xCoordinates;
  axesCoordinates[1] = yCoordinates;
  axesCoordinates[2] = zCoordinates;
327
  shared_ptr<XdmfRectilinearGrid> p(new XdmfRectilinearGrid(axesCoordinates));
328
  return p;
329 330
}

331 332
shared_ptr<XdmfRectilinearGrid>
XdmfRectilinearGrid::New(const std::vector<shared_ptr<XdmfArray> > & axesCoordinates)
333
{
334
  shared_ptr<XdmfRectilinearGrid> p(new XdmfRectilinearGrid(axesCoordinates));
335
  return p;
336 337
}

338
XdmfRectilinearGrid::XdmfRectilinearGrid(const std::vector<shared_ptr<XdmfArray> > & axesCoordinates) :
339 340 341
  XdmfGrid(XdmfRectilinearGridImpl::XdmfGeometryRectilinear::New(this),
           XdmfRectilinearGridImpl::XdmfTopologyRectilinear::New(this)),
  mImpl(new XdmfRectilinearGridImpl(axesCoordinates))
342 343 344
{
}

345
XdmfRectilinearGrid::~XdmfRectilinearGrid()
346
{
347
  delete mImpl;
348 349
}

350
const std::string XdmfRectilinearGrid::ItemTag = "Grid";
351

352
shared_ptr<XdmfArray>
353
XdmfRectilinearGrid::getCoordinates(const unsigned int axisIndex)
354
{
355 356 357
  return boost::const_pointer_cast<XdmfArray>
    (static_cast<const XdmfRectilinearGrid &>
     (*this).getCoordinates(axisIndex));
358 359
}

360
shared_ptr<const XdmfArray>
361
XdmfRectilinearGrid::getCoordinates(const unsigned int axisIndex) const
362
{
363 364 365
  if(axisIndex < mImpl->mCoordinates.size()) {
    return mImpl->mCoordinates[axisIndex];
  }
366
  return shared_ptr<XdmfArray>();
367 368
}

369
std::vector<shared_ptr<XdmfArray> >
370
XdmfRectilinearGrid::getCoordinates()
371
{
372
  return static_cast<const XdmfRectilinearGrid &>(*this).getCoordinates();
373 374
}

375
const std::vector<shared_ptr<XdmfArray> >
376
XdmfRectilinearGrid::getCoordinates() const
377
{
378
  return mImpl->mCoordinates;
379 380
}

381
shared_ptr<XdmfArray>
382
XdmfRectilinearGrid::getDimensions()
383
{
384 385
  return boost::const_pointer_cast<XdmfArray>
    (static_cast<const XdmfRectilinearGrid &>(*this).getDimensions());
386 387
}

388
shared_ptr<const XdmfArray>
389
XdmfRectilinearGrid::getDimensions() const
390
{
391
  shared_ptr<XdmfArray> dimensions = XdmfArray::New();
392
  dimensions->reserve(mImpl->mCoordinates.size());
393
  for(std::vector<shared_ptr<XdmfArray> >::const_iterator iter =
394 395 396 397 398 399
        mImpl->mCoordinates.begin();
      iter != mImpl->mCoordinates.end();
      ++iter) {
    dimensions->pushBack((*iter)->getSize());
  }
  return dimensions;
400 401
}

402 403
void
XdmfRectilinearGrid::populateItem(const std::map<std::string, std::string> & itemProperties,
404
                                  const std::vector<shared_ptr<XdmfItem> > & childItems,
405
                                  const XdmfCoreReader * const reader)
406
{
407 408
  XdmfGrid::populateItem(itemProperties, childItems, reader);

409
  for(std::vector<shared_ptr<XdmfItem> >::const_iterator iter =
410 411 412
        childItems.begin();
      iter != childItems.end();
      ++iter) {
413 414
    if(shared_ptr<XdmfRectilinearGrid> rectilinearGrid =
       shared_dynamic_cast<XdmfRectilinearGrid>(*iter)) {
415 416 417 418 419 420
      if(rectilinearGrid->getGeometry()->getType()->getDimensions() > 0) {
        this->setCoordinates(rectilinearGrid->getCoordinates());
        break;
      }
    }
  }
421 422
}

423 424
void
XdmfRectilinearGrid::setCoordinates(const unsigned int axisIndex,
425
                                    const shared_ptr<XdmfArray> axisCoordinates)
426
{
427 428 429 430 431 432 433 434 435
  if(mImpl->mCoordinates.size() <= axisIndex) {
    mImpl->mCoordinates.reserve(axisIndex + 1);
    unsigned int numArraysToInsert =
      axisIndex - mImpl->mCoordinates.size() + 1;
    for(unsigned int i=0; i<numArraysToInsert; ++i) {
      mImpl->mCoordinates.push_back(XdmfArray::New());
    }
  }
  mImpl->mCoordinates[axisIndex] = axisCoordinates;
436 437
}

438
void
439
XdmfRectilinearGrid::setCoordinates(const std::vector<shared_ptr<XdmfArray> > axesCoordinates)
440
{
441
  mImpl->mCoordinates = axesCoordinates;
442
}