XdmfRectilinearGrid.cpp 12.4 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
        XdmfError::message(XdmfError::FATAL, "Number of dimensions not 2 or 3 in XdmfGeometryTypeRectilinear::getProperties");
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
      }
    }

  private:

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

    const XdmfRectilinearGrid * const mRectilinearGrid;

  };

  class XdmfTopologyRectilinear : public XdmfTopology
  {

  public:

143
    static shared_ptr<XdmfTopologyRectilinear>
144 145
    New(const XdmfRectilinearGrid * const rectilinearGrid)
    {
146
      shared_ptr<XdmfTopologyRectilinear>
147 148 149 150 151 152 153
        p(new XdmfTopologyRectilinear(rectilinearGrid));
      return p;
    }

    unsigned int
    getNumberElements() const
    {
154
      const shared_ptr<const XdmfArray> dimensions = 
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        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:

182
    static shared_ptr<const XdmfTopologyTypeRectilinear>
183 184
    New(const XdmfRectilinearGrid * const rectilinearGrid)
    {
185
      shared_ptr<const XdmfTopologyTypeRectilinear>
186 187 188 189
        p(new XdmfTopologyTypeRectilinear(rectilinearGrid));
      return p;
    }

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    unsigned int
    getEdgesPerElement() const
    {
      const unsigned int dimensions = 
        mRectilinearGrid->getDimensions()->getSize();
      if(dimensions == 2) {
        return 4;
      }
      else if(dimensions == 3) {
        return 12;
      }
      else {
        XdmfError::message(XdmfError::FATAL, 
                           "Grid dimensions not 2 or 3 in "
                           "XdmfTopologyTypeRectilinear::getEdgesPerElement");
      }
      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 {
        XdmfError::message(XdmfError::FATAL, 
                           "Grid dimensions not 2 or 3 in "
                           "XdmfTopologyTypeRectilinear::getFacesPerElement");
      }
      return 0;
    }

228 229 230 231 232 233 234 235 236 237 238 239
    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
    {
240
      shared_ptr<const XdmfArray> dimensions = 
241 242 243 244 245 246 247 248
        mRectilinearGrid->getDimensions();
      if(dimensions->getSize() == 3) {
        collectedProperties["Type"] = "3DRectMesh";
      }
      else if(dimensions->getSize() == 2) {
        collectedProperties["Type"] = "2DRectMesh";
      }
      else {
249 250 251
        XdmfError::message(XdmfError::FATAL, 
                           "Number of dimensions not 2 or 3 in "
                           "XdmfTopologyTypeRectilinear::getProperties");
252 253 254 255 256 257 258
      }
      collectedProperties["Dimensions"] = dimensions->getValuesString();
    }

  private:

    XdmfTopologyTypeRectilinear(const XdmfRectilinearGrid * const rectilinearGrid) :
259
      XdmfTopologyType(0, 0, 0, "foo", XdmfTopologyType::Structured, 0x1101),
260 261 262 263 264 265 266 267
      mRectilinearGrid(rectilinearGrid)
    {
    }

    const XdmfRectilinearGrid * const mRectilinearGrid;

  };

268
  XdmfRectilinearGridImpl(const std::vector<shared_ptr<XdmfArray> > & coordinates) :
269 270 271 272
    mCoordinates(coordinates.begin(), coordinates.end())
  {
  }

273
  std::vector<shared_ptr<XdmfArray> > mCoordinates;
274 275 276

};

277 278 279
shared_ptr<XdmfRectilinearGrid>
XdmfRectilinearGrid::New(const shared_ptr<XdmfArray> xCoordinates,
                         const shared_ptr<XdmfArray> yCoordinates)
280
{
281
  std::vector<shared_ptr<XdmfArray> > axesCoordinates;
282 283 284
  axesCoordinates.resize(2);
  axesCoordinates[0] = xCoordinates;
  axesCoordinates[1] = yCoordinates;
285
  shared_ptr<XdmfRectilinearGrid> p(new XdmfRectilinearGrid(axesCoordinates));
286
  return p;
287 288
}

289 290 291 292
shared_ptr<XdmfRectilinearGrid>
XdmfRectilinearGrid::New(const shared_ptr<XdmfArray> xCoordinates,
                         const shared_ptr<XdmfArray> yCoordinates,
                         const shared_ptr<XdmfArray> zCoordinates)
