00001
00002
00003
00004
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++) {
00137 for (int e=0; e<coords[ws].size(); e++) {
00138 for (int j=0; j<coords[ws][e].size(); j++) {
00139 for (int d=0; d<mesh_dim; d++){
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
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
00208
00209
00210
00211
00212
00213
00214
00215 template<class Output>
00216 void
00217 AlbPUMI::FMDBDiscretization<Output>::setupMLCoords()
00218 {
00219
00220
00221
00222
00223
00224 if(rigidBodyModes.is_null()) return;
00225
00226 if(!rigidBodyModes->isMLUsed()) return;
00227
00228
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
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;
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
00356
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
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,false);
00420 else
00421 this->setSplitFields(solNames,solIndex,soln,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,false);
00434 else
00435 this->setSplitFields(solNames,solIndex,soln,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
00457 if (time > previous_time_label) {
00458 previous_time_label = time;
00459 return time;
00460 }
00461
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
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
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,false);
00485 else
00486 this->setSplitFields(resNames,solIndex,residual,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
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,false);
00501 else
00502 this->getSplitFields(solNames,solIndex,*soln,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,false);
00516 else
00517 this->setSplitFields(solNames,solIndex,soln,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
00530
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);
00551 apf::DynamicArray<apf::Node> ownedNodes;
00552 apf::getNodes(n,ownedNodes);
00553 numOwnedNodes = ownedNodes.getSize();
00554 apf::synchronize(n);
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
00602
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
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
00617
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
00644
00645 graph = Teuchos::rcp(new Epetra_CrsGraph(Copy, *map, nonzeroesPerRow(neq), false));
00646
00647
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
00666
00667
00668
00669
00670
00671
00672
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
00687 apf::MeshIterator* it = m->begin(numDim);
00688 apf::MeshEntity* element;
00689 while ((element = m->iterate(it)))
00690 {
00691
00692
00693 if ( ! m->isOwned(element))
00694 continue;
00695
00696
00697 elem_blk = reinterpret_cast<pGeomEnt>(m->toModel(element));
00698
00699
00700 buck_it = bucketMap.find(elem_blk);
00701
00702 if((buck_it == bucketMap.end()) ||
00703 (buckets[buck_it->second].size() >= worksetSize)){
00704
00705
00706 bucketMap[elem_blk] = bucket_counter;
00707
00708
00709 buckets.resize(bucket_counter + 1);
00710 wsEBNames.resize(bucket_counter + 1);
00711
00712
00713 buckets[bucket_counter].push_back(element);
00714
00715
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 {
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
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
00756 if(!elemGIDws.empty()) elemGIDws.clear();
00757
00758
00759
00760
00761
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
00770
00771 for (std::size_t i=0; i < buck.size(); i++) {
00772
00773
00774 element = buck[i];
00775
00776
00777 elemGIDws[apf::getNumber(en,element,0,0)].ws = b;
00778
00779
00780 elemGIDws[apf::getNumber(en,element,0,0)].LID = i;
00781
00782
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
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
00813
00814
00815
00816
00817
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
00832
00833 fmdbMeshStruct->scalarValue_states[i]->reAllocateBuffer(numBuckets);
00834 }
00835
00836
00837
00838
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
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
00867
00868 if(Teuchos::nonnull(fmdbMeshStruct->nodal_data_block)){
00869
00870 std::vector< std::vector<apf::Node> > nbuckets;
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
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
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
00900 nodeContainer->resize(node_map);
00901
00902
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
01019 int num_buckets = wsEBNames.size();
01020 sideSets.resize(num_buckets);
01021
01022
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
01030 for (std::vector<pSideSet>::iterator ss = side_sets.begin();
01031 ss != side_sets.end(); ++ss) {
01032
01033
01034 std::string ss_name;
01035 PUMI_SideSet_GetName(*ss, ss_name);
01036
01037
01038 ss_sides.clear();
01039 PUMI_SideSet_GetSide(mesh, *ss, ss_sides);
01040
01041
01042 for (std::vector<pMeshEnt>::iterator side = ss_sides.begin();
01043 side != ss_sides.end(); ++side) {
01044
01045
01046
01047
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
01055
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
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;
01067 sstruct.elem_LID = elemGIDws[sstruct.elem_GID].LID;
01068 sstruct.elem_ebIndex = fmdbMeshStruct->ebNameToIndex[wsEBNames[workset]];
01069
01070 int side_exodus_order;
01071 PUMI_MeshEnt_GetExodusOrder(elem, *side, &side_exodus_order);
01072 sstruct.side_local_id = side_exodus_order-1;
01073
01074 Albany::SideSetList& ssList = sideSets[workset];
01075
01076 Albany::SideSetList::iterator it = ssList.find(ss_name);
01077
01078
01079 if(it != ssList.end())
01080
01081 it->second.push_back(sstruct);
01082
01083 else {
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
01098 for (std::vector<std::string>::iterator ns_iter = fmdbMeshStruct->nsNames.begin();
01099 ns_iter != fmdbMeshStruct->nsNames.end(); ++ns_iter )
01100 {
01101 nodeSets[*ns_iter].resize(0);
01102 nodeSetCoords[*ns_iter].resize(0);
01103 nodeset_node_coords[*ns_iter].resize(0);
01104 }
01105
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();
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 }