00001
00002
00003
00004
00005
00006
00007
00008 #include <limits>
00009 #include "Epetra_Export.h"
00010
00011 #include "Albany_Utils.hpp"
00012 #include "Albany_STKDiscretization.hpp"
00013 #include "Albany_NodalGraphUtils.hpp"
00014 #include "Albany_STKNodeFieldContainer.hpp"
00015
00016 #include <string>
00017 #include <iostream>
00018 #include <fstream>
00019
00020 #include <Shards_BasicTopologies.hpp>
00021 #include "Shards_CellTopology.hpp"
00022 #include "Shards_CellTopologyData.h"
00023
00024 #include <stk_util/parallel/Parallel.hpp>
00025
00026 #include <stk_mesh/base/Entity.hpp>
00027 #include <stk_mesh/base/GetEntities.hpp>
00028 #include <stk_mesh/base/GetBuckets.hpp>
00029 #include <stk_mesh/base/FieldData.hpp>
00030 #include <stk_mesh/base/Selector.hpp>
00031
00032 #include <PHAL_Dimension.hpp>
00033
00034 #include <stk_mesh/fem/FEMHelpers.hpp>
00035
00036 #ifdef ALBANY_SEACAS
00037 #include <Ionit_Initializer.h>
00038 #include <netcdf.h>
00039
00040 #ifdef ALBANY_PAR_NETCDF
00041 extern "C" {
00042 #include <netcdf_par.h>
00043 }
00044 #endif
00045 #endif
00046
00047 #include <algorithm>
00048 #include "EpetraExt_MultiVectorOut.h"
00049
00050 const double pi = 3.1415926535897932385;
00051
00052
00053
00054
00055 Albany::STKDiscretization::STKDiscretization(Teuchos::RCP<Albany::AbstractSTKMeshStruct> stkMeshStruct_,
00056 const Teuchos::RCP<const Epetra_Comm>& comm_,
00057 const Teuchos::RCP<Piro::MLRigidBodyModes>& rigidBodyModes_) :
00058
00059 out(Teuchos::VerboseObjectBase::getDefaultOStream()),
00060 previous_time_label(-1.0e32),
00061 metaData(*stkMeshStruct_->metaData),
00062 bulkData(*stkMeshStruct_->bulkData),
00063 comm(comm_),
00064 rigidBodyModes(rigidBodyModes_),
00065 neq(stkMeshStruct_->neq),
00066 stkMeshStruct(stkMeshStruct_),
00067 interleavedOrdering(stkMeshStruct_->interleavedOrdering)
00068 {
00069 Albany::STKDiscretization::updateMesh();
00070 }
00071
00072 Albany::STKDiscretization::~STKDiscretization()
00073 {
00074 #ifdef ALBANY_SEACAS
00075 if (stkMeshStruct->exoOutput || stkMeshStruct->cdfOutput) delete mesh_data;
00076
00077 if (stkMeshStruct->cdfOutput)
00078 if (const int ierr = nc_close (netCDFp))
00079 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00080 "close returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
00081
00082 #endif
00083
00084 for (int i=0; i< toDelete.size(); i++) delete [] toDelete[i];
00085 }
00086
00087
00088 Teuchos::RCP<const Epetra_Map>
00089 Albany::STKDiscretization::getMap() const
00090 {
00091 return map;
00092 }
00093
00094 Teuchos::RCP<const Epetra_Map>
00095 Albany::STKDiscretization::getOverlapMap() const
00096 {
00097 return overlap_map;
00098 }
00099
00100 Teuchos::RCP<const Epetra_CrsGraph>
00101 Albany::STKDiscretization::getJacobianGraph() const
00102 {
00103 return graph;
00104 }
00105
00106 Teuchos::RCP<const Epetra_CrsGraph>
00107 Albany::STKDiscretization::getOverlapJacobianGraph() const
00108 {
00109 return overlap_graph;
00110 }
00111
00112 Teuchos::RCP<const Epetra_Map>
00113 Albany::STKDiscretization::getNodeMap() const
00114 {
00115 return node_map;
00116 }
00117
00118 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> > > >::type&
00119 Albany::STKDiscretization::getWsElNodeEqID() const
00120 {
00121 return wsElNodeEqID;
00122 }
00123
00124 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> > >::type&
00125 Albany::STKDiscretization::getWsElNodeID() const
00126 {
00127 return wsElNodeID;
00128 }
00129
00130 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type&
00131 Albany::STKDiscretization::getCoords() const
00132 {
00133 return coords;
00134 }
00135
00136 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double> > >::type&
00137 Albany::STKDiscretization::getSurfaceHeight() const
00138 {
00139 return sHeight;
00140 }
00141
00142 const Albany::WorksetArray<Teuchos::ArrayRCP<double> >::type&
00143 Albany::STKDiscretization::getTemperature() const
00144 {
00145 return temperature;
00146 }
00147
00148 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double> > >::type&
00149 Albany::STKDiscretization::getBasalFriction() const
00150 {
00151 return basalFriction;
00152 }
00153
00154 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double> > >::type&
00155 Albany::STKDiscretization::getThickness() const
00156 {
00157 return thickness;
00158 }
00159
00160 const Albany::WorksetArray<Teuchos::ArrayRCP<double> >::type&
00161 Albany::STKDiscretization::getFlowFactor() const
00162 {
00163 return flowFactor;
00164 }
00165
00166 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type&
00167 Albany::STKDiscretization::getSurfaceVelocity() const
00168 {
00169 return surfaceVelocity;
00170 }
00171
00172 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type&
00173 Albany::STKDiscretization::getVelocityRMS() const
00174 {
00175 return velocityRMS;
00176 }
00177
00178 void
00179 Albany::STKDiscretization::printCoords() const
00180 {
00181
00182 std::cout << "Processor " << bulkData.parallel_rank() << " has " << coords.size() << " worksets." << std::endl;
00183
00184 for (int ws=0; ws<coords.size(); ws++) {
00185 for (int e=0; e<coords[ws].size(); e++) {
00186 for (int j=0; j<coords[ws][e].size(); j++) {
00187 for (int d=0; d<stkMeshStruct->numDim; d++){
00188 std::cout << "Coord for workset: " << ws << " element: " << e << " node: " << j << " DOF: " << d << " is: " <<
00189 coords[ws][e][j][d] << std::endl;
00190 } } } }
00191
00192 }
00193
00194
00195 Teuchos::ArrayRCP<double>&
00196 Albany::STKDiscretization::getCoordinates() const
00197 {
00198
00199
00200
00201 AbstractSTKFieldContainer::VectorFieldType* coordinates_field = stkMeshStruct->getCoordinatesField();
00202
00203 for (int i=0; i < numOverlapNodes; i++) {
00204 int node_gid = gid(overlapnodes[i]);
00205 int node_lid = overlap_node_map->LID(node_gid);
00206
00207 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00208 for (int dim=0; dim<stkMeshStruct->numDim; dim++)
00209 coordinates[3*node_lid + dim] = x[dim];
00210
00211 }
00212
00213 return coordinates;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 void
00226 Albany::STKDiscretization::transformMesh()
00227 {
00228 using std::cout; using std::endl;
00229 AbstractSTKFieldContainer::VectorFieldType* coordinates_field = stkMeshStruct->getCoordinatesField();
00230 std::string transformType = stkMeshStruct->transformType;
00231
00232 if (transformType == "None") {}
00233 #ifdef ALBANY_FELIX
00234 else if (transformType == "ISMIP-HOM Test A") {
00235 #ifdef OUTPUT_TO_SCREEN
00236 *out << "Test A!" << endl;
00237 #endif
00238 double L = stkMeshStruct->felixL;
00239 double alpha = stkMeshStruct->felixAlpha;
00240 #ifdef OUTPUT_TO_SCREEN
00241 *out << "L: " << L << endl;
00242 *out << "alpha degrees: " << alpha << endl;
00243 #endif
00244 alpha = alpha*pi/180;
00245 #ifdef OUTPUT_TO_SCREEN
00246 *out << "alpha radians: " << alpha << endl;
00247 #endif
00248 stkMeshStruct->PBCStruct.scale[0]*=L;
00249 stkMeshStruct->PBCStruct.scale[1]*=L;
00250 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00251 for (int i=0; i < numOverlapNodes; i++) {
00252 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00253 x[0] = L*x[0];
00254 x[1] = L*x[1];
00255 double s = -x[0]*tan(alpha);
00256 double b = s - 1.0 + 0.5*sin(2*pi/L*x[0])*sin(2*pi/L*x[1]);
00257 x[2] = s*x[2] + b*(1-x[2]);
00258 *stk::mesh::field_data(*surfaceHeight_field, *overlapnodes[i]) = s;
00259 }
00260 }
00261 else if (transformType == "ISMIP-HOM Test B") {
00262 #ifdef OUTPUT_TO_SCREEN
00263 *out << "Test B!" << endl;
00264 #endif
00265 double L = stkMeshStruct->felixL;
00266 double alpha = stkMeshStruct->felixAlpha;
00267 #ifdef OUTPUT_TO_SCREEN
00268 *out << "L: " << L << endl;
00269 *out << "alpha degrees: " << alpha << endl;
00270 #endif
00271 alpha = alpha*pi/180;
00272 #ifdef OUTPUT_TO_SCREEN
00273 *out << "alpha radians: " << alpha << endl;
00274 #endif
00275 stkMeshStruct->PBCStruct.scale[0]*=L;
00276 stkMeshStruct->PBCStruct.scale[1]*=L;
00277 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00278 for (int i=0; i < numOverlapNodes; i++) {
00279 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00280 x[0] = L*x[0];
00281 x[1] = L*x[1];
00282 double s = -x[0]*tan(alpha);
00283 double b = s - 1.0 + 0.5*sin(2*pi/L*x[0]);
00284 x[2] = s*x[2] + b*(1-x[2]);
00285 *stk::mesh::field_data(*surfaceHeight_field, *overlapnodes[i]) = s;
00286 }
00287 }
00288 else if ((transformType == "ISMIP-HOM Test C") || (transformType == "ISMIP-HOM Test D")) {
00289 #ifdef OUTPUT_TO_SCREEN
00290 *out << "Test C and D!" << endl;
00291 #endif
00292 double L = stkMeshStruct->felixL;
00293 double alpha = stkMeshStruct->felixAlpha;
00294 #ifdef OUTPUT_TO_SCREEN
00295 *out << "L: " << L << endl;
00296 *out << "alpha degrees: " << alpha << endl;
00297 #endif
00298 alpha = alpha*pi/180;
00299 #ifdef OUTPUT_TO_SCREEN
00300 *out << "alpha radians: " << alpha << endl;
00301 #endif
00302 stkMeshStruct->PBCStruct.scale[0]*=L;
00303 stkMeshStruct->PBCStruct.scale[1]*=L;
00304 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00305 for (int i=0; i < numOverlapNodes; i++) {
00306 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00307 x[0] = L*x[0];
00308 x[1] = L*x[1];
00309 double s = -x[0]*tan(alpha);
00310 double b = s - 1.0;
00311 x[2] = s*x[2] + b*(1-x[2]);
00312 *stk::mesh::field_data(*surfaceHeight_field, *overlapnodes[i]) = s;
00313 }
00314 }
00315 else if (transformType == "Dome") {
00316 #ifdef OUTPUT_TO_SCREEN
00317 *out << "Dome transform!" << endl;
00318 #endif
00319 double L = 0.7071*30;
00320 stkMeshStruct->PBCStruct.scale[0]*=L;
00321 stkMeshStruct->PBCStruct.scale[1]*=L;
00322 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00323 for (int i=0; i < numOverlapNodes; i++) {
00324 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00325 x[0] = L*x[0];
00326 x[1] = L*x[1];
00327 double s = 0.7071*sqrt(450.0 - x[0]*x[0] - x[1]*x[1])/sqrt(450.0);
00328 x[2] = s*x[2];
00329 *stk::mesh::field_data(*surfaceHeight_field, *overlapnodes[i]) = s;
00330 }
00331 }
00332 else if (transformType == "Confined Shelf") {
00333 #ifdef OUTPUT_TO_SCREEN
00334 *out << "Confined shelf transform!" << endl;
00335 #endif
00336 double L = stkMeshStruct->felixL;
00337 cout << "L: " << L << endl;
00338 stkMeshStruct->PBCStruct.scale[0]*=L;
00339 stkMeshStruct->PBCStruct.scale[1]*=L;
00340 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00341 for (int i=0; i < numOverlapNodes; i++) {
00342 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00343 x[0] = L*x[0];
00344 x[1] = L*x[1];
00345 double s = 0.06;
00346 double b = -0.440;
00347 x[2] = s*x[2] + b*(1.0-x[2]);
00348 *stk::mesh::field_data(*surfaceHeight_field, *overlapnodes[i]) = s;
00349 }
00350 }
00351 else if (transformType == "Circular Shelf") {
00352 #ifdef OUTPUT_TO_SCREEN
00353 *out << "Circular shelf transform!" << endl;
00354 #endif
00355 double L = stkMeshStruct->felixL;
00356 #ifdef OUTPUT_TO_SCREEN
00357 *out << "L: " << L << endl;
00358 #endif
00359 double rhoIce = 910.0;
00360 double rhoOcean = 1028.0;
00361 stkMeshStruct->PBCStruct.scale[0]*=L;
00362 stkMeshStruct->PBCStruct.scale[1]*=L;
00363 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00364 for (int i=0; i < numOverlapNodes; i++) {
00365 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00366 x[0] = L*x[0];
00367 x[1] = L*x[1];
00368 double s = 1.0-rhoIce/rhoOcean;
00369 double b = s - 1.0;
00370 x[2] = s*x[2] + b*(1.0-x[2]);
00371 *stk::mesh::field_data(*surfaceHeight_field, *overlapnodes[i]) = s;
00372 }
00373 }
00374 #endif
00375 #ifdef ALBANY_AERAS
00376 else if (transformType == "Aeras Schar Mountain") {
00377 *out << "Aeras Schar Mountain transformation!" << endl;
00378 double rhoOcean = 1028.0;
00379 for (int i=0; i < numOverlapNodes; i++) {
00380 double* x = stk::mesh::field_data(*coordinates_field, *overlapnodes[i]);
00381 x[0] = x[0];
00382 double hstar = 0.0, h;
00383 if (std::abs(x[0]-150.0) <= 25.0) hstar = 3.0* std::pow(cos(M_PI*(x[0]-150.0) / 50.0),2);
00384 h = hstar * std::pow(cos(M_PI*(x[0]-150.0) / 8.0),2);
00385 x[1] = x[1] + h*(25.0 - x[1])/25.0;
00386 }
00387 }
00388 #endif
00389 else {
00390 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00391 "STKDiscretization::transformMesh() Unknown transform type :" << transformType << std::endl);
00392 }
00393 }
00394
00395 void
00396 Albany::STKDiscretization::setupMLCoords()
00397 {
00398
00399
00400
00401 if(rigidBodyModes.is_null()) return;
00402
00403 if(!rigidBodyModes->isMLUsed()) return;
00404
00405
00406 int numDim = stkMeshStruct->numDim;
00407 AbstractSTKFieldContainer::VectorFieldType* coordinates_field = stkMeshStruct->getCoordinatesField();
00408
00409 rigidBodyModes->resize(numDim, numOwnedNodes);
00410
00411 double *xx;
00412 double *yy;
00413 double *zz;
00414
00415 rigidBodyModes->getCoordArrays(&xx, &yy, &zz);
00416
00417 for (int i=0; i < numOwnedNodes; i++) {
00418 int node_gid = gid(ownednodes[i]);
00419 int node_lid = node_map->LID(node_gid);
00420
00421 double* X = stk::mesh::field_data(*coordinates_field, *ownednodes[i]);
00422 if (numDim > 0) xx[node_lid] = X[0];
00423 if (numDim > 1) yy[node_lid] = X[1];
00424 if (numDim > 2) zz[node_lid] = X[2];
00425 }
00426
00427
00428
00429 bool writeCoordsToMMFile = stkMeshStruct->writeCoordsToMMFile;
00430
00431 if (writeCoordsToMMFile == true) {
00432 if (node_map->Comm().MyPID()==0) {std::cout << "Writing mesh coordinates to Matrix Market file." << std::endl;}
00433
00434 Epetra_Vector xCoords(Copy, *node_map, xx);
00435 EpetraExt::MultiVectorToMatrixMarketFile("xCoords.mm", xCoords);
00436 if (yy != NULL) {
00437 Epetra_Vector yCoords(Copy, *node_map, yy);
00438 EpetraExt::MultiVectorToMatrixMarketFile("yCoords.mm", yCoords);
00439 }
00440 if (zz != NULL){
00441 Epetra_Vector zCoords(Copy, *node_map, zz);
00442 EpetraExt::MultiVectorToMatrixMarketFile("zCoords.mm", zCoords);
00443 }
00444 }
00445
00446 rigidBodyModes->informML();
00447
00448 }
00449
00450
00451 const Albany::WorksetArray<std::string>::type&
00452 Albany::STKDiscretization::getWsEBNames() const
00453 {
00454 return wsEBNames;
00455 }
00456
00457 const Albany::WorksetArray<int>::type&
00458 Albany::STKDiscretization::getWsPhysIndex() const
00459 {
00460 return wsPhysIndex;
00461 }
00462
00463
00464 void Albany::STKDiscretization::writeSolution(const Epetra_Vector& soln, const double time, const bool overlapped){
00465
00466
00467 if(!overlapped)
00468
00469 setSolutionField(soln);
00470
00471
00472 else
00473
00474 setOvlpSolutionField(soln);
00475
00476
00477 #ifdef ALBANY_SEACAS
00478
00479 if (stkMeshStruct->exoOutput && stkMeshStruct->transferSolutionToCoords) {
00480
00481 Teuchos::RCP<AbstractSTKFieldContainer> container = stkMeshStruct->getFieldContainer();
00482
00483 container->transferSolutionToCoords();
00484
00485 if (mesh_data != NULL) {
00486
00487
00488 delete mesh_data;
00489 setupExodusOutput();
00490
00491 }
00492 }
00493
00494
00495
00496 if (stkMeshStruct->exoOutput && !(outputInterval % stkMeshStruct->exoOutputInterval)) {
00497
00498 double time_label = monotonicTimeLabel(time);
00499
00500 int out_step = stk::io::process_output_request(*mesh_data, bulkData, time_label);
00501
00502 if (map->Comm().MyPID()==0) {
00503 *out << "Albany::STKDiscretization::writeSolution: writing time " << time;
00504 if (time_label != time) *out << " with label " << time_label;
00505 *out << " to index " <<out_step<<" in file "<<stkMeshStruct->exoOutFile<< std::endl;
00506 }
00507 }
00508 if (stkMeshStruct->cdfOutput && !(outputInterval % stkMeshStruct->cdfOutputInterval)) {
00509
00510 double time_label = monotonicTimeLabel(time);
00511
00512 const int out_step = processNetCDFOutputRequest();
00513
00514 if (map->Comm().MyPID()==0) {
00515 *out << "Albany::STKDiscretization::writeSolution: writing time " << time;
00516 if (time_label != time) *out << " with label " << time_label;
00517 *out << " to index " <<out_step<<" in file "<<stkMeshStruct->cdfOutFile<< std::endl;
00518 }
00519 }
00520 outputInterval++;
00521 #endif
00522 }
00523
00524 double
00525 Albany::STKDiscretization::monotonicTimeLabel(const double time)
00526 {
00527
00528 if (time > previous_time_label) {
00529 previous_time_label = time;
00530 return time;
00531 }
00532
00533 double time_label = fabs(time);
00534 if (time_label > previous_time_label) {
00535 previous_time_label = time_label;
00536 return time_label;
00537 }
00538
00539
00540 if (time_label+1.0 > previous_time_label) {
00541 previous_time_label = time_label+1.0;
00542 return time_label+1.0;
00543 }
00544
00545
00546 previous_time_label += 1.0;
00547 return previous_time_label;
00548 }
00549
00550 void
00551 Albany::STKDiscretization::setResidualField(const Epetra_Vector& residual)
00552 {
00553 #ifdef ALBANY_LCM
00554 Teuchos::RCP<AbstractSTKFieldContainer> container = stkMeshStruct->getFieldContainer();
00555
00556 if(container->hasResidualField()){
00557
00558
00559 stk::mesh::Selector locally_owned = metaData.locally_owned_part();
00560
00561 container->saveResVector(residual, locally_owned, node_map);
00562
00563
00564
00565
00566
00567 }
00568 #endif
00569 }
00570
00571 Teuchos::RCP<Epetra_Vector>
00572 Albany::STKDiscretization::getSolutionField() const
00573 {
00574
00575 Teuchos::RCP<Epetra_Vector> soln = Teuchos::rcp(new Epetra_Vector(*map));
00576 this->getSolutionField(*soln);
00577 return soln;
00578 }
00579
00580 int
00581 Albany::STKDiscretization::getSolutionFieldHistoryDepth() const
00582 {
00583 return stkMeshStruct->getSolutionFieldHistoryDepth();
00584 }
00585
00586 Teuchos::RCP<Epetra_MultiVector>
00587 Albany::STKDiscretization::getSolutionFieldHistory() const
00588 {
00589 const int stepCount = this->getSolutionFieldHistoryDepth();
00590 return this->getSolutionFieldHistoryImpl(stepCount);
00591 }
00592
00593 Teuchos::RCP<Epetra_MultiVector>
00594 Albany::STKDiscretization::getSolutionFieldHistory(int maxStepCount) const
00595 {
00596 const int stepCount = std::min(this->getSolutionFieldHistoryDepth(), maxStepCount);
00597 return this->getSolutionFieldHistoryImpl(stepCount);
00598 }
00599
00600 void
00601 Albany::STKDiscretization::getSolutionFieldHistory(Epetra_MultiVector &result) const
00602 {
00603 TEUCHOS_TEST_FOR_EXCEPT(!this->map->SameAs(result.Map()));
00604 const int stepCount = std::min(this->getSolutionFieldHistoryDepth(), result.NumVectors());
00605 Epetra_MultiVector head(View, result, 0, stepCount);
00606 this->getSolutionFieldHistoryImpl(head);
00607 }
00608
00609 Teuchos::RCP<Epetra_MultiVector>
00610 Albany::STKDiscretization::getSolutionFieldHistoryImpl(int stepCount) const
00611 {
00612 const int vectorCount = stepCount > 0 ? stepCount : 1;
00613 const Teuchos::RCP<Epetra_MultiVector> result = Teuchos::rcp(new Epetra_MultiVector(*map, vectorCount));
00614 if (stepCount > 0) {
00615 this->getSolutionFieldHistoryImpl(*result);
00616 }
00617 return result;
00618 }
00619
00620 void
00621 Albany::STKDiscretization::getSolutionFieldHistoryImpl(Epetra_MultiVector &result) const
00622 {
00623 const int stepCount = result.NumVectors();
00624 for (int i = 0; i < stepCount; ++i) {
00625 stkMeshStruct->loadSolutionFieldHistory(i);
00626 Epetra_Vector v(View, result, i);
00627 this->getSolutionField(v);
00628 }
00629 }
00630
00631 void
00632 Albany::STKDiscretization::getSolutionField(Epetra_Vector &result) const
00633 {
00634
00635 Teuchos::RCP<AbstractSTKFieldContainer> container = stkMeshStruct->getFieldContainer();
00636
00637
00638 stk::mesh::Selector locally_owned = metaData.locally_owned_part();
00639
00640 container->fillSolnVector(result, locally_owned, node_map);
00641
00642 }
00643
00644
00645
00646
00647
00648 void
00649 Albany::STKDiscretization::setSolutionField(const Epetra_Vector& soln)
00650 {
00651
00652
00653
00654 Teuchos::RCP<AbstractSTKFieldContainer> container = stkMeshStruct->getFieldContainer();
00655
00656
00657 stk::mesh::Selector locally_owned = metaData.locally_owned_part();
00658
00659 container->saveSolnVector(soln, locally_owned, node_map);
00660
00661 }
00662
00663 void
00664 Albany::STKDiscretization::setOvlpSolutionField(const Epetra_Vector& soln)
00665 {
00666
00667
00668
00669 Teuchos::RCP<AbstractSTKFieldContainer> container = stkMeshStruct->getFieldContainer();
00670
00671
00672 stk::mesh::Selector select_owned_or_shared = metaData.locally_owned_part() | metaData.globally_shared_part();
00673
00674 container->saveSolnVector(soln, select_owned_or_shared, overlap_node_map);
00675
00676 }
00677
00678 inline int Albany::STKDiscretization::gid(const stk::mesh::Entity& node) const
00679 { return node.identifier()-1; }
00680
00681 inline int Albany::STKDiscretization::gid(const stk::mesh::Entity* node) const
00682 { return gid(*node); }
00683
00684 int Albany::STKDiscretization::getOwnedDOF(const int inode, const int eq) const
00685 {
00686 if (interleavedOrdering) return inode*neq + eq;
00687 else return inode + numOwnedNodes*eq;
00688 }
00689
00690 int Albany::STKDiscretization::getOverlapDOF(const int inode, const int eq) const
00691 {
00692 if (interleavedOrdering) return inode*neq + eq;
00693 else return inode + numOverlapNodes*eq;
00694 }
00695
00696 int Albany::STKDiscretization::getGlobalDOF(const int inode, const int eq) const
00697 {
00698 if (interleavedOrdering) return inode*neq + eq;
00699 else return inode + numGlobalNodes*eq;
00700 }
00701
00702 int Albany::STKDiscretization::nonzeroesPerRow(const int neq) const
00703 {
00704 int numDim = stkMeshStruct->numDim;
00705 int estNonzeroesPerRow;
00706 switch (numDim) {
00707 case 0: estNonzeroesPerRow=1*neq; break;
00708 case 1: estNonzeroesPerRow=3*neq; break;
00709 case 2: estNonzeroesPerRow=9*neq; break;
00710 case 3: estNonzeroesPerRow=27*neq; break;
00711 default: TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00712 "STKDiscretization: Bad numDim"<< numDim);
00713 }
00714 return estNonzeroesPerRow;
00715 }
00716
00717 void Albany::STKDiscretization::computeOwnedNodesAndUnknowns()
00718 {
00719
00720
00721 stk::mesh::Selector select_owned_in_part =
00722 stk::mesh::Selector( metaData.universal_part() ) &
00723 stk::mesh::Selector( metaData.locally_owned_part() );
00724
00725 stk::mesh::get_selected_entities( select_owned_in_part ,
00726 bulkData.buckets( metaData.node_rank() ) ,
00727 ownednodes );
00728
00729 numOwnedNodes = ownednodes.size();
00730 std::vector<int> indices(numOwnedNodes);
00731 for (int i=0; i < numOwnedNodes; i++)
00732
00733 indices[i] = gid(ownednodes[i]);
00734
00735 node_map = Teuchos::null;
00736
00737 node_map = Teuchos::rcp(new Epetra_Map(-1, numOwnedNodes,
00738 &(indices[0]), 0, *comm));
00739
00740 numGlobalNodes = node_map->MaxAllGID() + 1;
00741
00742 if(Teuchos::nonnull(stkMeshStruct->nodal_data_block))
00743 stkMeshStruct->nodal_data_block->resizeLocalMap(indices, *comm);
00744
00745 indices.resize(numOwnedNodes * neq);
00746 for (int i=0; i < numOwnedNodes; i++)
00747 for (std::size_t j=0; j < neq; j++)
00748 indices[getOwnedDOF(i,j)] = getGlobalDOF(gid(ownednodes[i]),j);
00749
00750 map = Teuchos::null;
00751
00752 map = Teuchos::rcp(new Epetra_Map(-1, indices.size(), &(indices[0]), 0, *comm));
00753
00754
00755 }
00756
00757 void Albany::STKDiscretization::computeOverlapNodesAndUnknowns()
00758 {
00759
00760 std::vector<int> indices;
00761
00762 stk::mesh::Selector select_overlap_in_part =
00763 stk::mesh::Selector( metaData.universal_part() ) &
00764 ( stk::mesh::Selector( metaData.locally_owned_part() )
00765 | stk::mesh::Selector( metaData.globally_shared_part() ) );
00766
00767
00768 stk::mesh::get_selected_entities( select_overlap_in_part ,
00769 bulkData.buckets( metaData.node_rank() ) ,
00770 overlapnodes );
00771
00772 numOverlapNodes = overlapnodes.size();
00773 indices.resize(numOverlapNodes * neq);
00774 for (int i=0; i < numOverlapNodes; i++)
00775 for (std::size_t j=0; j < neq; j++)
00776 indices[getOverlapDOF(i,j)] = getGlobalDOF(gid(overlapnodes[i]),j);
00777
00778 overlap_map = Teuchos::null;
00779
00780 overlap_map = Teuchos::rcp(new Epetra_Map(-1, indices.size(),
00781 &(indices[0]), 0, *comm));
00782
00783
00784 indices.resize(numOverlapNodes);
00785 for (int i=0; i < numOverlapNodes; i++)
00786 indices[i] = gid(overlapnodes[i]);
00787
00788 overlap_node_map = Teuchos::null;
00789
00790 overlap_node_map = Teuchos::rcp(new Epetra_Map(-1, indices.size(),
00791 &(indices[0]), 0, *comm));
00792
00793 if(Teuchos::nonnull(stkMeshStruct->nodal_data_block))
00794 stkMeshStruct->nodal_data_block->resizeOverlapMap(indices, *comm);
00795
00796 coordinates.resize(3*numOverlapNodes);
00797
00798 }
00799
00800
00801 void Albany::STKDiscretization::computeGraphs()
00802 {
00803
00804 std::map<int, stk::mesh::Part*>::iterator pv = stkMeshStruct->partVec.begin();
00805 int nodes_per_element = metaData.get_cell_topology(*(pv->second)).getNodeCount();
00806
00807
00808
00809
00810 overlap_graph = Teuchos::null;
00811
00812 overlap_graph =
00813 Teuchos::rcp(new Epetra_CrsGraph(Copy, *overlap_map,
00814 neq*nodes_per_element, false));
00815
00816 stk::mesh::Selector select_owned_in_part =
00817 stk::mesh::Selector( metaData.universal_part() ) &
00818 stk::mesh::Selector( metaData.locally_owned_part() );
00819
00820 stk::mesh::get_selected_entities( select_owned_in_part ,
00821 bulkData.buckets( metaData.element_rank() ) ,
00822 cells );
00823
00824
00825 if (comm->MyPID()==0)
00826 *out << "STKDisc: " << cells.size() << " elements on Proc 0 " << std::endl;
00827
00828 int row, col;
00829
00830 for (std::size_t i=0; i < cells.size(); i++) {
00831 stk::mesh::Entity& e = *cells[i];
00832 stk::mesh::PairIterRelation rel = e.relations(metaData.NODE_RANK);
00833
00834
00835 for (std::size_t j=0; j < rel.size(); j++) {
00836 stk::mesh::Entity& rowNode = * rel[j].entity();
00837
00838
00839 for (std::size_t k=0; k < neq; k++) {
00840 row = getGlobalDOF(gid(rowNode), k);
00841 for (std::size_t l=0; l < rel.size(); l++) {
00842 stk::mesh::Entity& colNode = * rel[l].entity();
00843 for (std::size_t m=0; m < neq; m++) {
00844 col = getGlobalDOF(gid(colNode), m);
00845 overlap_graph->InsertGlobalIndices(row, 1, &col);
00846 }
00847 }
00848 }
00849 }
00850 }
00851 overlap_graph->FillComplete();
00852
00853
00854
00855 graph = Teuchos::null;
00856
00857 graph = Teuchos::rcp(new Epetra_CrsGraph(Copy, *map, nonzeroesPerRow(neq), false));
00858
00859
00860 Epetra_Export exporter(*overlap_map, *map);
00861 graph->Export(*overlap_graph, exporter, Insert);
00862 graph->FillComplete();
00863
00864 }
00865
00866 void Albany::STKDiscretization::computeWorksetInfo()
00867 {
00868
00869 stk::mesh::Selector select_owned_in_part =
00870 stk::mesh::Selector( metaData.universal_part() ) &
00871 stk::mesh::Selector( metaData.locally_owned_part() );
00872
00873 std::vector< stk::mesh::Bucket * > buckets ;
00874 stk::mesh::get_buckets( select_owned_in_part ,
00875 bulkData.buckets( metaData.element_rank() ) ,
00876 buckets);
00877
00878 int numBuckets = buckets.size();
00879
00880 AbstractSTKFieldContainer::VectorFieldType* coordinates_field = stkMeshStruct->getCoordinatesField();
00881 AbstractSTKFieldContainer::ScalarFieldType* surfaceHeight_field;
00882 AbstractSTKFieldContainer::ScalarFieldType* temperature_field;
00883 AbstractSTKFieldContainer::ScalarFieldType* basalFriction_field;
00884 AbstractSTKFieldContainer::ScalarFieldType* thickness_field;
00885 AbstractSTKFieldContainer::ScalarFieldType* flowFactor_field;
00886 AbstractSTKFieldContainer::VectorFieldType* surfaceVelocity_field;
00887 AbstractSTKFieldContainer::VectorFieldType* velocityRMS_field;
00888
00889 if(stkMeshStruct->getFieldContainer()->hasSurfaceHeightField())
00890 surfaceHeight_field = stkMeshStruct->getFieldContainer()->getSurfaceHeightField();
00891
00892 if(stkMeshStruct->getFieldContainer()->hasTemperatureField())
00893 temperature_field = stkMeshStruct->getFieldContainer()->getTemperatureField();
00894
00895 if(stkMeshStruct->getFieldContainer()->hasBasalFrictionField())
00896 basalFriction_field = stkMeshStruct->getFieldContainer()->getBasalFrictionField();
00897
00898 if(stkMeshStruct->getFieldContainer()->hasThicknessField())
00899 thickness_field = stkMeshStruct->getFieldContainer()->getThicknessField();
00900
00901 if(stkMeshStruct->getFieldContainer()->hasFlowFactorField())
00902 flowFactor_field = stkMeshStruct->getFieldContainer()->getFlowFactorField();
00903
00904 if(stkMeshStruct->getFieldContainer()->hasSurfaceVelocityField())
00905 surfaceVelocity_field = stkMeshStruct->getFieldContainer()->getSurfaceVelocityField();
00906
00907 if(stkMeshStruct->getFieldContainer()->hasVelocityRMSField())
00908 velocityRMS_field = stkMeshStruct->getFieldContainer()->getVelocityRMSField();
00909
00910 wsEBNames.resize(numBuckets);
00911 for (int i=0; i<numBuckets; i++) {
00912 std::vector< stk::mesh::Part * > bpv;
00913 buckets[i]->supersets(bpv);
00914 for (std::size_t j=0; j<bpv.size(); j++) {
00915 if (bpv[j]->primary_entity_rank() == metaData.element_rank()) {
00916 if (bpv[j]->name()[0] != '{') {
00917
00918
00919 wsEBNames[i]=bpv[j]->name();
00920 }
00921 }
00922 }
00923 }
00924
00925 wsPhysIndex.resize(numBuckets);
00926 if (stkMeshStruct->allElementBlocksHaveSamePhysics)
00927 for (int i=0; i<numBuckets; i++) wsPhysIndex[i]=0;
00928 else
00929 for (int i=0; i<numBuckets; i++) wsPhysIndex[i]=stkMeshStruct->ebNameToIndex[wsEBNames[i]];
00930
00931
00932
00933 wsElNodeEqID.resize(numBuckets);
00934 wsElNodeID.resize(numBuckets);
00935 coords.resize(numBuckets);
00936 sHeight.resize(numBuckets);
00937 temperature.resize(numBuckets);
00938 basalFriction.resize(numBuckets);
00939 thickness.resize(numBuckets);
00940 flowFactor.resize(numBuckets);
00941 surfaceVelocity.resize(numBuckets);
00942 velocityRMS.resize(numBuckets);
00943
00944
00945 if(!elemGIDws.empty()) elemGIDws.clear();
00946
00947 for (int b=0; b < numBuckets; b++) {
00948
00949 stk::mesh::Bucket& buck = *buckets[b];
00950 wsElNodeEqID[b].resize(buck.size());
00951 wsElNodeID[b].resize(buck.size());
00952 coords[b].resize(buck.size());
00953 #ifdef ALBANY_FELIX
00954 if(stkMeshStruct->getFieldContainer()->hasSurfaceHeightField())
00955 sHeight[b].resize(buck.size());
00956 if(stkMeshStruct->getFieldContainer()->hasTemperatureField())
00957 temperature[b].resize(buck.size());
00958 if(stkMeshStruct->getFieldContainer()->hasBasalFrictionField())
00959 basalFriction[b].resize(buck.size());
00960 if(stkMeshStruct->getFieldContainer()->hasThicknessField())
00961 thickness[b].resize(buck.size());
00962 if(stkMeshStruct->getFieldContainer()->hasFlowFactorField())
00963 flowFactor[b].resize(buck.size());
00964 if(stkMeshStruct->getFieldContainer()->hasSurfaceVelocityField())
00965 surfaceVelocity[b].resize(buck.size());
00966 if(stkMeshStruct->getFieldContainer()->hasVelocityRMSField())
00967 velocityRMS[b].resize(buck.size());
00968 #endif
00969
00970
00971
00972 for (std::size_t i=0; i < buck.size(); i++) {
00973
00974
00975 stk::mesh::Entity& element = buck[i];
00976
00977
00978 elemGIDws[gid(element)].ws = b;
00979
00980
00981 elemGIDws[gid(element)].LID = i;
00982
00983 stk::mesh::PairIterRelation rel = element.relations(metaData.NODE_RANK);
00984
00985 int nodes_per_element = rel.size();
00986 wsElNodeEqID[b][i].resize(nodes_per_element);
00987 wsElNodeID[b][i].resize(nodes_per_element);
00988 coords[b][i].resize(nodes_per_element);
00989 #ifdef ALBANY_FELIX
00990 if(stkMeshStruct->getFieldContainer()->hasSurfaceHeightField())
00991 sHeight[b][i].resize(nodes_per_element);
00992 if(stkMeshStruct->getFieldContainer()->hasTemperatureField())
00993 temperature[b][i] = *stk::mesh::field_data(*temperature_field, element);
00994 if(stkMeshStruct->getFieldContainer()->hasBasalFrictionField())
00995 basalFriction[b][i].resize(nodes_per_element);
00996 if(stkMeshStruct->getFieldContainer()->hasThicknessField())
00997 thickness[b][i].resize(nodes_per_element);
00998 if(stkMeshStruct->getFieldContainer()->hasFlowFactorField())
00999 flowFactor[b][i] = *stk::mesh::field_data(*flowFactor_field, element);
01000 if(stkMeshStruct->getFieldContainer()->hasSurfaceVelocityField())
01001 surfaceVelocity[b][i].resize(nodes_per_element);
01002 if(stkMeshStruct->getFieldContainer()->hasVelocityRMSField())
01003 velocityRMS[b][i].resize(nodes_per_element);
01004 #endif
01005
01006 for (int j=0; j < nodes_per_element; j++) {
01007 stk::mesh::Entity& rowNode = * rel[j].entity();
01008 int node_gid = gid(rowNode);
01009 int node_lid = overlap_node_map->LID(node_gid);
01010
01011 TEUCHOS_TEST_FOR_EXCEPTION(node_lid<0, std::logic_error,
01012 "STK1D_Disc: node_lid out of range " << node_lid << std::endl);
01013 coords[b][i][j] = stk::mesh::field_data(*coordinates_field, rowNode);
01014 #ifdef ALBANY_FELIX
01015 if(stkMeshStruct->getFieldContainer()->hasSurfaceHeightField())
01016 sHeight[b][i][j] = *stk::mesh::field_data(*surfaceHeight_field, rowNode);
01017 if(stkMeshStruct->getFieldContainer()->hasBasalFrictionField())
01018 basalFriction[b][i][j] = *stk::mesh::field_data(*basalFriction_field, rowNode);
01019 if(stkMeshStruct->getFieldContainer()->hasThicknessField())
01020 thickness[b][i][j] = *stk::mesh::field_data(*thickness_field, rowNode);
01021 if(stkMeshStruct->getFieldContainer()->hasSurfaceVelocityField())
01022 surfaceVelocity[b][i][j] = stk::mesh::field_data(*surfaceVelocity_field, rowNode);
01023 if(stkMeshStruct->getFieldContainer()->hasVelocityRMSField())
01024 velocityRMS[b][i][j] = stk::mesh::field_data(*velocityRMS_field, rowNode);
01025 #endif
01026
01027 wsElNodeEqID[b][i][j].resize(neq);
01028 wsElNodeID[b][i][j] = node_gid;
01029
01030 for (std::size_t eq=0; eq < neq; eq++)
01031 wsElNodeEqID[b][i][j][eq] = getOverlapDOF(node_lid,eq);
01032 }
01033 }
01034 }
01035
01036 for (int d=0; d<stkMeshStruct->numDim; d++) {
01037 if (stkMeshStruct->PBCStruct.periodic[d]) {
01038 for (int b=0; b < numBuckets; b++) {
01039 for (std::size_t i=0; i < buckets[b]->size(); i++) {
01040 int nodes_per_element = (*buckets[b])[i].relations(metaData.NODE_RANK).size();
01041 bool anyXeqZero=false;
01042 for (int j=0; j < nodes_per_element; j++) if (coords[b][i][j][d]==0.0) anyXeqZero=true;
01043 if (anyXeqZero) {
01044 bool flipZeroToScale=false;
01045 for (int j=0; j < nodes_per_element; j++)
01046 if (coords[b][i][j][d] > stkMeshStruct->PBCStruct.scale[d]/1.9) flipZeroToScale=true;
01047 if (flipZeroToScale) {
01048 for (int j=0; j < nodes_per_element; j++) {
01049 if (coords[b][i][j][d] == 0.0) {
01050 double* xleak = new double [stkMeshStruct->numDim];
01051 for (int k=0; k < stkMeshStruct->numDim; k++)
01052 if (k==d) xleak[d]=stkMeshStruct->PBCStruct.scale[d];
01053 else xleak[k] = coords[b][i][j][k];
01054 std::string transformType = stkMeshStruct->transformType;
01055 double alpha = stkMeshStruct->felixAlpha;
01056 alpha *= pi/180.;
01057 if ((transformType=="ISMIP-HOM Test A" || transformType == "ISMIP-HOM Test B" ||
01058 transformType=="ISMIP-HOM Test C" || transformType == "ISMIP-HOM Test D") && d==0) {
01059 xleak[2] -= stkMeshStruct->PBCStruct.scale[d]*tan(alpha);
01060 #ifdef ALBANY_FELIX
01061 if(stkMeshStruct->getFieldContainer()->hasSurfaceHeightField())
01062 sHeight[b][i][j] -= stkMeshStruct->PBCStruct.scale[d]*tan(alpha);
01063 #endif
01064 }
01065 coords[b][i][j] = xleak;
01066 toDelete.push_back(xleak);
01067 }
01068 }
01069 }
01070 }
01071 }
01072 }
01073 }
01074 }
01075
01076 typedef Albany::AbstractSTKFieldContainer::ScalarValueState ScalarValueState;
01077 typedef Albany::AbstractSTKFieldContainer::QPScalarState QPScalarState ;
01078 typedef Albany::AbstractSTKFieldContainer::QPVectorState QPVectorState;
01079 typedef Albany::AbstractSTKFieldContainer::QPTensorState QPTensorState;
01080
01081 typedef Albany::AbstractSTKFieldContainer::ScalarState ScalarState ;
01082 typedef Albany::AbstractSTKFieldContainer::VectorState VectorState;
01083 typedef Albany::AbstractSTKFieldContainer::TensorState TensorState;
01084
01085
01086
01087
01088 ScalarValueState scalarValue_states = stkMeshStruct->getFieldContainer()->getScalarValueStates();
01089 QPScalarState qpscalar_states = stkMeshStruct->getFieldContainer()->getQPScalarStates();
01090 QPVectorState qpvector_states = stkMeshStruct->getFieldContainer()->getQPVectorStates();
01091 QPTensorState qptensor_states = stkMeshStruct->getFieldContainer()->getQPTensorStates();
01092 double& time = stkMeshStruct->getFieldContainer()->getTime();
01093
01094 stateArrays.elemStateArrays.resize(numBuckets);
01095 for (std::size_t b=0; b < buckets.size(); b++) {
01096 stk::mesh::Bucket& buck = *buckets[b];
01097 for (QPScalarState::iterator qpss = qpscalar_states.begin();
01098 qpss != qpscalar_states.end(); ++qpss){
01099 stk::mesh::BucketArray<Albany::AbstractSTKFieldContainer::QPScalarFieldType> array(**qpss, buck);
01100
01101
01102 MDArray ar = array;
01103 stateArrays.elemStateArrays[b][(*qpss)->name()] = ar;
01104 }
01105 for (QPVectorState::iterator qpvs = qpvector_states.begin();
01106 qpvs != qpvector_states.end(); ++qpvs){
01107 stk::mesh::BucketArray<Albany::AbstractSTKFieldContainer::QPVectorFieldType> array(**qpvs, buck);
01108
01109
01110 MDArray ar = array;
01111 stateArrays.elemStateArrays[b][(*qpvs)->name()] = ar;
01112 }
01113 for (QPTensorState::iterator qpts = qptensor_states.begin();
01114 qpts != qptensor_states.end(); ++qpts){
01115 stk::mesh::BucketArray<Albany::AbstractSTKFieldContainer::QPTensorFieldType> array(**qpts, buck);
01116
01117
01118 MDArray ar = array;
01119 stateArrays.elemStateArrays[b][(*qpts)->name()] = ar;
01120 }
01121 for (ScalarValueState::iterator svs = scalarValue_states.begin();
01122 svs != scalarValue_states.end(); ++svs){
01123 const int size = 1;
01124 shards::Array<double, shards::NaturalOrder, Cell> array(&time, size);
01125 MDArray ar = array;
01126 stateArrays.elemStateArrays[b][*svs] = ar;
01127 }
01128 }
01129
01130
01131
01132 if(Teuchos::nonnull(stkMeshStruct->nodal_data_block)){
01133
01134 Teuchos::RCP<Albany::NodeFieldContainer> node_states = stkMeshStruct->nodal_data_block->getNodeContainer();
01135
01136 stk::mesh::get_buckets( select_owned_in_part ,
01137 bulkData.buckets( metaData.node_rank() ) ,
01138 buckets);
01139
01140 numBuckets = buckets.size();
01141
01142 stateArrays.nodeStateArrays.resize(numBuckets);
01143 for (std::size_t b=0; b < buckets.size(); b++) {
01144 stk::mesh::Bucket& buck = *buckets[b];
01145 for (Albany::NodeFieldContainer::iterator nfs = node_states->begin();
01146 nfs != node_states->end(); ++nfs){
01147 stateArrays.nodeStateArrays[b][(*nfs).first] =
01148 Teuchos::rcp_dynamic_cast<Albany::AbstractSTKNodeFieldContainer>((*nfs).second)->getMDA(buck);
01149 }
01150 }
01151 }
01152 }
01153
01154 void Albany::STKDiscretization::computeSideSets(){
01155
01156
01157
01158 for(int i = 0; i < sideSets.size(); i++)
01159 sideSets[i].clear();
01160
01161 const stk::mesh::EntityRank element_rank = metaData.element_rank();
01162
01163
01164 std::map<std::string, stk::mesh::Part*>::iterator ss = stkMeshStruct->ssPartVec.begin();
01165
01166 int numBuckets = wsEBNames.size();
01167
01168 sideSets.resize(numBuckets);
01169
01170 while ( ss != stkMeshStruct->ssPartVec.end() ) {
01171
01172
01173 stk::mesh::Selector select_owned_in_sspart =
01174
01175
01176 stk::mesh::Selector( *(ss->second) ) &
01177
01178 stk::mesh::Selector( metaData.locally_owned_part() );
01179
01180 std::vector< stk::mesh::Entity * > sides ;
01181 stk::mesh::get_selected_entities( select_owned_in_sspart ,
01182 bulkData.buckets( metaData.side_rank() ) ,
01183 sides );
01184
01185 *out << "STKDisc: sideset "<< ss->first <<" has size " << sides.size() << " on Proc 0." << std::endl;
01186
01187
01188
01189
01190 for (std::size_t localSideID=0; localSideID < sides.size(); localSideID++) {
01191
01192 stk::mesh::Entity &sidee = *sides[localSideID];
01193
01194 const stk::mesh::PairIterRelation side_elems = sidee.relations(element_rank);
01195
01196
01197
01198 TEUCHOS_TEST_FOR_EXCEPTION(side_elems.size() != 1, std::logic_error,
01199 "STKDisc: cannot figure out side set topology for side set " << ss->first << std::endl);
01200
01201 const stk::mesh::Entity & elem = *side_elems[0].entity();
01202
01203 SideStruct sStruct;
01204
01205
01206 sStruct.elem_GID = gid(elem);
01207
01208 int workset = elemGIDws[sStruct.elem_GID].ws;
01209
01210
01211 sStruct.elem_LID = elemGIDws[sStruct.elem_GID].LID;
01212
01213
01214 sStruct.side_local_id = determine_local_side_id(elem, sidee);
01215
01216
01217 sStruct.elem_ebIndex = stkMeshStruct->ebNameToIndex[wsEBNames[workset]];
01218
01219 SideSetList& ssList = sideSets[workset];
01220 SideSetList::iterator it = ssList.find(ss->first);
01221
01222
01223 if(it != ssList.end())
01224
01225 it->second.push_back(sStruct);
01226
01227 else {
01228
01229 std::vector<SideStruct> tmpSSVec;
01230 tmpSSVec.push_back(sStruct);
01231
01232 ssList.insert(SideSetList::value_type(ss->first, tmpSSVec));
01233
01234 }
01235
01236 }
01237
01238 ss++;
01239 }
01240 }
01241
01242 unsigned
01243 Albany::STKDiscretization::determine_local_side_id( const stk::mesh::Entity & elem , stk::mesh::Entity & side ) {
01244
01245 using namespace stk;
01246
01247 const CellTopologyData * const elem_top = mesh::fem::get_cell_topology( elem ).getCellTopologyData();
01248
01249 const mesh::PairIterRelation elem_nodes = elem.relations( mesh::fem::FEMMetaData::NODE_RANK );
01250 const mesh::PairIterRelation side_nodes = side.relations( mesh::fem::FEMMetaData::NODE_RANK );
01251
01252 int side_id = -1 ;
01253
01254 if(elem_nodes.size() == 0 || side_nodes.size() == 0){
01255
01256 int elem_rank = elem.entity_rank();
01257 const mesh::PairIterRelation elem_sides = elem.relations( elem_rank - 1);
01258
01259 for ( unsigned i = 0 ; i < elem_sides.size() ; ++i ) {
01260
01261 const stk::mesh::Entity & elem_side = *elem_sides[i].entity();
01262
01263 if(elem_side.identifier() == side.identifier()){
01264
01265 side_id = static_cast<int>(i);
01266
01267 return side_id;
01268
01269 }
01270
01271 }
01272
01273 if ( side_id < 0 ) {
01274 std::ostringstream msg ;
01275 msg << "determine_local_side_id( " ;
01276 msg << elem_top->name ;
01277 msg << " , Element[ " ;
01278 msg << elem.identifier();
01279 msg << " ]{" ;
01280 for ( unsigned i = 0 ; i < elem_sides.size() ; ++i ) {
01281 msg << " " << elem_sides[i].entity()->identifier();
01282 }
01283 msg << " } , Side[ " ;
01284 msg << side.identifier();
01285 msg << " ] ) FAILED" ;
01286 throw std::runtime_error( msg.str() );
01287 }
01288
01289 }
01290 else {
01291
01292 for ( unsigned i = 0 ; side_id == -1 && i < elem_top->side_count ; ++i ) {
01293 const CellTopologyData & side_top = * elem_top->side[i].topology ;
01294 const unsigned * side_map = elem_top->side[i].node ;
01295
01296 if ( side_nodes.size() == side_top.node_count ) {
01297
01298 side_id = i ;
01299
01300 for ( unsigned j = 0 ;
01301 side_id == static_cast<int>(i) && j < side_top.node_count ; ++j ) {
01302
01303 mesh::Entity * const elem_node = elem_nodes[ side_map[j] ].entity();
01304
01305 bool found = false ;
01306
01307 for ( unsigned k = 0 ; ! found && k < side_top.node_count ; ++k ) {
01308 found = elem_node == side_nodes[k].entity();
01309 }
01310
01311 if ( ! found ) { side_id = -1 ; }
01312 }
01313 }
01314 }
01315
01316 if ( side_id < 0 ) {
01317 std::ostringstream msg ;
01318 msg << "determine_local_side_id( " ;
01319 msg << elem_top->name ;
01320 msg << " , Element[ " ;
01321 msg << elem.identifier();
01322 msg << " ]{" ;
01323 for ( unsigned i = 0 ; i < elem_nodes.size() ; ++i ) {
01324 msg << " " << elem_nodes[i].entity()->identifier();
01325 }
01326 msg << " } , Side[ " ;
01327 msg << side.identifier();
01328 msg << " ]{" ;
01329 for ( unsigned i = 0 ; i < side_nodes.size() ; ++i ) {
01330 msg << " " << side_nodes[i].entity()->identifier();
01331 }
01332 msg << " } ) FAILED" ;
01333 throw std::runtime_error( msg.str() );
01334 }
01335 }
01336
01337 return static_cast<unsigned>(side_id) ;
01338 }
01339
01340 void Albany::STKDiscretization::computeNodeSets()
01341 {
01342
01343 std::map<std::string, stk::mesh::Part*>::iterator ns = stkMeshStruct->nsPartVec.begin();
01344 AbstractSTKFieldContainer::VectorFieldType* coordinates_field = stkMeshStruct->getCoordinatesField();
01345
01346 while ( ns != stkMeshStruct->nsPartVec.end() ) {
01347
01348 stk::mesh::Selector select_owned_in_nspart =
01349 stk::mesh::Selector( *(ns->second) ) &
01350 stk::mesh::Selector( metaData.locally_owned_part() );
01351
01352 std::vector< stk::mesh::Entity * > nodes ;
01353 stk::mesh::get_selected_entities( select_owned_in_nspart ,
01354 bulkData.buckets( metaData.node_rank() ) ,
01355 nodes );
01356
01357 nodeSets[ns->first].resize(nodes.size());
01358 nodeSetCoords[ns->first].resize(nodes.size());
01359
01360 *out << "STKDisc: nodeset "<< ns->first <<" has size " << nodes.size() << " on Proc 0." << std::endl;
01361 for (std::size_t i=0; i < nodes.size(); i++) {
01362 int node_gid = gid(nodes[i]);
01363 int node_lid = node_map->LID(node_gid);
01364 nodeSets[ns->first][i].resize(neq);
01365 for (std::size_t eq=0; eq < neq; eq++) nodeSets[ns->first][i][eq] = getOwnedDOF(node_lid,eq);
01366 nodeSetCoords[ns->first][i] = stk::mesh::field_data(*coordinates_field, *nodes[i]);
01367 }
01368 ns++;
01369 }
01370 }
01371
01372 void Albany::STKDiscretization::setupExodusOutput()
01373 {
01374 #ifdef ALBANY_SEACAS
01375 if (stkMeshStruct->exoOutput) {
01376
01377 outputInterval = 0;
01378
01379 std::string str = stkMeshStruct->exoOutFile;
01380
01381 Ioss::Init::Initializer io;
01382 mesh_data = new stk::io::MeshData();
01383 stk::io::create_output_mesh(str,
01384 Albany::getMpiCommFromEpetraComm(*comm),
01385 bulkData, *mesh_data);
01386
01387 stk::io::define_output_fields(*mesh_data, metaData);
01388
01389 }
01390 #else
01391 if (stkMeshStruct->exoOutput)
01392 *out << "\nWARNING: exodus output requested but SEACAS not compiled in:"
01393 << " disabling exodus output \n" << std::endl;
01394
01395 #endif
01396 }
01397
01398 namespace {
01399 const std::vector<double> spherical_to_cart(const std::pair<double, double> & sphere){
01400 const double radius_of_earth = 1;
01401 std::vector<double> cart(3);
01402
01403 cart[0] = radius_of_earth*std::cos(sphere.first)*std::cos(sphere.second);
01404 cart[1] = radius_of_earth*std::cos(sphere.first)*std::sin(sphere.second);
01405 cart[2] = radius_of_earth*std::sin(sphere.first);
01406
01407 return cart;
01408 }
01409 double distance (const double* x, const double* y) {
01410 const double d = std::sqrt((x[0]-y[0])*(x[0]-y[0]) +
01411 (x[1]-y[1])*(x[1]-y[1]) +
01412 (x[2]-y[2])*(x[2]-y[2]));
01413 return d;
01414 }
01415 double distance (const std::vector<double> &x, const std::vector<double> &y) {
01416 const double d = std::sqrt((x[0]-y[0])*(x[0]-y[0]) +
01417 (x[1]-y[1])*(x[1]-y[1]) +
01418 (x[2]-y[2])*(x[2]-y[2]));
01419 return d;
01420 }
01421
01422 bool point_inside(const Teuchos::ArrayRCP<double*> &coords,
01423 const std::vector<double> &sphere_xyz) {
01424
01425 const double tol_inside = 1e-12;
01426 const double elem_diam = std::max(::distance(coords[0],coords[2]), ::distance(coords[1],coords[3]));
01427 std::vector<double> center(3,0);
01428 for (unsigned i=0; i<4; ++i)
01429 for (unsigned j=0; j<3; ++j) center[j] += coords[i][j];
01430 for (unsigned j=0; j<3; ++j) center[j] /= 4;
01431 bool inside = true;
01432
01433 if ( ::distance(¢er[0],&sphere_xyz[0]) > 1.0*elem_diam ) inside = false;
01434
01435 unsigned j=3;
01436 for (unsigned i=0; i<4 && inside; ++i) {
01437 std::vector<double> cross(3);
01438
01439
01440 cross[0]= coords[i][1]*coords[j][2] - coords[i][2]*coords[j][1];
01441 cross[1]=-(coords[i][0]*coords[j][2] - coords[i][2]*coords[j][0]);
01442 cross[2]= coords[i][0]*coords[j][1] - coords[i][1]*coords[j][0];
01443 j = i;
01444 const double dotprod = cross[0]*sphere_xyz[0] +
01445 cross[1]*sphere_xyz[1] +
01446 cross[2]*sphere_xyz[2];
01447
01448
01449
01450 if (tol_inside*elem_diam < dotprod) inside = false;
01451 }
01452 return inside;
01453 }
01454
01455 std::pair<double, double> ref2sphere(const Teuchos::ArrayRCP<double*> &coords,
01456 const std::pair<double, double> &ref) {
01457
01458 static const double DIST_THRESHOLD= 1.0e-9;
01459 const double a = ref.first;
01460 const double b = ref.second;
01461 const double q[4]={ (1-a)*(1-b)/4,
01462 (1+a)*(1-b)/4,
01463 (1+a)*(1+b)/4,
01464 (1-a)*(1+b)/4} ;
01465
01466 double x[3]={0,0,0};
01467 for (unsigned i=0; i<3; ++i)
01468 for (unsigned j=0; j<4; ++j)
01469 x[i] += coords[j][i] * q[j];
01470
01471 const double r = std::sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
01472
01473 for (unsigned i=0; i<3; ++i) x[i] /= r;
01474
01475 std::pair<double, double> sphere(std::asin(x[2]), std::atan2(x[1],x[0]));
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 if (std::abs(std::abs(sphere.first)-pi/2) < DIST_THRESHOLD) sphere.second = 0;
01490 else if (sphere.second < 0) sphere.second += 2*pi;
01491
01492 return sphere;
01493 }
01494
01495 void Dmap(const Teuchos::ArrayRCP<double*> &coords,
01496 const std::pair<double, double> &sphere,
01497 const std::pair<double, double> &ref,
01498 double D[][2]) {
01499
01500 const double th = sphere.first;
01501 const double lam = sphere.second;
01502 const double sinlam = std::sin(lam);
01503 const double sinth = std::sin(th);
01504 const double coslam = std::cos(lam);
01505 const double costh = std::cos(th);
01506
01507 const double D1[2][3] = {{-sinlam, coslam, 0},
01508 { 0, 0, 1}};
01509
01510 const double D2[3][3] = {{ sinlam*sinlam*costh*costh+sinth*sinth, -sinlam*coslam*costh*costh, -coslam*sinth*costh},
01511 {-sinlam*coslam*costh*costh, coslam*coslam*costh*costh+sinth*sinth, -sinlam*sinth*costh},
01512 {-coslam*sinth, -sinlam*sinth, costh}};
01513
01514 const double DD[4][2] = {{ (-1+ref.second)/4, (-1+ref.first)/4 },
01515 { ( 1-ref.second)/4, (-1-ref.first)/4 },
01516 { ( 1+ref.second)/4, ( 1+ref.first)/4 },
01517 { (-1-ref.second)/4, ( 1-ref.first)/4 }};
01518
01519 double D3[3][2] = {0};
01520 for (unsigned i=0; i<3; ++i)
01521 for (unsigned j=0; j<2; ++j)
01522 for (unsigned k=0; k<4; ++k)
01523 D3[i][j] += coords[k][i] * DD[k][j];
01524
01525 double D4[3][2] = {0};
01526 for (unsigned i=0; i<3; ++i)
01527 for (unsigned j=0; j<2; ++j)
01528 for (unsigned k=0; k<3; ++k)
01529 D4[i][j] += D2[i][k] * D3[k][j];
01530
01531 for (unsigned i=0; i<2; ++i)
01532 for (unsigned j=0; j<2; ++j) D[i][j] = 0;
01533
01534 for (unsigned i=0; i<2; ++i)
01535 for (unsigned j=0; j<2; ++j)
01536 for (unsigned k=0; k<3; ++k)
01537 D[i][j] += D1[i][k] * D4[k][j];
01538
01539 }
01540
01541 std::pair<double, double> parametric_coordinates(const Teuchos::ArrayRCP<double*> &coords,
01542 const std::pair<double, double> &sphere) {
01543 static const double tol_sq = 1e-26;
01544 static const unsigned MAX_NR_ITER = 10;
01545 double costh = std::cos(sphere.first);
01546 double D[2][2], Dinv[2][2];
01547 double resa = 1;
01548 double resb = 1;
01549 std::pair<double, double> ref(0,0);
01550
01551 for (unsigned i=0; i<MAX_NR_ITER && tol_sq < (costh*resb*resb + resa*resa) ; ++i) {
01552 const std::pair<double, double> sph = ref2sphere(coords,ref);
01553 resa = sph.first - sphere.first;
01554 resb = sph.second - sphere.second;
01555
01556 if (resb > pi) resb -= 2*pi;
01557 if (resb < -pi) resb += 2*pi;
01558
01559 Dmap(coords, sph, ref, D);
01560 const double detD = D[0][0]*D[1][1] - D[0][1]*D[1][0];
01561 Dinv[0][0] = D[1][1]/detD;
01562 Dinv[0][1] = -D[0][1]/detD;
01563 Dinv[1][0] = -D[1][0]/detD;
01564 Dinv[1][1] = D[0][0]/detD;
01565
01566 const std::pair<double, double> del( Dinv[0][0]*costh*resb + Dinv[0][1]*resa,
01567 Dinv[1][0]*costh*resb + Dinv[1][1]*resa);
01568 ref.first -= del.first;
01569 ref.second -= del.second;
01570 }
01571 return ref;
01572 }
01573
01574 const std::pair<bool,std::pair<unsigned, unsigned> >point_in_element(const std::pair<double, double> &sphere,
01575 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type& coords,
01576 std::pair<double, double> ¶metric) {
01577 const std::vector<double> sphere_xyz = spherical_to_cart(sphere);
01578 std::pair<bool,std::pair<unsigned, unsigned> > element(false,std::pair<unsigned, unsigned>(0,0));
01579 for (unsigned i=0; i<coords.size() && !element.first; ++i) {
01580 for (unsigned j=0; j<coords[i].size() && !element.first; ++j) {
01581 const bool found = point_inside(coords[i][j], sphere_xyz);
01582 if (found) {
01583 parametric = parametric_coordinates(coords[i][j], sphere);
01584 if (parametric.first < -1) parametric.first = -1;
01585 if (parametric.second < -1) parametric.second = -1;
01586 if (1 < parametric.first ) parametric.first = 1;
01587 if (1 < parametric.second ) parametric.second = 1;
01588 element.first = true;
01589 element.second.first = i;
01590 element.second.second = j;
01591 }
01592 }
01593 }
01594 return element;
01595 }
01596
01597 void setup_latlon_interp(
01598 const unsigned nlat, const double nlon,
01599 const Albany::WorksetArray<Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > >::type& coords,
01600 Albany::WorksetArray<Teuchos::ArrayRCP<std::vector<Albany::STKDiscretization::interp> > >::type& interpdata,
01601 const Teuchos::RCP<const Epetra_Comm> comm) {
01602
01603 double err;
01604 std::vector<double> lat(nlat);
01605 std::vector<double> lon(nlon);
01606
01607 unsigned count=0;
01608 for (unsigned i=0; i<nlat; ++i) lat[i] = -pi/2 + i*pi/(nlat-1);
01609 for (unsigned i=0; i<nlon; ++i) lon[i] = 2*i*pi/nlon;
01610 for (unsigned i=0; i<nlat; ++i) {
01611 for (unsigned j=0; j<nlon; ++j) {
01612 const std::pair<double, double> sphere(lat[i],lon[j]);
01613 std::pair<double, double> paramtric;
01614 const std::pair<bool,std::pair<unsigned, unsigned> >element = point_in_element(sphere, coords, paramtric);
01615 if (element.first) {
01616
01617
01618 const unsigned b = element.second.first ;
01619 const unsigned e = element.second.second;
01620 const std::vector<double> sphere2_xyz = spherical_to_cart(ref2sphere(coords[b][e], paramtric));
01621 const std::vector<double> sphere_xyz = spherical_to_cart(sphere);
01622 err = std::max(err, ::distance(&sphere2_xyz[0],&sphere_xyz[0]));
01623 Albany::STKDiscretization::interp interp;
01624 interp.parametric_coords = paramtric;
01625 interp.latitude_longitude = std::pair<unsigned,unsigned>(i,j);
01626 interpdata[b][e].push_back(interp);
01627 ++count;
01628 }
01629 }
01630 if (!comm->MyPID() && (!(i%64) || i==nlat-1)) std::cout<< "Finished Latitude "<<i<<" of "<<nlat<<std::endl;
01631 }
01632 if (!comm->MyPID()) std::cout<<"Max interpolation point search error: "<<err<<std::endl;
01633 }
01634
01635 double interpolate_to_point(const Teuchos::ArrayRCP<double> height, const std::pair<double, double> ¶metric) {
01636 const double a = parametric.first;
01637 const double b = parametric.second;
01638 const double q[4]={ (1-a)*(1-b)/4,
01639 (1+a)*(1-b)/4,
01640 (1+a)*(1+b)/4,
01641 (1-a)*(1+b)/4} ;
01642 double y=0;
01643 for (unsigned j=0; j<4; ++j) y += height[j]*q[j];
01644 return y;
01645 }
01646 }
01647
01648 int Albany::STKDiscretization::processNetCDFOutputRequest() {
01649 #ifdef ALBANY_SEACAS
01650 const unsigned nlat = stkMeshStruct->nLat;
01651 const unsigned nlon = stkMeshStruct->nLon;
01652
01653 std::vector<double> local(nlat*nlon, -std::numeric_limits<double>::max());
01654
01655 unsigned count=0;
01656 Teuchos::ArrayRCP<double> height(4);
01657 const double theta = netCDFOutputRequest*pi/18;
01658 const double rot[2][2] = {{ std::sin(theta), std::cos(theta)},
01659 {-std::cos(theta), std::sin(theta)}};
01660
01661 for (unsigned b=0; b<interpolateData.size(); ++b) {
01662 Teuchos::ArrayRCP<std::vector<interp> > Interpb = interpolateData[b];
01663 Teuchos::ArrayRCP<Teuchos::ArrayRCP<double*> > Coordsb = coords[b];
01664
01665 for (unsigned e=0; e<Interpb.size(); ++e) {
01666 const std::vector<interp> &interp = Interpb[e];
01667 Teuchos::ArrayRCP<double*> coordp = Coordsb[e];
01668
01669 for (unsigned i=0; i<4; ++i) height[i] = rot[0][0]*coordp[i][0] + rot[0][1]*coordp[i][1];
01670 for (unsigned p=0; p<interp.size(); ++p) {
01671 Albany::STKDiscretization::interp par = interp[p];
01672 double y = interpolate_to_point(height, par.parametric_coords);
01673 std::pair<unsigned,unsigned> latlon = par.latitude_longitude;
01674 local[latlon.first + nlat*latlon.second] = y;
01675 ++count;
01676 }
01677 }
01678 }
01679 std::vector<double> global(nlat*nlon);
01680 comm->MaxAll(&local[0], &global[0], nlat*nlon);
01681
01682 const long long unsigned rank = comm->MyPID();
01683 #ifdef ALBANY_PAR_NETCDF
01684 const long long unsigned np = comm->NumProc();
01685 const size_t start = static_cast<size_t>((rank*nlat)/np);
01686 const size_t end = static_cast<size_t>(((rank+1)*nlat)/np);
01687 const size_t len = end-start;
01688
01689 const size_t startp[] = {netCDFOutputRequest, 0, start, 0};
01690 const size_t countp[] = {1, 1, len, nlon};
01691 if (const int ierr = nc_put_vara_double (netCDFp, varHeight, startp, countp, &global[0]))
01692 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01693 "nc_put_vara_double returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01694 #else
01695 const size_t startp[] = {netCDFOutputRequest, 0, 0, 0};
01696 const size_t countp[] = {1, 1, nlat, nlon};
01697 if (!rank)
01698 if (const int ierr = nc_put_vara_double (netCDFp, varHeight, startp, countp, &global[0]))
01699 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01700 "nc_put_vara returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01701 #endif
01702 #endif
01703 return netCDFOutputRequest++;
01704 }
01705
01706 void Albany::STKDiscretization::setupNetCDFOutput()
01707 {
01708 #ifdef ALBANY_SEACAS
01709 if (stkMeshStruct->cdfOutput) {
01710
01711 outputInterval = 0;
01712 const unsigned nlat = stkMeshStruct->nLat;
01713 const unsigned nlon = stkMeshStruct->nLon;
01714
01715
01716 std::string str = stkMeshStruct->cdfOutFile;
01717
01718 interpolateData.resize(coords.size());
01719 for (int b=0; b < coords.size(); b++) interpolateData[b].resize(coords[b].size());
01720
01721 setup_latlon_interp(nlat, nlon, coords, interpolateData, comm);
01722
01723 const std::string name = stkMeshStruct->cdfOutFile;
01724 netCDFp=0;
01725 netCDFOutputRequest=0;
01726
01727
01728 #ifdef ALBANY_PAR_NETCDF
01729 MPI_Comm theMPIComm = Albany::getMpiCommFromEpetraComm(*comm);
01730 MPI_Info info;
01731 MPI_Info_create(&info);
01732 if (const int ierr = nc_create_par (name.c_str(), NC_NETCDF4 | NC_MPIIO | NC_CLOBBER, theMPIComm, info, &netCDFp))
01733 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01734 "nc_create_par returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01735 MPI_Info_free(&info);
01736 #else
01737 if (const int ierr = nc_create (name.c_str(), NC_NETCDF4 | NC_CLOBBER, &netCDFp))
01738 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01739 "nc_create returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01740 #endif
01741
01742 const size_t nlev = 1;
01743 const char *dimnames[] = {"time","lev","lat","lon"};
01744 const size_t dimlen[] = {NC_UNLIMITED, nlev, nlat, nlon};
01745 int dimID[4]={0,0,0,0};
01746
01747 for (unsigned i=0; i<4; ++i) {
01748 if (const int ierr = nc_def_dim (netCDFp, dimnames[i], dimlen[i], &dimID[i]))
01749 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01750 "nc_def_dim returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01751 }
01752 const char *field_name = "height";
01753 varHeight=0;
01754 if (const int ierr = nc_def_var (netCDFp, field_name, NC_DOUBLE, 4, dimID, &varHeight))
01755 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01756 "nc_def_var "<<field_name<<" returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01757
01758 const double fillVal = -9999.0;
01759 if (const int ierr = nc_put_att (netCDFp, varHeight, "FillValue", NC_DOUBLE, 1, &fillVal))
01760 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01761 "nc_put_att FillValue returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01762
01763 const char lat_name[] = "latitude";
01764 const char lat_unit[] = "degrees_north";
01765 const char lon_name[] = "longitude";
01766 const char lon_unit[] = "degrees_east";
01767 int latVarID=0;
01768 if (const int ierr = nc_def_var (netCDFp, "lat", NC_DOUBLE, 1, &dimID[3], &latVarID))
01769 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01770 "nc_def_var lat returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01771 if (const int ierr = nc_put_att_text (netCDFp, latVarID, "long_name", sizeof(lat_name), lat_name))
01772 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01773 "nc_put_att_text "<<lat_name<<" returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01774 if (const int ierr = nc_put_att_text (netCDFp, latVarID, "units", sizeof(lat_unit), lat_unit))
01775 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01776 "nc_put_att_text "<<lat_unit<<" returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01777
01778 int lonVarID=0;
01779 if (const int ierr = nc_def_var (netCDFp, "lon", NC_DOUBLE, 1, &dimID[2], &lonVarID))
01780 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01781 "nc_def_var lon returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01782 if (const int ierr = nc_put_att_text (netCDFp, lonVarID, "long_name", sizeof(lon_name), lon_name))
01783 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01784 "nc_put_att_text "<<lon_name<<" returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01785 if (const int ierr = nc_put_att_text (netCDFp, lonVarID, "units", sizeof(lon_unit), lon_unit))
01786 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01787 "nc_put_att_text "<<lon_unit<<" returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01788
01789 const char history[]="Created by Albany";
01790 if (const int ierr = nc_put_att_text (netCDFp, NC_GLOBAL, "history", sizeof(history), history))
01791 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01792 "nc_put_att_text "<<history<<" returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01793
01794 if (const int ierr = nc_enddef (netCDFp))
01795 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01796 "nc_enddef returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01797
01798 std::vector<double> deglon(nlon);
01799 std::vector<double> deglat(nlat);
01800 for (unsigned i=0; i<nlon; ++i) deglon[i] =(( 2*i*pi/nlon) * (180./pi)) - 180.;
01801 for (unsigned i=0; i<nlat; ++i) deglat[i] = (-pi/2 + i*pi/(nlat-1))*(180./pi);
01802
01803
01804 if (const int ierr = nc_put_var (netCDFp, lonVarID, °lon[0]))
01805 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01806 "nc_put_var lon returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01807 if (const int ierr = nc_put_var (netCDFp, latVarID, °lat[0]))
01808 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01809 "nc_put_var lat returned error code "<<ierr<<" - "<<nc_strerror(ierr)<<std::endl);
01810
01811 }
01812 #else
01813 if (stkMeshStruct->cdfOutput)
01814 *out << "\nWARNING: NetCDF output requested but SEACAS not compiled in:"
01815 << " disabling NetCDF output \n" << std::endl;
01816 stkMeshStruct->cdfOutput = false;
01817
01818 #endif
01819 }
01820
01821 void Albany::STKDiscretization::reNameExodusOutput(std::string& filename)
01822 {
01823 #ifdef ALBANY_SEACAS
01824 if (stkMeshStruct->exoOutput && mesh_data != NULL) {
01825
01826
01827 delete mesh_data;
01828
01829 stkMeshStruct->exoOutFile = filename;
01830
01831
01832 previous_time_label = -1.0e32;
01833
01834 }
01835 #else
01836 if (stkMeshStruct->exoOutput)
01837 *out << "\nWARNING: exodus output requested but SEACAS not compiled in:"
01838 << " disabling exodus output \n" << std::endl;
01839
01840 #endif
01841 }
01842
01843 void
01844 Albany::STKDiscretization::meshToGraph()
01845 {
01846
01847
01848
01849
01850
01851 std::vector<std::vector<stk::mesh::Entity *> > sur_elem;
01852
01853
01854 sur_elem.resize(numOverlapNodes);
01855
01856 std::size_t max_nsur = 0;
01857
01858
01859 stk::mesh::Selector select_owned_in_part =
01860 stk::mesh::Selector( metaData.universal_part() ) &
01861 stk::mesh::Selector( metaData.locally_owned_part() );
01862
01863 std::vector< stk::mesh::Bucket * > buckets ;
01864 stk::mesh::get_buckets( select_owned_in_part ,
01865 bulkData.buckets( metaData.element_rank() ) ,
01866 buckets);
01867
01868 int numBuckets = buckets.size();
01869 std::vector<const std::size_t *> table(numBuckets);
01870 std::vector<std::size_t> nconnect(numBuckets);
01871
01872
01873 for (int b=0; b < numBuckets; b++) {
01874
01875 stk::mesh::Bucket& cells = *buckets[b];
01876
01877 const CellTopologyData * const elem_top
01878 = stk::mesh::fem::get_cell_topology( cells[0] ).getCellTopologyData();
01879
01880 if(strncmp(elem_top->name, "Hexahedron", 10) == 0){
01881 table[b] = hex_table;
01882 nconnect[b] = hex_nconnect;
01883 }
01884 else if(strncmp(elem_top->name, "Tetrahedron", 11) == 0){
01885 table[b] = tet_table;
01886 nconnect[b] = tet_nconnect;
01887 }
01888 else if(strncmp(elem_top->name, "Triangle", 8) == 0){
01889 table[b] = tri_table;
01890 nconnect[b] = tri_nconnect;
01891 }
01892 else if(strncmp(elem_top->name, "Quadrilateral", 13) == 0){
01893 table[b] = quad_table;
01894 nconnect[b] = quad_nconnect;
01895 }
01896 else
01897
01898 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01899 "Error - unknown element type : " << elem_top->name
01900 << " requested in nodal graph algorithm" << std::endl);
01901
01902
01903 for (std::size_t ecnt=0; ecnt < cells.size(); ecnt++) {
01904 stk::mesh::Entity& e = cells[ecnt];
01905 stk::mesh::PairIterRelation rel = e.relations(metaData.NODE_RANK);
01906
01907
01908 for (std::size_t ncnt=0; ncnt < rel.size(); ncnt++) {
01909 stk::mesh::Entity& rowNode = * rel[ncnt].entity();
01910 int nodeGID = gid(rowNode);
01911 int nodeLID = overlap_node_map->LID(nodeGID);
01912
01913
01914
01915
01916
01917
01918
01919
01920 if (sur_elem[nodeLID].empty() || entity_in_list(&e, sur_elem[nodeLID]) < 0) {
01921
01922 sur_elem[nodeLID].push_back(&e);
01923 }
01924 }
01925 }
01926 }
01927
01928 for(std::size_t ncnt=0; ncnt < numOverlapNodes; ncnt++) {
01929 if(sur_elem[ncnt].empty()) {
01930 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
01931 "Node = " << ncnt+1 << " has no elements" << std::endl);
01932 }
01933 else {
01934 std::size_t nsur = sur_elem[ncnt].size();
01935 if (nsur > max_nsur)
01936 max_nsur = nsur;
01937 }
01938 }
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948 nodalGraph.start.resize(numOverlapNodes + 1);
01949 nodalGraph.adj.clear();
01950 std::size_t nadj = 0;
01951
01952
01953
01954 for(std::size_t ncnt=0; ncnt < numOverlapNodes; ncnt++) {
01955
01956
01957 nodalGraph.start[ncnt] = nadj;
01958
01959 for(std::size_t ecnt=0; ecnt < sur_elem[ncnt].size(); ecnt++) {
01960 stk::mesh::Entity* elem = sur_elem[ncnt][ecnt];
01961
01962
01963 stk::mesh::PairIterRelation rel = elem->relations(metaData.NODE_RANK);
01964
01965 std::size_t ws = elemGIDws[gid(elem)].ws;
01966
01967
01968 for (std::size_t lnode=0; lnode < rel.size(); lnode++) {
01969 stk::mesh::Entity& node_a = * rel[lnode].entity();
01970
01971 std::size_t entry = gid(node_a);
01972
01973
01974
01975 if(overlap_node_map->GID(ncnt) == entry){
01976
01977
01978 for(std::size_t k = 0; k < nconnect[ws]; k++){
01979
01980 int local_node = table[ws][lnode * nconnect[ws] + k];
01981
01982 std::size_t global_node_id = gid(*rel[local_node].entity());
01983
01984
01985 if(in_list(global_node_id,
01986 nodalGraph.adj.size()-nodalGraph.start[ncnt],
01987 &nodalGraph.adj[nodalGraph.start[ncnt]]) < 0) {
01988 nodalGraph.adj.push_back(global_node_id);
01989
01990 }
01991 }
01992 break;
01993 }
01994 }
01995 }
01996
01997 nadj = nodalGraph.adj.size();
01998
01999 }
02000
02001 nodalGraph.start[numOverlapNodes] = nadj;
02002
02003
02004
02005 }
02006
02007 void
02008 Albany::STKDiscretization::printVertexConnectivity(){
02009
02010 for(std::size_t i = 0; i < numOverlapNodes; i++){
02011
02012 std::cout << "Center vert is : " << overlap_node_map->GID(i) + 1 << std::endl;
02013
02014 for(std::size_t j = nodalGraph.start[i]; j < nodalGraph.start[i + 1]; j++)
02015
02016 std::cout << " " << nodalGraph.adj[j] + 1 << std::endl;
02017
02018 }
02019 }
02020
02021 void
02022 Albany::STKDiscretization::updateMesh()
02023 {
02024
02025 computeOwnedNodesAndUnknowns();
02026
02027 setupMLCoords();
02028
02029 computeOverlapNodesAndUnknowns();
02030
02031 transformMesh();
02032
02033 computeGraphs();
02034
02035 computeWorksetInfo();
02036
02037 computeNodeSets();
02038
02039 computeSideSets();
02040
02041 setupExodusOutput();
02042
02043 setupNetCDFOutput();
02044
02045
02046
02047 }