293
{
294
  std::vector<shared_ptr<XdmfArray> > axesCoordinates;
295 296 297 298
  axesCoordinates.resize(3);
  axesCoordinates[0] = xCoordinates;
  axesCoordinates[1] = yCoordinates;
  axesCoordinates[2] = zCoordinates;
299
  shared_ptr<XdmfRectilinearGrid> p(new XdmfRectilinearGrid(axesCoordinates));
300
  return p;
301 302
}

303 304
shared_ptr<XdmfRectilinearGrid>
XdmfRectilinearGrid::New(const std::vector<shared_ptr<XdmfArray> > & axesCoordinates)
305
{
306
  shared_ptr<XdmfRectilinearGrid> p(new XdmfRectilinearGrid(axesCoordinates));
307
  return p;
308 309
}

310
XdmfRectilinearGrid::XdmfRectilinearGrid(const std::vector<shared_ptr<XdmfArray> > & axesCoordinates) :
311 312 313
  XdmfGrid(XdmfRectilinearGridImpl::XdmfGeometryRectilinear::New(this),
           XdmfRectilinearGridImpl::XdmfTopologyRectilinear::New(this)),
  mImpl(new XdmfRectilinearGridImpl(axesCoordinates))
314 315 316
{
}

317
XdmfRectilinearGrid::~XdmfRectilinearGrid()
318
{
319
  delete mImpl;
320 321
}

322
const std::string XdmfRectilinearGrid::ItemTag = "Grid";
323

324
shared_ptr<XdmfArray>
325
XdmfRectilinearGrid::getCoordinates(const unsigned int axisIndex)
326
{
327 328 329
  return boost::const_pointer_cast<XdmfArray>
    (static_cast<const XdmfRectilinearGrid &>
     (*this).getCoordinates(axisIndex));
330 331
}

332
shared_ptr<const XdmfArray>
333
XdmfRectilinearGrid::getCoordinates(const unsigned int axisIndex) const
334
{
335 336 337
  if(axisIndex < mImpl->mCoordinates.size()) {
    return mImpl->mCoordinates[axisIndex];
  }
338
  return shared_ptr<XdmfArray>();
339 340
}

341
std::vector<shared_ptr<XdmfArray> >
342
XdmfRectilinearGrid::getCoordinates()
343
{
344
  return static_cast<const XdmfRectilinearGrid &>(*this).getCoordinates();
345 346
}

347
const std::vector<shared_ptr<XdmfArray> >
348
XdmfRectilinearGrid::getCoordinates() const
349
{
350
  return mImpl->mCoordinates;
351 352
}

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

360
shared_ptr<const XdmfArray>
361
XdmfRectilinearGrid::getDimensions() const
362
{
363
  shared_ptr<XdmfArray> dimensions = XdmfArray::New();
364
  dimensions->reserve(mImpl->mCoordinates.size());
365
  for(std::vector<shared_ptr<XdmfArray> >::const_iterator iter =
366 367 368 369 370 371
        mImpl->mCoordinates.begin();
      iter != mImpl->mCoordinates.end();
      ++iter) {
    dimensions->pushBack((*iter)->getSize());
  }
  return dimensions;
372 373
}

374 375
void
XdmfRectilinearGrid::populateItem(const std::map<std::string, std::string> & itemProperties,
376
                                  const std::vector<shared_ptr<XdmfItem> > & childItems,
377
                                  const XdmfCoreReader * const reader)
378
{
379 380
  XdmfGrid::populateItem(itemProperties, childItems, reader);

381
  for(std::vector<shared_ptr<XdmfItem> >::const_iterator iter =
382 383 384
        childItems.begin();
      iter != childItems.end();
      ++iter) {
385 386
    if(shared_ptr<XdmfRectilinearGrid> rectilinearGrid =
       shared_dynamic_cast<XdmfRectilinearGrid>(*iter)) {
387 388 389 390 391 392
      if(rectilinearGrid->getGeometry()->getType()->getDimensions() > 0) {
        this->setCoordinates(rectilinearGrid->getCoordinates());
        break;
      }
    }
  }
393 394
}

395 396
void
XdmfRectilinearGrid::setCoordinates(const unsigned int axisIndex,
397
                                    const shared_ptr<XdmfArray> axisCoordinates)
398
{
399 400 401 402 403 404 405 406 407
  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;
408 409
}

410
void
411
XdmfRectilinearGrid::setCoordinates(const std::vector<shared_ptr<XdmfArray> > axesCoordinates)
412
{
413
  mImpl->mCoordinates = axesCoordinates;
414
}