• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Albany_Catalyst_Grid.cpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2013 Kitware Inc.                     //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 
00007 #include "Albany_Catalyst_Grid.hpp"
00008 
00009 #include "Shards_BasicTopologies.hpp"
00010 
00011 #include "Teuchos_VerboseObject.hpp"
00012 #include "Teuchos_TestForException.hpp"
00013 
00014 #include <vtkIdTypeArray.h>
00015 
00016 #include <cassert>
00017 #include <string>
00018 #include <vector>
00019 
00020 using Teuchos::RCP;
00021 using Teuchos::ArrayRCP;
00022 
00023 namespace Albany {
00024 namespace Catalyst {
00025 
00026 vtkStandardNewMacro(Grid)
00027 vtkStandardNewMacro(GridImplementation)
00028 
00029 GridImplementation::GridImplementation()
00030   : Discretization(NULL),
00031     DegreesOfFreedom(0),
00032     ElementsWsLid(NULL),
00033     ElementOffset(0)
00034 {
00035 }
00036 
00037 GridImplementation::~GridImplementation()
00038 {
00039 }
00040 
00041 void GridImplementation::PrintSelf(ostream &os, vtkIndent indent)
00042 {
00043   this->Superclass::PrintSelf(os, indent);
00044 }
00045 
00046 bool GridImplementation::SetDecorator(Decorator *decorator)
00047 {
00048   this->Discretization = decorator;
00049   this->DegreesOfFreedom = decorator->getNumEq();
00050   this->NodeLookup = decorator->getWsElNodeEqID();
00051 
00052   this->ElementsWsLid = &decorator->getElemGIDws();
00053   // The key of the first entry in the ElementsWsLid is the offset we should
00054   // use when accessing the ids:
00055   if (this->ElementsWsLid->size() > 0) {
00056     WsLIDList::const_iterator first = this->ElementsWsLid->begin();
00057     this->ElementOffset = first->first;
00058   }
00059   else {
00060     this->ElementOffset = 0;
00061   }
00062 
00063   // Build topology LUT
00064   typedef ArrayRCP<RCP<Albany::MeshSpecsStruct> > MeshSpecsT;
00065   typedef MeshSpecsT::const_iterator MeshSpecsIter;
00066   const MeshSpecsT &meshSpecs(decorator->getMeshStruct()->getMeshSpecs());
00067 
00068   typedef ArrayRCP<std::string> RCPStringsT;
00069   const RCPStringsT &ebNames(decorator->getWsEBNames());
00070 
00071   this->CellTypeLookup.resize(ebNames.size(), VTK_EMPTY_CELL);
00072 
00073   for (size_t wsId = 0; wsId < ebNames.size(); ++wsId) {
00074     const std::string &elName(ebNames[wsId]);
00075     for (MeshSpecsIter it = meshSpecs.begin(), itEnd = meshSpecs.end();
00076         it != itEnd; ++it) {
00077       if ((*it)->ebName == elName)  {
00078         this->CellTypeLookup[wsId] = TopologyToCellType(&(*it)->ctd);
00079         break;
00080       }
00081     }
00082     TEUCHOS_TEST_FOR_EXCEPTION(this->CellTypeLookup[wsId] == VTK_EMPTY_CELL,
00083                                std::runtime_error,
00084                                "No CellTopologyData instance found for element "
00085                                "block " << elName);
00086   }
00087 
00088   return true;
00089 }
00090 
00091 vtkIdType GridImplementation::GetNumberOfCells()
00092 {
00093   return static_cast<vtkIdType>(this->ElementsWsLid->size());
00094 }
00095 
00096 int GridImplementation::GetCellType(vtkIdType cellId)
00097 {
00098   int ws = -1;
00099   int unused = -1;
00100   this->GetWorksetFromCellId(cellId, ws, unused);
00101   return this->GetCellTypeFromWorkset(ws);
00102 }
00103 
00104 void GridImplementation::GetCellPoints(vtkIdType cellId, vtkIdList *ptIds)
00105 {
00106   int ws = -1;
00107   int lid = -1;
00108   this->GetWorksetFromCellId(cellId, ws, lid);
00109   typedef Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> > NodesType;
00110   const NodesType &nodes = this->NodeLookup[ws][lid];
00111   vtkIdType cellSize = static_cast<vtkIdType>(nodes.size());
00112   ptIds->SetNumberOfIds(cellSize);
00113 
00114   NodesType::const_iterator nodesIter = nodes.begin();
00115   vtkIdType *ptIdIter = ptIds->GetPointer(0);
00116 
00117   while ((cellSize--) > 0) {
00118     *(ptIdIter++) =
00119         static_cast<vtkIdType>(*(nodesIter++)[0] / this->DegreesOfFreedom);
00120   }
00121 
00122   // For wedge, swap points 0 <--> 1 and 3 <--> 4. All other supported cells
00123   // in VTK match shards' winding.
00124   if (this->GetCellTypeFromWorkset(ws) == VTK_WEDGE) {
00125     using namespace std;
00126     vtkIdType *pts = ptIds->GetPointer(0);
00127     swap(pts[0], pts[1]);
00128     swap(pts[3], pts[4]);
00129   }
00130 }
00131 
00132 namespace {
00133 // predicate for find_if in GetPointCells
00134 struct WsLidMatcher {
00135   wsLid needle;
00136   WsLidMatcher() { needle.ws = 0; needle.LID = 0; }
00137   bool operator()(const WsLIDList::value_type &val) const
00138   {
00139     return (val.second.ws == needle.ws && val.second.LID== needle.LID);
00140   }
00141 };
00142 } // end anon namespace
00143 
00144 void GridImplementation::GetPointCells(vtkIdType ptId, vtkIdList *cellIds)
00145 {
00146   // This is slow. Might be worth optimizing if it becomes a bottleneck.
00147   using Teuchos::ArrayRCP;
00148   typedef ArrayRCP<ArrayRCP<int> > NodeLevel;
00149   typedef ArrayRCP<NodeLevel> LidLevel;
00150 
00151   cellIds->Reset();
00152 
00153   // We'll use these to keep track of our iteration progress and lookup cellids:
00154   WsLidMatcher matcher;
00155   int &ws = matcher.needle.ws;
00156   int &lid = matcher.needle.LID;
00157 
00158   // For lookups
00159   WsLIDList::const_iterator haystackBegin = this->ElementsWsLid->begin();
00160   WsLIDList::const_iterator haystackEnd = this->ElementsWsLid->end();
00161   WsLIDList::const_iterator result;
00162 
00163   // Search for matching pt ids by iterating through all cells.
00164   for (ws = 0; ws < this->NodeLookup.size(); ++ws) {
00165     const LidLevel &lids(this->NodeLookup[ws]);
00166     for (lid = 0; lid < lids.size(); ++lid) {
00167       const NodeLevel &nodes(lids[lid]);
00168       for (int node = 0; node < nodes.size(); ++node) {
00169         if (static_cast<vtkIdType>(nodes[node][0] / this->DegreesOfFreedom)
00170             == ptId) {
00171           result = std::find_if(haystackBegin, haystackEnd, matcher);
00172           if (result != haystackEnd)
00173             cellIds->InsertNextId(static_cast<vtkIdType>(result->first));
00174         }
00175       }
00176     }
00177   }
00178 }
00179 
00180 int GridImplementation::GetMaxCellSize()
00181 {
00182   int size = 0;
00183   for (std::vector<VTKCellType>::const_iterator it = CellTypeLookup.begin(),
00184        itEnd = CellTypeLookup.end(); it != itEnd; ++it)
00185     size = std::max(size, static_cast<int>(GetCellSize(*it)));
00186   return size;
00187 }
00188 
00189 void GridImplementation::GetIdsOfCellsOfType(int type, vtkIdTypeArray *array)
00190 {
00191   // All cells within a workset are homogeneous, so just look for the entries
00192   // CellTypeLookup, which is indexed by WS, then lookup all of the cell ids
00193   // in the global element map.
00194 
00195   // Find worksets:
00196   std::vector<int> worksets;
00197   {
00198     typedef std::vector<VTKCellType>::const_iterator TypeIterT;
00199     TypeIterT begin(this->CellTypeLookup.begin());
00200     TypeIterT end = this->CellTypeLookup.end();
00201     TypeIterT typeIter = begin;
00202     while (typeIter != end) {
00203       if (*typeIter == static_cast<VTKCellType>(type))
00204         worksets.push_back(typeIter - begin);
00205       ++typeIter;
00206     }
00207   }
00208 
00209   // There are usually about 50 cells/workset:
00210   array->SetNumberOfComponents(1);
00211   array->Allocate(static_cast<vtkIdType>(50 * worksets.size()));
00212 
00213   // Get cells:
00214   {
00215     WsLIDList::const_iterator iter = this->ElementsWsLid->begin();
00216     WsLIDList::const_iterator end = this->ElementsWsLid->end();
00217 
00218     typedef std::vector<int>::iterator WsIterT;
00219     WsIterT wsBegin = worksets.begin();
00220     WsIterT wsEnd = worksets.end();
00221 
00222     std::sort(wsBegin, wsEnd);
00223 
00224     while (iter != end) {
00225       if (std::binary_search(wsBegin, wsEnd, iter->second.ws))
00226         array->InsertNextValue(static_cast<vtkIdType>(iter->second.ws));
00227     }
00228   }
00229 }
00230 
00231 int GridImplementation::IsHomogeneous()
00232 {
00233   if (!this->CellTypeLookup.empty()) {
00234     typedef std::vector<VTKCellType>::const_iterator CTIterT;
00235     CTIterT begin = this->CellTypeLookup.begin();
00236     CTIterT end = this->CellTypeLookup.end();
00237     VTKCellType type = *(begin++);
00238     while (begin != end) {
00239       if (*(begin++) != type)
00240         return false;
00241     }
00242   }
00243   return true;
00244 }
00245 
00246 void GridImplementation::Allocate(vtkIdType, int)
00247 {
00248   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00249                              "Read-only container.");
00250 }
00251 
00252 vtkIdType GridImplementation::InsertNextCell(int, vtkIdList*)
00253 {
00254   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00255                              "Read-only container.");
00256   return -1;
00257 }
00258 
00259 vtkIdType GridImplementation::InsertNextCell(int, vtkIdType, vtkIdType*)
00260 {
00261   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00262                              "Read-only container.");
00263   return -1;
00264 }
00265 
00266 vtkIdType GridImplementation::InsertNextCell(int, vtkIdType, vtkIdType*,
00267                                              vtkIdType, vtkIdType*)
00268 {
00269   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00270                              "Read-only container.");
00271   return -1;
00272 }
00273 
00274 void GridImplementation::ReplaceCell(vtkIdType cellId, int npts, vtkIdType *pts)
00275 {
00276   TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00277                              "Read-only container.");
00278 }
00279 
00280 inline VTKCellType GridImplementation::TopologyToCellType(const CellTopologyData *ctd)
00281 {
00285   switch (ctd->key) {
00286   default:
00287     *Teuchos::VerboseObjectBase::getDefaultOStream()
00288         << "Unrecognized key for CellTopologyData name '" << ctd->name << "'.";
00289     return VTK_EMPTY_CELL;
00290   case shards::Particle::key:
00291     return VTK_VERTEX;
00292   case shards::Line<2>::key:
00293     return VTK_LINE;
00294   case shards::Triangle<3>::key:
00295     return VTK_TRIANGLE;
00296   case shards::Quadrilateral<4>::key:
00297     return VTK_QUAD;
00298   case shards::Tetrahedron<4>::key:
00299     return VTK_TETRA;
00300   case shards::Hexahedron<8>::key:
00301     return VTK_HEXAHEDRON;
00302   case shards::Wedge<6>::key:
00303     return VTK_WEDGE;
00304   case shards::Pyramid<5>::key:
00305     return VTK_PYRAMID;
00306   }
00307 }
00308 
00309 inline vtkIdType GridImplementation::GetCellSize(VTKCellType cellType)
00310 {
00311   switch (cellType) {
00312   case VTK_TRIANGLE:
00313     return 3;
00314   case VTK_QUAD:
00315     return 4;
00316   case VTK_LINE:
00317     return 2;
00318   case VTK_TETRA:
00319     return 4;
00320   case VTK_VERTEX:
00321     return 1;
00322   case VTK_HEXAHEDRON:
00323     return 8;
00324   case VTK_WEDGE:
00325     return 6;
00326   case VTK_PYRAMID:
00327     return 5;
00328   default:
00329     *Teuchos::VerboseObjectBase::getDefaultOStream()
00330         << "Unhandled cell type: " << cellType;
00331   case VTK_EMPTY_CELL:
00332     return 0;
00333   }
00334 }
00335 
00336 inline void GridImplementation::GetWorksetFromCellId(vtkIdType cellId,
00337                                                      int &ws, int &lid)
00338 {
00339   WsLIDList::const_iterator match =
00340       this->ElementsWsLid->find(static_cast<int>(cellId) + this->ElementOffset);
00341   if (match != this->ElementsWsLid->end()) {
00342     const wsLid &result = match->second;
00343     ws = result.ws;
00344     lid = result.LID;
00345   }
00346   else {
00347     ws = -1;
00348     lid = -1;
00349   }
00350 }
00351 
00352 VTKCellType GridImplementation::GetCellTypeFromWorkset(int ws)
00353 {
00354   return (ws >= 0 && ws < this->CellTypeLookup.size())
00355       ? this->CellTypeLookup[ws] : VTK_EMPTY_CELL;
00356 }
00357 
00358 } // namespace Catalyst
00359 } // namespace Albany

Generated on Wed Mar 26 2014 18:36:36 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1