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

AlbPUMI_FMDBDiscretization_Def.hpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
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 <limits>
00008 #include "Epetra_Export.h"
00009 
00010 #include "Albany_Utils.hpp"
00011 #include "AlbPUMI_FMDBDiscretization.hpp"
00012 #include <string>
00013 #include <iostream>
00014 #include <fstream>
00015 
00016 #include <Shards_BasicTopologies.hpp>
00017 #include "Shards_CellTopology.hpp"
00018 #include "Shards_CellTopologyData.h"
00019 
00020 #include <PHAL_Dimension.hpp>
00021 
00022 #include <apfMesh.h>
00023 #include <apfShape.h>
00024 
00025 template<class Output>
00026 AlbPUMI::FMDBDiscretization<Output>::FMDBDiscretization(Teuchos::RCP<AlbPUMI::FMDBMeshStruct> fmdbMeshStruct_,
00027             const Teuchos::RCP<const Epetra_Comm>& comm_,
00028             const Teuchos::RCP<Piro::MLRigidBodyModes>& rigidBodyModes_) :
00029   out(Teuchos::VerboseObjectBase::getDefaultOStream()),
00030   previous_time_label(-1.0e32),
00031   comm(comm_),
00032   rigidBodyModes(rigidBodyModes_),
00033   neq(fmdbMeshStruct_->neq),
00034   fmdbMeshStruct(fmdbMeshStruct_),
00035   interleavedOrdering(fmdbMeshStruct_->interleavedOrdering),
00036   outputInterval(0),
00037   meshOutput(*fmdbMeshStruct_, comm_)
00038 {
00039   AlbPUMI::FMDBDiscretization<Output>::updateMesh();
00040 
00041   Teuchos::Array<std::string> layout = fmdbMeshStruct->solVectorLayout;
00042   int index;
00043 
00044   for (std::size_t i=0; i < layout.size(); i+=2) {
00045     solNames.push_back(layout[i]);
00046     resNames.push_back(layout[i].append("Res"));
00047     if (layout[i+1] == "S") {
00048       index = 1;
00049       solIndex.push_back(index);
00050     }
00051     else if (layout[i+1] == "V") {
00052       index = getNumDim();
00053       solIndex.push_back(index);
00054     }
00055   }
00056 
00057 }
00058 
00059 template<class Output>
00060 AlbPUMI::FMDBDiscretization<Output>::~FMDBDiscretization()
00061 {
00062 }
00063 
00064 template<class Output>
00065 Teuchos::RCP<const Epetra_Map>
00066 AlbPUMI::FMDBDiscretization<Output>::getMap() const
00067 {
00068   return map;
00069 }
00070 
00071 template<class Output>
00072 Teuchos::RCP<const Epetra_Map>
00073 AlbPUMI::FMDBDiscretization<Output>::getOverlapMap() const
00074 {
00075   return overlap_map;
00076 }
00077 
00078 template<class Output>
00079 Teuchos::RCP<const Epetra_CrsGraph>
00080 AlbPUMI::FMDBDiscretization<Output>::getJacobianGraph() const
00081 {
00082   return graph;
00083 }
00084 
00085 template<class Output>
00086 Teuchos::RCP<const Epetra_CrsGraph>
00087 AlbPUMI::FMDBDiscretization<Output>::getOverlapJacobianGraph() const
00088 {
00089   return overlap_graph;
00090 }
00091 
00092 template<class Output>
00093 Teuchos::RCP<const Epetra_Map>
00094 AlbPUMI::FMDBDiscretization<Output>::getNodeMap() const
00095 {
00096   return node_map;
00097 }
00098 
00099 template<class Output>
00100 Teuchos::RCP<const Epetra_Map>
00101 AlbPUMI::FMDBDiscretization<Output>::getOverlapNodeMap() const
00102 {
00103   return overlap_node_map;
00104 }
00105 
00106 template<class Output>
00107 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> > > >::type&
00108 AlbPUMI::FMDBDiscretization<Output>::getWsElNodeEqID() const
00109 {
00110   return wsElNodeEqID;
00111 }
00112 
00113 template<class Output>
00114 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> > >::type&
00115 AlbPUMI::FMDBDiscretization<Output>::getWsElNodeID() const
00116 {
00117   return wsElNodeID;
00118 }
00119 
00120 template<class Output>
00121 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type&
00122 AlbPUMI::FMDBDiscretization<Output>::getCoords() const
00123 {
00124   return coords;
00125 }
00126 
00127 template<class Output>
00128 void
00129 AlbPUMI::FMDBDiscretization<Output>::printCoords() const
00130 {
00131   int mesh_dim;
00132   FMDB_Mesh_GetDim(fmdbMeshStruct->getMesh(), &mesh_dim);
00133 
00134 std::cout << "Processor " << SCUTIL_CommRank() << " has " << coords.size() << " worksets." << std::endl;
00135 
00136        for (int ws=0; ws<coords.size(); ws++) {  //workset
00137          for (int e=0; e<coords[ws].size(); e++) { //cell
00138            for (int j=0; j<coords[ws][e].size(); j++) { //node
00139              for (int d=0; d<mesh_dim; d++){  //node
00140 std::cout << "Coord for workset: " << ws << " element: " << e << " node: " << j << " DOF: " << d << " is: " <<
00141                 coords[ws][e][j][d] << std::endl;
00142        } } } }
00143 
00144 }
00145 
00146 template<class Output>
00147 Teuchos::ArrayRCP<double>&
00148 AlbPUMI::FMDBDiscretization<Output>::getCoordinates() const
00149 {
00150   coordinates.resize(3 * numOverlapNodes);
00151   apf::Field* f = fmdbMeshStruct->apfMesh->getCoordinateField();
00152   for (size_t i=0; i < nodes.getSize(); ++i)
00153     apf::getComponents(f,nodes[i].entity,nodes[i].node,&(coordinates[3*i]));
00154   return coordinates;
00155 }
00156 
00157 // FELIX uninitialized variables (FIXME)
00158 template<class Output>
00159 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double> > >::type&
00160 AlbPUMI::FMDBDiscretization<Output>::getSurfaceHeight() const
00161 {
00162   return sHeight;
00163 }
00164 
00165 template<class Output>
00166 const Albany::WorksetArray<Teuchos::ArrayRCP<double> >::type&
00167 AlbPUMI::FMDBDiscretization<Output>::getTemperature() const
00168 {
00169   return temperature;
00170 }
00171 
00172 template<class Output>
00173 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double> > >::type&
00174 AlbPUMI::FMDBDiscretization<Output>::getBasalFriction() const
00175 {
00176   return basalFriction;
00177 }
00178 
00179 template<class Output>
00180 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double> > >::type&
00181 AlbPUMI::FMDBDiscretization<Output>::getThickness() const
00182 {
00183   return thickness;
00184 }
00185 
00186 template<class Output>
00187 const Albany::WorksetArray<Teuchos::ArrayRCP<double> >::type&
00188 AlbPUMI::FMDBDiscretization<Output>::getFlowFactor() const
00189 {
00190   return flowFactor;
00191 }
00192 
00193 template<class Output>
00194 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type&
00195 AlbPUMI::FMDBDiscretization<Output>::getSurfaceVelocity() const
00196 {
00197   return surfaceVelocity;
00198 }
00199 
00200 template<class Output>
00201 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type&
00202 AlbPUMI::FMDBDiscretization<Output>::getVelocityRMS() const
00203 {
00204   return velocityRMS;
00205 }
00206 
00207 //The function transformMesh() maps a unit cube domain by applying the transformation
00208 //x = L*x
00209 //y = L*y
00210 //z = s(x,y)*z + b(x,y)*(1-z)
00211 //where b(x,y) and s(x,y) are curves specifying the bedrock and top surface
00212 //geometries respectively.
00213 //Currently this function is only needed for some FELIX problems.
00214 
00215 template<class Output>
00216 void
00217 AlbPUMI::FMDBDiscretization<Output>::setupMLCoords()
00218 {
00219 
00220   // Function to return x,y,z at owned nodes as double*, specifically for ML
00221 
00222   // if ML is not used, return
00223 
00224   if(rigidBodyModes.is_null()) return;
00225 
00226   if(!rigidBodyModes->isMLUsed()) return;
00227 
00228   // get mesh dimension and part handle
00229   int mesh_dim, counter=0;
00230   FMDB_Mesh_GetDim(fmdbMeshStruct->getMesh(), &mesh_dim);
00231   pPart part;
00232   FMDB_Mesh_GetPart(fmdbMeshStruct->getMesh(), 0, part);
00233 
00234   rigidBodyModes->resize(mesh_dim, numOwnedNodes);
00235 
00236   double *xx;
00237   double *yy;
00238   double *zz;
00239 
00240   rigidBodyModes->getCoordArrays(&xx, &yy, &zz);
00241 
00242   double* node_coords=new double[3];
00243 
00244   pPartEntIter node_it;
00245   pMeshEnt node;
00246 
00247   int owner_partid, iterEnd = FMDB_PartEntIter_Init(part, FMDB_VERTEX, FMDB_ALLTOPO, node_it);
00248 
00249   /* DAI: this function also has to change for high-order fields */
00250   while (!iterEnd)
00251   {
00252     iterEnd = FMDB_PartEntIter_GetNext(node_it, node);
00253     if (iterEnd) break;
00254 
00255     FMDB_Ent_GetOwnPartID(node, part, &owner_partid);
00256     if (owner_partid!=FMDB_Part_ID(part)) continue; // skip un-owned entity
00257 
00258     FMDB_Vtx_GetCoord (node, node_coords);
00259     xx[counter]=node_coords[0];
00260     yy[counter]=node_coords[1];
00261     if (mesh_dim>2) zz[counter]=node_coords[2];
00262     ++counter;
00263   }
00264 
00265   FMDB_PartEntIter_Del (node_it);
00266   delete [] node_coords;
00267 
00268   rigidBodyModes->informML();
00269 
00270 }
00271 
00272 
00273 template<class Output>
00274 const Albany::WorksetArray<std::string>::type&
00275 AlbPUMI::FMDBDiscretization<Output>::getWsEBNames() const
00276 {
00277   return wsEBNames;
00278 }
00279 
00280 template<class Output>
00281 const Albany::WorksetArray<int>::type&
00282 AlbPUMI::FMDBDiscretization<Output>::getWsPhysIndex() const
00283 {
00284   return wsPhysIndex;
00285 }
00286 
00287 template<class Output>
00288 void AlbPUMI::FMDBDiscretization<Output>::setField(
00289     const char* name,
00290     const Epetra_Vector& data,
00291     bool overlapped,
00292     int offset)
00293 {
00294   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00295   apf::Field* f = m->findField(name);
00296   apf::Numbering* n = m->findNumbering("apf_owned_numbering");
00297   for (size_t i=0; i < nodes.getSize(); ++i)
00298   {
00299     apf::Node node = nodes[i];
00300     int node_gid = apf::getNumber(n,node.entity,node.node,0);
00301     int node_lid;
00302     if (overlapped)
00303       node_lid = overlap_node_map->LID(node_gid);
00304     else
00305     {
00306       if ( ! m->isOwned(node.entity)) continue;
00307       node_lid = node_map->LID(node_gid);
00308     }
00309     int firstDOF = getDOF(node_lid,offset);
00310     apf::setComponents(f,node.entity,node.node,&(data[firstDOF]));
00311   }
00312   if ( ! overlapped)
00313     apf::synchronize(f);
00314 }
00315 
00316 template<class Output>
00317 void AlbPUMI::FMDBDiscretization<Output>::setSplitFields(std::vector<std::string> names,
00318     std::vector<int> indices, const Epetra_Vector& data, bool overlapped)
00319 {
00320   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00321   int offset = 0;
00322   int indexSum = 0;
00323   for (std::size_t i=0; i < names.size(); ++i)
00324   {
00325     assert(indexSum==offset);
00326     this->setField(names[i].c_str(),data,overlapped,offset);
00327     offset += apf::countComponents(m->findField(names[i].c_str()));
00328     indexSum += indices[i];
00329   }
00330 }
00331 
00332 template<class Output>
00333 void AlbPUMI::FMDBDiscretization<Output>::getField(
00334     const char* name,
00335     Epetra_Vector& data,
00336     bool overlapped,
00337     int offset) const
00338 {
00339   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00340   apf::Field* f = m->findField(name);
00341   apf::Numbering* n = m->findNumbering("apf_owned_numbering");
00342   for (size_t i=0; i < nodes.getSize(); ++i)
00343   {
00344     apf::Node node = nodes[i];
00345     int node_gid = apf::getNumber(n,node.entity,node.node,0);
00346     int node_lid = node_map->LID(node_gid);
00347     if (overlapped)
00348       node_lid = overlap_node_map->LID(node_gid);
00349     else
00350     {
00351       if ( ! m->isOwned(node.entity)) continue;
00352       node_lid = node_map->LID(node_gid);
00353     }
00354     int firstDOF = getDOF(node_lid,offset);
00355 /* the only difference between setField and getField is this one char:
00356          V                                                           */
00357     apf::getComponents(f,node.entity,node.node,&(data[firstDOF]));
00358   }
00359 }
00360 
00361 template<class Output>
00362 void AlbPUMI::FMDBDiscretization<Output>::getSplitFields(std::vector<std::string> names,
00363    std::vector<int> indices, Epetra_Vector& data, bool overlapped) const
00364 {
00365   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00366   int offset = 0;
00367   int indexSum = 0;
00368   for (std::size_t i=0; i < names.size(); ++i)
00369   {
00370     assert(indexSum==offset);
00371  
00372     this->getField(names[i].c_str(),data,overlapped,offset);
00373     offset += apf::countComponents(m->findField(names[i].c_str()));
00374     indexSum += indices[i];
00375   }
00376 }
00377 
00378 
00379 template<class Output>
00380 void AlbPUMI::FMDBDiscretization<Output>::writeSolution(const Epetra_Vector& soln, const double time_value,
00381        const bool overlapped){
00382 
00383   if (fmdbMeshStruct->outputFileName.empty())
00384     return;
00385 
00386   // Skip this write unless the proper interval has been reached
00387   if(outputInterval++ % fmdbMeshStruct->outputInterval)
00388     return;
00389 
00390   double time_label = monotonicTimeLabel(time_value);
00391   int out_step = 0;
00392 
00393   if (map->Comm().MyPID()==0) {
00394     *out << "AlbPUMI::FMDBDiscretization::writeSolution: writing time " << time_value;
00395     if (time_label != time_value) *out << " with label " << time_label;
00396     *out << " to index " <<out_step<<" in file "<<fmdbMeshStruct->outputFileName<< std::endl;
00397   }
00398 
00399   if (solNames.size() == 0)
00400     this->setField("solution",soln,overlapped);
00401   else
00402     this->setSplitFields(solNames,solIndex,soln,overlapped);
00403 
00404   fmdbMeshStruct->solutionInitialized = true;
00405 
00406   outputInterval = 0;
00407 
00408   copyQPStatesToAPF();
00409   meshOutput.writeFile(time_label);
00410   removeQPStatesFromAPF();
00411 
00412 }
00413 
00414 template<class Output>
00415 void
00416 AlbPUMI::FMDBDiscretization<Output>::debugMeshWriteNative(const Epetra_Vector& soln, const char* filename){
00417 
00418   if (solNames.size() == 0 )
00419     this->setField("solution",soln,/*overlapped=*/false);
00420   else
00421     this->setSplitFields(solNames,solIndex,soln,/*overlapped=*/false);
00422 
00423   fmdbMeshStruct->solutionInitialized = true;
00424   fmdbMeshStruct->apfMesh->writeNative(filename);
00425 
00426 }
00427 
00428 template<class Output>
00429 void
00430 AlbPUMI::FMDBDiscretization<Output>::debugMeshWrite(const Epetra_Vector& soln, const char* filename){
00431 
00432   if (solNames.size() == 0 )
00433     this->setField("solution",soln,/*overlapped=*/false);
00434   else
00435     this->setSplitFields(solNames,solIndex,soln,/*overlapped=*/false);
00436 
00437   if (! PCU_Comm_Self()) {
00438     std::cout << "************************************************" << std::endl;
00439     std::cout << "Writing mesh debug output! " << std::endl;
00440     std::cout << "************************************************" << std::endl;
00441     std::cout << std::endl;
00442   }
00443 
00444   fmdbMeshStruct->solutionInitialized = true;
00445 
00446   copyQPStatesToAPF();
00447   meshOutput.debugMeshWrite(filename);
00448   removeQPStatesFromAPF();
00449 
00450 }
00451 
00452 template<class Output>
00453 double
00454 AlbPUMI::FMDBDiscretization<Output>::monotonicTimeLabel(const double time)
00455 {
00456   // If increasing, then all is good
00457   if (time > previous_time_label) {
00458     previous_time_label = time;
00459     return time;
00460   }
00461 // Try absolute value
00462   double time_label = fabs(time);
00463   if (time_label > previous_time_label) {
00464     previous_time_label = time_label;
00465     return time_label;
00466   }
00467 
00468   // Try adding 1.0 to time
00469   if (time_label+1.0 > previous_time_label) {
00470     previous_time_label = time_label+1.0;
00471     return time_label+1.0;
00472   }
00473 
00474   // Otherwise, just add 1.0 to previous
00475   previous_time_label += 1.0;
00476   return previous_time_label;
00477 }
00478 
00479 template<class Output>
00480 void
00481 AlbPUMI::FMDBDiscretization<Output>::setResidualField(const Epetra_Vector& residual)
00482 {
00483   if (solNames.size() == 0)
00484     this->setField("residual",residual,/*overlapped=*/false);
00485   else
00486     this->setSplitFields(resNames,solIndex,residual,/*overlapped=*/false);
00487 
00488   fmdbMeshStruct->residualInitialized = true;
00489 }
00490 
00491 template<class Output>
00492 Teuchos::RCP<Epetra_Vector>
00493 AlbPUMI::FMDBDiscretization<Output>::getSolutionField() const
00494 {
00495   // Copy soln vector into solution field, one node at a time
00496   Teuchos::RCP<Epetra_Vector> soln = Teuchos::rcp(new Epetra_Vector(*map));
00497 
00498   if (fmdbMeshStruct->solutionInitialized) {
00499     if (solNames.size() == 0)
00500       this->getField("solution",*soln,/*overlapped=*/false);
00501     else
00502       this->getSplitFields(solNames,solIndex,*soln,/*overlapped=*/false);
00503   }
00504   else if ( ! PCU_Comm_Self())
00505     *out <<__func__<<": uninit field" << std::endl;
00506 
00507   return soln;
00508 }
00509 
00510 template<class Output>
00511 void
00512 AlbPUMI::FMDBDiscretization<Output>::setSolutionField(const Epetra_Vector& soln)
00513 {
00514   if (solNames.size() == 0)
00515     this->setField("solution",soln,/*overlapped=*/false);
00516   else
00517     this->setSplitFields(solNames,solIndex,soln,/*overlapped=*/false);
00518 
00519   fmdbMeshStruct->solutionInitialized = true;
00520 }
00521 
00522 
00523 template<class Output>
00524 int AlbPUMI::FMDBDiscretization<Output>::nonzeroesPerRow(const int neq) const
00525 {
00526   int numDim;
00527   FMDB_Mesh_GetDim(fmdbMeshStruct->getMesh(), &numDim);
00528 
00529   /* DAI: this function should be revisited for overall correctness,
00530      especially in the case of higher-order fields */
00531   int estNonzeroesPerRow;
00532   switch (numDim) {
00533   case 0: estNonzeroesPerRow=1*neq; break;
00534   case 1: estNonzeroesPerRow=3*neq; break;
00535   case 2: estNonzeroesPerRow=9*neq; break;
00536   case 3: estNonzeroesPerRow=27*neq; break;
00537   default: TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00538             "FMDBDiscretization:  Bad numDim"<< numDim);
00539   }
00540   return estNonzeroesPerRow;
00541 }
00542 
00543 template<class Output>
00544 void AlbPUMI::FMDBDiscretization<Output>::computeOwnedNodesAndUnknowns()
00545 {
00546   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00547   apf::Numbering* n = m->findNumbering("apf_owned_numbering");
00548   if (n) apf::destroyNumbering(n);
00549   n = apf::numberOwnedNodes(m,"apf_owned_numbering");
00550   apf::globalize(n); /* turn local numbering to global numbering */
00551   apf::DynamicArray<apf::Node> ownedNodes;
00552   apf::getNodes(n,ownedNodes);
00553   numOwnedNodes = ownedNodes.getSize();
00554   apf::synchronize(n); /* this puts owned node numbers on non-owned overlap nodes */
00555   std::vector<int> indices(numOwnedNodes);
00556   for (int i=0; i < numOwnedNodes; ++i)
00557     indices[i] = getNumber(n,ownedNodes[i].entity,ownedNodes[i].node,0);
00558   node_map = Teuchos::rcp(new Epetra_Map(-1, numOwnedNodes,
00559            &(indices[0]), 0, *comm));
00560   numGlobalNodes = node_map->MaxAllGID() + 1;
00561   if(Teuchos::nonnull(fmdbMeshStruct->nodal_data_block))
00562     fmdbMeshStruct->nodal_data_block->resizeLocalMap(indices, *comm);
00563   indices.resize(numOwnedNodes*neq);
00564   for (int i=0; i < numOwnedNodes; ++i)
00565     for (int j=0; j < neq; ++j)
00566       indices[getDOF(i,j)] = 
00567         getDOF(getNumber(n,ownedNodes[i].entity,ownedNodes[i].node,0),j);
00568   map = Teuchos::rcp(new Epetra_Map(-1, indices.size(), &(indices[0]), 0, *comm));
00569 }
00570 
00571 template <class Output>
00572 void AlbPUMI::FMDBDiscretization<Output>::computeOverlapNodesAndUnknowns()
00573 {
00574   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00575   apf::Numbering* overlap = m->findNumbering("apf_overlap_numbering");
00576   if (overlap) apf::destroyNumbering(overlap);
00577   overlap = apf::numberOverlapNodes(m,"apf_overlap_numbering");
00578   apf::getNodes(overlap,nodes);
00579   numOverlapNodes = nodes.getSize();
00580   std::vector<int> nodeIndices(numOverlapNodes);
00581   std::vector<int> dofIndices(numOverlapNodes*neq);
00582   apf::Numbering* owned = m->findNumbering("apf_owned_numbering");
00583   for (int i=0; i < numOverlapNodes; ++i)
00584   {
00585     int global = apf::getNumber(owned,nodes[i].entity,nodes[i].node,0);
00586     nodeIndices[i] = global;
00587     for (int j=0; j < neq; ++j)
00588       dofIndices[getDOF(i,j)] = getDOF(global,j);
00589   }
00590   overlap_node_map = Teuchos::rcp(new Epetra_Map(-1, nodeIndices.size(),
00591              &(nodeIndices[0]), 0, *comm));
00592   overlap_map = Teuchos::rcp(new Epetra_Map(-1, dofIndices.size(),
00593               &(dofIndices[0]), 0, *comm));
00594   if(Teuchos::nonnull(fmdbMeshStruct->nodal_data_block))
00595     fmdbMeshStruct->nodal_data_block->resizeOverlapMap(nodeIndices, *comm);
00596 }
00597 
00598 template<class Output>
00599 void AlbPUMI::FMDBDiscretization<Output>::computeGraphs()
00600 {
00601   // GAH: the following assumes all element blocks in the problem have the same
00602   // number of nodes per element and that the cell topologies are the same.
00603   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00604   int numDim = m->getDimension();
00605   std::vector<apf::MeshEntity*> cells;
00606   cells.reserve(m->count(numDim));
00607   apf::MeshIterator* it = m->begin(numDim);
00608   apf::MeshEntity* e;
00609   while ((e = m->iterate(it)))
00610     cells.push_back(e);
00611   m->end(it);
00612   //got cells, count the nodes on the first one
00613   apf::Numbering* n = m->findNumbering("apf_owned_numbering");
00614   int nodes_per_element = apf::countElementNodes(
00615       apf::getShape(n),m->getType(cells[0]));
00616   /* construct the overlap graph of all local DOFs as they
00617      are coupled by element-node connectivity */
00618   overlap_graph =
00619     Teuchos::rcp(new Epetra_CrsGraph(Copy, *overlap_map,
00620                                      neq*nodes_per_element, false));
00621   for (size_t i=0; i < cells.size(); ++i)
00622   {
00623     apf::NewArray<int> cellNodes;
00624     apf::getElementNumbers(n,cells[i],cellNodes);
00625     for (int j=0; j < nodes_per_element; ++j)
00626     {
00627       for (int k=0; k < neq; ++k)
00628       {
00629         int row = getDOF(cellNodes[j],k);
00630         for (int l=0; l < nodes_per_element; ++l)
00631         {
00632           for (int m=0; m < neq; ++m)
00633           {
00634             int col = getDOF(cellNodes[l],m);
00635             overlap_graph->InsertGlobalIndices(row,1,&col);
00636           }
00637         }
00638       }
00639     }
00640   }
00641   overlap_graph->FillComplete();
00642 
00643   // Create Owned graph by exporting overlap with known row map
00644 
00645   graph = Teuchos::rcp(new Epetra_CrsGraph(Copy, *map, nonzeroesPerRow(neq), false));
00646 
00647   // Create non-overlapped matrix using two maps and export object
00648   Epetra_Export exporter(*overlap_map, *map);
00649   graph->Export(*overlap_graph, exporter, Insert);
00650   graph->FillComplete();
00651 }
00652 
00653 template<class Output>
00654 void AlbPUMI::FMDBDiscretization<Output>::computeWorksetInfo()
00655 {
00656   apf::Mesh* m = fmdbMeshStruct->apfMesh;
00657   int numDim = m->getDimension();
00658   apf::Numbering* en = m->findNumbering("apf_element_numbering");
00659   if (en) apf::destroyNumbering(en);
00660   en = apf::numberElements(m,"apf_element_numbering");
00661   apf::globalize(en);
00662   apf::Numbering* nn = m->findNumbering("apf_owned_numbering");
00663 
00664 /*
00665    * Note: Max workset size is given in input file, or set to a default in AlbPUMI_FMDBMeshStruct.cpp
00666    * The workset size is set in AlbPUMI_FMDBMeshStruct.cpp to be the maximum number in an element block if
00667    * the element block size < Max workset size.
00668    * STK bucket size is set to the workset size. We will "chunk" the elements into worksets here.
00669    *
00670 */
00671 
00672   // This function is called each adaptive cycle. Need to reset the 2D array "buckets" back to the initial size.
00673 
00674   for(int i = 0; i < buckets.size(); i++)
00675     buckets[i].clear();
00676 
00677   buckets.clear();
00678 
00679   pGeomEnt elem_blk;
00680   std::map<pElemBlk, int> bucketMap;
00681   std::map<pElemBlk, int>::iterator buck_it;
00682   int bucket_counter = 0;
00683 
00684   int worksetSize = fmdbMeshStruct->worksetSize;
00685 
00686   // iterate over all elements
00687   apf::MeshIterator* it = m->begin(numDim);
00688   apf::MeshEntity* element;
00689   while ((element = m->iterate(it)))
00690   {
00691 
00692     // skip owned elements
00693     if ( ! m->isOwned(element))
00694       continue;
00695 
00696     // Get the element block that the element is in
00697     elem_blk = reinterpret_cast<pGeomEnt>(m->toModel(element));
00698 
00699     // find which bucket holds the elements for the element block
00700     buck_it = bucketMap.find(elem_blk);
00701 
00702     if((buck_it == bucketMap.end()) ||  // Make a new bucket to hold the new element block's elements
00703        (buckets[buck_it->second].size() >= worksetSize)){ // old bucket is full, put the element in a new one
00704 
00705       // Associate this elem_blk with a new bucket
00706       bucketMap[elem_blk] = bucket_counter;
00707 
00708       // resize the bucket array larger by one
00709       buckets.resize(bucket_counter + 1);
00710       wsEBNames.resize(bucket_counter + 1);
00711 
00712       // save the element in the bucket
00713       buckets[bucket_counter].push_back(element);
00714 
00715       // save the name of the new element block
00716       std::string EB_name;
00717       PUMI_ElemBlk_GetName(elem_blk, EB_name);
00718       wsEBNames[bucket_counter] = EB_name;
00719 
00720       bucket_counter++;
00721 
00722     }
00723     else { // put the element in the proper bucket
00724 
00725       buckets[buck_it->second].push_back(element);
00726 
00727     }
00728 
00729   }
00730 
00731   int numBuckets = bucket_counter;
00732 
00733   wsPhysIndex.resize(numBuckets);
00734 
00735   if (fmdbMeshStruct->allElementBlocksHaveSamePhysics)
00736     for (int i=0; i<numBuckets; i++) wsPhysIndex[i]=0;
00737   else
00738     for (int i=0; i<numBuckets; i++) wsPhysIndex[i]=fmdbMeshStruct->ebNameToIndex[wsEBNames[i]];
00739 
00740   // Fill  wsElNodeEqID(workset, el_LID, local node, Eq) => unk_LID
00741 
00742   wsElNodeEqID.resize(numBuckets);
00743   wsElNodeID.resize(numBuckets);
00744   coords.resize(numBuckets);
00745   sHeight.resize(numBuckets);
00746   temperature.resize(numBuckets);
00747   basalFriction.resize(numBuckets);
00748   thickness.resize(numBuckets);
00749   surfaceVelocity.resize(numBuckets);
00750   velocityRMS.resize(numBuckets);
00751   flowFactor.resize(numBuckets);
00752   surfaceVelocity.resize(numBuckets);
00753   velocityRMS.resize(numBuckets);
00754 
00755   // Clear map if remeshing
00756   if(!elemGIDws.empty()) elemGIDws.clear();
00757 
00758   /* this block of code creates the wsElNodeEqID,
00759      wsElNodeID, and coords structures.
00760      These are (bucket, element, element_node, dof)-indexed
00761      structures to get numbers or coordinates */
00762   for (int b=0; b < numBuckets; b++) {
00763 
00764     std::vector<apf::MeshEntity*>& buck = buckets[b];
00765     wsElNodeEqID[b].resize(buck.size());
00766     wsElNodeID[b].resize(buck.size());
00767     coords[b].resize(buck.size());
00768 
00769     // i is the element index within bucket b
00770 
00771     for (std::size_t i=0; i < buck.size(); i++) {
00772 
00773       // Traverse all the elements in this bucket
00774       element = buck[i];
00775 
00776       // Now, save a map from element GID to workset on this PE
00777       elemGIDws[apf::getNumber(en,element,0,0)].ws = b;
00778 
00779       // Now, save a map element GID to local id on this workset on this PE
00780       elemGIDws[apf::getNumber(en,element,0,0)].LID = i;
00781 
00782       // get global node numbers
00783       apf::NewArray<int> nodeIDs;
00784       apf::getElementNumbers(nn,element,nodeIDs);
00785 
00786       int nodes_per_element = apf::countElementNodes(apf::getShape(nn),m->getType(element));
00787       wsElNodeEqID[b][i].resize(nodes_per_element);
00788       wsElNodeID[b][i].resize(nodes_per_element);
00789       coords[b][i].resize(nodes_per_element);
00790 
00791       // loop over local nodes
00792 
00793       for (int j=0; j < nodes_per_element; j++) {
00794 
00795         int node_gid = nodeIDs[j];
00796         int node_lid = overlap_node_map->LID(node_gid);
00797 
00798         TEUCHOS_TEST_FOR_EXCEPTION(node_lid<0, std::logic_error,
00799          "FMDB1D_Disc: node_lid out of range " << node_lid << std::endl);
00800 
00801         coords[b][i][j] = &coordinates[node_lid * 3];
00802         wsElNodeEqID[b][i][j].resize(neq);
00803         wsElNodeID[b][i][j] = node_gid;
00804 
00805         for (std::size_t eq=0; eq < neq; eq++)
00806           wsElNodeEqID[b][i][j][eq] = getDOF(node_lid,eq);
00807 
00808       }
00809     }
00810   }
00811 
00812   // (Re-)allocate storage for element data
00813   //
00814   // For each state, create storage for the data for on processor elements
00815   // elemGIDws.size() is the number of elements on this processor ...
00816   // Note however that Intrepid will stride over numBuckets * worksetSize
00817   // so we must allocate enough storage for that
00818 
00819   std::size_t numElementsAccessed = numBuckets * worksetSize;
00820 
00821   for (std::size_t i=0; i<fmdbMeshStruct->qpscalar_states.size(); i++) {
00822       fmdbMeshStruct->qpscalar_states[i]->reAllocateBuffer(numElementsAccessed);
00823   }
00824   for (std::size_t i=0; i<fmdbMeshStruct->qpvector_states.size(); i++) {
00825       fmdbMeshStruct->qpvector_states[i]->reAllocateBuffer(numElementsAccessed);
00826   }
00827   for (std::size_t i=0; i<fmdbMeshStruct->qptensor_states.size(); i++) {
00828       fmdbMeshStruct->qptensor_states[i]->reAllocateBuffer(numElementsAccessed);
00829   }
00830   for (std::size_t i=0; i<fmdbMeshStruct->scalarValue_states.size(); i++) {
00831       // special case : need to store one double value that represents all the elements in the workset (time)
00832       // numBuckets are the number of worksets
00833       fmdbMeshStruct->scalarValue_states[i]->reAllocateBuffer(numBuckets);
00834   }
00835 
00836   // Pull out pointers to shards::Arrays for every bucket, for every state
00837 
00838   // Note that numBuckets is typically larger each time the mesh is adapted
00839 
00840   stateArrays.elemStateArrays.resize(numBuckets);
00841 
00842   for (std::size_t b=0; b < buckets.size(); b++) {
00843 
00844     std::vector<apf::MeshEntity*>& buck = buckets[b];
00845 
00846     for (std::size_t i=0; i<fmdbMeshStruct->qpscalar_states.size(); i++) {
00847       stateArrays.elemStateArrays[b][fmdbMeshStruct->qpscalar_states[i]->name] =
00848                  fmdbMeshStruct->qpscalar_states[i]->getMDA(buck.size());
00849     }
00850     for (std::size_t i=0; i<fmdbMeshStruct->qpvector_states.size(); i++) {
00851       stateArrays.elemStateArrays[b][fmdbMeshStruct->qpvector_states[i]->name] =
00852                  fmdbMeshStruct->qpvector_states[i]->getMDA(buck.size());
00853     }
00854     for (std::size_t i=0; i<fmdbMeshStruct->qptensor_states.size(); i++) {
00855       stateArrays.elemStateArrays[b][fmdbMeshStruct->qptensor_states[i]->name] =
00856                  fmdbMeshStruct->qptensor_states[i]->getMDA(buck.size());
00857     }
00858     for (std::size_t i=0; i<fmdbMeshStruct->scalarValue_states.size(); i++) {
00859       // Store one double precision value per workset
00860       const int size = 1;
00861       stateArrays.elemStateArrays[b][fmdbMeshStruct->scalarValue_states[i]->name] =
00862                  fmdbMeshStruct->scalarValue_states[i]->getMDA(size);
00863     }
00864   }
00865 
00866 // Process node data sets if present
00867 
00868   if(Teuchos::nonnull(fmdbMeshStruct->nodal_data_block)){
00869 
00870     std::vector< std::vector<apf::Node> > nbuckets; // bucket of nodes
00871     int numNodeBuckets =  (int)ceil((double)numOwnedNodes / (double)worksetSize);
00872 
00873     nbuckets.resize(numNodeBuckets);
00874     int node_bucket_counter = 0;
00875     int node_in_bucket = 0;
00876 
00877     // iterate over all nodes and save the owned ones into buckets
00878     for (size_t i=0; i < nodes.getSize(); ++i)
00879       if (m->isOwned(nodes[i].entity))
00880       {
00881         nbuckets[node_bucket_counter].push_back(nodes[i]);
00882         node_in_bucket++;
00883         if (node_in_bucket >= worksetSize) {
00884           ++node_bucket_counter;
00885           node_in_bucket = 0;
00886         }
00887       }
00888 
00889     Teuchos::RCP<Albany::NodeFieldContainer> node_states = fmdbMeshStruct->nodal_data_block->getNodeContainer();
00890 
00891     stateArrays.nodeStateArrays.resize(numNodeBuckets);
00892 
00893     // Loop over all the node field containers
00894     for (Albany::NodeFieldContainer::iterator nfs = node_states->begin();
00895                 nfs != node_states->end(); ++nfs){
00896       Teuchos::RCP<AlbPUMI::AbstractPUMINodeFieldContainer> nodeContainer =
00897              Teuchos::rcp_dynamic_cast<AlbPUMI::AbstractPUMINodeFieldContainer>((*nfs).second);
00898 
00899       // resize the container to hold all the owned node's data
00900       nodeContainer->resize(node_map);
00901 
00902       // Now, loop over each workset to get a reference to each workset collection of nodes
00903       for (std::size_t b=0; b < nbuckets.size(); b++) {
00904          std::vector<apf::Node>& buck = nbuckets[b];
00905          stateArrays.nodeStateArrays[b][(*nfs).first] = nodeContainer->getMDA(buck);
00906       }
00907     }
00908   }
00909 }
00910 
00911 template<class Output>
00912 void AlbPUMI::FMDBDiscretization<Output>::copyQPScalarToAPF(
00913     unsigned nqp,
00914     QPData<double, 2>& state,
00915     apf::Field* f)
00916 {
00917   for (std::size_t b=0; b < buckets.size(); ++b) {
00918     std::vector<apf::MeshEntity*>& buck = buckets[b];
00919     Albany::MDArray& ar = stateArrays.elemStateArrays[b][state.name];
00920     for (std::size_t e=0; e < buck.size(); ++e)
00921       for (std::size_t p=0; p < nqp; ++p)
00922         apf::setScalar(f,buck[e],p,ar(e,p));
00923   }
00924 }
00925 
00926 template<class Output>
00927 void AlbPUMI::FMDBDiscretization<Output>::copyQPVectorToAPF(
00928     unsigned nqp,
00929     QPData<double, 3>& state,
00930     apf::Field* f)
00931 {
00932   for (std::size_t b=0; b < buckets.size(); ++b) {
00933     std::vector<apf::MeshEntity*>& buck = buckets[b];
00934     Albany::MDArray& ar = stateArrays.elemStateArrays[b][state.name];
00935     for (std::size_t e=0; e < buck.size(); ++e) {
00936       apf::Vector3 v;
00937       for (std::size_t p=0; p < nqp; ++p) {
00938         for (std::size_t i=0; i < 3; ++i)
00939           v[i] = ar(e,p,i);
00940         apf::setVector(f,buck[e],p,v);
00941       }
00942     }
00943   }
00944 }
00945 
00946 template <class Output>
00947 void AlbPUMI::FMDBDiscretization<Output>::copyQPTensorToAPF(
00948     unsigned nqp,
00949     QPData<double, 4>& state,
00950     apf::Field* f)
00951 {
00952   for (std::size_t b=0; b < buckets.size(); ++b) {
00953     std::vector<apf::MeshEntity*>& buck = buckets[b];
00954     Albany::MDArray& ar = stateArrays.elemStateArrays[b][state.name];
00955     for (std::size_t e=0; e < buck.size(); ++e) {
00956       apf::Matrix3x3 v;
00957       for (std::size_t p=0; p < nqp; ++p) {
00958         for (std::size_t i=0; i < 3; ++i)
00959         for (std::size_t j=0; j < 3; ++j)
00960           v[i][j] = ar(e,p,i,j);
00961         apf::setMatrix(f,buck[e],p,v);
00962       }
00963     }
00964   }
00965 }
00966 
00967 template<class Output>
00968 void AlbPUMI::FMDBDiscretization<Output>::copyQPStatesToAPF() {
00969   apf::Mesh2* m = fmdbMeshStruct->apfMesh;
00970   int order = fmdbMeshStruct->cubatureDegree;
00971   apf::Field* f;
00972   for (std::size_t i=0; i < fmdbMeshStruct->qpscalar_states.size(); ++i) {
00973     QPData<double, 2>& state = *(fmdbMeshStruct->qpscalar_states[i]);
00974     int nqp = state.dims[1];
00975     f = apf::createIPField(m,state.name.c_str(),apf::SCALAR,order);
00976     copyQPScalarToAPF(nqp,state,f);
00977   }
00978   for (std::size_t i=0; i < fmdbMeshStruct->qpvector_states.size(); ++i) {
00979     QPData<double, 3>& state = *(fmdbMeshStruct->qpvector_states[i]);
00980     int nqp = state.dims[1];
00981     f = apf::createIPField(m,state.name.c_str(),apf::VECTOR,order);
00982     copyQPVectorToAPF(nqp,state,f);
00983   }
00984   for (std::size_t i=0; i < fmdbMeshStruct->qptensor_states.size(); ++i) {
00985     QPData<double, 4>& state = *(fmdbMeshStruct->qptensor_states[i]);
00986     int nqp = state.dims[1];
00987     f = apf::createIPField(m,state.name.c_str(),apf::MATRIX,order);
00988     copyQPTensorToAPF(nqp,state,f);
00989   }
00990 }
00991 
00992 template<class Output>
00993 void AlbPUMI::FMDBDiscretization<Output>::removeQPStatesFromAPF() {
00994   apf::Mesh2* m = fmdbMeshStruct->apfMesh;
00995   for (std::size_t i=0; i < fmdbMeshStruct->qpscalar_states.size(); ++i) {
00996     QPData<double, 2>& state = *(fmdbMeshStruct->qpscalar_states[i]);
00997     apf::destroyField(m->findField(state.name.c_str()));
00998   }
00999   for (std::size_t i=0; i < fmdbMeshStruct->qpvector_states.size(); ++i) {
01000     QPData<double, 3>& state = *(fmdbMeshStruct->qpvector_states[i]);
01001     apf::destroyField(m->findField(state.name.c_str()));
01002   }
01003   for (std::size_t i=0; i < fmdbMeshStruct->qptensor_states.size(); ++i) {
01004     QPData<double, 4>& state = *(fmdbMeshStruct->qptensor_states[i]);
01005     apf::destroyField(m->findField(state.name.c_str()));
01006   }
01007 }
01008 
01009 template<class Output>
01010 void AlbPUMI::FMDBDiscretization<Output>::computeSideSets() {
01011 
01012   pMeshMdl mesh = fmdbMeshStruct->getMesh();
01013   pPart part;
01014   FMDB_Mesh_GetPart(mesh, 0, part);
01015   apf::Mesh* m = fmdbMeshStruct->apfMesh;
01016   apf::Numbering* en = m->findNumbering("apf_element_numbering");
01017 
01018   // need a sideset list per workset
01019   int num_buckets = wsEBNames.size();
01020   sideSets.resize(num_buckets);
01021 
01022   // get side sets
01023   std::vector<pSideSet> side_sets;
01024   PUMI_Exodus_GetSideSet(mesh, side_sets);
01025 
01026   std::vector<pMeshEnt> side_elems;
01027   std::vector<pMeshEnt> ss_sides;
01028 
01029   // loop over side sets
01030   for (std::vector<pSideSet>::iterator ss = side_sets.begin();
01031        ss != side_sets.end(); ++ss) {
01032 
01033     // get the name of this side set
01034     std::string ss_name;
01035     PUMI_SideSet_GetName(*ss, ss_name);
01036 
01037     // get sides on side the side set
01038     ss_sides.clear();
01039     PUMI_SideSet_GetSide(mesh, *ss, ss_sides);
01040 
01041     // loop over the sides in this side set
01042     for (std::vector<pMeshEnt>::iterator side = ss_sides.begin();
01043    side != ss_sides.end(); ++side) {
01044 
01045       // get the elements adjacent to this side
01046       // note - if the side is internal, it will show up twice in the element list,
01047       // once for each element that contains it
01048 
01049       side_elems.clear();
01050       int side_dim;
01051       FMDB_Ent_GetType(*side, &side_dim);
01052       FMDB_Ent_GetAdj(*side, side_dim+1, 1, side_elems);
01053 
01054       // according to template below - we are not yet considering non-manifold side sets?
01055       // i.e. side_elems.size() > 1
01056       TEUCHOS_TEST_FOR_EXCEPTION(side_elems.size() != 1, std::logic_error,
01057        "FMDBDisc: cannot figure out side set topology for side set "<<ss_name<<std::endl);
01058 
01059       pMeshEnt elem = side_elems[0];
01060 
01061       // fill in the data holder for a side struct
01062 
01063       Albany::SideStruct sstruct;
01064 
01065       sstruct.elem_GID = apf::getNumber(en,apf::castEntity(elem),0,0);
01066       int workset = elemGIDws[sstruct.elem_GID].ws; // workset ID that this element lives in
01067       sstruct.elem_LID = elemGIDws[sstruct.elem_GID].LID; // local element id in this workset
01068       sstruct.elem_ebIndex = fmdbMeshStruct->ebNameToIndex[wsEBNames[workset]]; // element block that workset lives in
01069 
01070       int side_exodus_order;
01071       PUMI_MeshEnt_GetExodusOrder(elem, *side, &side_exodus_order);
01072       sstruct.side_local_id = side_exodus_order-1; // local id of side wrt element
01073 
01074       Albany::SideSetList& ssList = sideSets[workset]; // Get a ref to the side set map for this ws
01075 
01076       Albany::SideSetList::iterator it = ssList.find(ss_name); // Get an iterator to the correct sideset (if
01077                                                        // it exists)
01078 
01079       if(it != ssList.end()) // The sideset has already been created
01080 
01081         it->second.push_back(sstruct); // Save this side to the vector that belongs to the name ss->first
01082 
01083       else { // Add the key ss_name to the map, and the side vector to that map
01084 
01085         std::vector<Albany::SideStruct> tmpSSVec;
01086         tmpSSVec.push_back(sstruct);
01087         ssList.insert(Albany::SideSetList::value_type(ss_name, tmpSSVec));
01088       }
01089 
01090     }
01091   }
01092 }
01093 
01094 template<class Output>
01095 void AlbPUMI::FMDBDiscretization<Output>::computeNodeSets()
01096 {
01097   // Make sure all the maps are allocated
01098   for (std::vector<std::string>::iterator ns_iter = fmdbMeshStruct->nsNames.begin();
01099         ns_iter != fmdbMeshStruct->nsNames.end(); ++ns_iter )
01100   { // Iterate over Node Sets
01101     nodeSets[*ns_iter].resize(0);
01102     nodeSetCoords[*ns_iter].resize(0);
01103     nodeset_node_coords[*ns_iter].resize(0);
01104   }
01105   //grab the node set geometric objects
01106   std::vector<pNodeSet> node_set;
01107   PUMI_Exodus_GetNodeSet(fmdbMeshStruct->getMesh(), node_set);
01108   apf::Mesh* m = fmdbMeshStruct->apfMesh;
01109   apf::Numbering* n = m->findNumbering("apf_owned_numbering");
01110   int mesh_dim = m->getDimension();
01111   for (std::vector<pNodeSet>::iterator node_set_it=node_set.begin(); node_set_it!=node_set.end(); ++node_set_it)
01112   {
01113     apf::DynamicArray<apf::Node> nodesInSet;
01114     apf::ModelEntity* me = reinterpret_cast<apf::ModelEntity*>(*node_set_it);
01115     apf::getNodesOnClosure(m,me,nodesInSet);
01116     std::vector<apf::Node> owned_ns_nodes;
01117     for (size_t i=0; i < nodesInSet.getSize(); ++i)
01118       if (m->isOwned(nodesInSet[i].entity))
01119         owned_ns_nodes.push_back(nodesInSet[i]);
01120     std::string NS_name;
01121     PUMI_NodeSet_GetName(*node_set_it, NS_name);
01122     nodeSets[NS_name].resize(owned_ns_nodes.size());
01123     nodeSetCoords[NS_name].resize(owned_ns_nodes.size());
01124     nodeset_node_coords[NS_name].resize(owned_ns_nodes.size() * mesh_dim);
01125     for (std::size_t i=0; i < owned_ns_nodes.size(); i++)
01126     {
01127       apf::Node node = owned_ns_nodes[i];
01128       nodeSets[NS_name][i].resize(neq);
01129       int node_gid = apf::getNumber(n,node.entity,node.node,0);
01130       int node_lid = node_map->LID(node_gid);
01131       assert(node_lid >= 0);
01132       assert(node_lid < numOwnedNodes);
01133       for (std::size_t eq=0; eq < neq; eq++)
01134         nodeSets[NS_name][i][eq] = getDOF(node_lid, eq);
01135       double* node_coords = &(nodeset_node_coords[NS_name][i*mesh_dim]);
01136       apf::getComponents(m->getCoordinateField(),node.entity,node.node,node_coords);
01137       nodeSetCoords[NS_name][i] = node_coords;
01138     }
01139   }
01140 }
01141 
01142 template<class Output>
01143 void
01144 AlbPUMI::FMDBDiscretization<Output>::updateMesh()
01145 {
01146   computeOwnedNodesAndUnknowns();
01147 #ifdef ALBANY_DEBUG
01148   std::cout<<"["<<SCUTIL_CommRank()<<"] "<<__func__<<": computeOwnedNodesAndUnknowns() completed\n";
01149 #endif
01150 
01151   computeOverlapNodesAndUnknowns();
01152 #ifdef ALBANY_DEBUG
01153   std::cout<<"["<<SCUTIL_CommRank()<<"] "<<__func__<<": computeOverlapNodesAndUnknowns() completed\n";
01154 #endif
01155 
01156   computeGraphs();
01157 #ifdef ALBANY_DEBUG
01158   std::cout<<"["<<SCUTIL_CommRank()<<"] "<<__func__<<": computeGraphs() completed\n";
01159 #endif
01160 
01161   getCoordinates(); //fill the coordinates array
01162 
01163   computeWorksetInfo();
01164 #ifdef ALBANY_DEBUG
01165   std::cout<<"["<<SCUTIL_CommRank()<<"] "<<__func__<<": computeWorksetInfo() completed\n";
01166 #endif
01167 
01168   computeNodeSets();
01169 #ifdef ALBANY_DEBUG
01170   std::cout<<"["<<SCUTIL_CommRank()<<"] "<<__func__<<": computeNodeSets() completed\n";
01171 #endif
01172 
01173   computeSideSets();
01174 #ifdef ALBANY_DEBUG
01175   std::cout<<"["<<SCUTIL_CommRank()<<"] "<<__func__<<": computeSideSets() completed\n";
01176 #endif
01177 
01178   static bool first = true;
01179   if (first)
01180     first = false;
01181   else
01182     apf::writeVtkFiles("updateMesh",fmdbMeshStruct->apfMesh);
01183 
01184 }

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